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 */
91struct 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 */
98struct 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 */
124struct packet_queue {
125 struct packet_queue *next;
126 struct queuebuf *buf;
127 void *ptr;
128};
129
130MEMB(neighbor_memb, struct neighbor_queue, CSMA_MAX_NEIGHBOR_QUEUES);
131MEMB(packet_memb, struct packet_queue, MAX_QUEUED_PACKETS);
132MEMB(metadata_memb, struct qbuf_metadata, MAX_QUEUED_PACKETS);
133LIST(neighbor_list);
134
135static void packet_sent(struct neighbor_queue *n,
136 struct packet_queue *q,
137 int status,
138 int num_transmissions);
139static void transmit_from_queue(void *ptr);
140/*---------------------------------------------------------------------------*/
141static struct neighbor_queue *
142neighbor_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/*---------------------------------------------------------------------------*/
154static clock_time_t
155backoff_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/*---------------------------------------------------------------------------*/
168static int
169send_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;
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/*---------------------------------------------------------------------------*/
256static void
257transmit_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/*---------------------------------------------------------------------------*/
275static void
276schedule_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/*---------------------------------------------------------------------------*/
295static void
296free_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/*---------------------------------------------------------------------------*/
322static void
323tx_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/*---------------------------------------------------------------------------*/
345static void
346rexmit(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/*---------------------------------------------------------------------------*/
354static void
355collision(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/*---------------------------------------------------------------------------*/
377static void
378noack(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/*---------------------------------------------------------------------------*/
394static void
395tx_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/*---------------------------------------------------------------------------*/
402static void
403packet_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/*---------------------------------------------------------------------------*/
440void
441csma_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_QUEUE_FULL, 1);
531}
532/*---------------------------------------------------------------------------*/
533void
534csma_output_init(void)
535{
536 memb_init(&packet_memb);
537 memb_init(&metadata_memb);
538 memb_init(&neighbor_memb);
539}
LLSEC802154 Security related configuration.
The 802.15.4 standard CSMA protocol (nonbeacon-enabled)
Header file for the callback timer.
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Definition: random.c:58
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
Definition: linkaddr.c:48
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
Definition: linkaddr.c:63
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition: linkaddr.c:69
void * list_head(const list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82
#define LIST(name)
Declare a linked list.
Definition: list.h:89
int list_length(const list_t list)
Get the length of a list.
Definition: list.c:272
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition: list.c:142
void list_remove(list_t list, const void *item)
Remove a specific element from a list.
Definition: list.c:237
void * list_item_next(const void *item)
Get the next item following this item.
Definition: list.c:322
#define LIST_STRUCT(name)
Declare a linked list inside a structure declaraction.
Definition: list.h:111
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
Definition: list.h:125
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition: memb.c:78
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
int memb_numfree(struct memb *m)
Count free memory blocks.
Definition: memb.c:108
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:90
uint16_t packetbuf_totlen(void)
Get the total length of the header and data in the packetbuf.
Definition: packetbuf.c:167
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:155
void * packetbuf_hdrptr(void)
Get a pointer to the header in the packetbuf, for outbound packets.
Definition: packetbuf.c:149
int packetbuf_holds_broadcast(void)
Checks whether the current packet is a broadcast.
Definition: packetbuf.c:231
@ RADIO_TX_COLLISION
TX failed due to a collision.
Definition: radio.h:503
@ RADIO_TX_OK
TX was successful and where an ACK was requested one was received.
Definition: radio.h:490
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
static void packet_sent(void *ptr, int status, int transmissions)
Callback function for the MAC packet sent callback.
Definition: sicslowpan.c:1517
Linked list manipulation routines.
Header file for the logging system.
@ MAC_TX_COLLISION
The MAC layer did not get an acknowledgement for the packet.
Definition: mac.h:91
@ MAC_TX_DEFERRED
The MAC layer transmission could not be performed because of an error.
Definition: mac.h:97
@ MAC_TX_OK
The MAC layer transmission was OK.
Definition: mac.h:87
@ MAC_TX_NOACK
The MAC layer deferred the transmission for a later time.
Definition: mac.h:94
@ MAC_TX_ERR_FATAL
The MAC layer transmission could not be performed because of insufficient queue space,...
Definition: mac.h:106
@ MAC_TX_ERR
The MAC layer transmission could not be performed because of a fatal error.
Definition: mac.h:101
Memory block allocation routines.
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
Header file for the Packet queue buffer management.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107