46 #include "dev/watchdog.h" 48 #include "sys/clock.h" 49 #include "lib/random.h" 53 #include "lib/assert.h" 57 #define LOG_MODULE "CSMA" 58 #define LOG_LEVEL LOG_LEVEL_MAC 63 #ifdef CSMA_CONF_MIN_BE 64 #define CSMA_MIN_BE CSMA_CONF_MIN_BE 70 #ifdef CSMA_CONF_MAX_BE 71 #define CSMA_MAX_BE CSMA_CONF_MAX_BE 77 #ifdef CSMA_CONF_MAX_BACKOFF 78 #define CSMA_MAX_BACKOFF CSMA_CONF_MAX_BACKOFF 80 #define CSMA_MAX_BACKOFF 5 84 #ifdef CSMA_CONF_MAX_FRAME_RETRIES 85 #define CSMA_MAX_FRAME_RETRIES CSMA_CONF_MAX_FRAME_RETRIES 87 #define CSMA_MAX_FRAME_RETRIES 7 91 struct qbuf_metadata {
94 uint8_t max_transmissions;
98 struct neighbor_queue {
99 struct neighbor_queue *next;
101 struct ctimer transmit_timer;
102 uint8_t transmissions;
108 #ifdef CSMA_CONF_MAX_NEIGHBOR_QUEUES 109 #define CSMA_MAX_NEIGHBOR_QUEUES CSMA_CONF_MAX_NEIGHBOR_QUEUES 111 #define CSMA_MAX_NEIGHBOR_QUEUES 2 115 #ifdef CSMA_CONF_MAX_PACKET_PER_NEIGHBOR 116 #define CSMA_MAX_PACKET_PER_NEIGHBOR CSMA_CONF_MAX_PACKET_PER_NEIGHBOR 118 #define CSMA_MAX_PACKET_PER_NEIGHBOR MAX_QUEUED_PACKETS 121 #define MAX_QUEUED_PACKETS QUEUEBUF_NUM 124 struct packet_queue {
125 struct packet_queue *next;
126 struct queuebuf *buf;
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);
136 struct packet_queue *q,
138 int num_transmissions);
139 static void transmit_from_queue(
void *ptr);
141 static struct neighbor_queue *
142 neighbor_queue_from_addr(
const linkaddr_t *
addr)
144 struct neighbor_queue *n =
list_head(neighbor_list);
157 #if CONTIKI_TARGET_COOJA 169 send_one_packet(
struct neighbor_queue *n,
struct packet_queue *q)
172 int last_sent_ok = 0;
175 packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
177 #if LLSEC802154_ENABLED 178 #if LLSEC802154_USES_EXPLICIT_KEYS 180 packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, CSMA_LLSEC_KEY_ID_MODE);
184 if(csma_security_create_frame() < 0) {
186 LOG_ERR(
"failed to create packet, seqno: %d\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
187 ret = MAC_TX_ERR_FATAL;
197 if(NETSTACK_RADIO.receiving_packet() ||
198 (!is_broadcast && NETSTACK_RADIO.pending_packet())) {
217 if(NETSTACK_RADIO.receiving_packet() ||
218 NETSTACK_RADIO.pending_packet() ||
219 NETSTACK_RADIO.channel_clear() == 0) {
221 uint8_t ackbuf[CSMA_ACK_LEN];
226 if(NETSTACK_RADIO.pending_packet()) {
227 len = NETSTACK_RADIO.read(ackbuf, CSMA_ACK_LEN);
228 if(len == CSMA_ACK_LEN && ackbuf[2] == dsn) {
239 case RADIO_TX_COLLISION:
257 transmit_from_queue(
void *ptr)
259 struct neighbor_queue *n = ptr;
261 struct packet_queue *q =
list_head(n->packet_queue);
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),
269 queuebuf_to_packetbuf(q->buf);
270 send_one_packet(n, q);
276 schedule_transmission(
struct neighbor_queue *n)
279 int backoff_exponent;
281 backoff_exponent = MIN(n->collisions + CSMA_MIN_BE, CSMA_MAX_BE);
284 delay = ((1 << backoff_exponent) - 1) * backoff_period();
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);
296 free_packet(
struct neighbor_queue *n,
struct packet_queue *p,
int status)
302 queuebuf_free(p->buf);
305 LOG_DBG(
"free_queued_packet, queue length %d, free packets %d\n",
309 n->transmissions = 0;
312 schedule_transmission(n);
323 tx_done(
int status,
struct packet_queue *q,
struct neighbor_queue *n)
326 struct qbuf_metadata *metadata;
330 metadata = (
struct qbuf_metadata *)q->ptr;
331 sent = metadata->sent;
332 cptr = metadata->cptr;
333 ntx = n->transmissions;
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);
341 free_packet(n, q, status);
342 mac_call_sent_callback(sent, cptr, status, ntx);
346 rexmit(
struct packet_queue *q,
struct neighbor_queue *n)
348 schedule_transmission(n);
351 queuebuf_update_attr_from_packetbuf(q->buf);
355 collision(
struct packet_queue *q,
struct neighbor_queue *n,
356 int num_transmissions)
358 struct qbuf_metadata *metadata;
360 metadata = (
struct qbuf_metadata *)q->ptr;
362 n->collisions += num_transmissions;
364 if(n->collisions > CSMA_MAX_BACKOFF) {
370 if(n->transmissions >= metadata->max_transmissions) {
378 noack(
struct packet_queue *q,
struct neighbor_queue *n,
int num_transmissions)
380 struct qbuf_metadata *metadata;
382 metadata = (
struct qbuf_metadata *)q->ptr;
385 n->transmissions += num_transmissions;
387 if(n->transmissions >= metadata->max_transmissions) {
395 tx_ok(
struct packet_queue *q,
struct neighbor_queue *n,
int num_transmissions)
398 n->transmissions += num_transmissions;
404 struct packet_queue *q,
406 int num_transmissions)
412 LOG_WARN(
"packet sent: no metadata\n");
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);
424 tx_ok(q, n, num_transmissions);
427 noack(q, n, num_transmissions);
430 collision(q, n, num_transmissions);
435 tx_done(status, q, n);
441 csma_output_packet(mac_callback_t sent,
void *ptr)
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);
460 packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
461 packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
464 n = neighbor_queue_from_addr(addr);
471 n->transmissions = 0;
482 if(
list_length(n->packet_queue) < CSMA_MAX_PACKET_PER_NEIGHBOR) {
487 q->buf = queuebuf_new_from_packetbuf();
489 struct qbuf_metadata *metadata = (
struct qbuf_metadata *)q->ptr;
491 metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
492 if(metadata->max_transmissions == 0) {
494 metadata->max_transmissions = CSMA_MAX_FRAME_RETRIES + 1;
496 metadata->sent = sent;
497 metadata->cptr = ptr;
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),
508 schedule_transmission(n);
513 LOG_WARN(
"could not allocate queuebuf, dropping packet\n");
516 LOG_WARN(
"could not allocate queuebuf, dropping packet\n");
524 LOG_WARN(
"Neighbor queue full\n");
526 LOG_WARN(
"could not allocate packet, dropping packet\n");
528 LOG_WARN(
"could not allocate neighbor, dropping packet\n");
530 mac_call_sent_callback(sent, ptr,
MAC_TX_ERR, 1);
534 csma_output_init(
void)
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
The MAC layer did not get an acknowledgement for the packet.
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
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.
LLSEC802154 Security related configuration
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
The MAC layer transmission was OK.
The MAC layer transmission could not be performed because of an error.
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
#define CLOCK_SECOND
A second, measured in system clock time.
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.
void * list_head(list_t list)
Get a pointer to the first element of a list.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
The MAC layer transmission could not be performed because of a fatal error.
int packetbuf_holds_broadcast(void)
Checks whether the current packet is a broadcast.
Memory block allocation routines.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
void list_add(list_t list, void *item)
Add an item at the end of a list.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
void * packetbuf_hdrptr(void)
Get a pointer to the header in the packetbuf, for outbound packets.
#define LIST(name)
Declare a linked list.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
#define LIST_STRUCT(name)
Declare a linked list inside a structure declaraction.
Header file for the Packet buffer (packetbuf) management
int memb_numfree(struct memb *m)
Count free memory blocks.
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().
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Header file for the logging system
The MAC layer deferred the transmission for a later time.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
void * list_item_next(void *item)
Get the next item following this item.
#define MEMB(name, structure, num)
Declare a memory block.
int list_length(list_t list)
Get the length of a list.