Significant rework of the Contiki data collection protocol:
* the new version makes use of MAC-layer feedback so that bad paths can be identified quicker and then avoided. * the new code uses transport layer ACKs that contain feedback from the collect protocol: when a packet cannot be forwarded due to lack of resources, the ACK contains a flag that indicates that the packet could not be forwarded. ACKs also contain the routing metric of the sender, which improves agility in face of rapid path changes. * loop detection and management has been improved: with higher path metric agility, the system is more prone to short-lived routing loops. Instead of dropping looping packets, the new version adjusts the routing metric for the routes that exhibit loops so that the risk for future loops is reduced. * make use of packet attributes to inform the MAC layer of how many times packets should be retransmitted.
This commit is contained in:
parent
b6b4941871
commit
7165a3866f
|
@ -1,6 +1,3 @@
|
||||||
/* XXX: send explicit congestion notification if already forwarding
|
|
||||||
packet. */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \addtogroup rimecollect
|
* \addtogroup rimecollect
|
||||||
* @{
|
* @{
|
||||||
|
@ -36,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.33 2010/02/23 18:35:23 adamdunkels Exp $
|
* $Id: collect.c,v 1.34 2010/02/28 09:18:01 adamdunkels Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,9 +53,7 @@
|
||||||
|
|
||||||
#include "dev/radio-sensor.h"
|
#include "dev/radio-sensor.h"
|
||||||
|
|
||||||
#if CONTIKI_TARGET_NETSIM
|
#include "lib/random.h"
|
||||||
#include "ether.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -78,12 +73,21 @@ struct recent_packet {
|
||||||
uint8_t seqno;
|
uint8_t seqno;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ack_msg {
|
||||||
|
uint8_t flags, dummy;
|
||||||
|
uint16_t rtmetric;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ACK_FLAGS_CONGESTED 0x80
|
||||||
|
#define ACK_FLAGS_DROPPED 0x40
|
||||||
|
#define ACK_FLAGS_LIFETIME_EXCEEDED 0x20
|
||||||
|
|
||||||
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 FORWARD_PACKET_LIFETIME (CLOCK_SECOND * 16)
|
#define FORWARD_PACKET_LIFETIME (CLOCK_SECOND * 16)
|
||||||
#define MAX_FORWARDING_QUEUE 6
|
#define MAX_SENDING_QUEUE 6
|
||||||
PACKETQUEUE(forwarding_queue, MAX_FORWARDING_QUEUE);
|
PACKETQUEUE(sending_queue, MAX_SENDING_QUEUE);
|
||||||
|
|
||||||
#define SINK 0
|
#define SINK 0
|
||||||
#define RTMETRIC_MAX COLLECT_MAX_DEPTH
|
#define RTMETRIC_MAX COLLECT_MAX_DEPTH
|
||||||
|
@ -104,64 +108,16 @@ PACKETQUEUE(forwarding_queue, MAX_FORWARDING_QUEUE);
|
||||||
#define PRINTF(...)
|
#define PRINTF(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
static void
|
|
||||||
send_queued_packet(void)
|
|
||||||
{
|
|
||||||
struct queuebuf *q;
|
|
||||||
struct neighbor *n;
|
|
||||||
struct packetqueue_item *i;
|
|
||||||
struct collect_conn *c;
|
|
||||||
|
|
||||||
i = packetqueue_first(&forwarding_queue);
|
#define REXMIT_TIME CLOCK_SECOND * 2
|
||||||
if(i == NULL) {
|
|
||||||
PRINTF("%d.%d: nothing on queue\n",
|
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
|
||||||
/* No packet on the queue, so there is nothing for us to send. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
c = packetqueue_ptr(i);
|
|
||||||
if(c == NULL) {
|
|
||||||
/* c should not be NULL, but we check it just to be sure. */
|
|
||||||
PRINTF("%d.%d: queue, c == NULL!\n",
|
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(c->forwarding) {
|
|
||||||
/* If we are currently forwarding a packet, we wait until the
|
|
||||||
packet is forwarded and try again then. */
|
|
||||||
PRINTF("%d.%d: queue, c is forwarding\n",
|
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
q = packetqueue_queuebuf(i);
|
|
||||||
if(q != NULL) {
|
|
||||||
PRINTF("%d.%d: queue, q is on queue\n",
|
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
|
||||||
queuebuf_to_packetbuf(q);
|
|
||||||
|
|
||||||
n = neighbor_best();
|
|
||||||
|
|
||||||
/* Don't send to the neighbor if it is the same neighbor that sent
|
|
||||||
us the packet. */
|
|
||||||
if(n != NULL && !rimeaddr_cmp(&n->addr, packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
|
|
||||||
#if CONTIKI_TARGET_NETSIM
|
#if CONTIKI_TARGET_NETSIM
|
||||||
ether_set_line(n->addr.u8[0], n->addr.u8[1]);
|
#include "ether.h"
|
||||||
#endif /* CONTIKI_TARGET_NETSIM */
|
#endif /* CONTIKI_TARGET_NETSIM */
|
||||||
PRINTF("%d.%d: sending packet to %d.%d\n",
|
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
|
||||||
n->addr.u8[0], n->addr.u8[1]);
|
|
||||||
|
|
||||||
c->forwarding = 1;
|
static void send_queued_packet(void);
|
||||||
runicast_send(&c->runicast_conn, &n->addr, packetbuf_attr(PACKETBUF_ATTR_MAX_REXMIT));
|
static void retransmit_callback(void *ptr);
|
||||||
} else {
|
|
||||||
PRINTF("%d.%d: did not find any neighbor to forward to\n",
|
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
update_rtmetric(struct collect_conn *tc)
|
update_rtmetric(struct collect_conn *tc)
|
||||||
|
@ -191,7 +147,6 @@ update_rtmetric(struct collect_conn *tc)
|
||||||
neighbor_discovery_set_val(&tc->neighbor_discovery_conn, tc->rtmetric);
|
neighbor_discovery_set_val(&tc->neighbor_discovery_conn, tc->rtmetric);
|
||||||
#endif /* COLLECT_ANNOUNCEMENTS */
|
#endif /* COLLECT_ANNOUNCEMENTS */
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* We set our rtmetric to the rtmetric of our best neighbor plus
|
/* We set our rtmetric to the rtmetric of our best neighbor plus
|
||||||
the expected transmissions to reach that neighbor. */
|
the expected transmissions to reach that neighbor. */
|
||||||
if(n->rtmetric + neighbor_etx(n) != tc->rtmetric) {
|
if(n->rtmetric + neighbor_etx(n) != tc->rtmetric) {
|
||||||
|
@ -201,8 +156,6 @@ update_rtmetric(struct collect_conn *tc)
|
||||||
|
|
||||||
#if ! COLLECT_ANNOUNCEMENTS
|
#if ! COLLECT_ANNOUNCEMENTS
|
||||||
|
|
||||||
/* neighbor_discovery_set_val(&tc->neighbor_discovery_conn, tc->rtmetric);*/
|
|
||||||
|
|
||||||
/* If we get a significantly better rtmetric than we had
|
/* If we get a significantly better rtmetric than we had
|
||||||
before, we call neighbor_discovery_start to start a new
|
before, we call neighbor_discovery_start to start a new
|
||||||
period. */
|
period. */
|
||||||
|
@ -234,7 +187,7 @@ update_rtmetric(struct collect_conn *tc)
|
||||||
if(tc->rtmetric == RTMETRIC_MAX) {
|
if(tc->rtmetric == RTMETRIC_MAX) {
|
||||||
strcpy(buf, " ");
|
strcpy(buf, " ");
|
||||||
} else {
|
} else {
|
||||||
sprintf(buf, "%.1f", (float)tc->rtmetric / NEIGHBOR_ETX_SCALE);
|
sPRINTF(buf, "%.1f", (float)tc->rtmetric / NEIGHBOR_ETX_SCALE);
|
||||||
}
|
}
|
||||||
ether_set_text(buf);
|
ether_set_text(buf);
|
||||||
}
|
}
|
||||||
|
@ -242,41 +195,250 @@ update_rtmetric(struct collect_conn *tc)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
node_packet_received(struct runicast_conn *c, const rimeaddr_t *from,
|
send_queued_packet(void)
|
||||||
uint8_t seqno)
|
{
|
||||||
|
struct queuebuf *q;
|
||||||
|
struct neighbor *n;
|
||||||
|
struct packetqueue_item *i;
|
||||||
|
struct collect_conn *c;
|
||||||
|
|
||||||
|
PRINTF("%d.%d: send_queued_packet queue len %d\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
packetqueue_len(&sending_queue));
|
||||||
|
|
||||||
|
i = packetqueue_first(&sending_queue);
|
||||||
|
if(i == NULL) {
|
||||||
|
PRINTF("%d.%d: nothing on queue\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
||||||
|
/* No packet on the queue, so there is nothing for us to send. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c = packetqueue_ptr(i);
|
||||||
|
if(c == NULL) {
|
||||||
|
/* c should not be NULL, but we check it just to be sure. */
|
||||||
|
PRINTF("%d.%d: queue, c == NULL!\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c->sending) {
|
||||||
|
/* If we are currently sending a packet, we wait until the
|
||||||
|
packet is forwarded and try again then. */
|
||||||
|
PRINTF("%d.%d: queue, c is sending\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
q = packetqueue_queuebuf(i);
|
||||||
|
if(q != NULL) {
|
||||||
|
PRINTF("%d.%d: queue, q is on queue\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
||||||
|
queuebuf_to_packetbuf(q);
|
||||||
|
|
||||||
|
n = neighbor_best();
|
||||||
|
|
||||||
|
while(n != NULL && rimeaddr_cmp(&n->addr, packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
|
||||||
|
PRINTF("%d.%d: avoiding fowarding loop to %d.%d\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
n->addr.u8[0], n->addr.u8[1]);
|
||||||
|
neighbor_remove(&n->addr);
|
||||||
|
update_rtmetric(c);
|
||||||
|
n = neighbor_best();;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't send to the neighbor if it is the same neighbor that sent
|
||||||
|
us the packet. */
|
||||||
|
if(n != NULL) {
|
||||||
|
clock_time_t time;
|
||||||
|
uint8_t rexmit_time_scaling;
|
||||||
|
#if CONTIKI_TARGET_NETSIM
|
||||||
|
ether_set_line(n->addr.u8[0], n->addr.u8[1]);
|
||||||
|
#endif /* CONTIKI_TARGET_NETSIM */
|
||||||
|
PRINTF("%d.%d: sending packet to %d.%d\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
n->addr.u8[0], n->addr.u8[1]);
|
||||||
|
|
||||||
|
rimeaddr_copy(&c->current_receiver, &n->addr);
|
||||||
|
c->sending = 1;
|
||||||
|
c->transmissions = 0;
|
||||||
|
c->max_rexmits = 8;//packetbuf_attr(PACKETBUF_ATTR_EMAX_REXMIT);
|
||||||
|
PRINTF("max_rexmits %d\n", c->max_rexmits);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_REXMIT, 2);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, c->seqno);
|
||||||
|
unicast_send(&c->unicast_conn, &n->addr);
|
||||||
|
rexmit_time_scaling = c->transmissions;
|
||||||
|
if(rexmit_time_scaling > 3) {
|
||||||
|
rexmit_time_scaling = 3;
|
||||||
|
}
|
||||||
|
time = REXMIT_TIME << rexmit_time_scaling;
|
||||||
|
time = time / 2 + random_rand() % (time / 2);
|
||||||
|
PRINTF("retransmission time %lu\n", time);
|
||||||
|
ctimer_set(&c->retransmission_timer, time,
|
||||||
|
retransmit_callback, c);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
send_next_packet(struct collect_conn *tc)
|
||||||
|
{
|
||||||
|
/* Cancel retransmission timer. */
|
||||||
|
ctimer_stop(&tc->retransmission_timer);
|
||||||
|
|
||||||
|
/* Remove the first packet on the queue, the packet that was just sent. */
|
||||||
|
packetqueue_dequeue(&sending_queue);
|
||||||
|
tc->seqno = (tc->seqno + 1) % (1 << COLLECT_PACKET_ID_BITS);
|
||||||
|
tc->sending = 0;
|
||||||
|
tc->transmissions = 0;
|
||||||
|
|
||||||
|
/* Send the next packet in the queue, if any. */
|
||||||
|
send_queued_packet();
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
handle_ack(struct collect_conn *tc)
|
||||||
|
{
|
||||||
|
struct ack_msg *msg;
|
||||||
|
uint16_t rtmetric;
|
||||||
|
struct neighbor *n;
|
||||||
|
|
||||||
|
if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER),
|
||||||
|
&tc->current_receiver) &&
|
||||||
|
packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == tc->seqno) {
|
||||||
|
|
||||||
|
|
||||||
|
msg = packetbuf_dataptr();
|
||||||
|
memcpy(&rtmetric, &msg->rtmetric, sizeof(uint16_t));
|
||||||
|
n = neighbor_find(packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||||
|
if(n != NULL) {
|
||||||
|
neighbor_update(n, rtmetric);
|
||||||
|
update_rtmetric(tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINTF("%d.%d: ACK from %d.%d after %d transmissions, flags %02x\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
tc->current_receiver.u8[0], tc->current_receiver.u8[1],
|
||||||
|
tc->transmissions,
|
||||||
|
msg->flags);
|
||||||
|
|
||||||
|
if(!(msg->flags & ACK_FLAGS_DROPPED)) {
|
||||||
|
send_next_packet(tc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
send_ack(struct collect_conn *tc, const rimeaddr_t *to, int congestion, int dropped, int ttl)
|
||||||
|
{
|
||||||
|
struct ack_msg *ack;
|
||||||
|
struct queuebuf *q;
|
||||||
|
uint16_t packet_seqno;
|
||||||
|
|
||||||
|
|
||||||
|
PRINTF("send_ack\n");
|
||||||
|
|
||||||
|
packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
|
||||||
|
|
||||||
|
q = queuebuf_new_from_packetbuf();
|
||||||
|
if(q != NULL) {
|
||||||
|
|
||||||
|
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 = (congestion? ACK_FLAGS_CONGESTED: 0) |
|
||||||
|
(dropped? ACK_FLAGS_DROPPED: 0) |
|
||||||
|
(ttl? ACK_FLAGS_LIFETIME_EXCEEDED: 0);
|
||||||
|
/* XXX: send explicit congestion notification in ACK queue full; add rtmetric to ACK. */
|
||||||
|
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_REXMIT, 2);
|
||||||
|
unicast_send(&tc->unicast_conn, to);
|
||||||
|
|
||||||
|
PRINTF("%d.%d: collect: Sending ACK to %d.%d for %d\n",
|
||||||
|
rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
|
||||||
|
to->u8[0],
|
||||||
|
to->u8[1],
|
||||||
|
packet_seqno);
|
||||||
|
|
||||||
|
RIMESTATS_ADD(acktx);
|
||||||
|
|
||||||
|
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],
|
||||||
|
to->u8[0], to->u8[1],
|
||||||
|
packet_seqno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
node_packet_received(struct unicast_conn *c, const rimeaddr_t *from)
|
||||||
{
|
{
|
||||||
struct collect_conn *tc = (struct collect_conn *)
|
struct collect_conn *tc = (struct collect_conn *)
|
||||||
((char *)c - offsetof(struct collect_conn, runicast_conn));
|
((char *)c - offsetof(struct collect_conn, unicast_conn));
|
||||||
int i;
|
int i;
|
||||||
struct neighbor *n;
|
struct neighbor *n;
|
||||||
|
|
||||||
/* To protect against forwarding duplicate packets, we keep a list
|
/* To protect against sending duplicate packets, we keep a list
|
||||||
of recently forwarded packet seqnos. If the seqno of the current
|
of recently forwarded packet seqnos. If the seqno of the current
|
||||||
packet exists in the list, we drop the packet and increase the
|
packet exists in the list, we drop the packet and increase the
|
||||||
ETX of the neighbor we sent it to in the first place. */
|
ETX of the neighbor we sent it to in the first place. */
|
||||||
|
if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
|
||||||
|
PACKETBUF_ATTR_PACKET_TYPE_DATA) {
|
||||||
|
rimeaddr_t ack_to;
|
||||||
|
uint8_t packet_seqno;
|
||||||
|
|
||||||
|
rimeaddr_copy(&ack_to, packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||||
|
packet_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
|
||||||
|
|
||||||
|
if(rimeaddr_cmp(&tc->last_received_addr, packetbuf_addr(PACKETBUF_ADDR_SENDER)) &&
|
||||||
|
tc->last_received_seqno == packetbuf_attr(PACKETBUF_ATTR_PACKET_ID)) {
|
||||||
|
/* This is a duplicate of the packet we last received, so we just send an ACK. */
|
||||||
|
send_ack(tc, &ack_to, 0, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rimeaddr_copy(&tc->last_received_addr, packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||||
|
tc->last_received_seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID);
|
||||||
|
|
||||||
for(i = 0; i < NUM_RECENT_PACKETS; i++) {
|
for(i = 0; i < NUM_RECENT_PACKETS; i++) {
|
||||||
if(recent_packets[i].seqno == packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID) &&
|
if(recent_packets[i].seqno == packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID) &&
|
||||||
rimeaddr_cmp(&recent_packets[i].originator,
|
rimeaddr_cmp(&recent_packets[i].originator,
|
||||||
packetbuf_addr(PACKETBUF_ADDR_ESENDER))) {
|
packetbuf_addr(PACKETBUF_ADDR_ESENDER))) {
|
||||||
PRINTF("%d.%d: dropping duplicate packet from %d.%d with seqno %d\n",
|
PRINTF("%d.%d: found duplicate packet from %d.%d with seqno %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],
|
||||||
recent_packets[i].originator.u8[0], recent_packets[i].originator.u8[1],
|
recent_packets[i].originator.u8[0], recent_packets[i].originator.u8[1],
|
||||||
packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID));
|
packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID),
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[0],
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[1]);
|
||||||
n = neighbor_find(&recent_packets[i].sent_to);
|
n = neighbor_find(&recent_packets[i].sent_to);
|
||||||
if(n != NULL) {
|
if(n != NULL) {
|
||||||
neighbor_update_etx(n, neighbor_etx(n) + NEIGHBOR_ETX_SCALE * 4);
|
neighbor_update_etx(n, neighbor_etx(n) / NEIGHBOR_ETX_SCALE + 4);
|
||||||
|
update_rtmetric(tc);
|
||||||
}
|
}
|
||||||
/* Drop the packet. */
|
break;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
recent_packets[recent_packet_ptr].seqno = packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID);
|
recent_packets[recent_packet_ptr].seqno = 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));
|
||||||
|
/* n = neighbor_best();*/
|
||||||
|
|
||||||
|
if(tc->rtmetric != SINK) {
|
||||||
n = neighbor_best();
|
n = neighbor_best();
|
||||||
rimeaddr_copy(&recent_packets[recent_packet_ptr].sent_to,
|
rimeaddr_copy(&recent_packets[recent_packet_ptr].sent_to,
|
||||||
&n->addr);
|
&n->addr);
|
||||||
|
} else {
|
||||||
|
rimeaddr_copy(&recent_packets[recent_packet_ptr].sent_to,
|
||||||
|
&rimeaddr_null);
|
||||||
|
}
|
||||||
|
|
||||||
recent_packet_ptr = (recent_packet_ptr + 1) % NUM_RECENT_PACKETS;
|
recent_packet_ptr = (recent_packet_ptr + 1) % NUM_RECENT_PACKETS;
|
||||||
|
|
||||||
|
@ -284,8 +446,11 @@ node_packet_received(struct runicast_conn *c, const rimeaddr_t *from,
|
||||||
|
|
||||||
/* If we are the sink, we call the receive function. */
|
/* If we are the sink, we call the receive function. */
|
||||||
|
|
||||||
PRINTF("%d.%d: sink received packet from %d.%d via %d.%d\n",
|
send_ack(tc, &ack_to, 0, 0, 0);
|
||||||
|
|
||||||
|
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],
|
||||||
|
packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID),
|
||||||
packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[0],
|
packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[0],
|
||||||
packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[1],
|
packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[1],
|
||||||
from->u8[0], from->u8[1]);
|
from->u8[0], from->u8[1]);
|
||||||
|
@ -305,16 +470,18 @@ node_packet_received(struct runicast_conn *c, const rimeaddr_t *from,
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_TTL, packetbuf_attr(PACKETBUF_ATTR_TTL) - 1);
|
packetbuf_set_attr(PACKETBUF_ATTR_TTL, packetbuf_attr(PACKETBUF_ATTR_TTL) - 1);
|
||||||
|
|
||||||
|
|
||||||
PRINTF("%d.%d: packet received from %d.%d via %d.%d, forwarding %d\n",
|
PRINTF("%d.%d: packet received from %d.%d via %d.%d, sending %d\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[0],
|
packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[0],
|
||||||
packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[1],
|
packetbuf_addr(PACKETBUF_ADDR_ESENDER)->u8[1],
|
||||||
from->u8[0], from->u8[1], tc->forwarding);
|
from->u8[0], from->u8[1], tc->sending);
|
||||||
|
|
||||||
if(packetqueue_enqueue_packetbuf(&forwarding_queue, FORWARD_PACKET_LIFETIME,
|
if(packetqueue_enqueue_packetbuf(&sending_queue, FORWARD_PACKET_LIFETIME,
|
||||||
tc)) {
|
tc)) {
|
||||||
|
send_ack(tc, &ack_to, 0, 0, 0);
|
||||||
send_queued_packet();
|
send_queued_packet();
|
||||||
} else {
|
} else {
|
||||||
|
send_ack(tc, &ack_to, 0, 1, 0);
|
||||||
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]);
|
||||||
}
|
}
|
||||||
|
@ -322,54 +489,73 @@ node_packet_received(struct runicast_conn *c, const rimeaddr_t *from,
|
||||||
PRINTF("%d.%d: packet dropped: ttl %d\n",
|
PRINTF("%d.%d: packet dropped: ttl %d\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
packetbuf_attr(PACKETBUF_ATTR_TTL));
|
packetbuf_attr(PACKETBUF_ATTR_TTL));
|
||||||
|
send_ack(tc, &ack_to, 0, 1, 1);
|
||||||
|
}
|
||||||
|
} else if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
|
||||||
|
PACKETBUF_ATTR_PACKET_TYPE_ACK) {
|
||||||
|
PRINTF("Collect: incoming ack %d from %d.%d (%d.%d) seqno %d (%d)\n",
|
||||||
|
packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE),
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[0],
|
||||||
|
packetbuf_addr(PACKETBUF_ADDR_SENDER)->u8[1],
|
||||||
|
tc->current_receiver.u8[0],
|
||||||
|
tc->current_receiver.u8[1],
|
||||||
|
packetbuf_attr(PACKETBUF_ATTR_PACKET_ID),
|
||||||
|
tc->seqno);
|
||||||
|
handle_ack(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
node_packet_sent(struct runicast_conn *c, const rimeaddr_t *to,
|
node_packet_sent(struct unicast_conn *c, int status, int transmissions)
|
||||||
uint8_t transmissions)
|
|
||||||
{
|
{
|
||||||
struct collect_conn *tc = (struct collect_conn *)
|
struct collect_conn *tc = (struct collect_conn *)
|
||||||
((char *)c - offsetof(struct collect_conn, runicast_conn));
|
((char *)c - offsetof(struct collect_conn, unicast_conn));
|
||||||
|
|
||||||
PRINTF("%d.%d: sent to %d.%d after %d retransmissions\n",
|
/* For data packets, we record the number of transmissions */
|
||||||
|
if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) ==
|
||||||
|
PACKETBUF_ATTR_PACKET_TYPE_DATA) {
|
||||||
|
PRINTF("%d.%d: sent to %d.%d after %d transmissions\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[1],
|
tc->current_receiver.u8[0], tc->current_receiver.u8[1],
|
||||||
transmissions);
|
transmissions);
|
||||||
|
|
||||||
|
/* neighbor_update_etx(neighbor_find(to), transmissions);
|
||||||
|
update_rtmetric(tc);*/
|
||||||
|
tc->transmissions += transmissions;
|
||||||
|
|
||||||
tc->forwarding = 0;
|
/* Update ETX with the number of transmissions. */
|
||||||
neighbor_update_etx(neighbor_find(to), transmissions);
|
PRINTF("Updating ETX with %d transmissions\n", tc->transmissions);
|
||||||
|
neighbor_update_etx(neighbor_find(&tc->current_receiver), tc->transmissions);
|
||||||
update_rtmetric(tc);
|
update_rtmetric(tc);
|
||||||
|
}
|
||||||
/* Remove the first packet on the queue, the packet that was just sent. */
|
|
||||||
packetqueue_dequeue(&forwarding_queue);
|
|
||||||
|
|
||||||
/* Send the next packet in the queue, if any. */
|
|
||||||
send_queued_packet();
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
node_packet_timedout(struct runicast_conn *c, const rimeaddr_t *to,
|
timedout(struct collect_conn *tc)
|
||||||
uint8_t transmissions)
|
|
||||||
{
|
{
|
||||||
struct collect_conn *tc = (struct collect_conn *)
|
|
||||||
((char *)c - offsetof(struct collect_conn, runicast_conn));
|
|
||||||
|
|
||||||
PRINTF("%d.%d: timedout after %d retransmissions: packet dropped\n",
|
PRINTF("%d.%d: timedout after %d retransmissions: packet dropped\n",
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], transmissions);
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], tc->transmissions);
|
||||||
|
|
||||||
tc->forwarding = 0;
|
tc->sending = 0;
|
||||||
neighbor_timedout_etx(neighbor_find(to), transmissions);
|
neighbor_timedout_etx(neighbor_find(&tc->current_receiver), tc->transmissions);
|
||||||
update_rtmetric(tc);
|
update_rtmetric(tc);
|
||||||
|
|
||||||
/* Remove the first packet on the queue, the packet that just timed out. */
|
send_next_packet(tc);
|
||||||
packetqueue_dequeue(&forwarding_queue);
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
retransmit_callback(void *ptr)
|
||||||
|
{
|
||||||
|
struct collect_conn *c = ptr;
|
||||||
|
|
||||||
/* Send the next packet in the queue, if any. */
|
PRINTF("retransmit\n");
|
||||||
|
if(c->transmissions >= c->max_rexmits) {
|
||||||
|
timedout(c);
|
||||||
|
} else {
|
||||||
|
c->sending = 0;
|
||||||
send_queued_packet();
|
send_queued_packet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#if !COLLECT_ANNOUNCEMENTS
|
#if !COLLECT_ANNOUNCEMENTS
|
||||||
|
@ -421,9 +607,8 @@ received_announcement(struct announcement *a, const rimeaddr_t *from,
|
||||||
}
|
}
|
||||||
#endif /* !COLLECT_ANNOUNCEMENTS */
|
#endif /* !COLLECT_ANNOUNCEMENTS */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static const struct runicast_callbacks runicast_callbacks = {node_packet_received,
|
static const struct unicast_callbacks unicast_callbacks = {node_packet_received,
|
||||||
node_packet_sent,
|
node_packet_sent};
|
||||||
node_packet_timedout};
|
|
||||||
#if !COLLECT_ANNOUNCEMENTS
|
#if !COLLECT_ANNOUNCEMENTS
|
||||||
static const struct neighbor_discovery_callbacks neighbor_discovery_callbacks =
|
static const struct neighbor_discovery_callbacks neighbor_discovery_callbacks =
|
||||||
{ adv_received, NULL};
|
{ adv_received, NULL};
|
||||||
|
@ -439,19 +624,19 @@ collect_open(struct collect_conn *tc, uint16_t channels,
|
||||||
CLOCK_SECOND * 32,
|
CLOCK_SECOND * 32,
|
||||||
CLOCK_SECOND * 600,
|
CLOCK_SECOND * 600,
|
||||||
&neighbor_discovery_callbacks);
|
&neighbor_discovery_callbacks);
|
||||||
#endif /* !COLLECT_ANNOUNCEMENTS */
|
neighbor_discovery_start(&tc->neighbor_discovery_conn, tc->rtmetric);
|
||||||
runicast_open(&tc->runicast_conn, channels + 1, &runicast_callbacks);
|
#else /* !COLLECT_ANNOUNCEMENTS */
|
||||||
channel_set_attributes(channels + 1, attributes);
|
|
||||||
tc->rtmetric = RTMETRIC_MAX;
|
|
||||||
tc->cb = cb;
|
|
||||||
#if COLLECT_ANNOUNCEMENTS
|
|
||||||
announcement_register(&tc->announcement, channels, tc->rtmetric,
|
announcement_register(&tc->announcement, channels, tc->rtmetric,
|
||||||
received_announcement);
|
received_announcement);
|
||||||
announcement_listen(2);
|
announcement_listen(2);
|
||||||
#else
|
#endif /* !COLLECT_ANNOUNCEMENTS */
|
||||||
neighbor_discovery_start(&tc->neighbor_discovery_conn, tc->rtmetric);
|
|
||||||
#endif /* COLLECT_ANNOUNCEMENTS */
|
unicast_open(&tc->unicast_conn, channels + 1, &unicast_callbacks);
|
||||||
|
channel_set_attributes(channels + 1, attributes);
|
||||||
|
tc->rtmetric = RTMETRIC_MAX;
|
||||||
|
tc->cb = cb;
|
||||||
neighbor_init();
|
neighbor_init();
|
||||||
|
packetqueue_init(&sending_queue);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
|
@ -462,7 +647,7 @@ collect_close(struct collect_conn *tc)
|
||||||
#else
|
#else
|
||||||
neighbor_discovery_close(&tc->neighbor_discovery_conn);
|
neighbor_discovery_close(&tc->neighbor_discovery_conn);
|
||||||
#endif /* COLLECT_ANNOUNCEMENTS */
|
#endif /* COLLECT_ANNOUNCEMENTS */
|
||||||
runicast_close(&tc->runicast_conn);
|
unicast_close(&tc->unicast_conn);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
|
@ -487,12 +672,19 @@ collect_send(struct collect_conn *tc, int rexmits)
|
||||||
{
|
{
|
||||||
struct neighbor *n;
|
struct neighbor *n;
|
||||||
|
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_EPACKET_ID, tc->seqno++);
|
packetbuf_set_attr(PACKETBUF_ATTR_EPACKET_ID, tc->eseqno++);
|
||||||
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);
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_MAX_REXMIT, rexmits);
|
packetbuf_set_attr(PACKETBUF_ATTR_MAX_REXMIT, rexmits);
|
||||||
|
|
||||||
|
PRINTF("%d.%d: originating packet %d\n",
|
||||||
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
|
||||||
|
packetbuf_attr(PACKETBUF_ATTR_EPACKET_ID));
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
if(tc->cb->recv != NULL) {
|
if(tc->cb->recv != NULL) {
|
||||||
|
@ -502,6 +694,7 @@ collect_send(struct collect_conn *tc, int rexmits)
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
update_rtmetric(tc);
|
||||||
n = neighbor_best();
|
n = neighbor_best();
|
||||||
if(n != NULL) {
|
if(n != NULL) {
|
||||||
#if CONTIKI_TARGET_NETSIM
|
#if CONTIKI_TARGET_NETSIM
|
||||||
|
@ -510,7 +703,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(&forwarding_queue, FORWARD_PACKET_LIFETIME,
|
if(packetqueue_enqueue_packetbuf(&sending_queue, FORWARD_PACKET_LIFETIME,
|
||||||
tc)) {
|
tc)) {
|
||||||
send_queued_packet();
|
send_queued_packet();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -519,13 +712,12 @@ collect_send(struct collect_conn *tc, int rexmits)
|
||||||
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* printf("Didn't find any neighbor\n");*/
|
|
||||||
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]);
|
||||||
#if COLLECT_ANNOUNCEMENTS
|
#if COLLECT_ANNOUNCEMENTS
|
||||||
announcement_listen(1);
|
announcement_listen(1);
|
||||||
#endif /* COLLECT_ANNOUNCEMENTS */
|
#endif /* COLLECT_ANNOUNCEMENTS */
|
||||||
if(packetqueue_enqueue_packetbuf(&forwarding_queue, FORWARD_PACKET_LIFETIME,
|
if(packetqueue_enqueue_packetbuf(&sending_queue, FORWARD_PACKET_LIFETIME,
|
||||||
tc)) {
|
tc)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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.12 2010/02/23 18:35:23 adamdunkels Exp $
|
* $Id: collect.h,v 1.13 2010/02/28 09:18:01 adamdunkels Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,12 +64,16 @@
|
||||||
#include "net/rime/runicast.h"
|
#include "net/rime/runicast.h"
|
||||||
#include "net/rime/neighbor-discovery.h"
|
#include "net/rime/neighbor-discovery.h"
|
||||||
|
|
||||||
|
#define COLLECT_PACKET_ID_BITS 4
|
||||||
|
|
||||||
#define COLLECT_ATTRIBUTES { PACKETBUF_ADDR_ESENDER, PACKETBUF_ADDRSIZE }, \
|
#define COLLECT_ATTRIBUTES { PACKETBUF_ADDR_ESENDER, PACKETBUF_ADDRSIZE }, \
|
||||||
{ PACKETBUF_ATTR_EPACKET_ID, PACKETBUF_ATTR_BIT * 4 }, \
|
{ PACKETBUF_ATTR_EPACKET_ID, PACKETBUF_ATTR_BIT * 4 }, \
|
||||||
|
{ PACKETBUF_ATTR_PACKET_ID, PACKETBUF_ATTR_BIT * COLLECT_PACKET_ID_BITS }, \
|
||||||
{ PACKETBUF_ATTR_TTL, PACKETBUF_ATTR_BIT * 4 }, \
|
{ PACKETBUF_ATTR_TTL, PACKETBUF_ATTR_BIT * 4 }, \
|
||||||
{ PACKETBUF_ATTR_HOPS, PACKETBUF_ATTR_BIT * 4 }, \
|
{ PACKETBUF_ATTR_HOPS, PACKETBUF_ATTR_BIT * 4 }, \
|
||||||
{ PACKETBUF_ATTR_MAX_REXMIT, PACKETBUF_ATTR_BIT * 3 }, \
|
{ PACKETBUF_ATTR_MAX_REXMIT, PACKETBUF_ATTR_BIT * 3 }, \
|
||||||
RUNICAST_ATTRIBUTES
|
{ PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_BIT }, \
|
||||||
|
UNICAST_ATTRIBUTES
|
||||||
|
|
||||||
struct collect_callbacks {
|
struct collect_callbacks {
|
||||||
void (* recv)(const rimeaddr_t *originator, uint8_t seqno,
|
void (* recv)(const rimeaddr_t *originator, uint8_t seqno,
|
||||||
|
@ -77,7 +81,7 @@ struct collect_callbacks {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct collect_conn {
|
struct collect_conn {
|
||||||
struct runicast_conn runicast_conn;
|
struct unicast_conn unicast_conn;
|
||||||
#if ! COLLECT_CONF_ANNOUNCEMENTS
|
#if ! COLLECT_CONF_ANNOUNCEMENTS
|
||||||
struct neighbor_discovery_conn neighbor_discovery_conn;
|
struct neighbor_discovery_conn neighbor_discovery_conn;
|
||||||
#else /* ! COLLECT_CONF_ANNOUNCEMENTS */
|
#else /* ! COLLECT_CONF_ANNOUNCEMENTS */
|
||||||
|
@ -86,8 +90,12 @@ struct collect_conn {
|
||||||
const struct collect_callbacks *cb;
|
const struct collect_callbacks *cb;
|
||||||
struct ctimer t;
|
struct ctimer t;
|
||||||
uint16_t rtmetric;
|
uint16_t rtmetric;
|
||||||
uint8_t forwarding;
|
uint8_t sending, transmissions, max_rexmits;
|
||||||
uint8_t seqno;
|
uint8_t seqno, last_received_seqno;
|
||||||
|
rimeaddr_t last_received_addr;
|
||||||
|
uint8_t eseqno;
|
||||||
|
struct ctimer retransmission_timer;
|
||||||
|
rimeaddr_t current_receiver;
|
||||||
};
|
};
|
||||||
|
|
||||||
void collect_open(struct collect_conn *c, uint16_t channels,
|
void collect_open(struct collect_conn *c, uint16_t channels,
|
||||||
|
|
Loading…
Reference in a new issue