Added a safety measure against a problem where a node in rare situations would turn itself into a sink. Not entirely sure why this happens, but the safety measure should at least avoid the results of the problem. Added more debug messages.

This commit is contained in:
adamdunkels 2010-04-30 07:33:51 +00:00
parent 0859d4b95f
commit 3d10dedecf

View file

@ -33,7 +33,7 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* $Id: collect.c,v 1.46 2010/04/01 11:08:36 fros4943 Exp $ * $Id: collect.c,v 1.47 2010/04/30 07:33:51 adamdunkels Exp $
*/ */
/** /**
@ -85,7 +85,7 @@ struct ack_msg {
static struct recent_packet recent_packets[NUM_RECENT_PACKETS]; static struct recent_packet recent_packets[NUM_RECENT_PACKETS];
static uint8_t recent_packet_ptr; static uint8_t recent_packet_ptr;
#define MAX_MAC_REXMITS 2 #define MAX_MAC_REXMITS 3
#define MAX_ACK_MAC_REXMITS 3 #define MAX_ACK_MAC_REXMITS 3
#define REXMIT_TIME CLOCK_SECOND * 2 #define REXMIT_TIME CLOCK_SECOND * 2
#define FORWARD_PACKET_LIFETIME (6 * (REXMIT_TIME) << 3) #define FORWARD_PACKET_LIFETIME (6 * (REXMIT_TIME) << 3)
@ -95,7 +95,7 @@ PACKETQUEUE(sending_queue, MAX_SENDING_QUEUE);
#define SINK 0 #define SINK 0
#define RTMETRIC_MAX COLLECT_MAX_DEPTH #define RTMETRIC_MAX COLLECT_MAX_DEPTH
#define MAX_HOPLIM 10 #define MAX_HOPLIM 15
#ifndef COLLECT_CONF_ANNOUNCEMENTS #ifndef COLLECT_CONF_ANNOUNCEMENTS
#define COLLECT_ANNOUNCEMENTS 0 #define COLLECT_ANNOUNCEMENTS 0
@ -151,9 +151,12 @@ update_rtmetric(struct collect_conn *tc)
if(best != NULL && (n == NULL || if(best != NULL && (n == NULL ||
collect_neighbor_etx(best) < collect_neighbor_etx(best) <
collect_neighbor_etx(n) - COLLECT_NEIGHBOR_ETX_SCALE)) { collect_neighbor_etx(n) - COLLECT_NEIGHBOR_ETX_SCALE)) {
PRINTF("Switched parent from %d.%d to %d.%d\n",
tc->parent.u8[0], tc->parent.u8[1],
best->addr.u8[0], best->addr.u8[1]);
PRINTF("#L %d 0\n", tc->parent.u8[0]);
PRINTF("#L %d 1\n", best->addr.u8[0]);
rimeaddr_copy(&tc->parent, &best->addr); rimeaddr_copy(&tc->parent, &best->addr);
PRINTF("Switched parent to %d.%d\n",
tc->parent.u8[0], tc->parent.u8[1]);
} }
/* If n is NULL, we have no best neighbor. */ /* If n is NULL, we have no best neighbor. */
@ -181,6 +184,14 @@ update_rtmetric(struct collect_conn *tc)
uint16_t old_rtmetric = tc->rtmetric; uint16_t old_rtmetric = tc->rtmetric;
tc->rtmetric = n->rtmetric + collect_neighbor_etx(n); tc->rtmetric = n->rtmetric + collect_neighbor_etx(n);
if(tc->rtmetric == SINK) {
/* Something strange happened - ETX to this neighbors is zero! */
printf("Error: n->rtmetric %d, collect_neighbor_etx(n) %d\n",
n->rtmetric, collect_neighbor_etx(n));
/* Fix the problem by setting ETX to one. */
tc->rtmetric = COLLECT_NEIGHBOR_ETX_SCALE;
}
#if ! COLLECT_ANNOUNCEMENTS #if ! COLLECT_ANNOUNCEMENTS
@ -211,6 +222,7 @@ update_rtmetric(struct collect_conn *tc)
#if ! COLLECT_CONF_WITH_LISTEN #if ! COLLECT_CONF_WITH_LISTEN
/* We got a new, working, route we send any queued packets we may have. */ /* We got a new, working, route we send any queued packets we may have. */
if(old_rtmetric == RTMETRIC_MAX) { if(old_rtmetric == RTMETRIC_MAX) {
PRINTF("Sending queued packet because rtmetric was max\n");
send_queued_packet(); send_queued_packet();
} }
#endif /* COLLECT_CONF_WITH_LISTEN */ #endif /* COLLECT_CONF_WITH_LISTEN */
@ -240,9 +252,9 @@ send_queued_packet(void)
struct packetqueue_item *i; struct packetqueue_item *i;
struct collect_conn *c; struct collect_conn *c;
PRINTF("%d.%d: send_queued_packet queue len %d\n", // PRINTF("%d.%d: send_queued_packet queue len %d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], // rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
packetqueue_len(&sending_queue)); // packetqueue_len(&sending_queue));
i = packetqueue_first(&sending_queue); i = packetqueue_first(&sending_queue);
if(i == NULL) { if(i == NULL) {
@ -267,11 +279,11 @@ send_queued_packet(void)
return; return;
} }
/* We should send the first packet from the queue. */
q = packetqueue_queuebuf(i); q = packetqueue_queuebuf(i);
if(q != NULL) { if(q != NULL) {
// PRINTF("%d.%d: queue, q is on queue\n",
PRINTF("%d.%d: queue, q is on queue\n", // rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
/* Place the queued packet into the packetbuf. */ /* Place the queued packet into the packetbuf. */
queuebuf_to_packetbuf(q); queuebuf_to_packetbuf(q);
@ -286,14 +298,14 @@ send_queued_packet(void)
#if CONTIKI_TARGET_NETSIM #if CONTIKI_TARGET_NETSIM
ether_set_line(n->addr.u8[0], n->addr.u8[1]); ether_set_line(n->addr.u8[0], n->addr.u8[1]);
#endif /* CONTIKI_TARGET_NETSIM */ #endif /* CONTIKI_TARGET_NETSIM */
PRINTF("%d.%d: sending packet to %d.%d\n", PRINTF("%d.%d: sending packet to %d.%d with eseqno %d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
n->addr.u8[0], n->addr.u8[1]); n->addr.u8[0], n->addr.u8[1],
packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID));
c->sending = 1; c->sending = 1;
c->transmissions = 0; c->transmissions = 0;
c->max_rexmits = packetbuf_attr(PACKETBUF_ATTR_MAX_REXMIT); c->max_rexmits = packetbuf_attr(PACKETBUF_ATTR_MAX_REXMIT);
PRINTF("max_rexmits %d\n", c->max_rexmits);
packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1); packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1);
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, MAX_MAC_REXMITS); packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, MAX_MAC_REXMITS);
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, c->seqno); packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, c->seqno);
@ -304,7 +316,7 @@ send_queued_packet(void)
} }
time = REXMIT_TIME << rexmit_time_scaling; time = REXMIT_TIME << rexmit_time_scaling;
time = time / 2 + random_rand() % (time / 2); time = time / 2 + random_rand() % (time / 2);
PRINTF("retransmission time %lu\n", time); // PRINTF("retransmission time %lu\n", time);
ctimer_set(&c->retransmission_timer, time, ctimer_set(&c->retransmission_timer, time,
retransmit_callback, c); retransmit_callback, c);
} else { } else {
@ -335,6 +347,9 @@ send_next_packet(struct collect_conn *tc)
tc->sending = 0; tc->sending = 0;
tc->transmissions = 0; tc->transmissions = 0;
PRINTF("sending next packet, seqno %d, queue len %d\n",
tc->seqno, packetqueue_len(&sending_queue));
/* Send the next packet in the queue, if any. */ /* Send the next packet in the queue, if any. */
send_queued_packet(); send_queued_packet();
} }
@ -346,11 +361,15 @@ handle_ack(struct collect_conn *tc)
uint16_t rtmetric; uint16_t rtmetric;
struct collect_neighbor *n; struct collect_neighbor *n;
PRINTF("handle_ack: sender %d.%d parent %d.%d, id %d seqno %d\n",
packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[0],
packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[1],
tc->parent.u8[0], tc->parent.u8[1],
packetbuf_attr(PACKETBUF_ATTR_PACKET_ID), tc->seqno);
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER),
&tc->parent) && &tc->parent) &&
packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == tc->seqno) { packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == tc->seqno) {
msg = packetbuf_dataptr(); msg = packetbuf_dataptr();
memcpy(&rtmetric, &msg->rtmetric, sizeof(uint16_t)); memcpy(&rtmetric, &msg->rtmetric, sizeof(uint16_t));
n = collect_neighbor_find(packetbuf_addr(PACKETBUF_ADDR_SENDER)); n = collect_neighbor_find(packetbuf_addr(PACKETBUF_ADDR_SENDER));
@ -376,12 +395,13 @@ send_ack(struct collect_conn *tc, const rimeaddr_t *to, int congestion, int drop
{ {
struct ack_msg *ack; struct ack_msg *ack;
struct queuebuf *q; struct queuebuf *q;
uint16_t packet_seqno; uint16_t packet_seqno, packet_eseqno;
PRINTF("send_ack\n"); // PRINTF("send_ack\n");
packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
packet_eseqno = packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID);
q = queuebuf_new_from_packetbuf(); q = queuebuf_new_from_packetbuf();
if(q != NULL) { if(q != NULL) {
@ -403,11 +423,11 @@ send_ack(struct collect_conn *tc, const rimeaddr_t *to, int congestion, int drop
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, MAX_ACK_MAC_REXMITS); packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, MAX_ACK_MAC_REXMITS);
unicast_send(&tc->unicast_conn, to); unicast_send(&tc->unicast_conn, to);
PRINTF("%d.%d: collect: Sending ACK to %d.%d for %d\n", PRINTF("%d.%d: collect: Sending ACK to %d.%d for %d (epacket_id %d)\n",
rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1], rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
to->u8[0], to->u8[0],
to->u8[1], to->u8[1],
packet_seqno); packet_seqno, packet_eseqno);
RIMESTATS_ADD(acktx); RIMESTATS_ADD(acktx);
@ -590,8 +610,8 @@ node_packet_sent(struct unicast_conn *c, int status, int transmissions)
} }
#endif /* 0 */ #endif /* 0 */
/* Update ETX with the number of transmissions. */ /* Update ETX with the number of transmissions. */
PRINTF("Updating ETX with %d transmissions (punished %d)\n", tc->transmissions, // PRINTF("Updating ETX with %d transmissions (punished %d)\n", tc->transmissions,
tx); // tx);
collect_neighbor_update_etx(collect_neighbor_find(&tc->parent), tx); collect_neighbor_update_etx(collect_neighbor_find(&tc->parent), tx);
update_rtmetric(tc); update_rtmetric(tc);
} }
@ -698,6 +718,7 @@ collect_open(struct collect_conn *tc, uint16_t channels,
tc->rtmetric = RTMETRIC_MAX; tc->rtmetric = RTMETRIC_MAX;
tc->cb = cb; tc->cb = cb;
tc->is_router = is_router; tc->is_router = is_router;
tc->seqno = 10;
collect_neighbor_init(); collect_neighbor_init();
packetqueue_init(&sending_queue); packetqueue_init(&sending_queue);
@ -765,8 +786,7 @@ collect_send(struct collect_conn *tc, int rexmits)
packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID), packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID),
packetbuf_attr(PACKETBUF_ATTR_MAX_REXMIT)); packetbuf_attr(PACKETBUF_ATTR_MAX_REXMIT));
// PRINTF("rexmit %d\n", rexmits);
PRINTF("rexmit %d\n", rexmits);
if(tc->rtmetric == SINK) { if(tc->rtmetric == SINK) {
packetbuf_set_attr(PACKETBUF_ATTR_HOPS, 0); packetbuf_set_attr(PACKETBUF_ATTR_HOPS, 0);
@ -777,7 +797,7 @@ collect_send(struct collect_conn *tc, int rexmits)
} }
return 1; return 1;
} else { } else {
update_rtmetric(tc); // update_rtmetric(tc);
n = collect_neighbor_best(); n = collect_neighbor_best();
if(n != NULL) { if(n != NULL) {
#if CONTIKI_TARGET_NETSIM #if CONTIKI_TARGET_NETSIM
@ -786,6 +806,7 @@ collect_send(struct collect_conn *tc, int rexmits)
PRINTF("%d.%d: sending to %d.%d\n", PRINTF("%d.%d: sending to %d.%d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
n->addr.u8[0], n->addr.u8[1]); n->addr.u8[0], n->addr.u8[1]);
if(packetqueue_enqueue_packetbuf(&sending_queue, FORWARD_PACKET_LIFETIME, if(packetqueue_enqueue_packetbuf(&sending_queue, FORWARD_PACKET_LIFETIME,
tc)) { tc)) {
send_queued_packet(); send_queued_packet();
@ -794,6 +815,7 @@ collect_send(struct collect_conn *tc, int rexmits)
PRINTF("%d.%d: drop originated packet: no queuebuf\n", PRINTF("%d.%d: drop originated packet: no queuebuf\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
} }
} else { } else {
PRINTF("%d.%d: did not find any neighbor to send to\n", PRINTF("%d.%d: did not find any neighbor to send to\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
@ -804,7 +826,6 @@ collect_send(struct collect_conn *tc, int rexmits)
ctimer_set(&tc->transmit_after_scan_timer, ANNOUNCEMENT_SCAN_TIME, ctimer_set(&tc->transmit_after_scan_timer, ANNOUNCEMENT_SCAN_TIME,
send_queued_packet, NULL); send_queued_packet, NULL);
#else /* COLLECT_CONF_WITH_LISTEN */ #else /* COLLECT_CONF_WITH_LISTEN */
PRINTF("bump neighbor value\n");
announcement_set_value(&tc->announcement, RTMETRIC_MAX); announcement_set_value(&tc->announcement, RTMETRIC_MAX);
announcement_bump(&tc->announcement); announcement_bump(&tc->announcement);
#endif /* COLLECT_CONF_WITH_LISTEN */ #endif /* COLLECT_CONF_WITH_LISTEN */
@ -833,6 +854,8 @@ collect_purge(struct collect_conn *tc)
{ {
collect_neighbor_purge(); collect_neighbor_purge();
update_rtmetric(tc); update_rtmetric(tc);
PRINTF("#L %d 0\n", tc->parent.u8[0]);
rimeaddr_copy(&tc->parent, &rimeaddr_null);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** @} */ /** @} */