From a7ce312ee3c30ff4a401bd3ecf9c5f8118dead34 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Thu, 17 Sep 2015 22:42:19 +0200 Subject: [PATCH 1/3] Enhanced RPL loop repair: send unicast DIO to source when detecting a loop from ext header, update rank along the path (when rank error is signaled) --- core/net/rpl/rpl-ext-header.c | 16 ++++++++++++++++ core/net/rpl/rpl-private.h | 1 + core/net/rpl/rpl-timers.c | 18 ++++++++++++++++++ core/net/rpl/rpl.h | 2 ++ 4 files changed, 37 insertions(+) diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c index 1e3250e20..67cf2c5a7 100644 --- a/core/net/rpl/rpl-ext-header.c +++ b/core/net/rpl/rpl-ext-header.c @@ -73,6 +73,7 @@ rpl_verify_header(int uip_ext_opt_offset) uint16_t sender_rank; uint8_t sender_closer; uip_ds6_route_t *route; + rpl_parent_t *sender = NULL; if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) { PRINTF("RPL: Hop-by-hop extension header has wrong size\n"); @@ -132,10 +133,25 @@ rpl_verify_header(int uip_ext_opt_offset) instance->current_dag->rank ); + sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER)); + + if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { + /* A rank error was signalled, attempt to repair it by updating + * the sender's rank from ext header */ + sender->rank = sender_rank; + rpl_select_dag(instance, sender); + } + if((down && !sender_closer) || (!down && sender_closer)) { PRINTF("RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n", sender_rank, instance->current_dag->rank, sender_closer); + /* Attempt to repair the loop by sending a unicast DIO back to the sender + * so that it gets a fresh update of our rank. */ + if(sender != NULL) { + instance->unicast_dio_target = sender; + rpl_schedule_unicast_dio_immediately(instance); + } if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { RPL_STAT(rpl_stats.loop_errors++); PRINTF("RPL: Rank error signalled in RPL option!\n"); diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index b49d71089..92f141fbf 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -312,6 +312,7 @@ rpl_of_t *rpl_find_of(rpl_ocp_t); /* Timer functions. */ void rpl_schedule_dao(rpl_instance_t *); void rpl_schedule_dao_immediately(rpl_instance_t *); +void rpl_schedule_unicast_dio_immediately(rpl_instance_t *instance); void rpl_cancel_dao(rpl_instance_t *instance); void rpl_schedule_probing(rpl_instance_t *instance); diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index 27fff0ddf..f9d8f84e4 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -327,6 +327,24 @@ rpl_cancel_dao(rpl_instance_t *instance) ctimer_stop(&instance->dao_lifetime_timer); } /*---------------------------------------------------------------------------*/ +static void +handle_unicast_dio_timer(void *ptr) +{ + rpl_instance_t *instance = (rpl_instance_t *)ptr; + uip_ipaddr_t *target_ipaddr = rpl_get_parent_ipaddr(instance->unicast_dio_target); + + if(target_ipaddr != NULL) { + dio_output(instance, target_ipaddr); + } +} +/*---------------------------------------------------------------------------*/ +void +rpl_schedule_unicast_dio_immediately(rpl_instance_t *instance) +{ + ctimer_set(&instance->unicast_dio_timer, 0, + handle_unicast_dio_timer, instance); +} +/*---------------------------------------------------------------------------*/ #if RPL_WITH_PROBING static rpl_parent_t * get_probing_target(rpl_dag_t *dag) diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 70c877aeb..535304986 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -230,6 +230,8 @@ struct rpl_instance { struct ctimer dio_timer; struct ctimer dao_timer; struct ctimer dao_lifetime_timer; + struct ctimer unicast_dio_timer; + rpl_parent_t *unicast_dio_target; }; /*---------------------------------------------------------------------------*/ From 66ec94fd74adc3fd6410b3a3e426ccf7666e4ed0 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Thu, 17 Sep 2015 22:42:59 +0200 Subject: [PATCH 2/3] Minor improvements to RPL probing --- core/net/rpl/rpl-timers.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index f9d8f84e4..50300f900 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -414,13 +414,15 @@ handle_probing_timer(void *ptr) { rpl_instance_t *instance = (rpl_instance_t *)ptr; rpl_parent_t *probing_target = RPL_PROBING_SELECT_FUNC(instance->current_dag); + uip_ipaddr_t *target_ipaddr = rpl_get_parent_ipaddr(probing_target); /* Perform probing */ - if(probing_target != NULL && rpl_get_parent_ipaddr(probing_target) != NULL) { - PRINTF("RPL: probing %3u\n", - nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7]); - /* Send probe, e.g. unicast DIO or DIS */ - RPL_PROBING_SEND_FUNC(instance, rpl_get_parent_ipaddr(probing_target)); + if(target_ipaddr != NULL) { + PRINTF("RPL: probing %u ((last tx %u min ago))\n", + nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7], + (unsigned)((clock_time() - probing_target->last_tx_time) / (60 * CLOCK_SECOND))); + /* Send probe (unicast DIO or DIS) */ + RPL_PROBING_SEND_FUNC(instance, target_ipaddr); } /* Schedule next probing */ From 79c436ac03e5bcfc0d5ecf540aba8e6efabe5cdc Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Mon, 16 Nov 2015 11:15:36 +0100 Subject: [PATCH 3/3] rpl_verify_header: sanity-check 'sender' before updating rank --- core/net/rpl/rpl-ext-header.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c index 67cf2c5a7..a2392c124 100644 --- a/core/net/rpl/rpl-ext-header.c +++ b/core/net/rpl/rpl-ext-header.c @@ -135,7 +135,7 @@ rpl_verify_header(int uip_ext_opt_offset) sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER)); - if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { + if(sender != NULL && (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR)) { /* A rank error was signalled, attempt to repair it by updating * the sender's rank from ext header */ sender->rank = sender_rank;