47 #include "lib/random.h"
62 #define PRINTF(...) printf(__VA_ARGS__)
67 #ifndef CSMA_MAX_MAC_TRANSMISSIONS
68 #ifdef CSMA_CONF_MAX_MAC_TRANSMISSIONS
69 #define CSMA_MAX_MAC_TRANSMISSIONS CSMA_CONF_MAX_MAC_TRANSMISSIONS
71 #define CSMA_MAX_MAC_TRANSMISSIONS 3
75 #if CSMA_MAX_MAC_TRANSMISSIONS < 1
76 #error CSMA_CONF_MAX_MAC_TRANSMISSIONS must be at least 1.
77 #error Change CSMA_CONF_MAX_MAC_TRANSMISSIONS in contiki-conf.h or in your Makefile.
80 struct queued_packet {
81 struct queued_packet *
next;
86 uint8_t transmissions, max_transmissions;
87 uint8_t collisions, deferrals;
90 #define MAX_QUEUED_PACKETS 6
91 MEMB(packet_memb,
struct queued_packet, MAX_QUEUED_PACKETS);
92 LIST(queued_packet_list);
94 static struct ctimer transmit_timer;
96 static uint8_t rdc_is_transmitting;
98 static void packet_sent(
void *ptr,
int status,
int num_transmissions);
102 default_timebase(
void)
107 time = NETSTACK_RDC.channel_check_interval();
119 transmit_queued_packet(
void *ptr)
122 struct queued_packet *q;
126 if(rdc_is_transmitting) {
135 queuebuf_to_packetbuf(q->buf);
136 PRINTF(
"csma: sending number %d %p, queue len %d\n", q->transmissions, q,
139 rdc_is_transmitting = 1;
140 NETSTACK_RDC.send(packet_sent, q);
145 start_transmission_timer(
void)
147 PRINTF(
"csma: start_transmission_timer, queue len %d\n",
152 transmit_queued_packet,
NULL);
158 free_queued_packet(
void)
160 struct queued_packet *q;
167 queuebuf_free(q->buf);
170 PRINTF(
"csma: free_queued_packet, queue length %d\n",
173 ctimer_set(&transmit_timer, default_timebase(), transmit_queued_packet,
NULL);
179 packet_sent(
void *ptr,
int status,
int num_transmissions)
181 struct queued_packet *q = ptr;
182 clock_time_t time = 0;
186 int backoff_transmissions;
188 rdc_is_transmitting = 0;
205 num_tx = q->transmissions;
215 PRINTF(
"csma: rexmit collision %d\n", q->transmissions);
218 PRINTF(
"csma: rexmit noack %d\n", q->transmissions);
221 PRINTF(
"csma: rexmit err %d, %d\n", status, q->transmissions);
226 time = default_timebase();
231 backoff_transmissions = q->transmissions + 1;
236 if(backoff_transmissions > 3) {
237 backoff_transmissions = 3;
239 time = time + (random_rand() % (backoff_transmissions * time));
241 if(q->transmissions < q->max_transmissions) {
242 PRINTF(
"csma: retransmitting with time %lu %p\n", time, q);
244 transmit_queued_packet,
NULL);
248 queuebuf_update_attr_from_packetbuf(q->buf);
251 PRINTF(
"csma: drop with status %d after %d transmissions, %d collisions\n",
252 status, q->transmissions, q->collisions);
254 free_queued_packet();
255 mac_call_sent_callback(sent, cptr, status, num_tx);
259 PRINTF(
"csma: rexmit ok %d\n", q->transmissions);
261 PRINTF(
"csma: rexmit failed %d: %d\n", q->transmissions, status);
264 free_queued_packet();
265 mac_call_sent_callback(sent, cptr, status, num_tx);
270 send_packet(mac_callback_t sent,
void *ptr)
272 struct queued_packet *q;
273 static uint16_t seqno;
275 packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
279 if(!
rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
285 q->buf = queuebuf_new_from_packetbuf();
287 if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
289 q->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
291 q->max_transmissions =
292 packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
294 q->transmissions = 0;
299 if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
300 PACKETBUF_ATTR_PACKET_TYPE_ACK) {
305 start_transmission_timer();
309 PRINTF(
"csma: could not allocate queuebuf, will drop if collision or noack\n");
311 PRINTF(
"csma: could not allocate memb, will drop if collision or noack\n");
313 PRINTF(
"csma: send broadcast (%d) or without retransmissions (%d)\n",
316 packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS));
318 NETSTACK_RDC.send(sent, ptr);
324 PRINTF(
"csma: got packet\n");
325 NETSTACK_NETWORK.input();
331 return NETSTACK_RDC.on();
335 off(
int keep_radio_on)
337 return NETSTACK_RDC.off(keep_radio_on);
340 static unsigned short
341 channel_check_interval(
void)
343 if(NETSTACK_RDC.channel_check_interval) {
344 return NETSTACK_RDC.channel_check_interval();
353 rdc_is_transmitting = 0;