45 #include "sys/clock.h"
47 #include "lib/random.h"
61 #define PRINTF(...) printf(__VA_ARGS__)
66 #ifndef CSMA_MAX_BACKOFF_EXPONENT
67 #ifdef CSMA_CONF_MAX_BACKOFF_EXPONENT
68 #define CSMA_MAX_BACKOFF_EXPONENT CSMA_CONF_MAX_BACKOFF_EXPONENT
70 #define CSMA_MAX_BACKOFF_EXPONENT 3
74 #ifndef CSMA_MAX_MAC_TRANSMISSIONS
75 #ifdef CSMA_CONF_MAX_MAC_TRANSMISSIONS
76 #define CSMA_MAX_MAC_TRANSMISSIONS CSMA_CONF_MAX_MAC_TRANSMISSIONS
78 #define CSMA_MAX_MAC_TRANSMISSIONS 3
82 #if CSMA_MAX_MAC_TRANSMISSIONS < 1
83 #error CSMA_CONF_MAX_MAC_TRANSMISSIONS must be at least 1.
84 #error Change CSMA_CONF_MAX_MAC_TRANSMISSIONS in contiki-conf.h or in your Makefile.
88 struct qbuf_metadata {
91 uint8_t max_transmissions;
95 struct neighbor_queue {
96 struct neighbor_queue *next;
98 struct ctimer transmit_timer;
99 uint8_t transmissions;
100 uint8_t collisions, deferrals;
105 #ifdef CSMA_CONF_MAX_NEIGHBOR_QUEUES
106 #define CSMA_MAX_NEIGHBOR_QUEUES CSMA_CONF_MAX_NEIGHBOR_QUEUES
108 #define CSMA_MAX_NEIGHBOR_QUEUES 2
111 #define MAX_QUEUED_PACKETS QUEUEBUF_NUM
112 MEMB(neighbor_memb,
struct neighbor_queue, CSMA_MAX_NEIGHBOR_QUEUES);
113 MEMB(packet_memb,
struct rdc_buf_list, MAX_QUEUED_PACKETS);
114 MEMB(metadata_memb,
struct qbuf_metadata, MAX_QUEUED_PACKETS);
117 static void packet_sent(
void *ptr,
int status,
int num_transmissions);
118 static void transmit_packet_list(
void *ptr);
121 static struct neighbor_queue *
122 neighbor_queue_from_addr(
const linkaddr_t *addr)
124 struct neighbor_queue *n =
list_head(neighbor_list);
135 default_timebase(
void)
140 time = NETSTACK_RDC.channel_check_interval();
152 transmit_packet_list(
void *ptr)
154 struct neighbor_queue *n = ptr;
156 struct rdc_buf_list *q =
list_head(n->queued_packet_list);
158 PRINTF(
"csma: preparing number %d %p, queue len %d\n", n->transmissions, q,
161 NETSTACK_RDC.send_list(packet_sent, n, q);
167 free_packet(
struct neighbor_queue *n,
struct rdc_buf_list *p)
173 queuebuf_free(p->buf);
176 PRINTF(
"csma: free_queued_packet, queue length %d\n",
180 n->transmissions = 0;
184 ctimer_set(&n->transmit_timer, default_timebase(),
185 transmit_packet_list, n);
196 packet_sent(
void *ptr,
int status,
int num_transmissions)
198 struct neighbor_queue *n;
199 struct rdc_buf_list *q;
200 struct qbuf_metadata *metadata;
201 clock_time_t time = 0;
205 int backoff_exponent;
206 int backoff_transmissions;
215 n->transmissions += num_transmissions;
218 n->collisions += num_transmissions;
221 n->deferrals += num_transmissions;
226 for(q =
list_head(n->queued_packet_list);
228 if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
229 packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
235 metadata = (
struct qbuf_metadata *)q->ptr;
237 if(metadata !=
NULL) {
238 sent = metadata->sent;
239 cptr = metadata->cptr;
240 num_tx = n->transmissions;
249 PRINTF(
"csma: rexmit collision %d\n", n->transmissions);
252 PRINTF(
"csma: rexmit noack %d\n", n->transmissions);
255 PRINTF(
"csma: rexmit err %d, %d\n", status, n->transmissions);
260 time = default_timebase();
265 backoff_exponent = num_tx;
268 if(backoff_exponent > CSMA_MAX_BACKOFF_EXPONENT) {
269 backoff_exponent = CSMA_MAX_BACKOFF_EXPONENT;
273 backoff_transmissions = 1 << backoff_exponent;
277 time = time + (
random_rand() % (backoff_transmissions * time));
279 if(n->transmissions < metadata->max_transmissions) {
280 PRINTF(
"csma: retransmitting with time %lu %p\n", time, q);
282 transmit_packet_list, n);
285 queuebuf_update_attr_from_packetbuf(q->buf);
287 PRINTF(
"csma: drop with status %d after %d transmissions, %d collisions\n",
288 status, n->transmissions, n->collisions);
290 mac_call_sent_callback(sent, cptr, status, num_tx);
294 PRINTF(
"csma: rexmit ok %d\n", n->transmissions);
296 PRINTF(
"csma: rexmit failed %d: %d\n", n->transmissions, status);
299 mac_call_sent_callback(sent, cptr, status, num_tx);
306 send_packet(mac_callback_t sent,
void *ptr)
308 struct rdc_buf_list *q;
309 struct neighbor_queue *n;
310 static uint8_t initialized = 0;
311 static uint16_t seqno;
312 const linkaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
325 packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
328 n = neighbor_queue_from_addr(addr);
335 n->transmissions = 0;
351 q->buf = queuebuf_new_from_packetbuf();
353 struct qbuf_metadata *metadata = (
struct qbuf_metadata *)q->ptr;
355 if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
357 metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
359 metadata->max_transmissions =
360 packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
362 metadata->sent = sent;
363 metadata->cptr = ptr;
365 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
366 PACKETBUF_ATTR_PACKET_TYPE_ACK) {
373 if(
list_head(n->queued_packet_list) == q) {
374 ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n);
379 PRINTF(
"csma: could not allocate queuebuf, dropping packet\n");
382 PRINTF(
"csma: could not allocate queuebuf, dropping packet\n");
389 PRINTF(
"csma: could not allocate packet, dropping packet\n");
391 PRINTF(
"csma: could not allocate neighbor, dropping packet\n");
393 mac_call_sent_callback(sent, ptr,
MAC_TX_ERR, 1);
399 NETSTACK_NETWORK.input();
405 return NETSTACK_RDC.on();
409 off(
int keep_radio_on)
411 return NETSTACK_RDC.off(keep_radio_on);
414 static unsigned short
415 channel_check_interval(
void)
417 if(NETSTACK_RDC.channel_check_interval) {
418 return NETSTACK_RDC.channel_check_interval();