Merge pull request #176 from adamdunkels/feature-net-bugfixes

Network system bugfixes
This commit is contained in:
Nicolas Tsiftes 2013-03-18 13:38:44 -07:00
commit 6a07172662
7 changed files with 191 additions and 176 deletions

View file

@ -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],

View file

@ -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,7 +375,8 @@ 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
of CHANNEL_CHECK_RATE */
if(sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) { if(sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) {
sync_cycle_phase = 0; sync_cycle_phase = 0;
sync_cycle_start += RTIMER_ARCH_SECOND; sync_cycle_start += RTIMER_ARCH_SECOND;
@ -475,9 +474,10 @@ 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) {
@ -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;
@ -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();
@ -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;
@ -769,7 +772,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
} }
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)) { }
@ -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();

View file

@ -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,15 +212,19 @@ packet_sent(void *ptr, int status, int num_transmissions)
break; break;
} }
q = list_head(n->queued_packet_list);
if(q != NULL) {
metadata = (struct qbuf_metadata *)q->ptr;
if(metadata != NULL) {
sent = metadata->sent; sent = metadata->sent;
cptr = metadata->cptr; cptr = metadata->cptr;
num_tx = n->transmissions; num_tx = n->transmissions;
if(status == MAC_TX_COLLISION || if(status == MAC_TX_COLLISION ||
status == MAC_TX_NOACK) { 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:
@ -269,6 +278,8 @@ packet_sent(void *ptr, int status, int num_transmissions)
mac_call_sent_callback(sent, cptr, status, num_tx); mac_call_sent_callback(sent, cptr, status, num_tx);
} }
} }
}
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
send_packet(mac_callback_t sent, void *ptr) send_packet(mac_callback_t sent, void *ptr)
@ -276,15 +287,10 @@ 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 */ /* Look for the neighbor entry */
n = neighbor_queue_from_addr(addr); n = neighbor_queue_from_addr(addr);
if(n == NULL) { if(n == NULL) {
@ -352,10 +358,6 @@ send_packet(mac_callback_t sent, void *ptr)
PRINTF("csma: could not allocate neighbor, dropping packet\n"); PRINTF("csma: could not allocate neighbor, dropping packet\n");
} }
mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1); mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
} else {
PRINTF("csma: send broadcast\n");
NETSTACK_RDC.send(sent, ptr);
}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void

View file

@ -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);

View file

@ -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;
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -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__ */

View file

@ -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();