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
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",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
clock_seconds(),
@ -66,6 +67,7 @@ print_stats(void)
rimestats.badsynch, rimestats.badcrc,
rimestats.contentiondrop, rimestats.sendingdrop,
rimestats.lltx, rimestats.llrx);
#endif /* RIMESTATS_CONF_ENABLED */
#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",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],

View file

@ -116,8 +116,6 @@ struct hdr {
/* Are we currently receiving a burst? */
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
next packet of a burst when FRAME_PENDING is set. */
@ -377,16 +375,17 @@ powercycle(struct rtimer *t, void *ptr)
static uint8_t count;
#if SYNC_CYCLE_STARTS
/* Compute cycle start when RTIMER_ARCH_SECOND is not a multiple of CHANNEL_CHECK_RATE */
if (sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) {
sync_cycle_phase = 0;
sync_cycle_start += RTIMER_ARCH_SECOND;
cycle_start = sync_cycle_start;
/* Compute cycle start when RTIMER_ARCH_SECOND is not a multiple
of CHANNEL_CHECK_RATE */
if(sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) {
sync_cycle_phase = 0;
sync_cycle_start += RTIMER_ARCH_SECOND;
cycle_start = sync_cycle_start;
} else {
#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
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
}
#else
@ -475,12 +474,13 @@ powercycle(struct rtimer *t, void *ptr)
}
if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 4)) {
/* Schedule the next powercycle interrupt, or sleep the mcu until then.
Sleeping will not exit from this interrupt, so ensure an occasional wake cycle
or foreground processing will be blocked until a packet is detected */
/* Schedule the next powercycle interrupt, or sleep the mcu
until then. Sleeping will not exit from this interrupt, so
ensure an occasional wake cycle or foreground processing will
be blocked until a packet is detected */
#if RDC_CONF_MCU_SLEEP
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));
} else {
sleepcycle = 0;
@ -519,7 +519,9 @@ broadcast_rate_drop(void)
}
/*---------------------------------------------------------------------------*/
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 encounter_time = 0;
@ -538,8 +540,8 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
struct hdr *chdr;
#endif /* WITH_CONTIKIMAC_HEADER */
/* Exit if RDC and radio were explicitly turned off */
if (!contikimac_is_on && !contikimac_keep_radio_on) {
/* Exit if RDC and radio were explicitly turned off */
if(!contikimac_is_on && !contikimac_keep_radio_on) {
PRINTF("contikimac: radio is turned off\n");
return MAC_TX_ERR_FATAL;
}
@ -612,7 +614,6 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
}
#endif
/* Make sure that the packet is longer or equal to the shortest
packet length. */
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. */
/* TODO: why does this give collisions before sending with the mc1322x? */
if(is_receiver_awake == 0) {
int i;
int i;
for(i = 0; i < CCA_COUNT_MAX_TX; ++i) {
t0 = RTIMER_NOW();
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(!is_broadcast) {
/* Turn radio on to receive expected unicast ack.
Not necessary with hardware ack detection, and may trigger an unnecessary cca or rx cycle */
/* Turn radio on to receive expected unicast ack. Not necessary
with hardware ack detection, and may trigger an unnecessary cca
or rx cycle */
on();
}
#endif
@ -738,14 +740,14 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
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]);
break;
}
len = 0;
{
rtimer_clock_t wt;
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);
#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(!is_broadcast) {
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");
collisions++;
}
wt = RTIMER_NOW();
wt = RTIMER_NOW();
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
#else
#else /* RDC_CONF_HARDWARE_ACK */
/* Wait for the ACK packet */
wt = RTIMER_NOW();
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)) { }
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;
encounter_time = txtime;
break;
@ -832,16 +835,16 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
}
#if WITH_PHASE_OPTIMIZATION
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);
}
if(!is_broadcast) {
if(collisions == 0 && is_receiver_awake == 0) {
phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER), encounter_time,
ret);
phase_update(&phase_list, packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
encounter_time, ret);
}
}
#endif /* WITH_PHASE_OPTIMIZATION */
@ -852,7 +855,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
static void
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) {
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 *next;
int ret;
int is_receiver_awake;
if(curr == NULL) {
return;
}
@ -887,7 +892,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
}
/* Send the current packet */
ret = send_packet(sent, ptr, curr);
ret = send_packet(sent, ptr, curr, is_receiver_awake);
if(ret != MAC_TX_DEFERRED) {
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;
}
} while(next != NULL);
is_receiver_awake = 0;
}
/*---------------------------------------------------------------------------*/
/* Timer callback triggered when receiving a burst, after having waited for a next
packet for a too long time. Turns the radio off and leaves burst reception mode */
/* Timer callback triggered when receiving a burst, after having
waited for a next packet for a too long time. Turns the radio off
and leaves burst reception mode */
static void
recv_burst_off(void *ptr)
{
@ -955,7 +960,8 @@ input_packet(void)
we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING);
if(we_are_receiving_burst) {
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);
} else {
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 struct
neighbor_queue *neighbor_queue_from_addr(const rimeaddr_t *addr) {
static struct neighbor_queue *
neighbor_queue_from_addr(const rimeaddr_t *addr)
{
struct neighbor_queue *n = list_head(neighbor_list);
while(n != NULL) {
if(rimeaddr_cmp(&n->addr, addr)) {
@ -185,15 +186,19 @@ free_first_packet(struct neighbor_queue *n)
static void
packet_sent(void *ptr, int status, int num_transmissions)
{
struct neighbor_queue *n = ptr;
struct rdc_buf_list *q = list_head(n->queued_packet_list);
struct qbuf_metadata *metadata = (struct qbuf_metadata *)q->ptr;
struct neighbor_queue *n;
struct rdc_buf_list *q;
struct qbuf_metadata *metadata;
clock_time_t time = 0;
mac_callback_t sent;
void *cptr;
int num_tx;
int backoff_transmissions;
n = ptr;
if(n == NULL) {
return;
}
switch(status) {
case MAC_TX_OK:
case MAC_TX_NOACK:
@ -207,66 +212,72 @@ packet_sent(void *ptr, int status, int num_transmissions)
break;
}
sent = metadata->sent;
cptr = metadata->cptr;
num_tx = n->transmissions;
q = list_head(n->queued_packet_list);
if(q != NULL) {
metadata = (struct qbuf_metadata *)q->ptr;
if(status == MAC_TX_COLLISION ||
status == MAC_TX_NOACK) {
if(metadata != NULL) {
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
noack, we must retransmit the packet. */
switch(status) {
case MAC_TX_COLLISION:
PRINTF("csma: rexmit collision %d\n", n->transmissions);
break;
case MAC_TX_NOACK:
PRINTF("csma: rexmit noack %d\n", n->transmissions);
break;
default:
PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions);
/* If the transmission was not performed because of a
collision or noack, we must retransmit the packet. */
switch(status) {
case MAC_TX_COLLISION:
PRINTF("csma: rexmit collision %d\n", n->transmissions);
break;
case MAC_TX_NOACK:
PRINTF("csma: rexmit noack %d\n", n->transmissions);
break;
default:
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 neighbor_queue *n;
static uint16_t seqno;
const rimeaddr_t *addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
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) {
/* 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");
/* 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);
}
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

View file

@ -45,7 +45,7 @@ void
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",
sent, ptr, status, num_tx);
(void *)sent, ptr, status, num_tx);
switch(status) {
case MAC_TX_COLLISION:
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
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);
send_packet(sent, ptr);
buf_list = buf_list->next;
}
}
/*---------------------------------------------------------------------------*/

View file

@ -55,8 +55,11 @@ struct rimestats {
unsigned long lltx, llrx;
};
#if RIMESTATS_CONF_ENABLED
extern struct rimestats rimestats;
#define RIMESTATS_ADD(x) rimestats.x++
#else /* RIMESTATS_CONF_ENABLED */
#define RIMESTATS_ADD(x)
#endif /* RIMESTATS_CONF_ENABLED */
#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_slen = len;
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);
#if UIP_CONF_IPV6
tcpip_ipv6_output();