RPL non-storing defensive link update: make sure the topology is loop-free at all times

This commit is contained in:
Simon Duquennoy 2016-06-08 14:14:03 +02:00
parent 819916668e
commit 535ff25da2

View File

@ -122,6 +122,7 @@ rpl_ns_update_node(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t
{ {
rpl_ns_node_t *child_node = rpl_ns_get_node(dag, child); rpl_ns_node_t *child_node = rpl_ns_get_node(dag, child);
rpl_ns_node_t *parent_node = rpl_ns_get_node(dag, parent); rpl_ns_node_t *parent_node = rpl_ns_get_node(dag, parent);
rpl_ns_node_t *old_parent_node;
if(parent != NULL) { if(parent != NULL) {
/* No node for the parent, add one with infinite lifetime */ /* No node for the parent, add one with infinite lifetime */
@ -140,6 +141,7 @@ rpl_ns_update_node(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t
if(child_node == NULL) { if(child_node == NULL) {
return NULL; return NULL;
} }
child_node->parent = NULL;
list_add(nodelist, child_node); list_add(nodelist, child_node);
num_nodes++; num_nodes++;
} }
@ -147,9 +149,24 @@ rpl_ns_update_node(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t
/* Initialize node */ /* Initialize node */
child_node->dag = dag; child_node->dag = dag;
child_node->lifetime = lifetime; child_node->lifetime = lifetime;
child_node->parent = parent_node;
memcpy(child_node->link_identifier, ((const unsigned char *)child) + 8, 8); memcpy(child_node->link_identifier, ((const unsigned char *)child) + 8, 8);
/* Is the node reachable before the update? */
if(rpl_ns_is_node_reachable(dag, child)) {
old_parent_node = child_node->parent;
/* Update node */
child_node->parent = parent_node;
/* Has the node become unreachable? May happen if we create a loop. */
if(!rpl_ns_is_node_reachable(dag, child)) {
/* The new parent makes the node unreachable, restore old parent.
* We will take the update next time, with chances we know more of
* the topology and the loop is gone. */
child_node->parent = old_parent_node;
}
} else {
child_node->parent = parent_node;
}
return child_node; return child_node;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/