Contiki-NG
csma-output.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Swedish Institute of Computer Science.
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  * The 802.15.4 standard CSMA protocol (nonbeacon-enabled).
36  * Output functions.
37  * \author
38  * Adam Dunkels <adam@sics.se>
39  * Simon Duquennoy <simon.duquennoy@inria.fr>
40  */
41 
42 #include "net/mac/csma/csma.h"
44 #include "net/packetbuf.h"
45 #include "net/queuebuf.h"
46 #include "dev/watchdog.h"
47 #include "sys/ctimer.h"
48 #include "sys/clock.h"
49 #include "lib/random.h"
50 #include "net/netstack.h"
51 #include "lib/list.h"
52 #include "lib/memb.h"
53 #include "lib/assert.h"
54 
55 /* Log configuration */
56 #include "sys/log.h"
57 #define LOG_MODULE "CSMA"
58 #define LOG_LEVEL LOG_LEVEL_MAC
59 
60 /* Constants of the IEEE 802.15.4 standard */
61 
62 /* macMinBE: Initial backoff exponent. Range 0--CSMA_MAX_BE */
63 #ifdef CSMA_CONF_MIN_BE
64 #define CSMA_MIN_BE CSMA_CONF_MIN_BE
65 #else
66 #define CSMA_MIN_BE 3
67 #endif
68 
69 /* macMaxBE: Maximum backoff exponent. Range 3--8 */
70 #ifdef CSMA_CONF_MAX_BE
71 #define CSMA_MAX_BE CSMA_CONF_MAX_BE
72 #else
73 #define CSMA_MAX_BE 5
74 #endif
75 
76 /* macMaxCSMABackoffs: Maximum number of backoffs in case of channel busy/collision. Range 0--5 */
77 #ifdef CSMA_CONF_MAX_BACKOFF
78 #define CSMA_MAX_BACKOFF CSMA_CONF_MAX_BACKOFF
79 #else
80 #define CSMA_MAX_BACKOFF 5
81 #endif
82 
83 /* macMaxFrameRetries: Maximum number of re-transmissions attampts. Range 0--7 */
84 #ifdef CSMA_CONF_MAX_FRAME_RETRIES
85 #define CSMA_MAX_FRAME_RETRIES CSMA_CONF_MAX_FRAME_RETRIES
86 #else
87 #define CSMA_MAX_FRAME_RETRIES 7
88 #endif
89 
90 /* Packet metadata */
91 struct qbuf_metadata {
92  mac_callback_t sent;
93  void *cptr;
94  uint8_t max_transmissions;
95 };
96 
97 /* Every neighbor has its own packet queue */
98 struct neighbor_queue {
99  struct neighbor_queue *next;
100  linkaddr_t addr;
101  struct ctimer transmit_timer;
102  uint8_t transmissions;
103  uint8_t collisions;
104  LIST_STRUCT(packet_queue);
105 };
106 
107 /* The maximum number of co-existing neighbor queues */
108 #ifdef CSMA_CONF_MAX_NEIGHBOR_QUEUES
109 #define CSMA_MAX_NEIGHBOR_QUEUES CSMA_CONF_MAX_NEIGHBOR_QUEUES
110 #else
111 #define CSMA_MAX_NEIGHBOR_QUEUES 2
112 #endif /* CSMA_CONF_MAX_NEIGHBOR_QUEUES */
113 
114 /* The maximum number of pending packet per neighbor */
115 #ifdef CSMA_CONF_MAX_PACKET_PER_NEIGHBOR
116 #define CSMA_MAX_PACKET_PER_NEIGHBOR CSMA_CONF_MAX_PACKET_PER_NEIGHBOR
117 #else
118 #define CSMA_MAX_PACKET_PER_NEIGHBOR MAX_QUEUED_PACKETS
119 #endif /* CSMA_CONF_MAX_PACKET_PER_NEIGHBOR */
120 
121 #define MAX_QUEUED_PACKETS QUEUEBUF_NUM
122 
123 /* Neighbor packet queue */
124 struct packet_queue {
125  struct packet_queue *next;
126  struct queuebuf *buf;
127  void *ptr;
128 };
129 
130 MEMB(neighbor_memb, struct neighbor_queue, CSMA_MAX_NEIGHBOR_QUEUES);
131 MEMB(packet_memb, struct packet_queue, MAX_QUEUED_PACKETS);
132 MEMB(metadata_memb, struct qbuf_metadata, MAX_QUEUED_PACKETS);
133 LIST(neighbor_list);
134 
135 static void packet_sent(struct neighbor_queue *n,
136  struct packet_queue *q,
137  int status,
138  int num_transmissions);
139 static void transmit_from_queue(void *ptr);
140 /*---------------------------------------------------------------------------*/
141 static struct neighbor_queue *
142 neighbor_queue_from_addr(const linkaddr_t *addr)
143 {
144  struct neighbor_queue *n = list_head(neighbor_list);
145  while(n != NULL) {
146  if(linkaddr_cmp(&n->addr, addr)) {
147  return n;
148  }
149  n = list_item_next(n);
150  }
151  return NULL;
152 }
153 /*---------------------------------------------------------------------------*/
154 static clock_time_t
155 backoff_period(void)
156 {
157 #if CONTIKI_TARGET_COOJA
158  /* Increase normal value by 20 to compensate for the coarse-grained
159  radio medium with Cooja motes */
160  return MAX(20 * CLOCK_SECOND / 3125, 1);
161 #else /* CONTIKI_TARGET_COOJA */
162  /* Use the default in IEEE 802.15.4: aUnitBackoffPeriod which is
163  * 20 symbols i.e. 320 usec. That is, 1/3125 second. */
164  return MAX(CLOCK_SECOND / 3125, 1);
165 #endif /* CONTIKI_TARGET_COOJA */
166 }
167 /*---------------------------------------------------------------------------*/
168 static int
169 send_one_packet(struct neighbor_queue *n, struct packet_queue *q)
170 {
171  int ret;
172  int last_sent_ok = 0;
173 
174  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
175  packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
176 
177 #if LLSEC802154_ENABLED
178 #if LLSEC802154_USES_EXPLICIT_KEYS
179  /* This should possibly be taken from upper layers in the future */
180  packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, CSMA_LLSEC_KEY_ID_MODE);
181 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
182 #endif /* LLSEC802154_ENABLED */
183 
184  if(csma_security_create_frame() < 0) {
185  /* Failed to allocate space for headers */
186  LOG_ERR("failed to create packet, seqno: %d\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
187  ret = MAC_TX_ERR_FATAL;
188  } else {
189  int is_broadcast;
190  uint8_t dsn;
191  dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff;
192 
193  NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen());
194 
195  is_broadcast = packetbuf_holds_broadcast();
196 
197  if(NETSTACK_RADIO.receiving_packet() ||
198  (!is_broadcast && NETSTACK_RADIO.pending_packet())) {
199 
200  /* Currently receiving a packet over air or the radio has
201  already received a packet that needs to be read before
202  sending with auto ack. */
203  ret = MAC_TX_COLLISION;
204  } else {
205 
206  switch(NETSTACK_RADIO.transmit(packetbuf_totlen())) {
207  case RADIO_TX_OK:
208  if(is_broadcast) {
209  ret = MAC_TX_OK;
210  } else {
211  /* Check for ack */
212 
213  /* Wait for max CSMA_ACK_WAIT_TIME */
214  RTIMER_BUSYWAIT_UNTIL(NETSTACK_RADIO.pending_packet(), CSMA_ACK_WAIT_TIME);
215 
216  ret = MAC_TX_NOACK;
217  if(NETSTACK_RADIO.receiving_packet() ||
218  NETSTACK_RADIO.pending_packet() ||
219  NETSTACK_RADIO.channel_clear() == 0) {
220  int len;
221  uint8_t ackbuf[CSMA_ACK_LEN];
222 
223  /* Wait an additional CSMA_AFTER_ACK_DETECTED_WAIT_TIME to complete reception */
224  RTIMER_BUSYWAIT_UNTIL(NETSTACK_RADIO.pending_packet(), CSMA_AFTER_ACK_DETECTED_WAIT_TIME);
225 
226  if(NETSTACK_RADIO.pending_packet()) {
227  len = NETSTACK_RADIO.read(ackbuf, CSMA_ACK_LEN);
228  if(len == CSMA_ACK_LEN && ackbuf[2] == dsn) {
229  /* Ack received */
230  ret = MAC_TX_OK;
231  } else {
232  /* Not an ack or ack not for us: collision */
233  ret = MAC_TX_COLLISION;
234  }
235  }
236  }
237  }
238  break;
239  case RADIO_TX_COLLISION:
240  ret = MAC_TX_COLLISION;
241  break;
242  default:
243  ret = MAC_TX_ERR;
244  break;
245  }
246  }
247  }
248  if(ret == MAC_TX_OK) {
249  last_sent_ok = 1;
250  }
251 
252  packet_sent(n, q, ret, 1);
253  return last_sent_ok;
254 }
255 /*---------------------------------------------------------------------------*/
256 static void
257 transmit_from_queue(void *ptr)
258 {
259  struct neighbor_queue *n = ptr;
260  if(n) {
261  struct packet_queue *q = list_head(n->packet_queue);
262  if(q != NULL) {
263  LOG_INFO("preparing packet for ");
264  LOG_INFO_LLADDR(&n->addr);
265  LOG_INFO_(", seqno %u, tx %u, queue %d\n",
266  queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO),
267  n->transmissions, list_length(n->packet_queue));
268  /* Send first packet in the neighbor queue */
269  queuebuf_to_packetbuf(q->buf);
270  send_one_packet(n, q);
271  }
272  }
273 }
274 /*---------------------------------------------------------------------------*/
275 static void
276 schedule_transmission(struct neighbor_queue *n)
277 {
278  clock_time_t delay;
279  int backoff_exponent; /* BE in IEEE 802.15.4 */
280 
281  backoff_exponent = MIN(n->collisions + CSMA_MIN_BE, CSMA_MAX_BE);
282 
283  /* Compute max delay as per IEEE 802.15.4: 2^BE-1 backoff periods */
284  delay = ((1 << backoff_exponent) - 1) * backoff_period();
285  if(delay > 0) {
286  /* Pick a time for next transmission */
287  delay = random_rand() % delay;
288  }
289 
290  LOG_DBG("scheduling transmission in %u ticks, NB=%u, BE=%u\n",
291  (unsigned)delay, n->collisions, backoff_exponent);
292  ctimer_set(&n->transmit_timer, delay, transmit_from_queue, n);
293 }
294 /*---------------------------------------------------------------------------*/
295 static void
296 free_packet(struct neighbor_queue *n, struct packet_queue *p, int status)
297 {
298  if(p != NULL) {
299  /* Remove packet from queue and deallocate */
300  list_remove(n->packet_queue, p);
301 
302  queuebuf_free(p->buf);
303  memb_free(&metadata_memb, p->ptr);
304  memb_free(&packet_memb, p);
305  LOG_DBG("free_queued_packet, queue length %d, free packets %d\n",
306  list_length(n->packet_queue), memb_numfree(&packet_memb));
307  if(list_head(n->packet_queue) != NULL) {
308  /* There is a next packet. We reset current tx information */
309  n->transmissions = 0;
310  n->collisions = 0;
311  /* Schedule next transmissions */
312  schedule_transmission(n);
313  } else {
314  /* This was the last packet in the queue, we free the neighbor */
315  ctimer_stop(&n->transmit_timer);
316  list_remove(neighbor_list, n);
317  memb_free(&neighbor_memb, n);
318  }
319  }
320 }
321 /*---------------------------------------------------------------------------*/
322 static void
323 tx_done(int status, struct packet_queue *q, struct neighbor_queue *n)
324 {
325  mac_callback_t sent;
326  struct qbuf_metadata *metadata;
327  void *cptr;
328  uint8_t ntx;
329 
330  metadata = (struct qbuf_metadata *)q->ptr;
331  sent = metadata->sent;
332  cptr = metadata->cptr;
333  ntx = n->transmissions;
334 
335  LOG_INFO("packet sent to ");
336  LOG_INFO_LLADDR(&n->addr);
337  LOG_INFO_(", seqno %u, status %u, tx %u, coll %u\n",
338  packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO),
339  status, n->transmissions, n->collisions);
340 
341  free_packet(n, q, status);
342  mac_call_sent_callback(sent, cptr, status, ntx);
343 }
344 /*---------------------------------------------------------------------------*/
345 static void
346 rexmit(struct packet_queue *q, struct neighbor_queue *n)
347 {
348  schedule_transmission(n);
349  /* This is needed to correctly attribute energy that we spent
350  transmitting this packet. */
351  queuebuf_update_attr_from_packetbuf(q->buf);
352 }
353 /*---------------------------------------------------------------------------*/
354 static void
355 collision(struct packet_queue *q, struct neighbor_queue *n,
356  int num_transmissions)
357 {
358  struct qbuf_metadata *metadata;
359 
360  metadata = (struct qbuf_metadata *)q->ptr;
361 
362  n->collisions += num_transmissions;
363 
364  if(n->collisions > CSMA_MAX_BACKOFF) {
365  n->collisions = 0;
366  /* Increment to indicate a next retry */
367  n->transmissions++;
368  }
369 
370  if(n->transmissions >= metadata->max_transmissions) {
371  tx_done(MAC_TX_COLLISION, q, n);
372  } else {
373  rexmit(q, n);
374  }
375 }
376 /*---------------------------------------------------------------------------*/
377 static void
378 noack(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions)
379 {
380  struct qbuf_metadata *metadata;
381 
382  metadata = (struct qbuf_metadata *)q->ptr;
383 
384  n->collisions = 0;
385  n->transmissions += num_transmissions;
386 
387  if(n->transmissions >= metadata->max_transmissions) {
388  tx_done(MAC_TX_NOACK, q, n);
389  } else {
390  rexmit(q, n);
391  }
392 }
393 /*---------------------------------------------------------------------------*/
394 static void
395 tx_ok(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions)
396 {
397  n->collisions = 0;
398  n->transmissions += num_transmissions;
399  tx_done(MAC_TX_OK, q, n);
400 }
401 /*---------------------------------------------------------------------------*/
402 static void
403 packet_sent(struct neighbor_queue *n,
404  struct packet_queue *q,
405  int status,
406  int num_transmissions)
407 {
408  assert(n != NULL);
409  assert(q != NULL);
410 
411  if(q->ptr == NULL) {
412  LOG_WARN("packet sent: no metadata\n");
413  return;
414  }
415 
416  LOG_INFO("tx to ");
417  LOG_INFO_LLADDR(&n->addr);
418  LOG_INFO_(", seqno %u, status %u, tx %u, coll %u\n",
419  packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO),
420  status, n->transmissions, n->collisions);
421 
422  switch(status) {
423  case MAC_TX_OK:
424  tx_ok(q, n, num_transmissions);
425  break;
426  case MAC_TX_NOACK:
427  noack(q, n, num_transmissions);
428  break;
429  case MAC_TX_COLLISION:
430  collision(q, n, num_transmissions);
431  break;
432  case MAC_TX_DEFERRED:
433  break;
434  default:
435  tx_done(status, q, n);
436  break;
437  }
438 }
439 /*---------------------------------------------------------------------------*/
440 void
441 csma_output_packet(mac_callback_t sent, void *ptr)
442 {
443  struct packet_queue *q;
444  struct neighbor_queue *n;
445  static uint8_t initialized = 0;
446  static uint8_t seqno;
447  const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
448 
449  if(!initialized) {
450  initialized = 1;
451  /* Initialize the sequence number to a random value as per 802.15.4. */
452  seqno = random_rand();
453  }
454 
455  if(seqno == 0) {
456  /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity
457  in framer-802154.c. */
458  seqno++;
459  }
460  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
461  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
462 
463  /* Look for the neighbor entry */
464  n = neighbor_queue_from_addr(addr);
465  if(n == NULL) {
466  /* Allocate a new neighbor entry */
467  n = memb_alloc(&neighbor_memb);
468  if(n != NULL) {
469  /* Init neighbor entry */
470  linkaddr_copy(&n->addr, addr);
471  n->transmissions = 0;
472  n->collisions = 0;
473  /* Init packet queue for this neighbor */
474  LIST_STRUCT_INIT(n, packet_queue);
475  /* Add neighbor to the neighbor list */
476  list_add(neighbor_list, n);
477  }
478  }
479 
480  if(n != NULL) {
481  /* Add packet to the neighbor's queue */
482  if(list_length(n->packet_queue) < CSMA_MAX_PACKET_PER_NEIGHBOR) {
483  q = memb_alloc(&packet_memb);
484  if(q != NULL) {
485  q->ptr = memb_alloc(&metadata_memb);
486  if(q->ptr != NULL) {
487  q->buf = queuebuf_new_from_packetbuf();
488  if(q->buf != NULL) {
489  struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
490  /* Neighbor and packet successfully allocated */
491  metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
492  if(metadata->max_transmissions == 0) {
493  /* If not set by the application, use the default CSMA value */
494  metadata->max_transmissions = CSMA_MAX_FRAME_RETRIES + 1;
495  }
496  metadata->sent = sent;
497  metadata->cptr = ptr;
498  list_add(n->packet_queue, q);
499 
500  LOG_INFO("sending to ");
501  LOG_INFO_LLADDR(addr);
502  LOG_INFO_(", len %u, seqno %u, queue length %d, free packets %d\n",
504  packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO),
505  list_length(n->packet_queue), memb_numfree(&packet_memb));
506  /* If q is the first packet in the neighbor's queue, send asap */
507  if(list_head(n->packet_queue) == q) {
508  schedule_transmission(n);
509  }
510  return;
511  }
512  memb_free(&metadata_memb, q->ptr);
513  LOG_WARN("could not allocate queuebuf, dropping packet\n");
514  }
515  memb_free(&packet_memb, q);
516  LOG_WARN("could not allocate queuebuf, dropping packet\n");
517  }
518  /* The packet allocation failed. Remove and free neighbor entry if empty. */
519  if(list_length(n->packet_queue) == 0) {
520  list_remove(neighbor_list, n);
521  memb_free(&neighbor_memb, n);
522  }
523  } else {
524  LOG_WARN("Neighbor queue full\n");
525  }
526  LOG_WARN("could not allocate packet, dropping packet\n");
527  } else {
528  LOG_WARN("could not allocate neighbor, dropping packet\n");
529  }
530  mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
531 }
532 /*---------------------------------------------------------------------------*/
533 void
534 csma_output_init(void)
535 {
536  memb_init(&packet_memb);
537  memb_init(&metadata_memb);
538  memb_init(&neighbor_memb);
539 }
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
Definition: list.h:125
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
The MAC layer did not get an acknowledgement for the packet.
Definition: mac.h:91
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
The 802.15.4 standard CSMA protocol (nonbeacon-enabled)
static void packet_sent(void *ptr, int status, int transmissions)
Callback function for the MAC packet sent callback.
Definition: sicslowpan.c:1460
LLSEC802154 Security related configuration
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
The MAC layer transmission was OK.
Definition: mac.h:87
The MAC layer transmission could not be performed because of an error.
Definition: mac.h:97
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:155
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
Definition: linkaddr.c:48
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
Header file for the callback timer
Header file for the Packet queue buffer management
Linked list manipulation routines.
uint16_t packetbuf_totlen(void)
Get the total length of the header and data in the packetbuf.
Definition: packetbuf.c:167
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
The MAC layer transmission could not be performed because of a fatal error.
Definition: mac.h:101
int packetbuf_holds_broadcast(void)
Checks whether the current packet is a broadcast.
Definition: packetbuf.c:231
Memory block allocation routines.
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 linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition: linkaddr.c:69
void * packetbuf_hdrptr(void)
Get a pointer to the header in the packetbuf, for outbound packets.
Definition: packetbuf.c:149
#define LIST(name)
Declare a linked list.
Definition: list.h:89
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition: memb.c:59
#define LIST_STRUCT(name)
Declare a linked list inside a structure declaraction.
Definition: list.h:111
Header file for the Packet buffer (packetbuf) management
int memb_numfree(struct memb *m)
Count free memory blocks.
Definition: memb.c:108
Include file for the Contiki low-layer network stack (NETSTACK)
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
Header file for the logging system
The MAC layer deferred the transmission for a later time.
Definition: mac.h:94
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
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:90
int list_length(list_t list)
Get the length of a list.
Definition: list.c:272