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) {
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 transmission could not be performed because of a fatal error.
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.
TX failed due to a collision.
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.
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.
The MAC layer did not get an acknowledgement for the packet.
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.
The MAC layer transmission was OK.
The MAC layer transmission could not be performed because of an error.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
int packetbuf_holds_broadcast(void)
Checks whether the current packet is a broadcast.
Memory block allocation routines.
The MAC layer deferred the transmission for a later time.
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
TX was successful and where an ACK was requested one was received.
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.