Merge pull request #1091 from simonduq/rpl-loop-repair
Enhanced RPL loop repair
This commit is contained in:
commit
94c26b90d0
|
@ -73,6 +73,7 @@ rpl_verify_header(int uip_ext_opt_offset)
|
||||||
uint16_t sender_rank;
|
uint16_t sender_rank;
|
||||||
uint8_t sender_closer;
|
uint8_t sender_closer;
|
||||||
uip_ds6_route_t *route;
|
uip_ds6_route_t *route;
|
||||||
|
rpl_parent_t *sender = NULL;
|
||||||
|
|
||||||
if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) {
|
if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) {
|
||||||
PRINTF("RPL: Hop-by-hop extension header has wrong size\n");
|
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
|
instance->current_dag->rank
|
||||||
);
|
);
|
||||||
|
|
||||||
|
sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
||||||
|
|
||||||
|
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;
|
||||||
|
rpl_select_dag(instance, sender);
|
||||||
|
}
|
||||||
|
|
||||||
if((down && !sender_closer) || (!down && sender_closer)) {
|
if((down && !sender_closer) || (!down && sender_closer)) {
|
||||||
PRINTF("RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n",
|
PRINTF("RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n",
|
||||||
sender_rank, instance->current_dag->rank,
|
sender_rank, instance->current_dag->rank,
|
||||||
sender_closer);
|
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) {
|
if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) {
|
||||||
RPL_STAT(rpl_stats.loop_errors++);
|
RPL_STAT(rpl_stats.loop_errors++);
|
||||||
PRINTF("RPL: Rank error signalled in RPL option!\n");
|
PRINTF("RPL: Rank error signalled in RPL option!\n");
|
||||||
|
|
|
@ -309,6 +309,7 @@ rpl_of_t *rpl_find_of(rpl_ocp_t);
|
||||||
/* Timer functions. */
|
/* Timer functions. */
|
||||||
void rpl_schedule_dao(rpl_instance_t *);
|
void rpl_schedule_dao(rpl_instance_t *);
|
||||||
void rpl_schedule_dao_immediately(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_cancel_dao(rpl_instance_t *instance);
|
||||||
void rpl_schedule_probing(rpl_instance_t *instance);
|
void rpl_schedule_probing(rpl_instance_t *instance);
|
||||||
|
|
||||||
|
|
|
@ -328,6 +328,24 @@ rpl_cancel_dao(rpl_instance_t *instance)
|
||||||
ctimer_stop(&instance->dao_lifetime_timer);
|
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
|
#if RPL_WITH_PROBING
|
||||||
static rpl_parent_t *
|
static rpl_parent_t *
|
||||||
get_probing_target(rpl_dag_t *dag)
|
get_probing_target(rpl_dag_t *dag)
|
||||||
|
@ -397,13 +415,15 @@ handle_probing_timer(void *ptr)
|
||||||
{
|
{
|
||||||
rpl_instance_t *instance = (rpl_instance_t *)ptr;
|
rpl_instance_t *instance = (rpl_instance_t *)ptr;
|
||||||
rpl_parent_t *probing_target = RPL_PROBING_SELECT_FUNC(instance->current_dag);
|
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 */
|
/* Perform probing */
|
||||||
if(probing_target != NULL && rpl_get_parent_ipaddr(probing_target) != NULL) {
|
if(target_ipaddr != NULL) {
|
||||||
PRINTF("RPL: probing %3u\n",
|
PRINTF("RPL: probing %u ((last tx %u min ago))\n",
|
||||||
nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7]);
|
nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7],
|
||||||
/* Send probe, e.g. unicast DIO or DIS */
|
(unsigned)((clock_time() - probing_target->last_tx_time) / (60 * CLOCK_SECOND)));
|
||||||
RPL_PROBING_SEND_FUNC(instance, rpl_get_parent_ipaddr(probing_target));
|
/* Send probe (unicast DIO or DIS) */
|
||||||
|
RPL_PROBING_SEND_FUNC(instance, target_ipaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Schedule next probing */
|
/* Schedule next probing */
|
||||||
|
|
|
@ -231,6 +231,8 @@ struct rpl_instance {
|
||||||
struct ctimer dio_timer;
|
struct ctimer dio_timer;
|
||||||
struct ctimer dao_timer;
|
struct ctimer dao_timer;
|
||||||
struct ctimer dao_lifetime_timer;
|
struct ctimer dao_lifetime_timer;
|
||||||
|
struct ctimer unicast_dio_timer;
|
||||||
|
rpl_parent_t *unicast_dio_target;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
Loading…
Reference in a new issue