Merge pull request #176 from adamdunkels/feature-net-bugfixes
Network system bugfixes
This commit is contained in:
commit
6a07172662
|
@ -55,6 +55,7 @@
|
||||||
void
|
void
|
||||||
print_stats(void)
|
print_stats(void)
|
||||||
{
|
{
|
||||||
|
#if RIMESTATS_CONF_ENABLED
|
||||||
PRINTA("S %d.%d clock %lu tx %lu rx %lu rtx %lu rrx %lu rexmit %lu acktx %lu noacktx %lu ackrx %lu timedout %lu badackrx %lu toolong %lu tooshort %lu badsynch %lu badcrc %lu contentiondrop %lu sendingdrop %lu lltx %lu llrx %lu\n",
|
PRINTA("S %d.%d clock %lu tx %lu rx %lu rtx %lu rrx %lu rexmit %lu acktx %lu noacktx %lu ackrx %lu timedout %lu badackrx %lu toolong %lu tooshort %lu badsynch %lu badcrc %lu contentiondrop %lu sendingdrop %lu lltx %lu llrx %lu\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
clock_seconds(),
|
clock_seconds(),
|
||||||
|
@ -66,6 +67,7 @@ print_stats(void)
|
||||||
rimestats.badsynch, rimestats.badcrc,
|
rimestats.badsynch, rimestats.badcrc,
|
||||||
rimestats.contentiondrop, rimestats.sendingdrop,
|
rimestats.contentiondrop, rimestats.sendingdrop,
|
||||||
rimestats.lltx, rimestats.llrx);
|
rimestats.lltx, rimestats.llrx);
|
||||||
|
#endif /* RIMESTATS_CONF_ENABLED */
|
||||||
#if ENERGEST_CONF_ON
|
#if ENERGEST_CONF_ON
|
||||||
PRINTA("E %d.%d clock %lu cpu %lu lpm %lu irq %lu gled %lu yled %lu rled %lu tx %lu listen %lu sensors %lu serial %lu\n",
|
PRINTA("E %d.%d clock %lu cpu %lu lpm %lu irq %lu gled %lu yled %lu rled %lu tx %lu listen %lu sensors %lu serial %lu\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
|
|
@ -116,8 +116,6 @@ struct hdr {
|
||||||
|
|
||||||
/* Are we currently receiving a burst? */
|
/* Are we currently receiving a burst? */
|
||||||
static int we_are_receiving_burst = 0;
|
static int we_are_receiving_burst = 0;
|
||||||
/* Has the receiver been awoken by a burst we're sending? */
|
|
||||||
static int is_receiver_awake = 0;
|
|
||||||
|
|
||||||
/* BURST_RECV_TIME is the maximum time a receiver waits for the
|
/* BURST_RECV_TIME is the maximum time a receiver waits for the
|
||||||
next packet of a burst when FRAME_PENDING is set. */
|
next packet of a burst when FRAME_PENDING is set. */
|
||||||
|
@ -377,16 +375,17 @@ powercycle(struct rtimer *t, void *ptr)
|
||||||
static uint8_t count;
|
static uint8_t count;
|
||||||
|
|
||||||
#if SYNC_CYCLE_STARTS
|
#if SYNC_CYCLE_STARTS
|
||||||
/* Compute cycle start when RTIMER_ARCH_SECOND is not a multiple of CHANNEL_CHECK_RATE */
|
/* Compute cycle start when RTIMER_ARCH_SECOND is not a multiple
|
||||||
if (sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) {
|
of CHANNEL_CHECK_RATE */
|
||||||
sync_cycle_phase = 0;
|
if(sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) {
|
||||||
sync_cycle_start += RTIMER_ARCH_SECOND;
|
sync_cycle_phase = 0;
|
||||||
cycle_start = sync_cycle_start;
|
sync_cycle_start += RTIMER_ARCH_SECOND;
|
||||||
|
cycle_start = sync_cycle_start;
|
||||||
} else {
|
} else {
|
||||||
#if (RTIMER_ARCH_SECOND * NETSTACK_RDC_CHANNEL_CHECK_RATE) > 65535
|
#if (RTIMER_ARCH_SECOND * NETSTACK_RDC_CHANNEL_CHECK_RATE) > 65535
|
||||||
cycle_start = sync_cycle_start + ((unsigned long)(sync_cycle_phase*RTIMER_ARCH_SECOND))/NETSTACK_RDC_CHANNEL_CHECK_RATE;
|
cycle_start = sync_cycle_start + ((unsigned long)(sync_cycle_phase*RTIMER_ARCH_SECOND))/NETSTACK_RDC_CHANNEL_CHECK_RATE;
|
||||||
#else
|
#else
|
||||||
cycle_start = sync_cycle_start + (sync_cycle_phase*RTIMER_ARCH_SECOND)/NETSTACK_RDC_CHANNEL_CHECK_RATE;
|
cycle_start = sync_cycle_start + (sync_cycle_phase*RTIMER_ARCH_SECOND)/NETSTACK_RDC_CHANNEL_CHECK_RATE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -475,12 +474,13 @@ powercycle(struct rtimer *t, void *ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 4)) {
|
if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 4)) {
|
||||||
/* Schedule the next powercycle interrupt, or sleep the mcu until then.
|
/* Schedule the next powercycle interrupt, or sleep the mcu
|
||||||
Sleeping will not exit from this interrupt, so ensure an occasional wake cycle
|
until then. Sleeping will not exit from this interrupt, so
|
||||||
or foreground processing will be blocked until a packet is detected */
|
ensure an occasional wake cycle or foreground processing will
|
||||||
|
be blocked until a packet is detected */
|
||||||
#if RDC_CONF_MCU_SLEEP
|
#if RDC_CONF_MCU_SLEEP
|
||||||
static uint8_t sleepcycle;
|
static uint8_t sleepcycle;
|
||||||
if ((sleepcycle++<16) && !we_are_sending && !radio_is_on) {
|
if((sleepcycle++ < 16) && !we_are_sending && !radio_is_on) {
|
||||||
rtimer_arch_sleep(CYCLE_TIME - (RTIMER_NOW() - cycle_start));
|
rtimer_arch_sleep(CYCLE_TIME - (RTIMER_NOW() - cycle_start));
|
||||||
} else {
|
} else {
|
||||||
sleepcycle = 0;
|
sleepcycle = 0;
|
||||||
|
@ -519,7 +519,9 @@ broadcast_rate_drop(void)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_list *buf_list)
|
send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
|
||||||
|
struct rdc_buf_list *buf_list,
|
||||||
|
int is_receiver_awake)
|
||||||
{
|
{
|
||||||
rtimer_clock_t t0;
|
rtimer_clock_t t0;
|
||||||
rtimer_clock_t encounter_time = 0;
|
rtimer_clock_t encounter_time = 0;
|
||||||
|
@ -538,8 +540,8 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
||||||
struct hdr *chdr;
|
struct hdr *chdr;
|
||||||
#endif /* WITH_CONTIKIMAC_HEADER */
|
#endif /* WITH_CONTIKIMAC_HEADER */
|
||||||
|
|
||||||
/* Exit if RDC and radio were explicitly turned off */
|
/* Exit if RDC and radio were explicitly turned off */
|
||||||
if (!contikimac_is_on && !contikimac_keep_radio_on) {
|
if(!contikimac_is_on && !contikimac_keep_radio_on) {
|
||||||
PRINTF("contikimac: radio is turned off\n");
|
PRINTF("contikimac: radio is turned off\n");
|
||||||
return MAC_TX_ERR_FATAL;
|
return MAC_TX_ERR_FATAL;
|
||||||
}
|
}
|
||||||
|
@ -612,7 +614,6 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Make sure that the packet is longer or equal to the shortest
|
/* Make sure that the packet is longer or equal to the shortest
|
||||||
packet length. */
|
packet length. */
|
||||||
transmit_len = packetbuf_totlen();
|
transmit_len = packetbuf_totlen();
|
||||||
|
@ -694,7 +695,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
||||||
/* Check if there are any transmissions by others. */
|
/* Check if there are any transmissions by others. */
|
||||||
/* TODO: why does this give collisions before sending with the mc1322x? */
|
/* TODO: why does this give collisions before sending with the mc1322x? */
|
||||||
if(is_receiver_awake == 0) {
|
if(is_receiver_awake == 0) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < CCA_COUNT_MAX_TX; ++i) {
|
for(i = 0; i < CCA_COUNT_MAX_TX; ++i) {
|
||||||
t0 = RTIMER_NOW();
|
t0 = RTIMER_NOW();
|
||||||
on();
|
on();
|
||||||
|
@ -723,8 +724,9 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
||||||
|
|
||||||
#if !RDC_CONF_HARDWARE_ACK
|
#if !RDC_CONF_HARDWARE_ACK
|
||||||
if(!is_broadcast) {
|
if(!is_broadcast) {
|
||||||
/* Turn radio on to receive expected unicast ack.
|
/* Turn radio on to receive expected unicast ack. Not necessary
|
||||||
Not necessary with hardware ack detection, and may trigger an unnecessary cca or rx cycle */
|
with hardware ack detection, and may trigger an unnecessary cca
|
||||||
|
or rx cycle */
|
||||||
on();
|
on();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -738,14 +740,14 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
||||||
|
|
||||||
watchdog_periodic();
|
watchdog_periodic();
|
||||||
|
|
||||||
if((is_receiver_awake || is_known_receiver) && !RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) {
|
if(!is_broadcast && (is_receiver_awake || is_known_receiver) &&
|
||||||
|
!RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + MAX_PHASE_STROBE_TIME)) {
|
||||||
PRINTF("miss to %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0]);
|
PRINTF("miss to %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
rtimer_clock_t wt;
|
rtimer_clock_t wt;
|
||||||
rtimer_clock_t txtime;
|
rtimer_clock_t txtime;
|
||||||
|
@ -755,7 +757,8 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
||||||
ret = NETSTACK_RADIO.transmit(transmit_len);
|
ret = NETSTACK_RADIO.transmit(transmit_len);
|
||||||
|
|
||||||
#if RDC_CONF_HARDWARE_ACK
|
#if RDC_CONF_HARDWARE_ACK
|
||||||
/* For radios that block in the transmit routine and detect the ACK in hardware */
|
/* For radios that block in the transmit routine and detect the
|
||||||
|
ACK in hardware */
|
||||||
if(ret == RADIO_TX_OK) {
|
if(ret == RADIO_TX_OK) {
|
||||||
if(!is_broadcast) {
|
if(!is_broadcast) {
|
||||||
got_strobe_ack = 1;
|
got_strobe_ack = 1;
|
||||||
|
@ -767,9 +770,9 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
||||||
PRINTF("contikimac: collisions while sending\n");
|
PRINTF("contikimac: collisions while sending\n");
|
||||||
collisions++;
|
collisions++;
|
||||||
}
|
}
|
||||||
wt = RTIMER_NOW();
|
wt = RTIMER_NOW();
|
||||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
|
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
|
||||||
#else
|
#else /* RDC_CONF_HARDWARE_ACK */
|
||||||
/* Wait for the ACK packet */
|
/* Wait for the ACK packet */
|
||||||
wt = RTIMER_NOW();
|
wt = RTIMER_NOW();
|
||||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
|
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
|
||||||
|
@ -782,7 +785,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
||||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
|
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
|
||||||
|
|
||||||
len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
|
len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
|
||||||
if(len == ACK_LEN && seqno == ackbuf[ACK_LEN-1]) {
|
if(len == ACK_LEN && seqno == ackbuf[ACK_LEN - 1]) {
|
||||||
got_strobe_ack = 1;
|
got_strobe_ack = 1;
|
||||||
encounter_time = txtime;
|
encounter_time = txtime;
|
||||||
break;
|
break;
|
||||||
|
@ -832,16 +835,16 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WITH_PHASE_OPTIMIZATION
|
#if WITH_PHASE_OPTIMIZATION
|
||||||
|
|
||||||
if(is_known_receiver && got_strobe_ack) {
|
if(is_known_receiver && got_strobe_ack) {
|
||||||
PRINTF("no miss %d wake-ups %d\n", packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
|
PRINTF("no miss %d wake-ups %d\n",
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[0],
|
||||||
strobes);
|
strobes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!is_broadcast) {
|
if(!is_broadcast) {
|
||||||
if(collisions == 0 && is_receiver_awake == 0) {
|
if(collisions == 0 && is_receiver_awake == 0) {
|
||||||
phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time,
|
phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
|
||||||
ret);
|
encounter_time, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_PHASE_OPTIMIZATION */
|
#endif /* WITH_PHASE_OPTIMIZATION */
|
||||||
|
@ -852,7 +855,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
|
||||||
static void
|
static void
|
||||||
qsend_packet(mac_callback_t sent, void *ptr)
|
qsend_packet(mac_callback_t sent, void *ptr)
|
||||||
{
|
{
|
||||||
int ret = send_packet(sent, ptr, NULL);
|
int ret = send_packet(sent, ptr, NULL, 0);
|
||||||
if(ret != MAC_TX_DEFERRED) {
|
if(ret != MAC_TX_DEFERRED) {
|
||||||
mac_call_sent_callback(sent, ptr, ret, 1);
|
mac_call_sent_callback(sent, ptr, ret, 1);
|
||||||
}
|
}
|
||||||
|
@ -864,6 +867,8 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
||||||
struct rdc_buf_list *curr = buf_list;
|
struct rdc_buf_list *curr = buf_list;
|
||||||
struct rdc_buf_list *next;
|
struct rdc_buf_list *next;
|
||||||
int ret;
|
int ret;
|
||||||
|
int is_receiver_awake;
|
||||||
|
|
||||||
if(curr == NULL) {
|
if(curr == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -887,7 +892,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send the current packet */
|
/* Send the current packet */
|
||||||
ret = send_packet(sent, ptr, curr);
|
ret = send_packet(sent, ptr, curr, is_receiver_awake);
|
||||||
if(ret != MAC_TX_DEFERRED) {
|
if(ret != MAC_TX_DEFERRED) {
|
||||||
mac_call_sent_callback(sent, ptr, ret, 1);
|
mac_call_sent_callback(sent, ptr, ret, 1);
|
||||||
}
|
}
|
||||||
|
@ -903,11 +908,11 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
||||||
next = NULL;
|
next = NULL;
|
||||||
}
|
}
|
||||||
} while(next != NULL);
|
} while(next != NULL);
|
||||||
is_receiver_awake = 0;
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* Timer callback triggered when receiving a burst, after having waited for a next
|
/* Timer callback triggered when receiving a burst, after having
|
||||||
packet for a too long time. Turns the radio off and leaves burst reception mode */
|
waited for a next packet for a too long time. Turns the radio off
|
||||||
|
and leaves burst reception mode */
|
||||||
static void
|
static void
|
||||||
recv_burst_off(void *ptr)
|
recv_burst_off(void *ptr)
|
||||||
{
|
{
|
||||||
|
@ -955,7 +960,8 @@ input_packet(void)
|
||||||
we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING);
|
we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING);
|
||||||
if(we_are_receiving_burst) {
|
if(we_are_receiving_burst) {
|
||||||
on();
|
on();
|
||||||
/* Set a timer to turn the radio off in case we do not receive a next packet */
|
/* Set a timer to turn the radio off in case we do not receive
|
||||||
|
a next packet */
|
||||||
ctimer_set(&ct, INTER_PACKET_DEADLINE, recv_burst_off, NULL);
|
ctimer_set(&ct, INTER_PACKET_DEADLINE, recv_burst_off, NULL);
|
||||||
} else {
|
} else {
|
||||||
off();
|
off();
|
||||||
|
|
|
@ -110,8 +110,9 @@ static void packet_sent(void *ptr, int status, int num_transmissions);
|
||||||
static void transmit_packet_list(void *ptr);
|
static void transmit_packet_list(void *ptr);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static struct
|
static struct neighbor_queue *
|
||||||
neighbor_queue *neighbor_queue_from_addr(const rimeaddr_t *addr) {
|
neighbor_queue_from_addr(const rimeaddr_t *addr)
|
||||||
|
{
|
||||||
struct neighbor_queue *n = list_head(neighbor_list);
|
struct neighbor_queue *n = list_head(neighbor_list);
|
||||||
while(n != NULL) {
|
while(n != NULL) {
|
||||||
if(rimeaddr_cmp(&n->addr, addr)) {
|
if(rimeaddr_cmp(&n->addr, addr)) {
|
||||||
|
@ -185,15 +186,19 @@ free_first_packet(struct neighbor_queue *n)
|
||||||
static void
|
static void
|
||||||
packet_sent(void *ptr, int status, int num_transmissions)
|
packet_sent(void *ptr, int status, int num_transmissions)
|
||||||
{
|
{
|
||||||
struct neighbor_queue *n = ptr;
|
struct neighbor_queue *n;
|
||||||
struct rdc_buf_list *q = list_head(n->queued_packet_list);
|
struct rdc_buf_list *q;
|
||||||
struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
|
struct qbuf_metadata *metadata;
|
||||||
clock_time_t time = 0;
|
clock_time_t time = 0;
|
||||||
mac_callback_t sent;
|
mac_callback_t sent;
|
||||||
void *cptr;
|
void *cptr;
|
||||||
int num_tx;
|
int num_tx;
|
||||||
int backoff_transmissions;
|
int backoff_transmissions;
|
||||||
|
|
||||||
|
n = ptr;
|
||||||
|
if(n == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
switch(status) {
|
switch(status) {
|
||||||
case MAC_TX_OK:
|
case MAC_TX_OK:
|
||||||
case MAC_TX_NOACK:
|
case MAC_TX_NOACK:
|
||||||
|
@ -207,66 +212,72 @@ packet_sent(void *ptr, int status, int num_transmissions)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sent = metadata->sent;
|
q = list_head(n->queued_packet_list);
|
||||||
cptr = metadata->cptr;
|
if(q != NULL) {
|
||||||
num_tx = n->transmissions;
|
metadata = (struct qbuf_metadata *)q->ptr;
|
||||||
|
|
||||||
if(status == MAC_TX_COLLISION ||
|
if(metadata != NULL) {
|
||||||
status == MAC_TX_NOACK) {
|
sent = metadata->sent;
|
||||||
|
cptr = metadata->cptr;
|
||||||
|
num_tx = n->transmissions;
|
||||||
|
if(status == MAC_TX_COLLISION ||
|
||||||
|
status == MAC_TX_NOACK) {
|
||||||
|
|
||||||
/* If the transmission was not performed because of a collision or
|
/* If the transmission was not performed because of a
|
||||||
noack, we must retransmit the packet. */
|
collision or noack, we must retransmit the packet. */
|
||||||
|
|
||||||
switch(status) {
|
switch(status) {
|
||||||
case MAC_TX_COLLISION:
|
case MAC_TX_COLLISION:
|
||||||
PRINTF("csma: rexmit collision %d\n", n->transmissions);
|
PRINTF("csma: rexmit collision %d\n", n->transmissions);
|
||||||
break;
|
break;
|
||||||
case MAC_TX_NOACK:
|
case MAC_TX_NOACK:
|
||||||
PRINTF("csma: rexmit noack %d\n", n->transmissions);
|
PRINTF("csma: rexmit noack %d\n", n->transmissions);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions);
|
PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The retransmission time must be proportional to the channel
|
||||||
|
check interval of the underlying radio duty cycling layer. */
|
||||||
|
time = default_timebase();
|
||||||
|
|
||||||
|
/* The retransmission time uses a linear backoff so that the
|
||||||
|
interval between the transmissions increase with each
|
||||||
|
retransmit. */
|
||||||
|
backoff_transmissions = n->transmissions + 1;
|
||||||
|
|
||||||
|
/* Clamp the number of backoffs so that we don't get a too long
|
||||||
|
timeout here, since that will delay all packets in the
|
||||||
|
queue. */
|
||||||
|
if(backoff_transmissions > 3) {
|
||||||
|
backoff_transmissions = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
time = time + (random_rand() % (backoff_transmissions * time));
|
||||||
|
|
||||||
|
if(n->transmissions < metadata->max_transmissions) {
|
||||||
|
PRINTF("csma: retransmitting with time %lu %p\n", time, q);
|
||||||
|
ctimer_set(&n->transmit_timer, time,
|
||||||
|
transmit_packet_list, n);
|
||||||
|
/* This is needed to correctly attribute energy that we spent
|
||||||
|
transmitting this packet. */
|
||||||
|
queuebuf_update_attr_from_packetbuf(q->buf);
|
||||||
|
} else {
|
||||||
|
PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n",
|
||||||
|
status, n->transmissions, n->collisions);
|
||||||
|
free_first_packet(n);
|
||||||
|
mac_call_sent_callback(sent, cptr, status, num_tx);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(status == MAC_TX_OK) {
|
||||||
|
PRINTF("csma: rexmit ok %d\n", n->transmissions);
|
||||||
|
} else {
|
||||||
|
PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status);
|
||||||
|
}
|
||||||
|
free_first_packet(n);
|
||||||
|
mac_call_sent_callback(sent, cptr, status, num_tx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The retransmission time must be proportional to the channel
|
|
||||||
check interval of the underlying radio duty cycling layer. */
|
|
||||||
time = default_timebase();
|
|
||||||
|
|
||||||
/* The retransmission time uses a linear backoff so that the
|
|
||||||
interval between the transmissions increase with each
|
|
||||||
retransmit. */
|
|
||||||
backoff_transmissions = n->transmissions + 1;
|
|
||||||
|
|
||||||
/* Clamp the number of backoffs so that we don't get a too long
|
|
||||||
timeout here, since that will delay all packets in the
|
|
||||||
queue. */
|
|
||||||
if(backoff_transmissions > 3) {
|
|
||||||
backoff_transmissions = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
time = time + (random_rand() % (backoff_transmissions * time));
|
|
||||||
|
|
||||||
if(n->transmissions < metadata->max_transmissions) {
|
|
||||||
PRINTF("csma: retransmitting with time %lu %p\n", time, q);
|
|
||||||
ctimer_set(&n->transmit_timer, time,
|
|
||||||
transmit_packet_list, n);
|
|
||||||
/* This is needed to correctly attribute energy that we spent
|
|
||||||
transmitting this packet. */
|
|
||||||
queuebuf_update_attr_from_packetbuf(q->buf);
|
|
||||||
} else {
|
|
||||||
PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n",
|
|
||||||
status, n->transmissions, n->collisions);
|
|
||||||
free_first_packet(n);
|
|
||||||
mac_call_sent_callback(sent, cptr, status, num_tx);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(status == MAC_TX_OK) {
|
|
||||||
PRINTF("csma: rexmit ok %d\n", n->transmissions);
|
|
||||||
} else {
|
|
||||||
PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status);
|
|
||||||
}
|
|
||||||
free_first_packet(n);
|
|
||||||
mac_call_sent_callback(sent, cptr, status, num_tx);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -276,86 +287,77 @@ send_packet(mac_callback_t sent, void *ptr)
|
||||||
struct rdc_buf_list *q;
|
struct rdc_buf_list *q;
|
||||||
struct neighbor_queue *n;
|
struct neighbor_queue *n;
|
||||||
static uint16_t seqno;
|
static uint16_t seqno;
|
||||||
|
const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
|
||||||
|
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
|
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno++);
|
||||||
|
|
||||||
/* If the packet is a broadcast, do not allocate a queue
|
|
||||||
entry. Instead, just send it out. */
|
|
||||||
if(!rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
|
|
||||||
&rimeaddr_null)) {
|
|
||||||
const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
|
|
||||||
|
|
||||||
/* Look for the neighbor entry */
|
|
||||||
n = neighbor_queue_from_addr(addr);
|
|
||||||
if(n == NULL) {
|
|
||||||
/* Allocate a new neighbor entry */
|
|
||||||
n = memb_alloc(&neighbor_memb);
|
|
||||||
if(n != NULL) {
|
|
||||||
/* Init neighbor entry */
|
|
||||||
rimeaddr_copy(&n->addr, addr);
|
|
||||||
n->transmissions = 0;
|
|
||||||
n->collisions = 0;
|
|
||||||
n->deferrals = 0;
|
|
||||||
/* Init packet list for this neighbor */
|
|
||||||
LIST_STRUCT_INIT(n, queued_packet_list);
|
|
||||||
/* Add neighbor to the list */
|
|
||||||
list_add(neighbor_list, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Look for the neighbor entry */
|
||||||
|
n = neighbor_queue_from_addr(addr);
|
||||||
|
if(n == NULL) {
|
||||||
|
/* Allocate a new neighbor entry */
|
||||||
|
n = memb_alloc(&neighbor_memb);
|
||||||
if(n != NULL) {
|
if(n != NULL) {
|
||||||
/* Add packet to the neighbor's queue */
|
/* Init neighbor entry */
|
||||||
q = memb_alloc(&packet_memb);
|
rimeaddr_copy(&n->addr, addr);
|
||||||
if(q != NULL) {
|
n->transmissions = 0;
|
||||||
q->ptr = memb_alloc(&metadata_memb);
|
n->collisions = 0;
|
||||||
if(q->ptr != NULL) {
|
n->deferrals = 0;
|
||||||
q->buf = queuebuf_new_from_packetbuf();
|
/* Init packet list for this neighbor */
|
||||||
if(q->buf != NULL) {
|
LIST_STRUCT_INIT(n, queued_packet_list);
|
||||||
struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
|
/* Add neighbor to the list */
|
||||||
/* Neighbor and packet successfully allocated */
|
list_add(neighbor_list, n);
|
||||||
if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
|
|
||||||
/* Use default configuration for max transmissions */
|
|
||||||
metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
|
|
||||||
} else {
|
|
||||||
metadata->max_transmissions =
|
|
||||||
packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
|
|
||||||
}
|
|
||||||
metadata->sent = sent;
|
|
||||||
metadata->cptr = ptr;
|
|
||||||
|
|
||||||
if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
|
|
||||||
PACKETBUF_ATTR_PACKET_TYPE_ACK) {
|
|
||||||
list_push(n->queued_packet_list, q);
|
|
||||||
} else {
|
|
||||||
list_add(n->queued_packet_list, q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If q is the first packet in the neighbor's queue, send asap */
|
|
||||||
if(list_head(n->queued_packet_list) == q) {
|
|
||||||
ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memb_free(&metadata_memb, q->ptr);
|
|
||||||
PRINTF("csma: could not allocate queuebuf, dropping packet\n");
|
|
||||||
}
|
|
||||||
memb_free(&packet_memb, q);
|
|
||||||
PRINTF("csma: could not allocate queuebuf, dropping packet\n");
|
|
||||||
}
|
|
||||||
/* The packet allocation failed. Remove and free neighbor entry if empty. */
|
|
||||||
if(list_length(n->queued_packet_list) == 0) {
|
|
||||||
list_remove(neighbor_list, n);
|
|
||||||
memb_free(&neighbor_memb, n);
|
|
||||||
}
|
|
||||||
PRINTF("csma: could not allocate packet, dropping packet\n");
|
|
||||||
} else {
|
|
||||||
PRINTF("csma: could not allocate neighbor, dropping packet\n");
|
|
||||||
}
|
}
|
||||||
mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
|
|
||||||
} else {
|
|
||||||
PRINTF("csma: send broadcast\n");
|
|
||||||
NETSTACK_RDC.send(sent, ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(n != NULL) {
|
||||||
|
/* Add packet to the neighbor's queue */
|
||||||
|
q = memb_alloc(&packet_memb);
|
||||||
|
if(q != NULL) {
|
||||||
|
q->ptr = memb_alloc(&metadata_memb);
|
||||||
|
if(q->ptr != NULL) {
|
||||||
|
q->buf = queuebuf_new_from_packetbuf();
|
||||||
|
if(q->buf != NULL) {
|
||||||
|
struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
|
||||||
|
/* Neighbor and packet successfully allocated */
|
||||||
|
if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) {
|
||||||
|
/* Use default configuration for max transmissions */
|
||||||
|
metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS;
|
||||||
|
} else {
|
||||||
|
metadata->max_transmissions =
|
||||||
|
packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS);
|
||||||
|
}
|
||||||
|
metadata->sent = sent;
|
||||||
|
metadata->cptr = ptr;
|
||||||
|
|
||||||
|
if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
|
||||||
|
PACKETBUF_ATTR_PACKET_TYPE_ACK) {
|
||||||
|
list_push(n->queued_packet_list, q);
|
||||||
|
} else {
|
||||||
|
list_add(n->queued_packet_list, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If q is the first packet in the neighbor's queue, send asap */
|
||||||
|
if(list_head(n->queued_packet_list) == q) {
|
||||||
|
ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memb_free(&metadata_memb, q->ptr);
|
||||||
|
PRINTF("csma: could not allocate queuebuf, dropping packet\n");
|
||||||
|
}
|
||||||
|
memb_free(&packet_memb, q);
|
||||||
|
PRINTF("csma: could not allocate queuebuf, dropping packet\n");
|
||||||
|
}
|
||||||
|
/* The packet allocation failed. Remove and free neighbor entry if empty. */
|
||||||
|
if(list_length(n->queued_packet_list) == 0) {
|
||||||
|
list_remove(neighbor_list, n);
|
||||||
|
memb_free(&neighbor_memb, n);
|
||||||
|
}
|
||||||
|
PRINTF("csma: could not allocate packet, dropping packet\n");
|
||||||
|
} else {
|
||||||
|
PRINTF("csma: could not allocate neighbor, dropping packet\n");
|
||||||
|
}
|
||||||
|
mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -45,7 +45,7 @@ void
|
||||||
mac_call_sent_callback(mac_callback_t sent, void *ptr, int status, int num_tx)
|
mac_call_sent_callback(mac_callback_t sent, void *ptr, int status, int num_tx)
|
||||||
{
|
{
|
||||||
PRINTF("mac_callback_t %p ptr %p status %d num_tx %d\n",
|
PRINTF("mac_callback_t %p ptr %p status %d num_tx %d\n",
|
||||||
sent, ptr, status, num_tx);
|
(void *)sent, ptr, status, num_tx);
|
||||||
switch(status) {
|
switch(status) {
|
||||||
case MAC_TX_COLLISION:
|
case MAC_TX_COLLISION:
|
||||||
PRINTF("mac: collision after %d tx\n", num_tx);
|
PRINTF("mac: collision after %d tx\n", num_tx);
|
||||||
|
|
|
@ -208,9 +208,10 @@ send_packet(mac_callback_t sent, void *ptr)
|
||||||
static void
|
static void
|
||||||
send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
|
||||||
{
|
{
|
||||||
if(buf_list != NULL) {
|
while(buf_list != NULL) {
|
||||||
queuebuf_to_packetbuf(buf_list->buf);
|
queuebuf_to_packetbuf(buf_list->buf);
|
||||||
send_packet(sent, ptr);
|
send_packet(sent, ptr);
|
||||||
|
buf_list = buf_list->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -55,8 +55,11 @@ struct rimestats {
|
||||||
unsigned long lltx, llrx;
|
unsigned long lltx, llrx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if RIMESTATS_CONF_ENABLED
|
||||||
extern struct rimestats rimestats;
|
extern struct rimestats rimestats;
|
||||||
|
|
||||||
#define RIMESTATS_ADD(x) rimestats.x++
|
#define RIMESTATS_ADD(x) rimestats.x++
|
||||||
|
#else /* RIMESTATS_CONF_ENABLED */
|
||||||
|
#define RIMESTATS_ADD(x)
|
||||||
|
#endif /* RIMESTATS_CONF_ENABLED */
|
||||||
|
|
||||||
#endif /* __RIMESTATS_H__ */
|
#endif /* __RIMESTATS_H__ */
|
||||||
|
|
|
@ -54,7 +54,8 @@ uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len)
|
||||||
uip_udp_conn = c;
|
uip_udp_conn = c;
|
||||||
uip_slen = len;
|
uip_slen = len;
|
||||||
memcpy(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data,
|
memcpy(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data,
|
||||||
len > UIP_BUFSIZE? UIP_BUFSIZE: len);
|
len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN?
|
||||||
|
UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len);
|
||||||
uip_process(UIP_UDP_SEND_CONN);
|
uip_process(UIP_UDP_SEND_CONN);
|
||||||
#if UIP_CONF_IPV6
|
#if UIP_CONF_IPV6
|
||||||
tcpip_ipv6_output();
|
tcpip_ipv6_output();
|
||||||
|
|
Loading…
Reference in a new issue