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