Contiki-NG
Loading...
Searching...
No Matches
tsch-queue.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014, SICS Swedish ICT.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * This file is part of the Contiki operating system.
30 *
31 */
32
33/**
34 * \file
35 * Per-neighbor packet queues for TSCH MAC.
36 * The list of neighbors uses the TSCH lock, but per-neighbor packet array are lock-free.
37 * Read-only operation on neighbor and packets are allowed from interrupts and outside of them.
38 * *Other operations are allowed outside of interrupt only.*
39 * \author
40 * Simon Duquennoy <simonduq@sics.se>
41 * Beshr Al Nahas <beshr@sics.se>
42 * Domenico De Guglielmo <d.deguglielmo@iet.unipi.it >
43 * Atis Elsts <atis.elsts@edi.lv>
44 */
45
46/**
47 * \addtogroup tsch
48 * @{
49*/
50
51#include "contiki.h"
52#include "lib/list.h"
53#include "lib/memb.h"
54#include "lib/random.h"
55#include "net/queuebuf.h"
56#include "net/mac/tsch/tsch.h"
57#include "net/nbr-table.h"
58#include <string.h>
59
60/* Log configuration */
61#include "sys/log.h"
62#define LOG_MODULE "TSCH Queue"
63#define LOG_LEVEL LOG_LEVEL_MAC
64
65/* Check if TSCH_QUEUE_NUM_PER_NEIGHBOR is power of two */
66#if (TSCH_QUEUE_NUM_PER_NEIGHBOR & (TSCH_QUEUE_NUM_PER_NEIGHBOR - 1)) != 0
67#error TSCH_QUEUE_NUM_PER_NEIGHBOR must be power of two
68#endif
69
70/* We have as many packets are there are queuebuf in the system */
71MEMB(packet_memb, struct tsch_packet, QUEUEBUF_NUM);
72NBR_TABLE(struct tsch_neighbor, tsch_neighbors);
73
74/* Broadcast and EB virtual neighbors */
75struct tsch_neighbor *n_broadcast;
76struct tsch_neighbor *n_eb;
77
78/*---------------------------------------------------------------------------*/
79/* Add a TSCH neighbor */
80struct tsch_neighbor *
81tsch_queue_add_nbr(const linkaddr_t *addr)
82{
83 struct tsch_neighbor *n = NULL;
84 /* If we have an entry for this neighbor already, we simply update it */
86 if(n == NULL) {
87 if(tsch_get_lock()) {
88 /* Allocate a neighbor */
89 n = (struct tsch_neighbor *)nbr_table_add_lladdr(tsch_neighbors, addr, NBR_TABLE_REASON_MAC, NULL);
90 if(n != NULL) {
91 /* Do not allow to garbage collect this neighbor by external code!
92 * The garbage collection is not aware of the tsch_lock, so is not interrupt safe.
93 */
94 nbr_table_lock(tsch_neighbors, n);
95 /* Initialize neighbor entry */
96 memset(n, 0, sizeof(struct tsch_neighbor));
97 ringbufindex_init(&n->tx_ringbuf, TSCH_QUEUE_NUM_PER_NEIGHBOR);
98 n->is_broadcast = linkaddr_cmp(addr, &tsch_eb_address)
99 || linkaddr_cmp(addr, &tsch_broadcast_address);
101 }
103 }
104 }
105 return n;
106}
107/*---------------------------------------------------------------------------*/
108/* Get a TSCH neighbor */
109struct tsch_neighbor *
110tsch_queue_get_nbr(const linkaddr_t *addr)
111{
112 if(!tsch_is_locked()) {
113 return (struct tsch_neighbor *)nbr_table_get_from_lladdr(tsch_neighbors, addr);
114 }
115 return NULL;
116}
117/*---------------------------------------------------------------------------*/
118/* Get a TSCH time source (we currently assume there is only one) */
119struct tsch_neighbor *
121{
122 if(!tsch_is_locked()) {
123 struct tsch_neighbor *curr_nbr = (struct tsch_neighbor *)nbr_table_head(tsch_neighbors);
124 while(curr_nbr != NULL) {
125 if(curr_nbr->is_time_source) {
126 return curr_nbr;
127 }
128 curr_nbr = (struct tsch_neighbor *)nbr_table_next(tsch_neighbors, curr_nbr);
129 }
130 }
131 return NULL;
132}
133/*---------------------------------------------------------------------------*/
134linkaddr_t *
136{
137 return nbr_table_get_lladdr(tsch_neighbors, n);
138}
139/*---------------------------------------------------------------------------*/
140/* Update TSCH time source */
141int
142tsch_queue_update_time_source(const linkaddr_t *new_addr)
143{
144 if(!tsch_is_locked()) {
145 if(!tsch_is_coordinator) {
146 struct tsch_neighbor *old_time_src = tsch_queue_get_time_source();
147 struct tsch_neighbor *new_time_src = NULL;
148
149 if(new_addr != NULL) {
150 /* Get/add neighbor, return 0 in case of failure */
151 new_time_src = tsch_queue_add_nbr(new_addr);
152 if(new_time_src == NULL) {
153 return 0;
154 }
155 }
156
157 if(new_time_src != old_time_src) {
158 LOG_INFO("update time source: ");
159 LOG_INFO_LLADDR(tsch_queue_get_nbr_address(old_time_src));
160 LOG_INFO_(" -> ");
161 LOG_INFO_LLADDR(tsch_queue_get_nbr_address(new_time_src));
162 LOG_INFO_("\n");
163
164 /* Update time source */
165 if(new_time_src != NULL) {
166 new_time_src->is_time_source = 1;
167 /* (Re)set keep-alive timeout */
168 tsch_set_ka_timeout(TSCH_KEEPALIVE_TIMEOUT);
169 } else {
170 /* Stop sending keepalives */
172 }
173
174 if(old_time_src != NULL) {
175 old_time_src->is_time_source = 0;
176 }
177
178 tsch_stats_reset_neighbor_stats();
179
180#ifdef TSCH_CALLBACK_NEW_TIME_SOURCE
181 TSCH_CALLBACK_NEW_TIME_SOURCE(old_time_src, new_time_src);
182#endif
183 }
184
185 return 1;
186 }
187 }
188 return 0;
189}
190/*---------------------------------------------------------------------------*/
191/* Flush a neighbor queue */
192static void
193tsch_queue_flush_nbr_queue(struct tsch_neighbor *n)
194{
195 while(!tsch_queue_is_empty(n)) {
197 if(p != NULL) {
198 /* Set return status for packet_sent callback */
199 p->ret = MAC_TX_ERR;
200 LOG_WARN("! flushing packet\n");
201 /* Call packet_sent callback */
202 mac_call_sent_callback(p->sent, p->ptr, p->ret, p->transmissions);
203 /* Free packet queuebuf */
205 }
206 }
207}
208/*---------------------------------------------------------------------------*/
209/* Remove TSCH neighbor queue */
210static void
211tsch_queue_remove_nbr(struct tsch_neighbor *n)
212{
213 if(n != NULL) {
214 if(tsch_get_lock()) {
215
217
218 /* Flush queue */
219 tsch_queue_flush_nbr_queue(n);
220
221 /* Free neighbor */
222 nbr_table_remove(tsch_neighbors, n);
223 }
224 }
225}
226/*---------------------------------------------------------------------------*/
227/* Add packet to neighbor queue. Use same lockfree implementation as ringbuf.c (put is atomic) */
228struct tsch_packet *
229tsch_queue_add_packet(const linkaddr_t *addr, uint8_t max_transmissions,
230 mac_callback_t sent, void *ptr)
231{
232 struct tsch_neighbor *n = NULL;
233 int16_t put_index = -1;
234 struct tsch_packet *p = NULL;
235
236#ifdef TSCH_CALLBACK_PACKET_READY
237 /* The scheduler provides a callback which sets the timeslot and other attributes */
238 if(TSCH_CALLBACK_PACKET_READY() < 0) {
239 /* No scheduled slots for the packet available; drop it early to save queue space. */
240 LOG_DBG("tsch_queue_add_packet(): rejected by the scheduler\n");
241 return NULL;
242 }
243#endif
244
245 if(!tsch_is_locked()) {
247 if(n != NULL) {
248 put_index = ringbufindex_peek_put(&n->tx_ringbuf);
249 if(put_index != -1) {
250 p = memb_alloc(&packet_memb);
251 if(p != NULL) {
252 /* Enqueue packet */
253 p->qb = queuebuf_new_from_packetbuf();
254 if(p->qb != NULL) {
255 p->sent = sent;
256 p->ptr = ptr;
257 p->ret = MAC_TX_DEFERRED;
258 p->transmissions = 0;
259 p->max_transmissions = max_transmissions;
260 /* Add to ringbuf (actual add committed through atomic operation) */
261 n->tx_array[put_index] = p;
262 ringbufindex_put(&n->tx_ringbuf);
263 LOG_DBG("packet is added put_index %u, packet %p\n",
264 put_index, p);
265 return p;
266 } else {
267 memb_free(&packet_memb, p);
268 }
269 }
270 }
271 }
272 }
273 LOG_ERR("! add packet failed: %u %p %d %p %p\n", tsch_is_locked(), n, put_index, p, p ? p->qb : NULL);
274 return NULL;
275}
276/*---------------------------------------------------------------------------*/
277/* Returns the number of packets currently in any TSCH queue */
278int
280{
281 return QUEUEBUF_NUM - memb_numfree(&packet_memb);
282}
283/*---------------------------------------------------------------------------*/
284/* Returns the number of packets currently in the queue */
285int
287{
288 if(n != NULL) {
289 return ringbufindex_elements(&n->tx_ringbuf);
290 }
291 return -1;
292}
293/*---------------------------------------------------------------------------*/
294/* Remove first packet from a neighbor queue */
295struct tsch_packet *
297{
298 if(!tsch_is_locked()) {
299 if(n != NULL) {
300 /* Get and remove packet from ringbuf (remove committed through an atomic operation */
301 int16_t get_index = ringbufindex_get(&n->tx_ringbuf);
302 if(get_index != -1) {
303 return n->tx_array[get_index];
304 } else {
305 return NULL;
306 }
307 }
308 }
309 return NULL;
310}
311/*---------------------------------------------------------------------------*/
312/* Free a packet */
313void
315{
316 if(p != NULL) {
317 queuebuf_free(p->qb);
318 memb_free(&packet_memb, p);
319 }
320}
321/*---------------------------------------------------------------------------*/
322/* Free all packets to a neighbor */
323void
325{
326 struct tsch_neighbor *n = NULL;
327 if(!tsch_is_locked()) {
329 if(n != NULL) {
330 tsch_queue_flush_nbr_queue(n);
331 }
332 }
333}
334/*---------------------------------------------------------------------------*/
335/* Updates neighbor queue state after a transmission */
336int
338 struct tsch_link *link, uint8_t mac_tx_status)
339{
340 int in_queue = 1;
341 int is_shared_link = link->link_options & LINK_OPTION_SHARED;
342 int is_unicast = !n->is_broadcast;
343
344 if(mac_tx_status == MAC_TX_OK) {
345 /* Successful transmission */
347 in_queue = 0;
348
349 /* Update CSMA state in the unicast case */
350 if(is_unicast) {
351 if(is_shared_link || tsch_queue_is_empty(n)) {
352 /* If this is a shared link, reset backoff on success.
353 * Otherwise, do so only is the queue is empty */
355 }
356 }
357 } else {
358 /* Failed transmission */
359 if(p->transmissions >= p->max_transmissions) {
360 /* Drop packet */
362 in_queue = 0;
363 }
364 /* Update CSMA state in the unicast case */
365 if(is_unicast) {
366 /* Failures on dedicated (== non-shared) leave the backoff
367 * window nor exponent unchanged */
368 if(is_shared_link) {
369 /* Shared link: increment backoff exponent, pick a new window */
371 }
372 }
373 }
374
375 return in_queue;
376}
377/*---------------------------------------------------------------------------*/
378/* Flush all neighbor queues */
379void
381{
382 /* Deallocate unneeded neighbors */
383 if(!tsch_is_locked()) {
384 struct tsch_neighbor *n = (struct tsch_neighbor *)nbr_table_head(tsch_neighbors);
385 while(n != NULL) {
386 struct tsch_neighbor *next_n = (struct tsch_neighbor *)nbr_table_next(tsch_neighbors, n);
387 /* Flush queue */
388 tsch_queue_flush_nbr_queue(n);
389 /* Reset backoff exponent */
391 n = next_n;
392 }
393 }
394}
395/*---------------------------------------------------------------------------*/
396/* Deallocate neighbors with empty queue */
397void
399{
400 /* Deallocate unneeded neighbors */
401 if(!tsch_is_locked()) {
402 struct tsch_neighbor *n = (struct tsch_neighbor *)nbr_table_head(tsch_neighbors);
403 while(n != NULL) {
404 struct tsch_neighbor *next_n = (struct tsch_neighbor *)nbr_table_next(tsch_neighbors, n);
405 /* Queue is empty, no tx link to this neighbor: deallocate.
406 * Always keep time source and virtual broadcast neighbors. */
407 if(!n->is_broadcast && !n->is_time_source && !n->tx_links_count
408 && tsch_queue_is_empty(n)) {
409 tsch_queue_remove_nbr(n);
410 }
411 n = next_n;
412 }
413 }
414}
415/*---------------------------------------------------------------------------*/
416/* Is the neighbor queue empty? */
417int
419{
420 return !tsch_is_locked() && n != NULL && ringbufindex_empty(&n->tx_ringbuf);
421}
422/*---------------------------------------------------------------------------*/
423/* Returns the first packet from a neighbor queue */
424struct tsch_packet *
426{
427 if(!tsch_is_locked()) {
428 int is_shared_link = link != NULL && link->link_options & LINK_OPTION_SHARED;
429 if(n != NULL) {
430 int16_t get_index = ringbufindex_peek_get(&n->tx_ringbuf);
431 if(get_index != -1 &&
432 !(is_shared_link && !tsch_queue_backoff_expired(n))) { /* If this is a shared link,
433 make sure the backoff has expired */
434#if TSCH_WITH_LINK_SELECTOR
435 int packet_attr_slotframe = queuebuf_attr(n->tx_array[get_index]->qb, PACKETBUF_ATTR_TSCH_SLOTFRAME);
436 int packet_attr_timeslot = queuebuf_attr(n->tx_array[get_index]->qb, PACKETBUF_ATTR_TSCH_TIMESLOT);
437 if(packet_attr_slotframe != 0xffff && packet_attr_slotframe != link->slotframe_handle) {
438 return NULL;
439 }
440 if(packet_attr_timeslot != 0xffff && packet_attr_timeslot != link->timeslot) {
441 return NULL;
442 }
443#endif
444 return n->tx_array[get_index];
445 }
446 }
447 }
448 return NULL;
449}
450/*---------------------------------------------------------------------------*/
451/* Returns the head packet from a neighbor queue (from neighbor address) */
452struct tsch_packet *
453tsch_queue_get_packet_for_dest_addr(const linkaddr_t *addr, struct tsch_link *link)
454{
455 if(!tsch_is_locked()) {
457 }
458 return NULL;
459}
460/*---------------------------------------------------------------------------*/
461/* Returns the head packet of any neighbor queue with zero backoff counter.
462 * Writes pointer to the neighbor in *n */
463struct tsch_packet *
465{
466 if(!tsch_is_locked()) {
467 struct tsch_neighbor *curr_nbr = (struct tsch_neighbor *)nbr_table_head(tsch_neighbors);
468 struct tsch_packet *p = NULL;
469 while(curr_nbr != NULL) {
470 if(!curr_nbr->is_broadcast && curr_nbr->tx_links_count == 0) {
471 /* Only look up for non-broadcast neighbors we do not have a tx link to */
472 p = tsch_queue_get_packet_for_nbr(curr_nbr, link);
473 if(p != NULL) {
474 if(n != NULL) {
475 *n = curr_nbr;
476 }
477 return p;
478 }
479 }
480 curr_nbr = (struct tsch_neighbor *)nbr_table_next(tsch_neighbors, curr_nbr);
481 }
482 }
483 return NULL;
484}
485/*---------------------------------------------------------------------------*/
486/* May the neighbor transmit over a shared link? */
487int
489{
490 return n->backoff_window == 0;
491}
492/*---------------------------------------------------------------------------*/
493/* Reset neighbor backoff */
494void
496{
497 n->backoff_window = 0;
498 n->backoff_exponent = TSCH_MAC_MIN_BE;
499}
500/*---------------------------------------------------------------------------*/
501/* Increment backoff exponent, pick a new window */
502void
504{
505 /* Increment exponent */
506 n->backoff_exponent = MIN(n->backoff_exponent + 1, TSCH_MAC_MAX_BE);
507 /* Pick a window (number of shared slots to skip). Ignore least significant
508 * few bits, which, on some embedded implementations of rand (e.g. msp430-libc),
509 * are known to have poor pseudo-random properties. */
510 n->backoff_window = (random_rand() >> 6) % (1ul << n->backoff_exponent);
511 /* Add one to the window as we will decrement it at the end of the current slot
512 * through tsch_queue_update_all_backoff_windows */
513 if(n->backoff_window < UINT16_MAX) {
514 n->backoff_window++;
515 }
516}
517/*---------------------------------------------------------------------------*/
518/* Decrement backoff window for all queues directed at dest_addr */
519void
520tsch_queue_update_all_backoff_windows(const linkaddr_t *dest_addr)
521{
522 if(!tsch_is_locked()) {
523 int is_broadcast = linkaddr_cmp(dest_addr, &tsch_broadcast_address);
524 struct tsch_neighbor *n = (struct tsch_neighbor *)nbr_table_head(tsch_neighbors);
525 while(n != NULL) {
526 if(n->backoff_window != 0 /* Is the queue in backoff state? */
527 && ((n->tx_links_count == 0 && is_broadcast)
528 || (n->tx_links_count > 0 && linkaddr_cmp(dest_addr, tsch_queue_get_nbr_address(n))))) {
529 n->backoff_window--;
530 }
531 n = (struct tsch_neighbor *)nbr_table_next(tsch_neighbors, n);
532 }
533 }
534}
535/*---------------------------------------------------------------------------*/
536/* Initialize TSCH queue module */
537void
539{
540 nbr_table_register(tsch_neighbors, NULL);
541 memb_init(&packet_memb);
542 /* Add virtual EB and the broadcast neighbors */
543 n_eb = tsch_queue_add_nbr(&tsch_eb_address);
544 n_broadcast = tsch_queue_add_nbr(&tsch_broadcast_address);
545}
546/*---------------------------------------------------------------------------*/
547/** @} */
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Definition random.c:58
bool linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition linkaddr.c:69
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition memb.c:78
size_t memb_numfree(struct memb *m)
Count free memory blocks.
Definition memb.c:108
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition memb.c:59
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
Definition memb.c:52
#define MEMB(name, structure, num)
Declare a memory block.
Definition memb.h:91
struct tsch_packet * tsch_queue_get_packet_for_dest_addr(const linkaddr_t *addr, struct tsch_link *link)
Returns the first packet that can be sent to a given address on a given link.
Definition tsch-queue.c:453
struct tsch_neighbor * tsch_queue_get_nbr(const linkaddr_t *addr)
Get a TSCH neighbor.
Definition tsch-queue.c:110
void tsch_queue_free_unused_neighbors(void)
Deallocate all neighbors with empty queue.
Definition tsch-queue.c:398
struct tsch_neighbor * tsch_queue_get_time_source(void)
Get the TSCH time source (we currently assume there is only one)
Definition tsch-queue.c:120
void tsch_queue_update_all_backoff_windows(const linkaddr_t *dest_addr)
Decrement backoff window for the queue(s) able to Tx to a given address.
Definition tsch-queue.c:520
void tsch_queue_free_packet(struct tsch_packet *p)
Free a packet.
Definition tsch-queue.c:314
int tsch_queue_global_packet_count(void)
Returns the number of packets currently in all TSCH queues.
Definition tsch-queue.c:279
struct tsch_packet * tsch_queue_get_packet_for_nbr(const struct tsch_neighbor *n, struct tsch_link *link)
Returns the first packet that can be sent from a queue on a given link.
Definition tsch-queue.c:425
int tsch_queue_update_time_source(const linkaddr_t *new_addr)
Update TSCH time source.
Definition tsch-queue.c:142
struct tsch_packet * tsch_queue_add_packet(const linkaddr_t *addr, uint8_t max_transmissions, mac_callback_t sent, void *ptr)
Add packet to neighbor queue.
Definition tsch-queue.c:229
int tsch_queue_backoff_expired(const struct tsch_neighbor *n)
Is the neighbor backoff timer expired?
Definition tsch-queue.c:488
int tsch_queue_nbr_packet_count(const struct tsch_neighbor *n)
Returns the number of packets currently a given neighbor queue (by pointer)
Definition tsch-queue.c:286
int tsch_get_lock(void)
Takes the TSCH lock.
void tsch_set_ka_timeout(uint32_t timeout)
Set the desynchronization timeout after which a node sends a unicasst keep-alive (KA) to its time sou...
Definition tsch.c:190
void tsch_release_lock(void)
Releases the TSCH lock.
void tsch_queue_reset(void)
Reset neighbor queues module.
Definition tsch-queue.c:380
int tsch_queue_packet_sent(struct tsch_neighbor *n, struct tsch_packet *p, struct tsch_link *link, uint8_t mac_tx_status)
Updates neighbor queue state after a transmission.
Definition tsch-queue.c:337
struct tsch_neighbor * tsch_queue_add_nbr(const linkaddr_t *addr)
Add a TSCH neighbor queue.
Definition tsch-queue.c:81
void tsch_queue_init(void)
Initialize TSCH queue module.
Definition tsch-queue.c:538
struct tsch_packet * tsch_queue_get_unicast_packet_for_any(struct tsch_neighbor **n, struct tsch_link *link)
Gets the head packet of any neighbor queue with zero backoff counter.
Definition tsch-queue.c:464
void tsch_queue_free_packets_to(const linkaddr_t *addr)
Flush packets to a specific address.
Definition tsch-queue.c:324
struct tsch_packet * tsch_queue_remove_packet_from_queue(struct tsch_neighbor *n)
Remove first packet from a neighbor queue.
Definition tsch-queue.c:296
int tsch_is_locked(void)
Checks if the TSCH lock is set.
int tsch_queue_is_empty(const struct tsch_neighbor *n)
Is the neighbor queue empty?
Definition tsch-queue.c:418
void tsch_queue_backoff_inc(struct tsch_neighbor *n)
Increment backoff exponent of a given neighbor queue, pick a new window.
Definition tsch-queue.c:503
linkaddr_t * tsch_queue_get_nbr_address(const struct tsch_neighbor *n)
Get the address of a neighbor.
Definition tsch-queue.c:135
void tsch_queue_backoff_reset(struct tsch_neighbor *n)
Reset neighbor backoff.
Definition tsch-queue.c:495
Linked list manipulation routines.
Header file for the logging system.
@ MAC_TX_DEFERRED
The MAC layer transmission could not be performed because of an error.
Definition mac.h:103
@ MAC_TX_OK
The MAC layer transmission was OK.
Definition mac.h:93
@ MAC_TX_ERR
The MAC layer transmission could not be performed because of a fatal error.
Definition mac.h:107
Memory block allocation routines.
Header file for the Packet queue buffer management.
int ringbufindex_peek_get(const struct ringbufindex *r)
Return the index of the first element which will be removed if calling ringbufindex_get.
void ringbufindex_init(struct ringbufindex *r, uint8_t size)
Initialize a ring buffer.
int ringbufindex_put(struct ringbufindex *r)
Put one element to the ring buffer.
int ringbufindex_get(struct ringbufindex *r)
Remove the first element and return its index.
int ringbufindex_peek_put(const struct ringbufindex *r)
Check if there is space to put an element.
static int ringbufindex_elements(const struct ringbufindex *r)
Return the number of elements currently in the ring buffer.
static int ringbufindex_empty(const struct ringbufindex *r)
Is the ring buffer empty?
TSCH neighbor information.
Definition tsch-types.h:109
TSCH packet information.
Definition tsch-types.h:97
Main API declarations for TSCH.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition uip-nd6.c:107