Several bugfixes to the proactive link estimate maintenance code, which is now enabled by default. Simplified DRAW_TREE code for drawing routing graph in Cooja. Added routing metric penalty to parents that are congested or that drop packets.
This commit is contained in:
parent
212e73faa6
commit
65d640ac53
1 changed files with 78 additions and 39 deletions
|
@ -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.55 2010/10/03 20:08:44 adamdunkels Exp $
|
* $Id: collect.c,v 1.56 2010/10/04 20:27:50 adamdunkels Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,7 +127,7 @@ struct ack_msg {
|
||||||
#define MAX_MAC_REXMITS 2
|
#define MAX_MAC_REXMITS 2
|
||||||
#define MAX_ACK_MAC_REXMITS 3
|
#define MAX_ACK_MAC_REXMITS 3
|
||||||
#define REXMIT_TIME CLOCK_SECOND * 1
|
#define REXMIT_TIME CLOCK_SECOND * 1
|
||||||
#define FORWARD_PACKET_LIFETIME (60 * (REXMIT_TIME) << 3)
|
#define FORWARD_PACKET_LIFETIME (8 * (REXMIT_TIME) << 3)
|
||||||
#define MAX_SENDING_QUEUE 16
|
#define MAX_SENDING_QUEUE 16
|
||||||
#define KEEPALIVE_REXMITS 8
|
#define KEEPALIVE_REXMITS 8
|
||||||
|
|
||||||
|
@ -156,8 +156,7 @@ MEMB(send_queue_memb, struct packetqueue_item, MAX_SENDING_QUEUE);
|
||||||
queue, the system periodically sends a dummy packet to potential
|
queue, the system periodically sends a dummy packet to potential
|
||||||
parents, i.e., neighbors with a lower rtmetric than we have but for
|
parents, i.e., neighbors with a lower rtmetric than we have but for
|
||||||
which we do not yet have a link quality estimate. */
|
which we do not yet have a link quality estimate. */
|
||||||
#define WITH_PROACTIVE_MAINTENANCE 0
|
#define PROACTIVE_MAINTENANCE_INTERVAL CLOCK_SECOND * 60
|
||||||
#define PROACTIVE_MAINTENANCE_INTERVAL CLOCK_SECOND * 60 * 4
|
|
||||||
#define PROACTIVE_MAINTENANCE_REXMITS 8
|
#define PROACTIVE_MAINTENANCE_REXMITS 8
|
||||||
|
|
||||||
/* COLLECT_CONF_ANNOUNCEMENTS defines if the Collect implementation
|
/* COLLECT_CONF_ANNOUNCEMENTS defines if the Collect implementation
|
||||||
|
@ -201,7 +200,7 @@ struct {
|
||||||
} stats;
|
} stats;
|
||||||
|
|
||||||
/* Debug definition: draw routing tree in Cooja. */
|
/* Debug definition: draw routing tree in Cooja. */
|
||||||
#define DRAW_TREE 0
|
#define DRAW_TREE 1
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -289,6 +288,12 @@ update_parent(struct collect_conn *tc)
|
||||||
by Gnawali et al (SenSys 2009). */
|
by Gnawali et al (SenSys 2009). */
|
||||||
|
|
||||||
if(best != NULL) {
|
if(best != NULL) {
|
||||||
|
rimeaddr_t previous_parent;
|
||||||
|
|
||||||
|
if(DRAW_TREE) {
|
||||||
|
rimeaddr_copy(&previous_parent, &tc->parent);
|
||||||
|
}
|
||||||
|
|
||||||
if(current == NULL) {
|
if(current == NULL) {
|
||||||
/* New parent. */
|
/* New parent. */
|
||||||
PRINTF("update_parent: new parent %d.%d\n",
|
PRINTF("update_parent: new parent %d.%d\n",
|
||||||
|
@ -296,9 +301,6 @@ update_parent(struct collect_conn *tc)
|
||||||
rimeaddr_copy(&tc->parent, &best->addr);
|
rimeaddr_copy(&tc->parent, &best->addr);
|
||||||
stats.foundroute++;
|
stats.foundroute++;
|
||||||
} else {
|
} else {
|
||||||
#if DRAW_TREE
|
|
||||||
printf("#L %d 0\n", tc->parent.u8[0]);
|
|
||||||
#endif /* DRAW_TREE */
|
|
||||||
if(collect_neighbor_rtmetric_link_estimate(best) +
|
if(collect_neighbor_rtmetric_link_estimate(best) +
|
||||||
SIGNIFICANT_RTMETRIC_PARENT_CHANGE <
|
SIGNIFICANT_RTMETRIC_PARENT_CHANGE <
|
||||||
collect_neighbor_rtmetric_link_estimate(current)) {
|
collect_neighbor_rtmetric_link_estimate(current)) {
|
||||||
|
@ -312,15 +314,20 @@ update_parent(struct collect_conn *tc)
|
||||||
stats.newparent++;
|
stats.newparent++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if DRAW_TREE
|
if(DRAW_TREE) {
|
||||||
|
if(!rimeaddr_cmp(&previous_parent, &tc->parent)) {
|
||||||
|
if(!rimeaddr_cmp(&previous_parent, &rimeaddr_null)) {
|
||||||
|
printf("#L %d 0\n", previous_parent.u8[0]);
|
||||||
|
}
|
||||||
printf("#L %d 1\n", tc->parent.u8[0]);
|
printf("#L %d 1\n", tc->parent.u8[0]);
|
||||||
#endif /* DRAW_TREE */
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* No parent. */
|
/* No parent. */
|
||||||
if(!rimeaddr_cmp(&tc->parent, &rimeaddr_null)) {
|
if(!rimeaddr_cmp(&tc->parent, &rimeaddr_null)) {
|
||||||
#if DRAW_TREE
|
if(DRAW_TREE) {
|
||||||
printf("#L %d 0\n", tc->parent.u8[0]);
|
printf("#L %d 0\n", tc->parent.u8[0]);
|
||||||
#endif /* DRAW_TREE */
|
}
|
||||||
stats.routelost++;
|
stats.routelost++;
|
||||||
}
|
}
|
||||||
rimeaddr_copy(&tc->parent, &rimeaddr_null);
|
rimeaddr_copy(&tc->parent, &rimeaddr_null);
|
||||||
|
@ -411,11 +418,13 @@ update_rtmetric(struct collect_conn *tc)
|
||||||
PRINTF("Sending queued packet because rtmetric was max\n");
|
PRINTF("Sending queued packet because rtmetric was max\n");
|
||||||
send_queued_packet(tc);
|
send_queued_packet(tc);
|
||||||
}
|
}
|
||||||
|
if(DRAW_TREE) {
|
||||||
|
if(old_rtmetric != new_rtmetric) {
|
||||||
|
printf("#A rt=%d,p=%d\n", tc->rtmetric, tc->parent.u8[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DRAW_TREE
|
|
||||||
printf("#A rt=%d,p=%d\n", tc->rtmetric, tc->parent.u8[0]);
|
|
||||||
#endif /* DRAW_TREE */
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
|
@ -425,7 +434,6 @@ enqueue_dummy_packet(struct collect_conn *c, int rexmits)
|
||||||
|
|
||||||
packetbuf_clear();
|
packetbuf_clear();
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_EPACKET_ID, c->eseqno - 1);
|
packetbuf_set_attr(PACKETBUF_ATTR_EPACKET_ID, c->eseqno - 1);
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, c->seqno - 1);
|
|
||||||
packetbuf_set_addr(PACKETBUF_ADDR_ESENDER, &rimeaddr_node_addr);
|
packetbuf_set_addr(PACKETBUF_ADDR_ESENDER, &rimeaddr_node_addr);
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_HOPS, 1);
|
packetbuf_set_attr(PACKETBUF_ATTR_HOPS, 1);
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_TTL, 1);
|
packetbuf_set_attr(PACKETBUF_ATTR_TTL, 1);
|
||||||
|
@ -485,19 +493,20 @@ send_queued_packet(struct collect_conn *c)
|
||||||
estimate and send a dummy packet to it. This allows us to
|
estimate and send a dummy packet to it. This allows us to
|
||||||
quickly gauge the link quality of neighbors that we do not
|
quickly gauge the link quality of neighbors that we do not
|
||||||
currently use as parents. */
|
currently use as parents. */
|
||||||
if(WITH_PROACTIVE_MAINTENANCE && timer_expired(&c->proactive_maintenence_timer)) {
|
if(timer_expired(&c->proactive_maintenence_timer)) {
|
||||||
struct collect_neighbor *n;
|
struct collect_neighbor *n;
|
||||||
|
|
||||||
timer_set(&c->proactive_maintenence_timer,
|
timer_set(&c->proactive_maintenence_timer,
|
||||||
PROACTIVE_MAINTENANCE_INTERVAL);
|
PROACTIVE_MAINTENANCE_INTERVAL);
|
||||||
|
|
||||||
|
/* Find the neighbor with the lowest number of estimates. */
|
||||||
for(n = list_head(collect_neighbor_list(&c->neighbor_list));
|
for(n = list_head(collect_neighbor_list(&c->neighbor_list));
|
||||||
n != NULL; n = list_item_next(n)) {
|
n != NULL; n = list_item_next(n)) {
|
||||||
if(n->rtmetric + COLLECT_LINK_ESTIMATE_UNIT < c->rtmetric &&
|
if(n->rtmetric + COLLECT_LINK_ESTIMATE_UNIT < c->rtmetric &&
|
||||||
collect_link_estimate_num_estimates(&n->le) == 0) {
|
collect_link_estimate_num_estimates(&n->le) == 0) {
|
||||||
rimeaddr_t current_parent;
|
rimeaddr_t current_parent;
|
||||||
|
|
||||||
printf("proactive maintenance: found neighbor with no link estimate, %d.%d\n",
|
PRINTF("proactive maintenance: found neighbor with no link estimate, %d.%d\n",
|
||||||
n->addr.u8[0], n->addr.u8[1]);
|
n->addr.u8[0], n->addr.u8[1]);
|
||||||
|
|
||||||
rimeaddr_copy(¤t_parent, &c->parent);
|
rimeaddr_copy(¤t_parent, &c->parent);
|
||||||
|
@ -506,7 +515,7 @@ send_queued_packet(struct collect_conn *c)
|
||||||
send_queued_packet(c);
|
send_queued_packet(c);
|
||||||
}
|
}
|
||||||
rimeaddr_copy(&c->parent, ¤t_parent);
|
rimeaddr_copy(&c->parent, ¤t_parent);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -632,7 +641,7 @@ retransmit_current_packet(struct collect_conn *c)
|
||||||
collect_neighbor_tx(current_neighbor, c->max_rexmits);
|
collect_neighbor_tx(current_neighbor, c->max_rexmits);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
printf("parent change from %d.%d to %d.%d after %d tx\n",
|
PRINTF("parent change from %d.%d to %d.%d after %d tx\n",
|
||||||
c->current_parent.u8[0], c->current_parent.u8[1],
|
c->current_parent.u8[0], c->current_parent.u8[1],
|
||||||
c->parent.u8[0], c->parent.u8[1],
|
c->parent.u8[0], c->parent.u8[1],
|
||||||
c->transmissions);
|
c->transmissions);
|
||||||
|
@ -741,10 +750,33 @@ handle_ack(struct collect_conn *tc)
|
||||||
msg->flags,
|
msg->flags,
|
||||||
rtmetric);
|
rtmetric);
|
||||||
|
|
||||||
|
/* The ack contains information about the state of the packet and
|
||||||
|
of the node that received it. We do different things depending
|
||||||
|
on whether or not the packet was dropped. First, we check if
|
||||||
|
the receiving node was congested. If so, we add a maximum
|
||||||
|
transmission number to its routing metric, which increases the
|
||||||
|
chance that another parent will be chosen. */
|
||||||
|
if(msg->flags & ACK_FLAGS_CONGESTED) {
|
||||||
|
collect_neighbor_tx(n, tc->max_rexmits);
|
||||||
|
update_rtmetric(tc);
|
||||||
|
}
|
||||||
if(!(msg->flags & ACK_FLAGS_DROPPED)) {
|
if(!(msg->flags & ACK_FLAGS_DROPPED)) {
|
||||||
|
/* If the packet was successfully received, we send the next packet. */
|
||||||
send_next_packet(tc);
|
send_next_packet(tc);
|
||||||
} else {
|
} else {
|
||||||
PRINTF("ack drop flag\n");
|
/* If the packet was lost due to its lifetime being exceeded,
|
||||||
|
there is not much more we can do with the packet, so we send
|
||||||
|
the next one instead. */
|
||||||
|
if((msg->flags & ACK_FLAGS_LIFETIME_EXCEEDED)) {
|
||||||
|
send_next_packet(tc);
|
||||||
|
} else {
|
||||||
|
/* If the packet was dropped, but without the node being
|
||||||
|
congested or the packets lifetime being exceeded, we
|
||||||
|
penalize the parent and try sending the packet again. */
|
||||||
|
collect_neighbor_tx(n, tc->max_rexmits);
|
||||||
|
update_rtmetric(tc);
|
||||||
|
send_queued_packet(tc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(msg->flags & ACK_FLAGS_RTMETRIC_NEEDS_UPDATE) {
|
if(msg->flags & ACK_FLAGS_RTMETRIC_NEEDS_UPDATE) {
|
||||||
bump_advertisement(tc);
|
bump_advertisement(tc);
|
||||||
|
@ -843,15 +875,18 @@ node_packet_received(struct unicast_conn *c, const rimeaddr_t *from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remember that we have seen this packet for later. */
|
/* Remember that we have seen this packet for later, but only if
|
||||||
|
it has a length that is larger than zero. Packets with size
|
||||||
|
zero are keepalive or proactive link estimate probes, so we do
|
||||||
|
not record them in our history. */
|
||||||
|
if(packetbuf_datalen() > sizeof(struct data_msg_hdr)) {
|
||||||
recent_packets[recent_packet_ptr].eseqno =
|
recent_packets[recent_packet_ptr].eseqno =
|
||||||
packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID);
|
packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID);
|
||||||
rimeaddr_copy(&recent_packets[recent_packet_ptr].originator,
|
rimeaddr_copy(&recent_packets[recent_packet_ptr].originator,
|
||||||
packetbuf_addr(PACKETBUF_ADDR_ESENDER));
|
packetbuf_addr(PACKETBUF_ADDR_ESENDER));
|
||||||
recent_packets[recent_packet_ptr].conn = tc;
|
recent_packets[recent_packet_ptr].conn = tc;
|
||||||
|
|
||||||
recent_packet_ptr = (recent_packet_ptr + 1) % NUM_RECENT_PACKETS;
|
recent_packet_ptr = (recent_packet_ptr + 1) % NUM_RECENT_PACKETS;
|
||||||
|
}
|
||||||
/* If we are the sink, the packet has reached its final
|
/* If we are the sink, the packet has reached its final
|
||||||
destination and we call the receive function. */
|
destination and we call the receive function. */
|
||||||
if(tc->rtmetric == RTMETRIC_SINK) {
|
if(tc->rtmetric == RTMETRIC_SINK) {
|
||||||
|
@ -928,7 +963,7 @@ node_packet_received(struct unicast_conn *c, const rimeaddr_t *from)
|
||||||
} else {
|
} else {
|
||||||
send_ack(tc, &ack_to,
|
send_ack(tc, &ack_to,
|
||||||
ackflags | ACK_FLAGS_DROPPED | ACK_FLAGS_CONGESTED);
|
ackflags | ACK_FLAGS_DROPPED | ACK_FLAGS_CONGESTED);
|
||||||
printf("%d.%d: packet dropped: no queue buffer available\n",
|
PRINTF("%d.%d: packet dropped: no queue buffer available\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
||||||
stats.qdrop++;
|
stats.qdrop++;
|
||||||
}
|
}
|
||||||
|
@ -994,7 +1029,7 @@ static void
|
||||||
timedout(struct collect_conn *tc)
|
timedout(struct collect_conn *tc)
|
||||||
{
|
{
|
||||||
struct collect_neighbor *n;
|
struct collect_neighbor *n;
|
||||||
printf("%d.%d: timedout after %d retransmissions to %d.%d (max retransmissions %d): packet dropped\n",
|
PRINTF("%d.%d: timedout after %d retransmissions to %d.%d (max retransmissions %d): packet dropped\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], tc->transmissions,
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], tc->transmissions,
|
||||||
tc->current_parent.u8[0], tc->current_parent.u8[1],
|
tc->current_parent.u8[0], tc->current_parent.u8[1],
|
||||||
tc->max_rexmits);
|
tc->max_rexmits);
|
||||||
|
@ -1229,6 +1264,10 @@ collect_set_sink(struct collect_conn *tc, int should_be_sink)
|
||||||
update_rtmetric(tc);
|
update_rtmetric(tc);
|
||||||
|
|
||||||
bump_advertisement(tc);
|
bump_advertisement(tc);
|
||||||
|
|
||||||
|
if(DRAW_TREE) {
|
||||||
|
printf("#A rt=0,p=0\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
int
|
int
|
||||||
|
@ -1286,7 +1325,7 @@ collect_send(struct collect_conn *tc, int rexmits)
|
||||||
send_queued_packet(tc);
|
send_queued_packet(tc);
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1310,7 +1349,7 @@ collect_send(struct collect_conn *tc, int rexmits)
|
||||||
tc)) {
|
tc)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1330,9 +1369,9 @@ collect_purge(struct collect_conn *tc)
|
||||||
collect_neighbor_list_purge(&tc->neighbor_list);
|
collect_neighbor_list_purge(&tc->neighbor_list);
|
||||||
rimeaddr_copy(&tc->parent, &rimeaddr_null);
|
rimeaddr_copy(&tc->parent, &rimeaddr_null);
|
||||||
update_rtmetric(tc);
|
update_rtmetric(tc);
|
||||||
#if DRAW_TREE
|
if(DRAW_TREE) {
|
||||||
printf("#L %d 0\n", tc->parent.u8[0]);
|
printf("#L %d 0\n", tc->parent.u8[0]);
|
||||||
#endif /* DRAW_TREE */
|
}
|
||||||
rimeaddr_copy(&tc->parent, &rimeaddr_null);
|
rimeaddr_copy(&tc->parent, &rimeaddr_null);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
Loading…
Reference in a new issue