A number of changes to the collect code:
* Added an optional "keep alive" mechanism whereby an idle network is periodically probed by dummy packets to maintain a recent quality metric when there is no traffic. * Bugfix in when new routing metrics should be advertised * Rewrote the ACK logic so that a queuebuf is not allocated for each ack, only for those acks generated by the sink node. * Updated the wrap-around logic for sequence numbers: when a sequence number wraps, it won't go back to 0. Instead, it wraps to 128. This allows us to understand when a node has rebooted: when its seqno is < 128, it has recently rebooted.
This commit is contained in:
parent
2cae71e89b
commit
eed22a6f3c
2 changed files with 170 additions and 56 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.52 2010/09/14 06:48:36 adamdunkels Exp $
|
* $Id: collect.c,v 1.53 2010/09/22 22:08:08 adamdunkels Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,6 +129,8 @@ struct ack_msg {
|
||||||
#define REXMIT_TIME CLOCK_SECOND * 1
|
#define REXMIT_TIME CLOCK_SECOND * 1
|
||||||
#define FORWARD_PACKET_LIFETIME (6 * (REXMIT_TIME) << 3)
|
#define FORWARD_PACKET_LIFETIME (6 * (REXMIT_TIME) << 3)
|
||||||
#define MAX_SENDING_QUEUE 16
|
#define MAX_SENDING_QUEUE 16
|
||||||
|
#define KEEPALIVE_REXMITS 4
|
||||||
|
|
||||||
MEMB(send_queue_memb, struct packetqueue_item, MAX_SENDING_QUEUE);
|
MEMB(send_queue_memb, struct packetqueue_item, MAX_SENDING_QUEUE);
|
||||||
|
|
||||||
/* These specifiy the sink's routing metric (0) and the maximum
|
/* These specifiy the sink's routing metric (0) and the maximum
|
||||||
|
@ -204,6 +206,8 @@ struct {
|
||||||
/* Forward declarations. */
|
/* Forward declarations. */
|
||||||
static void send_queued_packet(struct collect_conn *c);
|
static void send_queued_packet(struct collect_conn *c);
|
||||||
static void retransmit_callback(void *ptr);
|
static void retransmit_callback(void *ptr);
|
||||||
|
static void set_keepalive_timer(struct collect_conn *c);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* This function computes the current rtmetric by adding the last
|
* This function computes the current rtmetric by adding the last
|
||||||
|
@ -233,7 +237,7 @@ rtmetric_compute(struct collect_conn *tc)
|
||||||
} else {
|
} else {
|
||||||
/* Our rtmetric is the rtmetric of our parent neighbor plus
|
/* Our rtmetric is the rtmetric of our parent neighbor plus
|
||||||
the expected transmissions to reach that neighbor. */
|
the expected transmissions to reach that neighbor. */
|
||||||
rtmetric = collect_neighbor_rtmetric(n);
|
rtmetric = collect_neighbor_rtmetric_link_estimate(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rtmetric;
|
return rtmetric;
|
||||||
|
@ -287,8 +291,8 @@ update_parent(struct collect_conn *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 */
|
#endif /* DRAW_TREE */
|
||||||
if(collect_neighbor_rtmetric(best) + SIGNIFICANT_RTMETRIC_CHANGE <
|
if(collect_neighbor_rtmetric_link_estimate(best) + SIGNIFICANT_RTMETRIC_CHANGE <
|
||||||
collect_neighbor_rtmetric(current)) {
|
collect_neighbor_rtmetric_link_estimate(current)) {
|
||||||
/* We switch parent. */
|
/* We switch parent. */
|
||||||
PRINTF("update_parent: new parent %d.%d (%d) old parent %d.%d (%d)\n",
|
PRINTF("update_parent: new parent %d.%d (%d) old parent %d.%d (%d)\n",
|
||||||
best->addr.u8[0], best->addr.u8[1],
|
best->addr.u8[0], best->addr.u8[1],
|
||||||
|
@ -381,7 +385,7 @@ update_rtmetric(struct collect_conn *tc)
|
||||||
/* If we now have a significantly better or worse rtmetric than
|
/* If we now have a significantly better or worse rtmetric than
|
||||||
we had before, what we need to make sure that our neighbors
|
we had before, what we need to make sure that our neighbors
|
||||||
find out about this quickly. */
|
find out about this quickly. */
|
||||||
if(new_rtmetric + SIGNIFICANT_RTMETRIC_CHANGE < old_rtmetric &&
|
if(new_rtmetric < old_rtmetric - SIGNIFICANT_RTMETRIC_CHANGE ||
|
||||||
new_rtmetric > old_rtmetric + SIGNIFICANT_RTMETRIC_CHANGE) {
|
new_rtmetric > old_rtmetric + SIGNIFICANT_RTMETRIC_CHANGE) {
|
||||||
PRINTF("update_rtmetric: new_rtmetric %d + %d < old_rtmetric %d\n",
|
PRINTF("update_rtmetric: new_rtmetric %d + %d < old_rtmetric %d\n",
|
||||||
new_rtmetric, SIGNIFICANT_RTMETRIC_CHANGE, old_rtmetric);
|
new_rtmetric, SIGNIFICANT_RTMETRIC_CHANGE, old_rtmetric);
|
||||||
|
@ -464,7 +468,7 @@ send_queued_packet(struct collect_conn *c)
|
||||||
|
|
||||||
/* Remember the parent that we sent this packet to. */
|
/* Remember the parent that we sent this packet to. */
|
||||||
rimeaddr_copy(&c->current_parent, &c->parent);
|
rimeaddr_copy(&c->current_parent, &c->parent);
|
||||||
|
|
||||||
/* This is the first time we transmit this packet, so set
|
/* This is the first time we transmit this packet, so set
|
||||||
transmissions to zero. */
|
transmissions to zero. */
|
||||||
c->transmissions = 0;
|
c->transmissions = 0;
|
||||||
|
@ -502,7 +506,7 @@ send_queued_packet(struct collect_conn *c)
|
||||||
PRINTF("listen\n");
|
PRINTF("listen\n");
|
||||||
announcement_listen(1);
|
announcement_listen(1);
|
||||||
ctimer_set(&c->transmit_after_scan_timer, ANNOUNCEMENT_SCAN_TIME,
|
ctimer_set(&c->transmit_after_scan_timer, ANNOUNCEMENT_SCAN_TIME,
|
||||||
send_queued_packet, tc);
|
send_queued_packet, c);
|
||||||
#else /* COLLECT_CONF_WITH_LISTEN */
|
#else /* COLLECT_CONF_WITH_LISTEN */
|
||||||
announcement_set_value(&c->announcement, RTMETRIC_MAX);
|
announcement_set_value(&c->announcement, RTMETRIC_MAX);
|
||||||
announcement_bump(&c->announcement);
|
announcement_bump(&c->announcement);
|
||||||
|
@ -631,13 +635,13 @@ handle_ack(struct collect_conn *tc)
|
||||||
tc->transmissions);
|
tc->transmissions);
|
||||||
n = collect_neighbor_list_find(&tc->neighbor_list,
|
n = collect_neighbor_list_find(&tc->neighbor_list,
|
||||||
packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||||
collect_neighbor_tx(n, tc->transmissions);
|
|
||||||
|
|
||||||
if(n != NULL) {
|
if(n != NULL) {
|
||||||
|
collect_neighbor_tx(n, tc->transmissions);
|
||||||
collect_neighbor_update_rtmetric(n, rtmetric);
|
collect_neighbor_update_rtmetric(n, rtmetric);
|
||||||
update_rtmetric(tc);
|
update_rtmetric(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINTF("%d.%d: ACK from %d.%d after %d transmissions, flags %02x, rtmetric %d\n",
|
PRINTF("%d.%d: ACK from %d.%d after %d transmissions, flags %02x, rtmetric %d\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
tc->current_parent.u8[0], tc->current_parent.u8[1],
|
tc->current_parent.u8[0], tc->current_parent.u8[1],
|
||||||
|
@ -651,6 +655,7 @@ handle_ack(struct collect_conn *tc)
|
||||||
if(msg->flags & ACK_FLAGS_RTMETRIC_NEEDS_UPDATE) {
|
if(msg->flags & ACK_FLAGS_RTMETRIC_NEEDS_UPDATE) {
|
||||||
bump_advertisement(tc);
|
bump_advertisement(tc);
|
||||||
}
|
}
|
||||||
|
set_keepalive_timer(tc);
|
||||||
} else {
|
} else {
|
||||||
stats.badack++;
|
stats.badack++;
|
||||||
}
|
}
|
||||||
|
@ -660,48 +665,32 @@ static void
|
||||||
send_ack(struct collect_conn *tc, const rimeaddr_t *to, int flags)
|
send_ack(struct collect_conn *tc, const rimeaddr_t *to, int flags)
|
||||||
{
|
{
|
||||||
struct ack_msg *ack;
|
struct ack_msg *ack;
|
||||||
struct queuebuf *q;
|
uint16_t packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
|
||||||
uint16_t packet_seqno, packet_eseqno;
|
uint16_t packet_eseqno = packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID);
|
||||||
|
|
||||||
|
packetbuf_clear();
|
||||||
|
packetbuf_set_datalen(sizeof(struct ack_msg));
|
||||||
|
ack = packetbuf_dataptr();
|
||||||
|
memset(ack, 0, sizeof(struct ack_msg));
|
||||||
|
ack->rtmetric = tc->rtmetric;
|
||||||
|
ack->flags = flags;
|
||||||
|
|
||||||
packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
|
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, to);
|
||||||
packet_eseqno = packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID);
|
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_ACK);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 0);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_ERELIABLE, 0);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, packet_seqno);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, MAX_ACK_MAC_REXMITS);
|
||||||
|
unicast_send(&tc->unicast_conn, to);
|
||||||
|
|
||||||
q = queuebuf_new_from_packetbuf();
|
PRINTF("%d.%d: collect: Sending ACK to %d.%d for %d (epacket_id %d)\n",
|
||||||
if(q != NULL) {
|
rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
|
||||||
|
to->u8[0],
|
||||||
|
to->u8[1],
|
||||||
|
packet_seqno, packet_eseqno);
|
||||||
|
|
||||||
packetbuf_clear();
|
RIMESTATS_ADD(acktx);
|
||||||
packetbuf_set_datalen(sizeof(struct ack_msg));
|
stats.acksent++;
|
||||||
ack = packetbuf_dataptr();
|
|
||||||
memset(ack, 0, sizeof(struct ack_msg));
|
|
||||||
ack->rtmetric = tc->rtmetric;
|
|
||||||
ack->flags = flags;
|
|
||||||
|
|
||||||
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, to);
|
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_ACK);
|
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 0);
|
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_ERELIABLE, 0);
|
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, packet_seqno);
|
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, MAX_ACK_MAC_REXMITS);
|
|
||||||
unicast_send(&tc->unicast_conn, to);
|
|
||||||
|
|
||||||
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],
|
|
||||||
to->u8[0],
|
|
||||||
to->u8[1],
|
|
||||||
packet_seqno, packet_eseqno);
|
|
||||||
|
|
||||||
RIMESTATS_ADD(acktx);
|
|
||||||
|
|
||||||
queuebuf_to_packetbuf(q);
|
|
||||||
queuebuf_free(q);
|
|
||||||
stats.acksent++;
|
|
||||||
} else {
|
|
||||||
PRINTF("%d.%d: collect: could not send ACK to %d.%d for %d: no queued buffers\n",
|
|
||||||
rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
|
|
||||||
to->u8[0], to->u8[1],
|
|
||||||
packet_seqno);
|
|
||||||
stats.ackdrop++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
@ -774,9 +763,23 @@ node_packet_received(struct unicast_conn *c, const rimeaddr_t *from)
|
||||||
/* 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) {
|
||||||
|
struct queuebuf *q;
|
||||||
|
|
||||||
|
/* We first send the ACK. We copy the data packet to a queuebuf
|
||||||
|
first. */
|
||||||
|
q = queuebuf_new_from_packetbuf();
|
||||||
|
if(q != NULL) {
|
||||||
|
send_ack(tc, &ack_to, 0);
|
||||||
|
queuebuf_to_packetbuf(q);
|
||||||
|
queuebuf_free(q);
|
||||||
|
} else {
|
||||||
|
PRINTF("%d.%d: collect: could not send ACK to %d.%d for %d: no queued buffers\n",
|
||||||
|
rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
|
||||||
|
ack_to.u8[0], ack_to.u8[1],
|
||||||
|
packet_seqno);
|
||||||
|
stats.ackdrop++;
|
||||||
|
}
|
||||||
|
|
||||||
/* We first send the ACK. */
|
|
||||||
send_ack(tc, &ack_to, 0);
|
|
||||||
|
|
||||||
PRINTF("%d.%d: sink received packet %d from %d.%d via %d.%d\n",
|
PRINTF("%d.%d: sink received packet %d from %d.%d via %d.%d\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
@ -831,7 +834,8 @@ node_packet_received(struct unicast_conn *c, const rimeaddr_t *from)
|
||||||
send_ack(tc, &ack_to, ackflags);
|
send_ack(tc, &ack_to, ackflags);
|
||||||
send_queued_packet(tc);
|
send_queued_packet(tc);
|
||||||
} else {
|
} else {
|
||||||
send_ack(tc, &ack_to, ackflags | ACK_FLAGS_DROPPED | ACK_FLAGS_CONGESTED);
|
send_ack(tc, &ack_to,
|
||||||
|
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++;
|
||||||
|
@ -906,8 +910,8 @@ timedout(struct collect_conn *tc)
|
||||||
&tc->current_parent),
|
&tc->current_parent),
|
||||||
tc->max_rexmits);
|
tc->max_rexmits);
|
||||||
update_rtmetric(tc);
|
update_rtmetric(tc);
|
||||||
|
|
||||||
send_next_packet(tc);
|
send_next_packet(tc);
|
||||||
|
set_keepalive_timer(tc);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
@ -938,7 +942,22 @@ adv_received(struct neighbor_discovery_conn *c, const rimeaddr_t *from,
|
||||||
|
|
||||||
if(n == NULL) {
|
if(n == NULL) {
|
||||||
collect_neighbor_list_add(&tc->neighbor_list, from, rtmetric);
|
collect_neighbor_list_add(&tc->neighbor_list, from, rtmetric);
|
||||||
|
if(rtmetric == RTMETRIC_MAX) {
|
||||||
|
bump_advertisement(tc);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
/* Check if the advertised rtmetric has changed to
|
||||||
|
RTMETRIC_MAX. This may indicate that the neighbor has lost its
|
||||||
|
routes or that it has rebooted. In either case, we bump our
|
||||||
|
advertisement rate to allow our neighbor to receive a new
|
||||||
|
rtmetric from us. If our neighbor already happens to have an
|
||||||
|
rtmetric of RTMETRIC_MAX recorded, it may mean that our
|
||||||
|
neighbor does not hear our advertisements. If this is the case,
|
||||||
|
we should not bump our advertisement rate. */
|
||||||
|
if(rtmetric == RTMETRIC_MAX &&
|
||||||
|
collect_neighbor_rtmetric(n) != RTMETRIC_MAX) {
|
||||||
|
bump_advertisement(tc);
|
||||||
|
}
|
||||||
collect_neighbor_update_rtmetric(n, rtmetric);
|
collect_neighbor_update_rtmetric(n, rtmetric);
|
||||||
PRINTF("%d.%d: updating neighbor %d.%d, etx %d\n",
|
PRINTF("%d.%d: updating neighbor %d.%d, etx %d\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
@ -963,7 +982,22 @@ received_announcement(struct announcement *a, const rimeaddr_t *from,
|
||||||
PRINTF("%d.%d: new neighbor %d.%d, etx %d\n",
|
PRINTF("%d.%d: new neighbor %d.%d, etx %d\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
from->u8[0], from->u8[1], value);
|
from->u8[0], from->u8[1], value);
|
||||||
|
if(value == RTMETRIC_MAX) {
|
||||||
|
bump_advertisement(tc);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
/* Check if the advertised rtmetric has changed to
|
||||||
|
RTMETRIC_MAX. This may indicate that the neighbor has lost its
|
||||||
|
routes or that it has rebooted. In either case, we bump our
|
||||||
|
advertisement rate to allow our neighbor to receive a new
|
||||||
|
rtmetric from us. If our neighbor already happens to have an
|
||||||
|
rtmetric of RTMETRIC_MAX recorded, it may mean that our
|
||||||
|
neighbor does not hear our advertisements. If this is the case,
|
||||||
|
we should not bump our advertisement rate. */
|
||||||
|
if(value == RTMETRIC_MAX &&
|
||||||
|
collect_neighbor_rtmetric(n) != RTMETRIC_MAX) {
|
||||||
|
bump_advertisement(tc);
|
||||||
|
}
|
||||||
collect_neighbor_update_rtmetric(n, value);
|
collect_neighbor_update_rtmetric(n, value);
|
||||||
PRINTF("%d.%d: updating neighbor %d.%d, etx %d\n",
|
PRINTF("%d.%d: updating neighbor %d.%d, etx %d\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
@ -1021,6 +1055,64 @@ collect_open(struct collect_conn *tc, uint16_t channels,
|
||||||
#endif /* !COLLECT_ANNOUNCEMENTS */
|
#endif /* !COLLECT_ANNOUNCEMENTS */
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
send_keepalive(void *ptr)
|
||||||
|
{
|
||||||
|
struct collect_conn *c = ptr;
|
||||||
|
struct collect_neighbor *n;
|
||||||
|
|
||||||
|
set_keepalive_timer(c);
|
||||||
|
|
||||||
|
/* Send keepalive message only if there are no pending transmissions. */
|
||||||
|
if(packetqueue_len(&c->send_queue) == 0) {
|
||||||
|
packetbuf_clear();
|
||||||
|
packetbuf_set_addr(PACKETBUF_ADDR_ESENDER, &rimeaddr_node_addr);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_HOPS, 1);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_TTL, 1);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_MAX_REXMIT, KEEPALIVE_REXMITS);
|
||||||
|
|
||||||
|
PRINTF("%d.%d: saending keepalive packet %d, max_rexmits %d\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID),
|
||||||
|
packetbuf_attr(PACKETBUF_ATTR_MAX_REXMIT));
|
||||||
|
|
||||||
|
/* Allocate space for the header. */
|
||||||
|
packetbuf_hdralloc(sizeof(struct data_msg_hdr));
|
||||||
|
|
||||||
|
n = collect_neighbor_list_find(&c->neighbor_list, &c->parent);
|
||||||
|
if(n != NULL) {
|
||||||
|
PRINTF("%d.%d: sending keepalive to %d.%d\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
n->addr.u8[0], n->addr.u8[1]);
|
||||||
|
|
||||||
|
if(packetqueue_enqueue_packetbuf(&c->send_queue,
|
||||||
|
FORWARD_PACKET_LIFETIME,
|
||||||
|
c)) {
|
||||||
|
send_queued_packet(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
set_keepalive_timer(struct collect_conn *c)
|
||||||
|
{
|
||||||
|
if(c->keepalive_period != 0) {
|
||||||
|
ctimer_set(&c->keepalive_timer, (c->keepalive_period / 2) +
|
||||||
|
(random_rand() % (c->keepalive_period / 2)),
|
||||||
|
send_keepalive, c);
|
||||||
|
} else {
|
||||||
|
ctimer_stop(&c->keepalive_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
collect_set_keepalive(struct collect_conn *c, clock_time_t period)
|
||||||
|
{
|
||||||
|
c->keepalive_period = period;
|
||||||
|
set_keepalive_timer(c);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
collect_close(struct collect_conn *tc)
|
collect_close(struct collect_conn *tc)
|
||||||
{
|
{
|
||||||
|
@ -1050,6 +1142,8 @@ collect_set_sink(struct collect_conn *tc, int should_be_sink)
|
||||||
announcement_set_value(&tc->announcement, tc->rtmetric);
|
announcement_set_value(&tc->announcement, tc->rtmetric);
|
||||||
#endif /* COLLECT_ANNOUNCEMENTS */
|
#endif /* COLLECT_ANNOUNCEMENTS */
|
||||||
update_rtmetric(tc);
|
update_rtmetric(tc);
|
||||||
|
|
||||||
|
bump_advertisement(tc);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
int
|
int
|
||||||
|
@ -1057,7 +1151,21 @@ collect_send(struct collect_conn *tc, int rexmits)
|
||||||
{
|
{
|
||||||
struct collect_neighbor *n;
|
struct collect_neighbor *n;
|
||||||
|
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_EPACKET_ID, tc->eseqno++);
|
packetbuf_set_attr(PACKETBUF_ATTR_EPACKET_ID, tc->eseqno);
|
||||||
|
|
||||||
|
/* Increase the sequence number for the packet we send out. We
|
||||||
|
employ a trick that allows us to see that a node has been
|
||||||
|
rebooted: if the sequence number wraps to 0, we set it to half of
|
||||||
|
the sequence number space. This allows us to detect reboots,
|
||||||
|
since if a sequence number is less than half of the sequence
|
||||||
|
number space, the data comes from a node that was recently
|
||||||
|
rebooted. */
|
||||||
|
|
||||||
|
tc->eseqno = (tc->eseqno + 1) % (1 << COLLECT_PACKET_ID_BITS);
|
||||||
|
|
||||||
|
if(tc->eseqno == 0) {
|
||||||
|
tc->eseqno = ((int)(1 << COLLECT_PACKET_ID_BITS)) / 2;
|
||||||
|
}
|
||||||
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, MAX_HOPLIM);
|
packetbuf_set_attr(PACKETBUF_ATTR_TTL, MAX_HOPLIM);
|
||||||
|
@ -1086,7 +1194,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(&tc->send_queue,
|
if(packetqueue_enqueue_packetbuf(&tc->send_queue,
|
||||||
FORWARD_PACKET_LIFETIME,
|
FORWARD_PACKET_LIFETIME,
|
||||||
tc)) {
|
tc)) {
|
||||||
|
@ -1135,6 +1243,7 @@ void
|
||||||
collect_purge(struct collect_conn *tc)
|
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);
|
||||||
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]);
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
*
|
*
|
||||||
* This file is part of the Contiki operating system.
|
* This file is part of the Contiki operating system.
|
||||||
*
|
*
|
||||||
* $Id: collect.h,v 1.20 2010/09/13 13:28:14 adamdunkels Exp $
|
* $Id: collect.h,v 1.21 2010/09/22 22:08:08 adamdunkels Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,11 +93,14 @@ struct collect_conn {
|
||||||
struct ctimer transmit_after_scan_timer;
|
struct ctimer transmit_after_scan_timer;
|
||||||
#endif /* COLLECT_CONF_ANNOUNCEMENTS */
|
#endif /* COLLECT_CONF_ANNOUNCEMENTS */
|
||||||
const struct collect_callbacks *cb;
|
const struct collect_callbacks *cb;
|
||||||
struct ctimer t;
|
|
||||||
struct ctimer retransmission_timer;
|
struct ctimer retransmission_timer;
|
||||||
LIST_STRUCT(send_queue_list);
|
LIST_STRUCT(send_queue_list);
|
||||||
struct packetqueue send_queue;
|
struct packetqueue send_queue;
|
||||||
struct collect_neighbor_list neighbor_list;
|
struct collect_neighbor_list neighbor_list;
|
||||||
|
|
||||||
|
struct ctimer keepalive_timer;
|
||||||
|
clock_time_t keepalive_period;
|
||||||
|
|
||||||
rimeaddr_t parent, current_parent;
|
rimeaddr_t parent, current_parent;
|
||||||
uint16_t rtmetric;
|
uint16_t rtmetric;
|
||||||
uint8_t seqno;
|
uint8_t seqno;
|
||||||
|
@ -122,6 +125,8 @@ void collect_set_sink(struct collect_conn *c, int should_be_sink);
|
||||||
|
|
||||||
int collect_depth(struct collect_conn *c);
|
int collect_depth(struct collect_conn *c);
|
||||||
|
|
||||||
|
void collect_set_keepalive(struct collect_conn *c, clock_time_t period);
|
||||||
|
|
||||||
void collect_print_stats(void);
|
void collect_print_stats(void);
|
||||||
|
|
||||||
#define COLLECT_MAX_DEPTH 255
|
#define COLLECT_MAX_DEPTH 255
|
||||||
|
|
Loading…
Reference in a new issue