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)

This commit is contained in:
Simon Duquennoy 2015-09-17 22:42:19 +02:00
parent c792993664
commit a7ce312ee3
4 changed files with 37 additions and 0 deletions

View file

@ -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");

View file

@ -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);

View file

@ -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)

View file

@ -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;
};
/*---------------------------------------------------------------------------*/