Contiki-NG
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  */
44 
45 /**
46  * \addtogroup tsch
47  * @{
48 */
49 
50 #include "contiki.h"
51 #include "lib/list.h"
52 #include "lib/memb.h"
53 #include "lib/random.h"
54 #include "net/queuebuf.h"
55 #include "net/mac/tsch/tsch.h"
56 #include <string.h>
57 
58 /* Log configuration */
59 #include "sys/log.h"
60 #define LOG_MODULE "TSCH Queue"
61 #define LOG_LEVEL LOG_LEVEL_MAC
62 
63 /* Check if TSCH_QUEUE_NUM_PER_NEIGHBOR is power of two */
64 #if (TSCH_QUEUE_NUM_PER_NEIGHBOR & (TSCH_QUEUE_NUM_PER_NEIGHBOR - 1)) != 0
65 #error TSCH_QUEUE_NUM_PER_NEIGHBOR must be power of two
66 #endif
67 
68 /* We have as many packets are there are queuebuf in the system */
69 MEMB(packet_memb, struct tsch_packet, QUEUEBUF_NUM);
70 MEMB(neighbor_memb, struct tsch_neighbor, TSCH_QUEUE_MAX_NEIGHBOR_QUEUES);
71 LIST(neighbor_list);
72 
73 /* Broadcast and EB virtual neighbors */
74 struct tsch_neighbor *n_broadcast;
75 struct tsch_neighbor *n_eb;
76 
77 /*---------------------------------------------------------------------------*/
78 /* Add a TSCH neighbor */
79 struct tsch_neighbor *
80 tsch_queue_add_nbr(const linkaddr_t *addr)
81 {
82  struct tsch_neighbor *n = NULL;
83  /* If we have an entry for this neighbor already, we simply update it */
84  n = tsch_queue_get_nbr(addr);
85  if(n == NULL) {
86  if(tsch_get_lock()) {
87  /* Allocate a neighbor */
88  n = memb_alloc(&neighbor_memb);
89  if(n != NULL) {
90  /* Initialize neighbor entry */
91  memset(n, 0, sizeof(struct tsch_neighbor));
92  ringbufindex_init(&n->tx_ringbuf, TSCH_QUEUE_NUM_PER_NEIGHBOR);
93  linkaddr_copy(&n->addr, addr);
94  n->is_broadcast = linkaddr_cmp(addr, &tsch_eb_address)
95  || linkaddr_cmp(addr, &tsch_broadcast_address);
97  /* Add neighbor to the list */
98  list_add(neighbor_list, n);
99  }
101  }
102  }
103  return n;
104 }
105 /*---------------------------------------------------------------------------*/
106 /* Get a TSCH neighbor */
107 struct tsch_neighbor *
108 tsch_queue_get_nbr(const linkaddr_t *addr)
109 {
110  if(!tsch_is_locked()) {
111  struct tsch_neighbor *n = list_head(neighbor_list);
112  while(n != NULL) {
113  if(linkaddr_cmp(&n->addr, addr)) {
114  return n;
115  }
116  n = list_item_next(n);
117  }
118  }
119  return NULL;
120 }
121 /*---------------------------------------------------------------------------*/
122 /* Get a TSCH time source (we currently assume there is only one) */
123 struct tsch_neighbor *
125 {
126  if(!tsch_is_locked()) {
127  struct tsch_neighbor *curr_nbr = list_head(neighbor_list);
128  while(curr_nbr != NULL) {
129  if(curr_nbr->is_time_source) {
130  return curr_nbr;
131  }
132  curr_nbr = list_item_next(curr_nbr);
133  }
134  }
135  return NULL;
136 }
137 /*---------------------------------------------------------------------------*/
138 /* Update TSCH time source */
139 int
140 tsch_queue_update_time_source(const linkaddr_t *new_addr)
141 {
142  if(!tsch_is_locked()) {
143  if(!tsch_is_coordinator) {
144  struct tsch_neighbor *old_time_src = tsch_queue_get_time_source();
145  struct tsch_neighbor *new_time_src = NULL;
146 
147  if(new_addr != NULL) {
148  /* Get/add neighbor, return 0 in case of failure */
149  new_time_src = tsch_queue_add_nbr(new_addr);
150  if(new_time_src == NULL) {
151  return 0;
152  }
153  }
154 
155  if(new_time_src != old_time_src) {
156  LOG_INFO("update time source: ");
157  LOG_INFO_LLADDR(old_time_src ? &old_time_src->addr : NULL);
158  LOG_INFO_(" -> ");
159  LOG_INFO_LLADDR(new_time_src ? &new_time_src->addr : NULL);
160  LOG_INFO_("\n");
161 
162  /* Update time source */
163  if(new_time_src != NULL) {
164  new_time_src->is_time_source = 1;
165  /* (Re)set keep-alive timeout */
166  tsch_set_ka_timeout(TSCH_KEEPALIVE_TIMEOUT);
167  } else {
168  /* Stop sending keepalives */
170  }
171 
172  if(old_time_src != NULL) {
173  old_time_src->is_time_source = 0;
174  }
175 
176  tsch_stats_reset_neighbor_stats();
177 
178 #ifdef TSCH_CALLBACK_NEW_TIME_SOURCE
179  TSCH_CALLBACK_NEW_TIME_SOURCE(old_time_src, new_time_src);
180 #endif
181  }
182 
183  return 1;
184  }
185  }
186  return 0;
187 }
188 /*---------------------------------------------------------------------------*/
189 /* Flush a neighbor queue */
190 static void
191 tsch_queue_flush_nbr_queue(struct tsch_neighbor *n)
192 {
193  while(!tsch_queue_is_empty(n)) {
195  if(p != NULL) {
196  /* Set return status for packet_sent callback */
197  p->ret = MAC_TX_ERR;
198  LOG_WARN("! flushing packet\n");
199  /* Call packet_sent callback */
200  mac_call_sent_callback(p->sent, p->ptr, p->ret, p->transmissions);
201  /* Free packet queuebuf */
203  }
204  }
205 }
206 /*---------------------------------------------------------------------------*/
207 /* Remove TSCH neighbor queue */
208 static void
209 tsch_queue_remove_nbr(struct tsch_neighbor *n)
210 {
211  if(n != NULL) {
212  if(tsch_get_lock()) {
213 
214  /* Remove neighbor from list */
215  list_remove(neighbor_list, n);
216 
218 
219  /* Flush queue */
220  tsch_queue_flush_nbr_queue(n);
221 
222  /* Free neighbor */
223  memb_free(&neighbor_memb, n);
224  }
225  }
226 }
227 /*---------------------------------------------------------------------------*/
228 /* Add packet to neighbor queue. Use same lockfree implementation as ringbuf.c (put is atomic) */
229 struct tsch_packet *
230 tsch_queue_add_packet(const linkaddr_t *addr, uint8_t max_transmissions,
231  mac_callback_t sent, void *ptr)
232 {
233  struct tsch_neighbor *n = NULL;
234  int16_t put_index = -1;
235  struct tsch_packet *p = NULL;
236 
237 #ifdef TSCH_CALLBACK_PACKET_READY
238  /* The scheduler provides a callback which sets the timeslot and other attributes */
239  if(TSCH_CALLBACK_PACKET_READY() < 0) {
240  /* No scheduled slots for the packet available; drop it early to save queue space. */
241  LOG_DBG("tsch_queue_add_packet(): rejected by the scheduler\n");
242  return NULL;
243  }
244 #endif
245 
246  if(!tsch_is_locked()) {
247  n = tsch_queue_add_nbr(addr);
248  if(n != NULL) {
249  put_index = ringbufindex_peek_put(&n->tx_ringbuf);
250  if(put_index != -1) {
251  p = memb_alloc(&packet_memb);
252  if(p != NULL) {
253  /* Enqueue packet */
254  p->qb = queuebuf_new_from_packetbuf();
255  if(p->qb != NULL) {
256  p->sent = sent;
257  p->ptr = ptr;
258  p->ret = MAC_TX_DEFERRED;
259  p->transmissions = 0;
260  p->max_transmissions = max_transmissions;
261  /* Add to ringbuf (actual add committed through atomic operation) */
262  n->tx_array[put_index] = p;
263  ringbufindex_put(&n->tx_ringbuf);
264  LOG_DBG("packet is added put_index %u, packet %p\n",
265  put_index, p);
266  return p;
267  } else {
268  memb_free(&packet_memb, p);
269  }
270  }
271  }
272  }
273  }
274  LOG_ERR("! add packet failed: %u %p %d %p %p\n", tsch_is_locked(), n, put_index, p, p ? p->qb : NULL);
275  return NULL;
276 }
277 /*---------------------------------------------------------------------------*/
278 /* Returns the number of packets currently in any TSCH queue */
279 int
281 {
282  return QUEUEBUF_NUM - memb_numfree(&packet_memb);
283 }
284 /*---------------------------------------------------------------------------*/
285 /* Returns the number of packets currently in the queue */
286 int
287 tsch_queue_packet_count(const linkaddr_t *addr)
288 {
289  struct tsch_neighbor *n = NULL;
290  if(!tsch_is_locked()) {
291  n = tsch_queue_add_nbr(addr);
292  if(n != NULL) {
293  return ringbufindex_elements(&n->tx_ringbuf);
294  }
295  }
296  return -1;
297 }
298 /*---------------------------------------------------------------------------*/
299 /* Remove first packet from a neighbor queue */
300 struct tsch_packet *
302 {
303  if(!tsch_is_locked()) {
304  if(n != NULL) {
305  /* Get and remove packet from ringbuf (remove committed through an atomic operation */
306  int16_t get_index = ringbufindex_get(&n->tx_ringbuf);
307  if(get_index != -1) {
308  return n->tx_array[get_index];
309  } else {
310  return NULL;
311  }
312  }
313  }
314  return NULL;
315 }
316 /*---------------------------------------------------------------------------*/
317 /* Free a packet */
318 void
320 {
321  if(p != NULL) {
322  queuebuf_free(p->qb);
323  memb_free(&packet_memb, p);
324  }
325 }
326 /*---------------------------------------------------------------------------*/
327 /* Updates neighbor queue state after a transmission */
328 int
330  struct tsch_link *link, uint8_t mac_tx_status)
331 {
332  int in_queue = 1;
333  int is_shared_link = link->link_options & LINK_OPTION_SHARED;
334  int is_unicast = !n->is_broadcast;
335 
336  if(mac_tx_status == MAC_TX_OK) {
337  /* Successful transmission */
339  in_queue = 0;
340 
341  /* Update CSMA state in the unicast case */
342  if(is_unicast) {
343  if(is_shared_link || tsch_queue_is_empty(n)) {
344  /* If this is a shared link, reset backoff on success.
345  * Otherwise, do so only is the queue is empty */
347  }
348  }
349  } else {
350  /* Failed transmission */
351  if(p->transmissions >= p->max_transmissions) {
352  /* Drop packet */
354  in_queue = 0;
355  }
356  /* Update CSMA state in the unicast case */
357  if(is_unicast) {
358  /* Failures on dedicated (== non-shared) leave the backoff
359  * window nor exponent unchanged */
360  if(is_shared_link) {
361  /* Shared link: increment backoff exponent, pick a new window */
363  }
364  }
365  }
366 
367  return in_queue;
368 }
369 /*---------------------------------------------------------------------------*/
370 /* Flush all neighbor queues */
371 void
373 {
374  /* Deallocate unneeded neighbors */
375  if(!tsch_is_locked()) {
376  struct tsch_neighbor *n = list_head(neighbor_list);
377  while(n != NULL) {
378  struct tsch_neighbor *next_n = list_item_next(n);
379  /* Flush queue */
380  tsch_queue_flush_nbr_queue(n);
381  /* Reset backoff exponent */
383  n = next_n;
384  }
385  }
386 }
387 /*---------------------------------------------------------------------------*/
388 /* Deallocate neighbors with empty queue */
389 void
391 {
392  /* Deallocate unneeded neighbors */
393  if(!tsch_is_locked()) {
394  struct tsch_neighbor *n = list_head(neighbor_list);
395  while(n != NULL) {
396  struct tsch_neighbor *next_n = list_item_next(n);
397  /* Queue is empty, no tx link to this neighbor: deallocate.
398  * Always keep time source and virtual broadcast neighbors. */
399  if(!n->is_broadcast && !n->is_time_source && !n->tx_links_count
400  && tsch_queue_is_empty(n)) {
401  tsch_queue_remove_nbr(n);
402  }
403  n = next_n;
404  }
405  }
406 }
407 /*---------------------------------------------------------------------------*/
408 /* Is the neighbor queue empty? */
409 int
411 {
412  return !tsch_is_locked() && n != NULL && ringbufindex_empty(&n->tx_ringbuf);
413 }
414 /*---------------------------------------------------------------------------*/
415 /* Returns the first packet from a neighbor queue */
416 struct tsch_packet *
418 {
419  if(!tsch_is_locked()) {
420  int is_shared_link = link != NULL && link->link_options & LINK_OPTION_SHARED;
421  if(n != NULL) {
422  int16_t get_index = ringbufindex_peek_get(&n->tx_ringbuf);
423  if(get_index != -1 &&
424  !(is_shared_link && !tsch_queue_backoff_expired(n))) { /* If this is a shared link,
425  make sure the backoff has expired */
426 #if TSCH_WITH_LINK_SELECTOR
427  int packet_attr_slotframe = queuebuf_attr(n->tx_array[get_index]->qb, PACKETBUF_ATTR_TSCH_SLOTFRAME);
428  int packet_attr_timeslot = queuebuf_attr(n->tx_array[get_index]->qb, PACKETBUF_ATTR_TSCH_TIMESLOT);
429  if(packet_attr_slotframe != 0xffff && packet_attr_slotframe != link->slotframe_handle) {
430  return NULL;
431  }
432  if(packet_attr_timeslot != 0xffff && packet_attr_timeslot != link->timeslot) {
433  return NULL;
434  }
435 #endif
436  return n->tx_array[get_index];
437  }
438  }
439  }
440  return NULL;
441 }
442 /*---------------------------------------------------------------------------*/
443 /* Returns the head packet from a neighbor queue (from neighbor address) */
444 struct tsch_packet *
445 tsch_queue_get_packet_for_dest_addr(const linkaddr_t *addr, struct tsch_link *link)
446 {
447  if(!tsch_is_locked()) {
449  }
450  return NULL;
451 }
452 /*---------------------------------------------------------------------------*/
453 /* Returns the head packet of any neighbor queue with zero backoff counter.
454  * Writes pointer to the neighbor in *n */
455 struct tsch_packet *
457 {
458  if(!tsch_is_locked()) {
459  struct tsch_neighbor *curr_nbr = list_head(neighbor_list);
460  struct tsch_packet *p = NULL;
461  while(curr_nbr != NULL) {
462  if(!curr_nbr->is_broadcast && curr_nbr->tx_links_count == 0) {
463  /* Only look up for non-broadcast neighbors we do not have a tx link to */
464  p = tsch_queue_get_packet_for_nbr(curr_nbr, link);
465  if(p != NULL) {
466  if(n != NULL) {
467  *n = curr_nbr;
468  }
469  return p;
470  }
471  }
472  curr_nbr = list_item_next(curr_nbr);
473  }
474  }
475  return NULL;
476 }
477 /*---------------------------------------------------------------------------*/
478 /* May the neighbor transmit over a shared link? */
479 int
481 {
482  return n->backoff_window == 0;
483 }
484 /*---------------------------------------------------------------------------*/
485 /* Reset neighbor backoff */
486 void
488 {
489  n->backoff_window = 0;
490  n->backoff_exponent = TSCH_MAC_MIN_BE;
491 }
492 /*---------------------------------------------------------------------------*/
493 /* Increment backoff exponent, pick a new window */
494 void
496 {
497  /* Increment exponent */
498  n->backoff_exponent = MIN(n->backoff_exponent + 1, TSCH_MAC_MAX_BE);
499  /* Pick a window (number of shared slots to skip). Ignore least significant
500  * few bits, which, on some embedded implementations of rand (e.g. msp430-libc),
501  * are known to have poor pseudo-random properties. */
502  n->backoff_window = (random_rand() >> 6) % (1 << n->backoff_exponent);
503  /* Add one to the window as we will decrement it at the end of the current slot
504  * through tsch_queue_update_all_backoff_windows */
505  n->backoff_window++;
506 }
507 /*---------------------------------------------------------------------------*/
508 /* Decrement backoff window for all queues directed at dest_addr */
509 void
510 tsch_queue_update_all_backoff_windows(const linkaddr_t *dest_addr)
511 {
512  if(!tsch_is_locked()) {
513  int is_broadcast = linkaddr_cmp(dest_addr, &tsch_broadcast_address);
514  struct tsch_neighbor *n = list_head(neighbor_list);
515  while(n != NULL) {
516  if(n->backoff_window != 0 /* Is the queue in backoff state? */
517  && ((n->tx_links_count == 0 && is_broadcast)
518  || (n->tx_links_count > 0 && linkaddr_cmp(dest_addr, &n->addr)))) {
519  n->backoff_window--;
520  }
521  n = list_item_next(n);
522  }
523  }
524 }
525 /*---------------------------------------------------------------------------*/
526 /* Initialize TSCH queue module */
527 void
529 {
530  list_init(neighbor_list);
531  memb_init(&neighbor_memb);
532  memb_init(&packet_memb);
533  /* Add virtual EB and the broadcast neighbors */
534  n_eb = tsch_queue_add_nbr(&tsch_eb_address);
535  n_broadcast = tsch_queue_add_nbr(&tsch_broadcast_address);
536 }
537 /*---------------------------------------------------------------------------*/
538 /** @} */
TSCH packet information.
Definition: tsch-types.h:97
int tsch_queue_global_packet_count(void)
Returns the number of packets currently in all TSCH queues.
Definition: tsch-queue.c:280
struct tsch_neighbor * tsch_queue_get_nbr(const linkaddr_t *addr)
Get a TSCH neighbor.
Definition: tsch-queue.c:108
void ringbufindex_init(struct ringbufindex *r, uint8_t size)
Initialize a ring buffer.
Definition: ringbufindex.c:50
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition: memb.c:78
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
int ringbufindex_peek_get(const struct ringbufindex *r)
Return the index of the first element which will be removed if calling ringbufindex_get.
Definition: ringbufindex.c:115
int tsch_get_lock(void)
Takes the TSCH lock.
void tsch_release_lock(void)
Releases the TSCH lock.
TSCH neighbor information.
Definition: tsch-types.h:109
void tsch_queue_init(void)
Initialize TSCH queue module.
Definition: tsch-queue.c:528
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:510
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:124
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
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:445
The MAC layer transmission was OK.
Definition: mac.h:87
void tsch_queue_free_unused_neighbors(void)
Deallocate all neighbors with empty queue.
Definition: tsch-queue.c:390
The MAC layer transmission could not be performed because of an error.
Definition: mac.h:97
int tsch_queue_backoff_expired(const struct tsch_neighbor *n)
Is the neighbor backoff timer expired?
Definition: tsch-queue.c:480
struct tsch_neighbor * tsch_queue_add_nbr(const linkaddr_t *addr)
Add a TSCH neighbor queue.
Definition: tsch-queue.c:80
Header file for the Packet queue buffer management
Linked list manipulation routines.
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:495
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82
int tsch_queue_update_time_source(const linkaddr_t *new_addr)
Update TSCH time source.
Definition: tsch-queue.c:140
Main API declarations for TSCH.
The MAC layer transmission could not be performed because of a fatal error.
Definition: mac.h:101
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:417
int ringbufindex_elements(const struct ringbufindex *r)
Return the number of elements currently in the ring buffer.
Definition: ringbufindex.c:134
Memory block allocation routines.
int tsch_is_locked(void)
Checks if the TSCH lock is set.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
Definition: linkaddr.c:63
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition: list.c:142
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:329
struct tsch_packet * tsch_queue_remove_packet_from_queue(struct tsch_neighbor *n)
Remove first packet from a neighbor queue.
Definition: tsch-queue.c:301
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition: linkaddr.c:69
void tsch_queue_reset(void)
Reset neighbor queues module.
Definition: tsch-queue.c:372
void list_init(list_t list)
Initialize a list.
Definition: list.c:65
int tsch_queue_is_empty(const struct tsch_neighbor *n)
Is the neighbor queue empty?
Definition: tsch-queue.c:410
#define LIST(name)
Declare a linked list.
Definition: list.h:89
int tsch_queue_packet_count(const linkaddr_t *addr)
Returns the number of packets currently a given neighbor queue.
Definition: tsch-queue.c:287
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition: memb.c:59
int ringbufindex_get(struct ringbufindex *r)
Remove the first element and return its index.
Definition: ringbufindex.c:90
int ringbufindex_peek_put(const struct ringbufindex *r)
Check if there is space to put an element.
Definition: ringbufindex.c:78
int memb_numfree(struct memb *m)
Count free memory blocks.
Definition: memb.c:108
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:456
void tsch_queue_free_packet(struct tsch_packet *p)
Free a packet.
Definition: tsch-queue.c:319
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
Definition: memb.c:52
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Definition: random.c:58
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:230
Header file for the logging system
int ringbufindex_put(struct ringbufindex *r)
Put one element to the ring buffer.
Definition: ringbufindex.c:58
void list_remove(list_t list, void *item)
Remove a specific element from a list.
Definition: list.c:237
void * list_item_next(void *item)
Get the next item following this item.
Definition: list.c:322
void tsch_queue_backoff_reset(struct tsch_neighbor *n)
Reset neighbor backoff.
Definition: tsch-queue.c:487
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:90
int ringbufindex_empty(const struct ringbufindex *r)
Is the ring buffer empty?
Definition: ringbufindex.c:146