45 #include "dev/watchdog.h" 47 #include "sys/clock.h" 48 #include "lib/random.h" 53 #if CONTIKI_TARGET_COOJA 54 #include "lib/simEnvChange.h" 55 #include "sys/cooja_mt.h" 60 #define LOG_MODULE "CSMA" 61 #define LOG_LEVEL LOG_LEVEL_MAC 66 #ifdef CSMA_CONF_MIN_BE 67 #define CSMA_MIN_BE CSMA_CONF_MIN_BE 73 #ifdef CSMA_CONF_MAX_BE 74 #define CSMA_MAX_BE CSMA_CONF_MAX_BE 80 #ifdef CSMA_CONF_MAX_BACKOFF 81 #define CSMA_MAX_BACKOFF CSMA_CONF_MAX_BACKOFF 83 #define CSMA_MAX_BACKOFF 5 87 #ifdef CSMA_CONF_MAX_FRAME_RETRIES 88 #define CSMA_MAX_FRAME_RETRIES CSMA_CONF_MAX_FRAME_RETRIES 90 #define CSMA_MAX_FRAME_RETRIES 7 94 struct qbuf_metadata {
97 uint8_t max_transmissions;
101 struct neighbor_queue {
102 struct neighbor_queue *next;
104 struct ctimer transmit_timer;
105 uint8_t transmissions;
111 #ifdef CSMA_CONF_MAX_NEIGHBOR_QUEUES 112 #define CSMA_MAX_NEIGHBOR_QUEUES CSMA_CONF_MAX_NEIGHBOR_QUEUES 114 #define CSMA_MAX_NEIGHBOR_QUEUES 2 118 #ifdef CSMA_CONF_MAX_PACKET_PER_NEIGHBOR 119 #define CSMA_MAX_PACKET_PER_NEIGHBOR CSMA_CONF_MAX_PACKET_PER_NEIGHBOR 121 #define CSMA_MAX_PACKET_PER_NEIGHBOR MAX_QUEUED_PACKETS 124 #define MAX_QUEUED_PACKETS QUEUEBUF_NUM 127 struct packet_queue {
128 struct packet_queue *next;
129 struct queuebuf *buf;
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);
138 static void packet_sent(
void *ptr,
int status,
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(
void *ptr)
172 int last_sent_ok = 0;
175 packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
177 if(NETSTACK_FRAMER.create() < 0) {
179 LOG_ERR(
"failed to create packet\n");
180 ret = MAC_TX_ERR_FATAL;
190 if(NETSTACK_RADIO.receiving_packet() ||
191 (!is_broadcast && NETSTACK_RADIO.pending_packet())) {
209 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), wt + CSMA_ACK_WAIT_TIME)) {
210 #if CONTIKI_TARGET_COOJA 211 simProcessRunValue = 1;
217 if(NETSTACK_RADIO.receiving_packet() ||
218 NETSTACK_RADIO.pending_packet() ||
219 NETSTACK_RADIO.channel_clear() == 0) {
221 uint8_t ackbuf[CSMA_ACK_LEN];
223 if(CSMA_AFTER_ACK_DETECTED_WAIT_TIME > 0) {
227 wt + CSMA_AFTER_ACK_DETECTED_WAIT_TIME)) {
228 #if CONTIKI_TARGET_COOJA 229 simProcessRunValue = 1;
235 if(NETSTACK_RADIO.pending_packet()) {
236 len = NETSTACK_RADIO.read(ackbuf, CSMA_ACK_LEN);
237 if(len == CSMA_ACK_LEN && ackbuf[2] == dsn) {
248 case RADIO_TX_COLLISION:
266 transmit_from_queue(
void *ptr)
268 struct neighbor_queue *n = ptr;
270 struct packet_queue *q =
list_head(n->packet_queue);
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),
278 queuebuf_to_packetbuf(q->buf);
285 schedule_transmission(
struct neighbor_queue *n)
288 int backoff_exponent;
290 backoff_exponent = MIN(n->collisions + CSMA_MIN_BE, CSMA_MAX_BE);
293 delay = ((1 << backoff_exponent) - 1) * backoff_period();
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);
305 free_packet(
struct neighbor_queue *n,
struct packet_queue *p,
int status)
311 queuebuf_free(p->buf);
314 LOG_DBG(
"free_queued_packet, queue length %d, free packets %d\n",
315 list_length(n->packet_queue), memb_numfree(&packet_memb));
318 n->transmissions = 0;
321 schedule_transmission(n);
332 tx_done(
int status,
struct packet_queue *q,
struct neighbor_queue *n)
335 struct qbuf_metadata *metadata;
339 metadata = (
struct qbuf_metadata *)q->ptr;
340 sent = metadata->sent;
341 cptr = metadata->cptr;
342 ntx = n->transmissions;
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);
350 free_packet(n, q, status);
351 mac_call_sent_callback(sent, cptr, status, ntx);
355 rexmit(
struct packet_queue *q,
struct neighbor_queue *n)
357 schedule_transmission(n);
360 queuebuf_update_attr_from_packetbuf(q->buf);
364 collision(
struct packet_queue *q,
struct neighbor_queue *n,
365 int num_transmissions)
367 struct qbuf_metadata *metadata;
369 metadata = (
struct qbuf_metadata *)q->ptr;
371 n->collisions += num_transmissions;
373 if(n->collisions > CSMA_MAX_BACKOFF) {
379 if(n->transmissions >= metadata->max_transmissions) {
387 noack(
struct packet_queue *q,
struct neighbor_queue *n,
int num_transmissions)
389 struct qbuf_metadata *metadata;
391 metadata = (
struct qbuf_metadata *)q->ptr;
394 n->transmissions += num_transmissions;
396 if(n->transmissions >= metadata->max_transmissions) {
404 tx_ok(
struct packet_queue *q,
struct neighbor_queue *n,
int num_transmissions)
407 n->transmissions += num_transmissions;
412 packet_sent(
void *ptr,
int status,
int num_transmissions)
414 struct neighbor_queue *n;
415 struct packet_queue *q;
425 if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
426 packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
432 LOG_WARN(
"packet sent: seqno %u not found\n",
433 packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
435 }
else if(q->ptr == NULL) {
436 LOG_WARN(
"packet sent: no metadata\n");
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);
448 tx_ok(q, n, num_transmissions);
451 noack(q, n, num_transmissions);
454 collision(q, n, num_transmissions);
459 tx_done(status, q, n);
465 csma_output_packet(mac_callback_t sent,
void *ptr)
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);
484 packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
485 packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
488 n = neighbor_queue_from_addr(addr);
495 n->transmissions = 0;
506 if(
list_length(n->packet_queue) < CSMA_MAX_PACKET_PER_NEIGHBOR) {
511 q->buf = queuebuf_new_from_packetbuf();
513 struct qbuf_metadata *metadata = (
struct qbuf_metadata *)q->ptr;
515 metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
516 if(metadata->max_transmissions == 0) {
518 metadata->max_transmissions = CSMA_MAX_FRAME_RETRIES + 1;
520 metadata->sent = sent;
521 metadata->cptr = ptr;
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));
532 schedule_transmission(n);
537 LOG_WARN(
"could not allocate queuebuf, dropping packet\n");
540 LOG_WARN(
"could not allocate queuebuf, dropping packet\n");
548 LOG_WARN(
"Neighbor queue full\n");
550 LOG_WARN(
"could not allocate packet, dropping packet\n");
552 LOG_WARN(
"could not allocate neighbor, dropping packet\n");
554 mac_call_sent_callback(sent, ptr,
MAC_TX_ERR, 1);
558 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.
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.
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 RTIMER_NOW()
Get the current clock time.
#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
Include file for the Contiki low-layer network stack (NETSTACK)
void watchdog_periodic(void)
Writes the WDT clear sequence.
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.
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
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.