Make RPL use neighbor tables. RPL locks the neighbor used as preferred parent.
This commit is contained in:
parent
09d26f8060
commit
c50d10aa53
|
@ -45,6 +45,7 @@
|
|||
#include "net/rpl/rpl-private.h"
|
||||
#include "net/uip.h"
|
||||
#include "net/uip-nd6.h"
|
||||
#include "net/neighbor-table.h"
|
||||
#include "lib/list.h"
|
||||
#include "lib/memb.h"
|
||||
#include "sys/ctimer.h"
|
||||
|
@ -62,13 +63,6 @@
|
|||
extern rpl_of_t RPL_OF;
|
||||
static rpl_of_t * const objective_functions[] = {&RPL_OF};
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#ifndef RPL_CONF_MAX_PARENTS_PER_DAG
|
||||
#define RPL_MAX_PARENTS_PER_DAG 8
|
||||
#else
|
||||
#define RPL_MAX_PARENTS_PER_DAG RPL_CONF_MAX_PARENTS_PER_DAG
|
||||
#endif /* !RPL_CONF_MAX_PARENTS_PER_DAG */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* RPL definitions. */
|
||||
|
||||
|
@ -79,14 +73,49 @@ static rpl_of_t * const objective_functions[] = {&RPL_OF};
|
|||
#endif /* !RPL_CONF_GROUNDED */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Allocate parents from the same static MEMB chunk to reduce memory waste. */
|
||||
MEMB(parent_memb, struct rpl_parent,
|
||||
RPL_MAX_PARENTS_PER_DAG * RPL_MAX_INSTANCES * RPL_MAX_DAG_PER_INSTANCE);
|
||||
/* Per-parent RPL information */
|
||||
NEIGHBOR_TABLE(rpl_parent_t, rpl_parents);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Allocate instance table. */
|
||||
rpl_instance_t instance_table[RPL_MAX_INSTANCES];
|
||||
rpl_instance_t *default_instance;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
rpl_dag_init()
|
||||
{
|
||||
nbr_table_register(rpl_parents, (remove_callback_func *)rpl_remove_parent);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
rpl_rank_t
|
||||
rpl_get_parent_rank(uip_lladdr_t *addr)
|
||||
{
|
||||
rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (rimeaddr_t *)addr);
|
||||
if(p != NULL) {
|
||||
return p->rank;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uip_ipaddr_t *
|
||||
rpl_get_parent_ipaddr(rpl_parent_t *p)
|
||||
{
|
||||
rimeaddr_t *lladdr = nbr_table_get_lladdr(rpl_parents, p);
|
||||
return uip_ds6_nbr_ipaddr_from_lladdr((uip_lladdr_t *)lladdr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
rpl_set_preferred_parent(rpl_dag_t *dag, rpl_parent_t *p)
|
||||
{
|
||||
if(dag != NULL && dag->preferred_parent != p) {
|
||||
/* Always keep the preferred parent locked, so it remains in the
|
||||
* neighbor table. */
|
||||
nbr_table_unlock(rpl_parents, dag->preferred_parent);
|
||||
nbr_table_lock(rpl_parents, p);
|
||||
}
|
||||
dag->preferred_parent = p;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Greater-than function for the lollipop counter. */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
|
@ -107,53 +136,34 @@ lollipop_greater_than(int a, int b)
|
|||
static void
|
||||
remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
|
||||
{
|
||||
rpl_parent_t *p, *p2;
|
||||
rpl_parent_t *p;
|
||||
|
||||
PRINTF("RPL: Removing parents (minimum rank %u)\n",
|
||||
minimum_rank);
|
||||
|
||||
for(p = list_head(dag->parents); p != NULL; p = p2) {
|
||||
p2 = p->next;
|
||||
if(p->rank >= minimum_rank) {
|
||||
rpl_remove_parent(dag, p);
|
||||
p = nbr_table_head(rpl_parents);
|
||||
while(p != NULL) {
|
||||
if(dag == p->dag && p->rank >= minimum_rank) {
|
||||
rpl_remove_parent(p);
|
||||
}
|
||||
p = nbr_table_next(rpl_parents, p);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
nullify_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
|
||||
{
|
||||
rpl_parent_t *p, *p2;
|
||||
rpl_parent_t *p;
|
||||
|
||||
PRINTF("RPL: Removing parents (minimum rank %u)\n",
|
||||
minimum_rank);
|
||||
|
||||
for(p = list_head(dag->parents); p != NULL; p = p2) {
|
||||
p2 = p->next;
|
||||
if(p->rank >= minimum_rank) {
|
||||
rpl_nullify_parent(dag, p);
|
||||
p = nbr_table_head(rpl_parents);
|
||||
while(p != NULL) {
|
||||
if(dag == p->dag && p->rank >= minimum_rank) {
|
||||
rpl_nullify_parent(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
remove_worst_parent(rpl_dag_t *dag, rpl_rank_t min_worst_rank)
|
||||
{
|
||||
rpl_parent_t *p, *worst;
|
||||
|
||||
PRINTF("RPL: Removing the worst parent\n");
|
||||
|
||||
/* Find the parent with the highest rank. */
|
||||
worst = NULL;
|
||||
for(p = list_head(dag->parents); p != NULL; p = list_item_next(p)) {
|
||||
if(p != dag->preferred_parent &&
|
||||
(worst == NULL || p->rank > worst->rank)) {
|
||||
worst = p;
|
||||
}
|
||||
}
|
||||
/* Remove the neighbor if its rank is worse than the minimum worst rank. */
|
||||
if(worst != NULL && worst->rank > min_worst_rank) {
|
||||
rpl_remove_parent(dag, worst);
|
||||
p = nbr_table_next(rpl_parents, p);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -231,7 +241,7 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id)
|
|||
dag->grounded = RPL_GROUNDED;
|
||||
instance->mop = RPL_MOP_DEFAULT;
|
||||
instance->of = &RPL_OF;
|
||||
dag->preferred_parent = NULL;
|
||||
rpl_set_preferred_parent(dag, NULL);
|
||||
|
||||
memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id));
|
||||
|
||||
|
@ -378,8 +388,8 @@ rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from)
|
|||
PRINT6ADDR(from);
|
||||
PRINTF("\n");
|
||||
instance->def_route = uip_ds6_defrt_add(from,
|
||||
RPL_LIFETIME(instance,
|
||||
instance->default_lifetime));
|
||||
RPL_LIFETIME(instance,
|
||||
instance->default_lifetime));
|
||||
if(instance->def_route == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -430,7 +440,6 @@ rpl_alloc_dag(uint8_t instance_id, uip_ipaddr_t *dag_id)
|
|||
for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
|
||||
if(!dag->used) {
|
||||
memset(dag, 0, sizeof(*dag));
|
||||
LIST_STRUCT_INIT(dag, parents);
|
||||
dag->used = 1;
|
||||
dag->rank = INFINITE_RANK;
|
||||
dag->min_rank = INFINITE_RANK;
|
||||
|
@ -502,77 +511,65 @@ rpl_free_dag(rpl_dag_t *dag)
|
|||
rpl_parent_t *
|
||||
rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr)
|
||||
{
|
||||
rpl_parent_t *p;
|
||||
rpl_parent_t *p = NULL;
|
||||
/* Is the parent known by ds6? Drop this request if not.
|
||||
* Typically, the parent is added upon receiving a DIO. */
|
||||
uip_lladdr_t *lladdr = uip_ds6_nbr_lladdr_from_ipaddr(addr);
|
||||
|
||||
if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS_PER_DAG) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = memb_alloc(&parent_memb);
|
||||
if(p == NULL) {
|
||||
RPL_STAT(rpl_stats.mem_overflows++);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(&p->addr, addr, sizeof(p->addr));
|
||||
p->dag = dag;
|
||||
p->rank = dio->rank;
|
||||
p->dtsn = dio->dtsn;
|
||||
p->link_metric = RPL_INIT_LINK_METRIC;
|
||||
if(lladdr != NULL) {
|
||||
/* Add parent in rpl_parents */
|
||||
p = nbr_table_add_lladdr(rpl_parents, (rimeaddr_t *)lladdr);
|
||||
p->dag = dag;
|
||||
p->rank = dio->rank;
|
||||
p->dtsn = dio->dtsn;
|
||||
p->link_metric = RPL_INIT_LINK_METRIC;
|
||||
#if RPL_DAG_MC != RPL_DAG_MC_NONE
|
||||
memcpy(&p->mc, &dio->mc, sizeof(p->mc));
|
||||
memcpy(&p->mc, &dio->mc, sizeof(p->mc));
|
||||
#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
|
||||
list_add(dag->parents, p);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static rpl_parent_t *
|
||||
find_parent_any_dag_any_instance(uip_ipaddr_t *addr)
|
||||
{
|
||||
uip_ds6_nbr_t *ds6_nbr = uip_ds6_nbr_lookup(addr);
|
||||
uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(ds6_nbr);
|
||||
return nbr_table_get_from_lladdr(rpl_parents, (rimeaddr_t *)lladdr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
rpl_parent_t *
|
||||
rpl_find_parent(rpl_dag_t *dag, uip_ipaddr_t *addr)
|
||||
{
|
||||
rpl_parent_t *p;
|
||||
|
||||
for(p = list_head(dag->parents); p != NULL; p = p->next) {
|
||||
if(uip_ipaddr_cmp(&p->addr, addr)) {
|
||||
return p;
|
||||
}
|
||||
rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
|
||||
if(p != NULL && p->dag == dag) {
|
||||
return p;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static rpl_dag_t *
|
||||
find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr)
|
||||
{
|
||||
rpl_parent_t *p;
|
||||
rpl_dag_t *dag, *end;
|
||||
|
||||
for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
|
||||
if(dag->used) {
|
||||
for(p = list_head(dag->parents); p != NULL; p = p->next) {
|
||||
if(uip_ipaddr_cmp(&p->addr, addr)) {
|
||||
return dag;
|
||||
}
|
||||
}
|
||||
}
|
||||
rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
|
||||
if(p != NULL) {
|
||||
return p->dag;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
rpl_parent_t *
|
||||
rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr)
|
||||
{
|
||||
rpl_parent_t *p;
|
||||
rpl_dag_t *dag, *end;
|
||||
|
||||
for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
|
||||
if(dag->used) {
|
||||
for(p = list_head(dag->parents); p != NULL; p = p->next) {
|
||||
if(uip_ipaddr_cmp(&p->addr, addr)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
|
||||
if(p && p->dag && p->dag->instance == instance) {
|
||||
return p;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
rpl_dag_t *
|
||||
|
@ -636,7 +633,7 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p)
|
|||
best_dag->min_rank = best_dag->rank;
|
||||
} else if(!acceptable_rank(best_dag, best_dag->rank)) {
|
||||
PRINTF("RPL: New rank unacceptable!\n");
|
||||
instance->current_dag->preferred_parent = NULL;
|
||||
rpl_set_preferred_parent(instance->current_dag, NULL);
|
||||
if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES && last_parent != NULL) {
|
||||
/* Send a No-Path DAO to the removed preferred parent. */
|
||||
dao_output(last_parent, RPL_ZERO_LIFETIME);
|
||||
|
@ -645,7 +642,7 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p)
|
|||
}
|
||||
|
||||
if(best_dag->preferred_parent != last_parent) {
|
||||
rpl_set_default_route(instance, &best_dag->preferred_parent->addr);
|
||||
rpl_set_default_route(instance, rpl_get_parent_ipaddr(best_dag->preferred_parent));
|
||||
PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n",
|
||||
(unsigned)old_rank, best_dag->rank);
|
||||
RPL_STAT(rpl_stats.parent_switch++);
|
||||
|
@ -672,7 +669,9 @@ rpl_select_parent(rpl_dag_t *dag)
|
|||
rpl_parent_t *p, *best;
|
||||
|
||||
best = NULL;
|
||||
for(p = list_head(dag->parents); p != NULL; p = p->next) {
|
||||
|
||||
p = nbr_table_head(rpl_parents);
|
||||
while(p != NULL) {
|
||||
if(p->rank == INFINITE_RANK) {
|
||||
/* ignore this neighbor */
|
||||
} else if(best == NULL) {
|
||||
|
@ -680,42 +679,43 @@ rpl_select_parent(rpl_dag_t *dag)
|
|||
} else {
|
||||
best = dag->instance->of->best_parent(best, p);
|
||||
}
|
||||
p = nbr_table_next(rpl_parents, p);
|
||||
}
|
||||
|
||||
if(best != NULL) {
|
||||
dag->preferred_parent = best;
|
||||
rpl_set_preferred_parent(dag, best);
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
rpl_remove_parent(rpl_dag_t *dag, rpl_parent_t *parent)
|
||||
rpl_remove_parent(rpl_parent_t *parent)
|
||||
{
|
||||
rpl_nullify_parent(dag, parent);
|
||||
|
||||
PRINTF("RPL: Removing parent ");
|
||||
PRINT6ADDR(&parent->addr);
|
||||
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||
PRINTF("\n");
|
||||
|
||||
list_remove(dag->parents, parent);
|
||||
memb_free(&parent_memb, parent);
|
||||
rpl_nullify_parent(parent);
|
||||
|
||||
nbr_table_remove(rpl_parents, parent);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
rpl_nullify_parent(rpl_dag_t *dag, rpl_parent_t *parent)
|
||||
rpl_nullify_parent(rpl_parent_t *parent)
|
||||
{
|
||||
rpl_dag_t *dag = parent->dag;
|
||||
/* This function can be called when the preferred parent is NULL, so we
|
||||
need to handle this condition in order to trigger uip_ds6_defrt_rm. */
|
||||
if(parent == dag->preferred_parent || dag->preferred_parent == NULL) {
|
||||
dag->preferred_parent = NULL;
|
||||
rpl_set_preferred_parent(dag, NULL);
|
||||
dag->rank = INFINITE_RANK;
|
||||
if(dag->joined) {
|
||||
if(dag->instance->def_route != NULL) {
|
||||
PRINTF("RPL: Removing default route ");
|
||||
PRINT6ADDR(&parent->addr);
|
||||
PRINTF("\n");
|
||||
uip_ds6_defrt_rm(dag->instance->def_route);
|
||||
PRINTF("RPL: Removing default route ");
|
||||
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||
PRINTF("\n");
|
||||
uip_ds6_defrt_rm(dag->instance->def_route);
|
||||
dag->instance->def_route = NULL;
|
||||
}
|
||||
dao_output(parent, RPL_ZERO_LIFETIME);
|
||||
|
@ -723,7 +723,7 @@ rpl_nullify_parent(rpl_dag_t *dag, rpl_parent_t *parent)
|
|||
}
|
||||
|
||||
PRINTF("RPL: Nullifying parent ");
|
||||
PRINT6ADDR(&parent->addr);
|
||||
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||
PRINTF("\n");
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -731,11 +731,11 @@ void
|
|||
rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent)
|
||||
{
|
||||
if(parent == dag_src->preferred_parent) {
|
||||
dag_src->preferred_parent = NULL;
|
||||
rpl_set_preferred_parent(dag_src, NULL);
|
||||
dag_src->rank = INFINITE_RANK;
|
||||
if(dag_src->joined && dag_src->instance->def_route != NULL) {
|
||||
PRINTF("RPL: Removing default route ");
|
||||
PRINT6ADDR(&parent->addr);
|
||||
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||
PRINTF("\n");
|
||||
PRINTF("rpl_move_parent\n");
|
||||
uip_ds6_defrt_rm(dag_src->instance->def_route);
|
||||
|
@ -743,11 +743,11 @@ rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent)
|
|||
}
|
||||
} else if(dag_src->joined) {
|
||||
/* Remove uIPv6 routes that have this parent as the next hop. */
|
||||
rpl_remove_routes_by_nexthop(&parent->addr, dag_src);
|
||||
rpl_remove_routes_by_nexthop(rpl_get_parent_ipaddr(parent), dag_src);
|
||||
}
|
||||
|
||||
PRINTF("RPL: Moving parent ");
|
||||
PRINT6ADDR(&parent->addr);
|
||||
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||
PRINTF("\n");
|
||||
|
||||
list_remove(dag_src->parents, parent);
|
||||
|
@ -831,7 +831,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
if(of == NULL) {
|
||||
PRINTF("RPL: DIO for DAG instance %u does not specify a supported OF\n",
|
||||
dio->instance_id);
|
||||
rpl_remove_parent(dag, p);
|
||||
rpl_remove_parent(p);
|
||||
instance->used = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -866,7 +866,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
/* Copy prefix information from the DIO into the DAG object. */
|
||||
memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t));
|
||||
|
||||
dag->preferred_parent = p;
|
||||
rpl_set_preferred_parent(dag, p);
|
||||
instance->of->update_metric_container(instance);
|
||||
dag->rank = instance->of->calculate_rank(p, 0);
|
||||
/* So far this is the lowest rank we are aware of. */
|
||||
|
@ -943,7 +943,7 @@ rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
instance->lifetime_unit != dio->lifetime_unit) {
|
||||
PRINTF("RPL: DIO for DAG instance %u uncompatible with previos DIO\n",
|
||||
dio->instance_id);
|
||||
rpl_remove_parent(dag, p);
|
||||
rpl_remove_parent(p);
|
||||
dag->used = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -958,7 +958,7 @@ rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
/* copy prefix information into the dag */
|
||||
memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t));
|
||||
|
||||
dag->preferred_parent = p;
|
||||
rpl_set_preferred_parent(dag, p);
|
||||
dag->rank = instance->of->calculate_rank(p, 0);
|
||||
dag->min_rank = dag->rank; /* So far this is the lowest rank we know of. */
|
||||
|
||||
|
@ -1022,38 +1022,22 @@ rpl_local_repair(rpl_instance_t *instance)
|
|||
void
|
||||
rpl_recalculate_ranks(void)
|
||||
{
|
||||
rpl_instance_t *instance, *end;
|
||||
rpl_parent_t *p;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We recalculate ranks when we receive feedback from the system rather
|
||||
* than RPL protocol messages. This periodical recalculation is called
|
||||
* from a timer in order to keep the stack depth reasonably low.
|
||||
*/
|
||||
for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES;
|
||||
instance < end; ++instance) {
|
||||
if(instance->used) {
|
||||
for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; i++) {
|
||||
if(instance->dag_table[i].used) {
|
||||
for(p = list_head(instance->dag_table[i].parents);
|
||||
p != NULL; p = p->next) {
|
||||
if(p->updated) {
|
||||
p->updated = 0;
|
||||
if(!rpl_process_parent_event(instance, p)) {
|
||||
PRINTF("RPL: A parent was dropped\n");
|
||||
}
|
||||
/*
|
||||
* Stop calculating here because the parent list may have changed.
|
||||
* If more ranks need to be recalculated, it will be taken care of
|
||||
* in subsequent calls to this functions.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
p = nbr_table_head(rpl_parents);
|
||||
while(p != NULL) {
|
||||
if(p->dag != NULL && p->dag->instance && p->updated) {
|
||||
p->updated = 0;
|
||||
if(!rpl_process_parent_event(p->dag->instance, p)) {
|
||||
PRINTF("RPL: A parent was dropped\n");
|
||||
}
|
||||
}
|
||||
p = nbr_table_next(rpl_parents, p);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -1070,11 +1054,10 @@ rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p)
|
|||
/* The candidate parent is no longer valid: the rank increase resulting
|
||||
from the choice of it as a parent would be too high. */
|
||||
PRINTF("RPL: Unacceptable rank %u\n", (unsigned)p->rank);
|
||||
rpl_nullify_parent(p);
|
||||
if(p != instance->current_dag->preferred_parent) {
|
||||
rpl_nullify_parent(p->dag, p);
|
||||
return 0;
|
||||
} else {
|
||||
rpl_nullify_parent(p->dag, p);
|
||||
return_value = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1092,7 +1075,7 @@ rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p)
|
|||
DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank, instance));
|
||||
if(instance->current_dag->rank != INFINITE_RANK) {
|
||||
PRINTF("RPL: The preferred parent is ");
|
||||
PRINT6ADDR(&instance->current_dag->preferred_parent->addr);
|
||||
PRINT6ADDR(rpl_get_parent_ipaddr(instance->current_dag->preferred_parent));
|
||||
PRINTF(" (rank %u)\n",
|
||||
(unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank, instance));
|
||||
} else {
|
||||
|
@ -1143,8 +1126,8 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
/* The DIO sender is on an older version of the DAG. */
|
||||
PRINTF("RPL: old version received => inconsistency detected\n");
|
||||
if(dag->joined) {
|
||||
rpl_reset_dio_timer(instance);
|
||||
return;
|
||||
rpl_reset_dio_timer(instance);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1196,10 +1179,6 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
|||
if(p == NULL) {
|
||||
previous_dag = find_parent_dag(instance, from);
|
||||
if(previous_dag == NULL) {
|
||||
if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS_PER_DAG) {
|
||||
/* Make room for a new parent. */
|
||||
remove_worst_parent(dag, dio->rank);
|
||||
}
|
||||
/* Add the DIO sender as a candidate parent. */
|
||||
p = rpl_add_parent(dag, dio, from);
|
||||
if(p == NULL) {
|
||||
|
|
|
@ -664,7 +664,7 @@ dao_input(void)
|
|||
|
||||
if(lifetime == RPL_ZERO_LIFETIME) {
|
||||
/* No-Path DAO received; invoke the route purging routine. */
|
||||
if(rep != NULL && rep->state.nopath_received == 0 && rep->length == prefixlen && uip_ipaddr_cmp(&rep->nexthop, &dao_sender_addr)) {
|
||||
if(rep != NULL && rep->state.nopath_received == 0 && rep->length == prefixlen && uip_ipaddr_cmp(uip_ds6_route_nexthop(rep), &dao_sender_addr)) {
|
||||
PRINTF("RPL: Setting expiration timer for prefix ");
|
||||
PRINT6ADDR(&prefix);
|
||||
PRINTF("\n");
|
||||
|
@ -706,7 +706,7 @@ dao_input(void)
|
|||
PRINTF("RPL: Forwarding DAO to parent ");
|
||||
PRINT6ADDR(&dag->preferred_parent->addr);
|
||||
PRINTF("\n");
|
||||
uip_icmp6_send(&dag->preferred_parent->addr,
|
||||
uip_icmp6_send(rpl_get_parent_ipaddr(dag->preferred_parent),
|
||||
ICMP6_RPL, RPL_CODE_DAO, buffer_length);
|
||||
}
|
||||
if(flags & RPL_DAO_K_FLAG) {
|
||||
|
@ -792,7 +792,7 @@ dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime)
|
|||
PRINT6ADDR(&parent->addr);
|
||||
PRINTF("\n");
|
||||
|
||||
uip_icmp6_send(&parent->addr, ICMP6_RPL, RPL_CODE_DAO, pos);
|
||||
uip_icmp6_send(rpl_get_parent_ipaddr(parent), ICMP6_RPL, RPL_CODE_DAO, pos);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
|
|
|
@ -290,8 +290,8 @@ void rpl_free_instance(rpl_instance_t *);
|
|||
rpl_parent_t *rpl_add_parent(rpl_dag_t *, rpl_dio_t *dio, uip_ipaddr_t *);
|
||||
rpl_parent_t *rpl_find_parent(rpl_dag_t *, uip_ipaddr_t *);
|
||||
rpl_parent_t *rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr);
|
||||
void rpl_nullify_parent(rpl_dag_t *, rpl_parent_t *);
|
||||
void rpl_remove_parent(rpl_dag_t *, rpl_parent_t *);
|
||||
void rpl_nullify_parent(rpl_parent_t *);
|
||||
void rpl_remove_parent(rpl_parent_t *);
|
||||
void rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent);
|
||||
rpl_parent_t *rpl_select_parent(rpl_dag_t *dag);
|
||||
rpl_dag_t *rpl_select_dag(rpl_instance_t *instance,rpl_parent_t *parent);
|
||||
|
|
|
@ -240,6 +240,7 @@ rpl_init(void)
|
|||
PRINTF("RPL started\n");
|
||||
default_instance = NULL;
|
||||
|
||||
rpl_dag_init();
|
||||
rpl_reset_periodic_timer();
|
||||
neighbor_info_subscribe(rpl_link_neighbor_callback);
|
||||
|
||||
|
|
|
@ -113,9 +113,8 @@ struct rpl_parent {
|
|||
#if RPL_DAG_MC != RPL_DAG_MC_NONE
|
||||
rpl_metric_container_t mc;
|
||||
#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
|
||||
uip_ipaddr_t addr;
|
||||
rpl_rank_t rank;
|
||||
uint8_t link_metric;
|
||||
uint16_t link_metric;
|
||||
uint8_t dtsn;
|
||||
uint8_t updated;
|
||||
};
|
||||
|
@ -243,5 +242,8 @@ int rpl_update_header_final(uip_ipaddr_t *addr);
|
|||
int rpl_verify_header(int);
|
||||
void rpl_remove_header(void);
|
||||
uint8_t rpl_invert_header(void);
|
||||
uip_ipaddr_t *rpl_get_parent_ipaddr(rpl_parent_t *nbr);
|
||||
rpl_rank_t rpl_get_parent_rank(uip_lladdr_t *addr);
|
||||
void rpl_dag_init();
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#endif /* RPL_H */
|
||||
|
|
Loading…
Reference in a new issue