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  * 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 */
71 MEMB(packet_memb, struct tsch_packet, QUEUEBUF_NUM);
72 NBR_TABLE(struct tsch_neighbor, tsch_neighbors);
73 
74 /* Broadcast and EB virtual neighbors */
75 struct tsch_neighbor *n_broadcast;
76 struct tsch_neighbor *n_eb;
77 
78 /*---------------------------------------------------------------------------*/
79 /* Add a TSCH neighbor */
80 struct tsch_neighbor *
81 tsch_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 */
85  n = tsch_queue_get_nbr(addr);
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 */
109 struct tsch_neighbor *
110 tsch_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) */
119 struct 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 /*---------------------------------------------------------------------------*/
134 linkaddr_t *
136 {
137  return nbr_table_get_lladdr(tsch_neighbors, n);
138 }
139 /*---------------------------------------------------------------------------*/
140 /* Update TSCH time source */
141 int
142 tsch_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 */
192 static void
193 tsch_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 */
210 static void
211 tsch_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) */
228 struct tsch_packet *
229 tsch_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()) {
246  n = tsch_queue_add_nbr(addr);
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 */
278 int
280 {
281  return QUEUEBUF_NUM - memb_numfree(&packet_memb);
282 }
283 /*---------------------------------------------------------------------------*/
284 /* Returns the number of packets currently in the queue */
285 int
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 */
295 struct 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 */
313 void
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 */
323 void
325 {
326  struct tsch_neighbor *n = NULL;
327  if(!tsch_is_locked()) {
328  n = tsch_queue_get_nbr(addr);
329  if(n != NULL) {
330  tsch_queue_flush_nbr_queue(n);
331  }
332  }
333 }
334 /*---------------------------------------------------------------------------*/
335 /* Updates neighbor queue state after a transmission */
336 int
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 */
379 void
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 */
397 void
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? */
417 int
419 {
420  return !tsch_is_locked() && n != NULL && ringbufindex_empty(&n->tx_ringbuf);
421 }
422 /*---------------------------------------------------------------------------*/
423 /* Returns the first packet from a neighbor queue */
424 struct 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) */
452 struct tsch_packet *
453 tsch_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 */
463 struct 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? */
487 int
489 {
490  return n->backoff_window == 0;
491 }
492 /*---------------------------------------------------------------------------*/
493 /* Reset neighbor backoff */
494 void
496 {
497  n->backoff_window = 0;
498  n->backoff_exponent = TSCH_MAC_MIN_BE;
499 }
500 /*---------------------------------------------------------------------------*/
501 /* Increment backoff exponent, pick a new window */
502 void
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) % (1 << 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  n->backoff_window++;
514 }
515 /*---------------------------------------------------------------------------*/
516 /* Decrement backoff window for all queues directed at dest_addr */
517 void
518 tsch_queue_update_all_backoff_windows(const linkaddr_t *dest_addr)
519 {
520  if(!tsch_is_locked()) {
521  int is_broadcast = linkaddr_cmp(dest_addr, &tsch_broadcast_address);
522  struct tsch_neighbor *n = (struct tsch_neighbor *)nbr_table_head(tsch_neighbors);
523  while(n != NULL) {
524  if(n->backoff_window != 0 /* Is the queue in backoff state? */
525  && ((n->tx_links_count == 0 && is_broadcast)
526  || (n->tx_links_count > 0 && linkaddr_cmp(dest_addr, tsch_queue_get_nbr_address(n))))) {
527  n->backoff_window--;
528  }
529  n = (struct tsch_neighbor *)nbr_table_next(tsch_neighbors, n);
530  }
531  }
532 }
533 /*---------------------------------------------------------------------------*/
534 /* Initialize TSCH queue module */
535 void
537 {
538  nbr_table_register(tsch_neighbors, NULL);
539  memb_init(&packet_memb);
540  /* Add virtual EB and the broadcast neighbors */
541  n_eb = tsch_queue_add_nbr(&tsch_eb_address);
542  n_broadcast = tsch_queue_add_nbr(&tsch_broadcast_address);
543 }
544 /*---------------------------------------------------------------------------*/
545 /** @} */
TSCH packet information.
Definition: tsch-types.h:97
The MAC layer transmission could not be performed because of a fatal error.
Definition: mac.h:101
int tsch_queue_global_packet_count(void)
Returns the number of packets currently in all TSCH queues.
Definition: tsch-queue.c:279
struct tsch_neighbor * tsch_queue_get_nbr(const linkaddr_t *addr)
Get a TSCH neighbor.
Definition: tsch-queue.c:110
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:536
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:518
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_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:191
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
void tsch_queue_free_unused_neighbors(void)
Deallocate all neighbors with empty queue.
Definition: tsch-queue.c:398
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
linkaddr_t * tsch_queue_get_nbr_address(const struct tsch_neighbor *n)
Get the address of a neighbor.
Definition: tsch-queue.c:135
struct tsch_neighbor * tsch_queue_add_nbr(const linkaddr_t *addr)
Add a TSCH neighbor queue.
Definition: tsch-queue.c:81
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:503
int tsch_queue_update_time_source(const linkaddr_t *new_addr)
Update TSCH time source.
Definition: tsch-queue.c:142
Main API declarations for TSCH.
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 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.
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_packet * tsch_queue_remove_packet_from_queue(struct tsch_neighbor *n)
Remove first packet from a neighbor queue.
Definition: tsch-queue.c:296
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:380
int tsch_queue_is_empty(const struct tsch_neighbor *n)
Is the neighbor queue empty?
Definition: tsch-queue.c:418
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:464
void tsch_queue_free_packet(struct tsch_packet *p)
Free a packet.
Definition: tsch-queue.c:314
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:229
The MAC layer transmission was OK.
Definition: mac.h:87
Header file for the logging system
int ringbufindex_put(struct ringbufindex *r)
Put one element to the ring buffer.
Definition: ringbufindex.c:58
void tsch_queue_backoff_reset(struct tsch_neighbor *n)
Reset neighbor backoff.
Definition: tsch-queue.c:495
void tsch_queue_free_packets_to(const linkaddr_t *addr)
Flush packets to a specific address.
Definition: tsch-queue.c:324
#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
The MAC layer transmission could not be performed because of an error.
Definition: mac.h:97