TSCH: time-source recovery in case of failed keep-alive

This commit is contained in:
Simon Duquennoy 2017-06-26 16:39:01 +02:00
parent 89cbf87eee
commit eadc38ac1f
4 changed files with 48 additions and 8 deletions

View File

@ -98,6 +98,8 @@ PROCESS_NAME(tsch_pending_events_process);
/* Set TSCH to send a keepalive message after TSCH_KEEPALIVE_TIMEOUT */
void tsch_schedule_keepalive(void);
/* Set TSCH to send a keepalive message immediately */
void tsch_schedule_keepalive_immediately(void);
/* Leave the TSCH network */
void tsch_disassociate(void);

View File

@ -164,8 +164,6 @@ tsch_queue_update_time_source(const linkaddr_t *new_addr)
new_time_src->is_time_source = 1;
/* (Re)set keep-alive timeout */
tsch_set_ka_timeout(TSCH_KEEPALIVE_TIMEOUT);
/* Start sending keepalives */
tsch_schedule_keepalive();
} else {
/* Stop sending keepalives */
tsch_set_ka_timeout(0);

View File

@ -118,7 +118,9 @@ tsch_rpl_callback_new_dio_interval(clock_time_t dio_interval)
void
tsch_rpl_callback_parent_switch(rpl_parent_t *old, rpl_parent_t *new)
{
if(tsch_is_associated == 1) {
/* Map the TSCH time source on the RPL preferred parent (but stick to the
* current time source if there is no preferred aarent) */
if(tsch_is_associated == 1 && new != NULL) {
tsch_queue_update_time_source(
(const linkaddr_t *)uip_ds6_nbr_lladdr_from_ipaddr(
rpl_parent_get_ipaddr(new)));

View File

@ -75,6 +75,12 @@ void uip_ds6_link_neighbor_callback(int status, int numtx);
#endif /* NETSTACK_CONF_WITH_IPV6 */
#endif /* TSCH_LINK_NEIGHBOR_CALLBACK */
/* The address of the last node we received an EB from (other than our time source).
* Used for recovery */
static linkaddr_t last_eb_nbr_addr;
/* The join priority advertised by last_eb_nbr_addr */
static uint8_t last_eb_nbr_jp;
/* Let TSCH select a time source with no help of an upper layer.
* We do so using statistics from incoming EBs */
#if TSCH_AUTOSELECT_TIME_SOURCE
@ -178,6 +184,11 @@ void
tsch_set_ka_timeout(uint32_t timeout)
{
tsch_current_ka_timeout = timeout;
if(timeout == 0) {
ctimer_stop(&keepalive_timer);
} else {
tsch_schedule_keepalive();
}
}
/*---------------------------------------------------------------------------*/
void
@ -209,11 +220,18 @@ tsch_reset(void)
#ifdef TSCH_CALLBACK_LEAVING_NETWORK
TSCH_CALLBACK_LEAVING_NETWORK();
#endif
linkaddr_copy(&last_eb_nbr_addr, &linkaddr_null);
#if TSCH_AUTOSELECT_TIME_SOURCE
struct nbr_sync_stat *stat;
best_neighbor_eb_count = 0;
nbr_table_register(eb_stats, NULL);
/* Remove all nbr stats */
stat = nbr_table_head(sync_stats);
while(stat != NULL) {
nbr_table_remove(sync_stats, stat);
stat = nbr_table_next(sync_stats, stat);
}
#endif /* TSCH_AUTOSELECT_TIME_SOURCE */
tsch_set_eb_period(TSCH_EB_PERIOD);
#endif
}
/* TSCH keep-alive functions */
@ -260,6 +278,16 @@ tsch_schedule_keepalive()
}
}
/*---------------------------------------------------------------------------*/
/* Set ctimer to send a keepalive message immediately */
void
tsch_schedule_keepalive_immediately(void)
{
/* Pick a delay in the range [tsch_current_ka_timeout*0.9, tsch_current_ka_timeout[ */
if(!tsch_is_coordinator && tsch_is_associated) {
ctimer_set(&keepalive_timer, 0, keepalive_send, NULL);
}
}
/*---------------------------------------------------------------------------*/
static void
eb_input(struct input_packet *current_input)
{
@ -273,6 +301,14 @@ eb_input(struct input_packet *current_input)
&frame, &eb_ies, NULL, 1)) {
/* PAN ID check and authentication done at rx time */
/* Got an EB from a different neighbor than our time source, keep enough data
* to switch to it in case we lose the link to our time source */
struct tsch_neighbor *ts = tsch_queue_get_time_source();
if(ts == NULL || !linkaddr_cmp(&last_eb_nbr_addr, &ts->addr)) {
linkaddr_copy(&last_eb_nbr_addr, (linkaddr_t *)&frame.src_addr);
last_eb_nbr_jp = eb_ies.ie_join_priority;
}
#if TSCH_AUTOSELECT_TIME_SOURCE
if(!tsch_is_coordinator) {
/* Maintain EB received counter for every neighbor */
@ -304,11 +340,10 @@ eb_input(struct input_packet *current_input)
tsch_join_priority = best_stat->jp + 1;
}
}
#endif
#endif /* TSCH_AUTOSELECT_TIME_SOURCE */
struct tsch_neighbor *n = tsch_queue_get_time_source();
/* Did the EB come from our time source? */
if(n != NULL && linkaddr_cmp((linkaddr_t *)&frame.src_addr, &n->addr)) {
if(ts != NULL && linkaddr_cmp((linkaddr_t *)&frame.src_addr, &ts->addr)) {
/* Check for ASN drift */
int32_t asn_diff = TSCH_ASN_DIFF(current_input->rx_asn, eb_ies.ie_asn);
if(asn_diff != 0) {
@ -854,6 +889,9 @@ tsch_init(void)
tsch_log_init();
ringbufindex_init(&input_ringbuf, TSCH_MAX_INCOMING_PACKETS);
ringbufindex_init(&dequeued_ringbuf, TSCH_DEQUEUED_ARRAY_SIZE);
#if TSCH_AUTOSELECT_TIME_SOURCE
nbr_table_register(sync_stats, NULL);
#endif /* TSCH_AUTOSELECT_TIME_SOURCE */
tsch_is_initialized = 1;