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"
43 #include "net/packetbuf.h"
44 #include "net/queuebuf.h"
45 #include "dev/watchdog.h"
46 #include "sys/ctimer.h"
47 #include "sys/clock.h"
48 #include "lib/random.h"
49 #include "net/netstack.h"
50 #include "lib/list.h"
51 #include "lib/memb.h"
52 
53 #if CONTIKI_TARGET_COOJA
54 #include "lib/simEnvChange.h"
55 #include "sys/cooja_mt.h"
56 #endif /* CONTIKI_TARGET_COOJA */
57 
58 /* Log configuration */
59 #include "sys/log.h"
60 #define LOG_MODULE "CSMA"
61 #define LOG_LEVEL LOG_LEVEL_MAC
62 
63 /* Constants of the IEEE 802.15.4 standard */
64 
65 /* macMinBE: Initial backoff exponent. Range 0--CSMA_MAX_BE */
66 #ifdef CSMA_CONF_MIN_BE
67 #define CSMA_MIN_BE CSMA_CONF_MIN_BE
68 #else
69 #define CSMA_MIN_BE 3
70 #endif
71 
72 /* macMaxBE: Maximum backoff exponent. Range 3--8 */
73 #ifdef CSMA_CONF_MAX_BE
74 #define CSMA_MAX_BE CSMA_CONF_MAX_BE
75 #else
76 #define CSMA_MAX_BE 5
77 #endif
78 
79 /* macMaxCSMABackoffs: Maximum number of backoffs in case of channel busy/collision. Range 0--5 */
80 #ifdef CSMA_CONF_MAX_BACKOFF
81 #define CSMA_MAX_BACKOFF CSMA_CONF_MAX_BACKOFF
82 #else
83 #define CSMA_MAX_BACKOFF 5
84 #endif
85 
86 /* macMaxFrameRetries: Maximum number of re-transmissions attampts. Range 0--7 */
87 #ifdef CSMA_CONF_MAX_FRAME_RETRIES
88 #define CSMA_MAX_FRAME_RETRIES CSMA_CONF_MAX_FRAME_RETRIES
89 #else
90 #define CSMA_MAX_FRAME_RETRIES 7
91 #endif
92 
93 /* Packet metadata */
94 struct qbuf_metadata {
95  mac_callback_t sent;
96  void *cptr;
97  uint8_t max_transmissions;
98 };
99 
100 /* Every neighbor has its own packet queue */
101 struct neighbor_queue {
102  struct neighbor_queue *next;
103  linkaddr_t addr;
104  struct ctimer transmit_timer;
105  uint8_t transmissions;
106  uint8_t collisions;
107  LIST_STRUCT(packet_queue);
108 };
109 
110 /* The maximum number of co-existing neighbor queues */
111 #ifdef CSMA_CONF_MAX_NEIGHBOR_QUEUES
112 #define CSMA_MAX_NEIGHBOR_QUEUES CSMA_CONF_MAX_NEIGHBOR_QUEUES
113 #else
114 #define CSMA_MAX_NEIGHBOR_QUEUES 2
115 #endif /* CSMA_CONF_MAX_NEIGHBOR_QUEUES */
116 
117 /* The maximum number of pending packet per neighbor */
118 #ifdef CSMA_CONF_MAX_PACKET_PER_NEIGHBOR
119 #define CSMA_MAX_PACKET_PER_NEIGHBOR CSMA_CONF_MAX_PACKET_PER_NEIGHBOR
120 #else
121 #define CSMA_MAX_PACKET_PER_NEIGHBOR MAX_QUEUED_PACKETS
122 #endif /* CSMA_CONF_MAX_PACKET_PER_NEIGHBOR */
123 
124 #define MAX_QUEUED_PACKETS QUEUEBUF_NUM
125 
126 /* Neighbor packet queue */
127 struct packet_queue {
128  struct packet_queue *next;
129  struct queuebuf *buf;
130  void *ptr;
131 };
132 
133 MEMB(neighbor_memb, struct neighbor_queue, CSMA_MAX_NEIGHBOR_QUEUES);
134 MEMB(packet_memb, struct packet_queue, MAX_QUEUED_PACKETS);
135 MEMB(metadata_memb, struct qbuf_metadata, MAX_QUEUED_PACKETS);
136 LIST(neighbor_list);
137 
138 static void packet_sent(void *ptr, int status, 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(void *ptr)
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(NETSTACK_FRAMER.create() < 0) {
178  /* Failed to allocate space for headers */
179  LOG_ERR("failed to create packet\n");
180  ret = MAC_TX_ERR_FATAL;
181  } else {
182  int is_broadcast;
183  uint8_t dsn;
184  dsn = ((uint8_t *)packetbuf_hdrptr())[2] & 0xff;
185 
186  NETSTACK_RADIO.prepare(packetbuf_hdrptr(), packetbuf_totlen());
187 
188  is_broadcast = packetbuf_holds_broadcast();
189 
190  if(NETSTACK_RADIO.receiving_packet() ||
191  (!is_broadcast && NETSTACK_RADIO.pending_packet())) {
192 
193  /* Currently receiving a packet over air or the radio has
194  already received a packet that needs to be read before
195  sending with auto ack. */
196  ret = MAC_TX_COLLISION;
197  } else {
198 
199  switch(NETSTACK_RADIO.transmit(packetbuf_totlen())) {
200  case RADIO_TX_OK:
201  if(is_broadcast) {
202  ret = MAC_TX_OK;
203  } else {
204  rtimer_clock_t wt;
205 
206  /* Check for ack */
207  wt = RTIMER_NOW();
209  while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + CSMA_ACK_WAIT_TIME)) {
210 #if CONTIKI_TARGET_COOJA
211  simProcessRunValue = 1;
212  cooja_mt_yield();
213 #endif /* CONTIKI_TARGET_COOJA */
214  }
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  if(CSMA_AFTER_ACK_DETECTED_WAIT_TIME > 0) {
224  wt = RTIMER_NOW();
226  while(RTIMER_CLOCK_LT(RTIMER_NOW(),
227  wt + CSMA_AFTER_ACK_DETECTED_WAIT_TIME)) {
228 #if CONTIKI_TARGET_COOJA
229  simProcessRunValue = 1;
230  cooja_mt_yield();
231 #endif /* CONTIKI_TARGET_COOJA */
232  }
233  }
234 
235  if(NETSTACK_RADIO.pending_packet()) {
236  len = NETSTACK_RADIO.read(ackbuf, CSMA_ACK_LEN);
237  if(len == CSMA_ACK_LEN && ackbuf[2] == dsn) {
238  /* Ack received */
239  ret = MAC_TX_OK;
240  } else {
241  /* Not an ack or ack not for us: collision */
242  ret = MAC_TX_COLLISION;
243  }
244  }
245  }
246  }
247  break;
248  case RADIO_TX_COLLISION:
249  ret = MAC_TX_COLLISION;
250  break;
251  default:
252  ret = MAC_TX_ERR;
253  break;
254  }
255  }
256  }
257  if(ret == MAC_TX_OK) {
258  last_sent_ok = 1;
259  }
260 
261  packet_sent(ptr, ret, 1);
262  return last_sent_ok;
263 }
264 /*---------------------------------------------------------------------------*/
265 static void
266 transmit_from_queue(void *ptr)
267 {
268  struct neighbor_queue *n = ptr;
269  if(n) {
270  struct packet_queue *q = list_head(n->packet_queue);
271  if(q != NULL) {
272  LOG_INFO("preparing packet for ");
273  LOG_INFO_LLADDR(&n->addr);
274  LOG_INFO_(", seqno %u, tx %u, queue %d\n",
275  queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO),
276  n->transmissions, list_length(n->packet_queue));
277  /* Send first packet in the neighbor queue */
278  queuebuf_to_packetbuf(q->buf);
279  send_one_packet(n);
280  }
281  }
282 }
283 /*---------------------------------------------------------------------------*/
284 static void
285 schedule_transmission(struct neighbor_queue *n)
286 {
287  clock_time_t delay;
288  int backoff_exponent; /* BE in IEEE 802.15.4 */
289 
290  backoff_exponent = MIN(n->collisions + CSMA_MIN_BE, CSMA_MAX_BE);
291 
292  /* Compute max delay as per IEEE 802.15.4: 2^BE-1 backoff periods */
293  delay = ((1 << backoff_exponent) - 1) * backoff_period();
294  if(delay > 0) {
295  /* Pick a time for next transmission */
296  delay = random_rand() % delay;
297  }
298 
299  LOG_DBG("scheduling transmission in %u ticks, NB=%u, BE=%u\n",
300  (unsigned)delay, n->collisions, backoff_exponent);
301  ctimer_set(&n->transmit_timer, delay, transmit_from_queue, n);
302 }
303 /*---------------------------------------------------------------------------*/
304 static void
305 free_packet(struct neighbor_queue *n, struct packet_queue *p, int status)
306 {
307  if(p != NULL) {
308  /* Remove packet from queue and deallocate */
309  list_remove(n->packet_queue, p);
310 
311  queuebuf_free(p->buf);
312  memb_free(&metadata_memb, p->ptr);
313  memb_free(&packet_memb, p);
314  LOG_DBG("free_queued_packet, queue length %d, free packets %d\n",
315  list_length(n->packet_queue), memb_numfree(&packet_memb));
316  if(list_head(n->packet_queue) != NULL) {
317  /* There is a next packet. We reset current tx information */
318  n->transmissions = 0;
319  n->collisions = 0;
320  /* Schedule next transmissions */
321  schedule_transmission(n);
322  } else {
323  /* This was the last packet in the queue, we free the neighbor */
324  ctimer_stop(&n->transmit_timer);
325  list_remove(neighbor_list, n);
326  memb_free(&neighbor_memb, n);
327  }
328  }
329 }
330 /*---------------------------------------------------------------------------*/
331 static void
332 tx_done(int status, struct packet_queue *q, struct neighbor_queue *n)
333 {
334  mac_callback_t sent;
335  struct qbuf_metadata *metadata;
336  void *cptr;
337  uint8_t ntx;
338 
339  metadata = (struct qbuf_metadata *)q->ptr;
340  sent = metadata->sent;
341  cptr = metadata->cptr;
342  ntx = n->transmissions;
343 
344  LOG_INFO("packet sent to ");
345  LOG_INFO_LLADDR(&n->addr);
346  LOG_INFO_(", seqno %u, status %u, tx %u, coll %u\n",
347  packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO),
348  status, n->transmissions, n->collisions);
349 
350  free_packet(n, q, status);
351  mac_call_sent_callback(sent, cptr, status, ntx);
352 }
353 /*---------------------------------------------------------------------------*/
354 static void
355 rexmit(struct packet_queue *q, struct neighbor_queue *n)
356 {
357  schedule_transmission(n);
358  /* This is needed to correctly attribute energy that we spent
359  transmitting this packet. */
360  queuebuf_update_attr_from_packetbuf(q->buf);
361 }
362 /*---------------------------------------------------------------------------*/
363 static void
364 collision(struct packet_queue *q, struct neighbor_queue *n,
365  int num_transmissions)
366 {
367  struct qbuf_metadata *metadata;
368 
369  metadata = (struct qbuf_metadata *)q->ptr;
370 
371  n->collisions += num_transmissions;
372 
373  if(n->collisions > CSMA_MAX_BACKOFF) {
374  n->collisions = 0;
375  /* Increment to indicate a next retry */
376  n->transmissions++;
377  }
378 
379  if(n->transmissions >= metadata->max_transmissions) {
380  tx_done(MAC_TX_COLLISION, q, n);
381  } else {
382  rexmit(q, n);
383  }
384 }
385 /*---------------------------------------------------------------------------*/
386 static void
387 noack(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions)
388 {
389  struct qbuf_metadata *metadata;
390 
391  metadata = (struct qbuf_metadata *)q->ptr;
392 
393  n->collisions = 0;
394  n->transmissions += num_transmissions;
395 
396  if(n->transmissions >= metadata->max_transmissions) {
397  tx_done(MAC_TX_NOACK, q, n);
398  } else {
399  rexmit(q, n);
400  }
401 }
402 /*---------------------------------------------------------------------------*/
403 static void
404 tx_ok(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions)
405 {
406  n->collisions = 0;
407  n->transmissions += num_transmissions;
408  tx_done(MAC_TX_OK, q, n);
409 }
410 /*---------------------------------------------------------------------------*/
411 static void
412 packet_sent(void *ptr, int status, int num_transmissions)
413 {
414  struct neighbor_queue *n;
415  struct packet_queue *q;
416 
417  n = ptr;
418  if(n == NULL) {
419  return;
420  }
421 
422  /* Find out what packet this callback refers to */
423  for(q = list_head(n->packet_queue);
424  q != NULL; q = list_item_next(q)) {
425  if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
426  packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
427  break;
428  }
429  }
430 
431  if(q == NULL) {
432  LOG_WARN("packet sent: seqno %u not found\n",
433  packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
434  return;
435  } else if(q->ptr == NULL) {
436  LOG_WARN("packet sent: no metadata\n");
437  return;
438  }
439 
440  LOG_INFO("tx to ");
441  LOG_INFO_LLADDR(&n->addr);
442  LOG_INFO_(", seqno %u, status %u, tx %u, coll %u\n",
443  packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO),
444  status, n->transmissions, n->collisions);
445 
446  switch(status) {
447  case MAC_TX_OK:
448  tx_ok(q, n, num_transmissions);
449  break;
450  case MAC_TX_NOACK:
451  noack(q, n, num_transmissions);
452  break;
453  case MAC_TX_COLLISION:
454  collision(q, n, num_transmissions);
455  break;
456  case MAC_TX_DEFERRED:
457  break;
458  default:
459  tx_done(status, q, n);
460  break;
461  }
462 }
463 /*---------------------------------------------------------------------------*/
464 void
465 csma_output_packet(mac_callback_t sent, void *ptr)
466 {
467  struct packet_queue *q;
468  struct neighbor_queue *n;
469  static uint8_t initialized = 0;
470  static uint8_t seqno;
471  const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
472 
473  if(!initialized) {
474  initialized = 1;
475  /* Initialize the sequence number to a random value as per 802.15.4. */
476  seqno = random_rand();
477  }
478 
479  if(seqno == 0) {
480  /* PACKETBUF_ATTR_MAC_SEQNO cannot be zero, due to a pecuilarity
481  in framer-802154.c. */
482  seqno++;
483  }
484  packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
485  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
486 
487  /* Look for the neighbor entry */
488  n = neighbor_queue_from_addr(addr);
489  if(n == NULL) {
490  /* Allocate a new neighbor entry */
491  n = memb_alloc(&neighbor_memb);
492  if(n != NULL) {
493  /* Init neighbor entry */
494  linkaddr_copy(&n->addr, addr);
495  n->transmissions = 0;
496  n->collisions = 0;
497  /* Init packet queue for this neighbor */
498  LIST_STRUCT_INIT(n, packet_queue);
499  /* Add neighbor to the neighbor list */
500  list_add(neighbor_list, n);
501  }
502  }
503 
504  if(n != NULL) {
505  /* Add packet to the neighbor's queue */
506  if(list_length(n->packet_queue) < CSMA_MAX_PACKET_PER_NEIGHBOR) {
507  q = memb_alloc(&packet_memb);
508  if(q != NULL) {
509  q->ptr = memb_alloc(&metadata_memb);
510  if(q->ptr != NULL) {
511  q->buf = queuebuf_new_from_packetbuf();
512  if(q->buf != NULL) {
513  struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
514  /* Neighbor and packet successfully allocated */
515  metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
516  if(metadata->max_transmissions == 0) {
517  /* If not set by the application, use the default CSMA value */
518  metadata->max_transmissions = CSMA_MAX_FRAME_RETRIES + 1;
519  }
520  metadata->sent = sent;
521  metadata->cptr = ptr;
522  list_add(n->packet_queue, q);
523 
524  LOG_INFO("sending to ");
525  LOG_INFO_LLADDR(addr);
526  LOG_INFO_(", len %u, seqno %u, queue length %d, free packets %d\n",
528  packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO),
529  list_length(n->packet_queue), memb_numfree(&packet_memb));
530  /* If q is the first packet in the neighbor's queue, send asap */
531  if(list_head(n->packet_queue) == q) {
532  schedule_transmission(n);
533  }
534  return;
535  }
536  memb_free(&metadata_memb, q->ptr);
537  LOG_WARN("could not allocate queuebuf, dropping packet\n");
538  }
539  memb_free(&packet_memb, q);
540  LOG_WARN("could not allocate queuebuf, dropping packet\n");
541  }
542  /* The packet allocation failed. Remove and free neighbor entry if empty. */
543  if(list_length(n->packet_queue) == 0) {
544  list_remove(neighbor_list, n);
545  memb_free(&neighbor_memb, n);
546  }
547  } else {
548  LOG_WARN("Neighbor queue full\n");
549  }
550  LOG_WARN("could not allocate packet, dropping packet\n");
551  } else {
552  LOG_WARN("could not allocate neighbor, dropping packet\n");
553  }
554  mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
555 }
556 /*---------------------------------------------------------------------------*/
557 void
558 csma_output_init(void)
559 {
560  memb_init(&packet_memb);
561  memb_init(&metadata_memb);
562  memb_init(&neighbor_memb);
563  queuebuf_init();
564 }
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
Definition: list.h:124
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:88
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:115
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:1444
The MAC layer transmission was OK.
Definition: mac.h:84
The MAC layer transmission could not be performed because of an error.
Definition: mac.h:94
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 RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:158
#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:98
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:88
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:110
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:85
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
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition: memb.c:79
Header file for the logging system
The MAC layer deferred the transmission for a later time.
Definition: mac.h:91
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:89
int list_length(list_t list)
Get the length of a list.
Definition: list.c:272