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/rpl/rpl-private.h"
|
||||||
#include "net/uip.h"
|
#include "net/uip.h"
|
||||||
#include "net/uip-nd6.h"
|
#include "net/uip-nd6.h"
|
||||||
|
#include "net/neighbor-table.h"
|
||||||
#include "lib/list.h"
|
#include "lib/list.h"
|
||||||
#include "lib/memb.h"
|
#include "lib/memb.h"
|
||||||
#include "sys/ctimer.h"
|
#include "sys/ctimer.h"
|
||||||
|
@ -62,13 +63,6 @@
|
||||||
extern rpl_of_t RPL_OF;
|
extern rpl_of_t RPL_OF;
|
||||||
static rpl_of_t * const objective_functions[] = {&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. */
|
/* RPL definitions. */
|
||||||
|
|
||||||
|
@ -79,14 +73,49 @@ static rpl_of_t * const objective_functions[] = {&RPL_OF};
|
||||||
#endif /* !RPL_CONF_GROUNDED */
|
#endif /* !RPL_CONF_GROUNDED */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* Allocate parents from the same static MEMB chunk to reduce memory waste. */
|
/* Per-parent RPL information */
|
||||||
MEMB(parent_memb, struct rpl_parent,
|
NEIGHBOR_TABLE(rpl_parent_t, rpl_parents);
|
||||||
RPL_MAX_PARENTS_PER_DAG * RPL_MAX_INSTANCES * RPL_MAX_DAG_PER_INSTANCE);
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* Allocate instance table. */
|
/* Allocate instance table. */
|
||||||
rpl_instance_t instance_table[RPL_MAX_INSTANCES];
|
rpl_instance_t instance_table[RPL_MAX_INSTANCES];
|
||||||
rpl_instance_t *default_instance;
|
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. */
|
/* Greater-than function for the lollipop counter. */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
|
@ -107,53 +136,34 @@ lollipop_greater_than(int a, int b)
|
||||||
static void
|
static void
|
||||||
remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
|
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",
|
PRINTF("RPL: Removing parents (minimum rank %u)\n",
|
||||||
minimum_rank);
|
minimum_rank);
|
||||||
|
|
||||||
for(p = list_head(dag->parents); p != NULL; p = p2) {
|
p = nbr_table_head(rpl_parents);
|
||||||
p2 = p->next;
|
while(p != NULL) {
|
||||||
if(p->rank >= minimum_rank) {
|
if(dag == p->dag && p->rank >= minimum_rank) {
|
||||||
rpl_remove_parent(dag, p);
|
rpl_remove_parent(p);
|
||||||
}
|
}
|
||||||
|
p = nbr_table_next(rpl_parents, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
nullify_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
|
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",
|
PRINTF("RPL: Removing parents (minimum rank %u)\n",
|
||||||
minimum_rank);
|
minimum_rank);
|
||||||
|
|
||||||
for(p = list_head(dag->parents); p != NULL; p = p2) {
|
p = nbr_table_head(rpl_parents);
|
||||||
p2 = p->next;
|
while(p != NULL) {
|
||||||
if(p->rank >= minimum_rank) {
|
if(dag == p->dag && p->rank >= minimum_rank) {
|
||||||
rpl_nullify_parent(dag, p);
|
rpl_nullify_parent(p);
|
||||||
}
|
}
|
||||||
}
|
p = nbr_table_next(rpl_parents, 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -231,7 +241,7 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id)
|
||||||
dag->grounded = RPL_GROUNDED;
|
dag->grounded = RPL_GROUNDED;
|
||||||
instance->mop = RPL_MOP_DEFAULT;
|
instance->mop = RPL_MOP_DEFAULT;
|
||||||
instance->of = &RPL_OF;
|
instance->of = &RPL_OF;
|
||||||
dag->preferred_parent = NULL;
|
rpl_set_preferred_parent(dag, NULL);
|
||||||
|
|
||||||
memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id));
|
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);
|
PRINT6ADDR(from);
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
instance->def_route = uip_ds6_defrt_add(from,
|
instance->def_route = uip_ds6_defrt_add(from,
|
||||||
RPL_LIFETIME(instance,
|
RPL_LIFETIME(instance,
|
||||||
instance->default_lifetime));
|
instance->default_lifetime));
|
||||||
if(instance->def_route == NULL) {
|
if(instance->def_route == NULL) {
|
||||||
return 0;
|
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) {
|
for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
|
||||||
if(!dag->used) {
|
if(!dag->used) {
|
||||||
memset(dag, 0, sizeof(*dag));
|
memset(dag, 0, sizeof(*dag));
|
||||||
LIST_STRUCT_INIT(dag, parents);
|
|
||||||
dag->used = 1;
|
dag->used = 1;
|
||||||
dag->rank = INFINITE_RANK;
|
dag->rank = INFINITE_RANK;
|
||||||
dag->min_rank = INFINITE_RANK;
|
dag->min_rank = INFINITE_RANK;
|
||||||
|
@ -502,77 +511,65 @@ rpl_free_dag(rpl_dag_t *dag)
|
||||||
rpl_parent_t *
|
rpl_parent_t *
|
||||||
rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr)
|
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) {
|
if(lladdr != NULL) {
|
||||||
return NULL;
|
/* Add parent in rpl_parents */
|
||||||
}
|
p = nbr_table_add_lladdr(rpl_parents, (rimeaddr_t *)lladdr);
|
||||||
|
p->dag = dag;
|
||||||
p = memb_alloc(&parent_memb);
|
p->rank = dio->rank;
|
||||||
if(p == NULL) {
|
p->dtsn = dio->dtsn;
|
||||||
RPL_STAT(rpl_stats.mem_overflows++);
|
p->link_metric = RPL_INIT_LINK_METRIC;
|
||||||
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 RPL_DAG_MC != RPL_DAG_MC_NONE
|
#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 */
|
#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
|
||||||
list_add(dag->parents, p);
|
}
|
||||||
|
|
||||||
return 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_parent_t *
|
||||||
rpl_find_parent(rpl_dag_t *dag, uip_ipaddr_t *addr)
|
rpl_find_parent(rpl_dag_t *dag, uip_ipaddr_t *addr)
|
||||||
{
|
{
|
||||||
rpl_parent_t *p;
|
rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
|
||||||
|
if(p != NULL && p->dag == dag) {
|
||||||
for(p = list_head(dag->parents); p != NULL; p = p->next) {
|
return p;
|
||||||
if(uip_ipaddr_cmp(&p->addr, addr)) {
|
} else {
|
||||||
return p;
|
return NULL;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static rpl_dag_t *
|
static rpl_dag_t *
|
||||||
find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr)
|
find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr)
|
||||||
{
|
{
|
||||||
rpl_parent_t *p;
|
rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
|
||||||
rpl_dag_t *dag, *end;
|
if(p != NULL) {
|
||||||
|
return p->dag;
|
||||||
for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
|
} else {
|
||||||
if(dag->used) {
|
return NULL;
|
||||||
for(p = list_head(dag->parents); p != NULL; p = p->next) {
|
|
||||||
if(uip_ipaddr_cmp(&p->addr, addr)) {
|
|
||||||
return dag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
rpl_parent_t *
|
rpl_parent_t *
|
||||||
rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr)
|
rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr)
|
||||||
{
|
{
|
||||||
rpl_parent_t *p;
|
rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
|
||||||
rpl_dag_t *dag, *end;
|
if(p && p->dag && p->dag->instance == instance) {
|
||||||
|
return p;
|
||||||
for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
|
} else {
|
||||||
if(dag->used) {
|
return NULL;
|
||||||
for(p = list_head(dag->parents); p != NULL; p = p->next) {
|
|
||||||
if(uip_ipaddr_cmp(&p->addr, addr)) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
rpl_dag_t *
|
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;
|
best_dag->min_rank = best_dag->rank;
|
||||||
} else if(!acceptable_rank(best_dag, best_dag->rank)) {
|
} else if(!acceptable_rank(best_dag, best_dag->rank)) {
|
||||||
PRINTF("RPL: New rank unacceptable!\n");
|
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) {
|
if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES && last_parent != NULL) {
|
||||||
/* Send a No-Path DAO to the removed preferred parent. */
|
/* Send a No-Path DAO to the removed preferred parent. */
|
||||||
dao_output(last_parent, RPL_ZERO_LIFETIME);
|
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) {
|
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",
|
PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n",
|
||||||
(unsigned)old_rank, best_dag->rank);
|
(unsigned)old_rank, best_dag->rank);
|
||||||
RPL_STAT(rpl_stats.parent_switch++);
|
RPL_STAT(rpl_stats.parent_switch++);
|
||||||
|
@ -672,7 +669,9 @@ rpl_select_parent(rpl_dag_t *dag)
|
||||||
rpl_parent_t *p, *best;
|
rpl_parent_t *p, *best;
|
||||||
|
|
||||||
best = NULL;
|
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) {
|
if(p->rank == INFINITE_RANK) {
|
||||||
/* ignore this neighbor */
|
/* ignore this neighbor */
|
||||||
} else if(best == NULL) {
|
} else if(best == NULL) {
|
||||||
|
@ -680,42 +679,43 @@ rpl_select_parent(rpl_dag_t *dag)
|
||||||
} else {
|
} else {
|
||||||
best = dag->instance->of->best_parent(best, p);
|
best = dag->instance->of->best_parent(best, p);
|
||||||
}
|
}
|
||||||
|
p = nbr_table_next(rpl_parents, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(best != NULL) {
|
if(best != NULL) {
|
||||||
dag->preferred_parent = best;
|
rpl_set_preferred_parent(dag, best);
|
||||||
}
|
}
|
||||||
|
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
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 ");
|
PRINTF("RPL: Removing parent ");
|
||||||
PRINT6ADDR(&parent->addr);
|
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
|
|
||||||
list_remove(dag->parents, parent);
|
rpl_nullify_parent(parent);
|
||||||
memb_free(&parent_memb, parent);
|
|
||||||
|
nbr_table_remove(rpl_parents, parent);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
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
|
/* 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. */
|
need to handle this condition in order to trigger uip_ds6_defrt_rm. */
|
||||||
if(parent == dag->preferred_parent || dag->preferred_parent == NULL) {
|
if(parent == dag->preferred_parent || dag->preferred_parent == NULL) {
|
||||||
dag->preferred_parent = NULL;
|
rpl_set_preferred_parent(dag, NULL);
|
||||||
dag->rank = INFINITE_RANK;
|
dag->rank = INFINITE_RANK;
|
||||||
if(dag->joined) {
|
if(dag->joined) {
|
||||||
if(dag->instance->def_route != NULL) {
|
if(dag->instance->def_route != NULL) {
|
||||||
PRINTF("RPL: Removing default route ");
|
PRINTF("RPL: Removing default route ");
|
||||||
PRINT6ADDR(&parent->addr);
|
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
uip_ds6_defrt_rm(dag->instance->def_route);
|
uip_ds6_defrt_rm(dag->instance->def_route);
|
||||||
dag->instance->def_route = NULL;
|
dag->instance->def_route = NULL;
|
||||||
}
|
}
|
||||||
dao_output(parent, RPL_ZERO_LIFETIME);
|
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 ");
|
PRINTF("RPL: Nullifying parent ");
|
||||||
PRINT6ADDR(&parent->addr);
|
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -731,11 +731,11 @@ void
|
||||||
rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent)
|
rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent)
|
||||||
{
|
{
|
||||||
if(parent == dag_src->preferred_parent) {
|
if(parent == dag_src->preferred_parent) {
|
||||||
dag_src->preferred_parent = NULL;
|
rpl_set_preferred_parent(dag_src, NULL);
|
||||||
dag_src->rank = INFINITE_RANK;
|
dag_src->rank = INFINITE_RANK;
|
||||||
if(dag_src->joined && dag_src->instance->def_route != NULL) {
|
if(dag_src->joined && dag_src->instance->def_route != NULL) {
|
||||||
PRINTF("RPL: Removing default route ");
|
PRINTF("RPL: Removing default route ");
|
||||||
PRINT6ADDR(&parent->addr);
|
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
PRINTF("rpl_move_parent\n");
|
PRINTF("rpl_move_parent\n");
|
||||||
uip_ds6_defrt_rm(dag_src->instance->def_route);
|
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) {
|
} else if(dag_src->joined) {
|
||||||
/* Remove uIPv6 routes that have this parent as the next hop. */
|
/* 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 ");
|
PRINTF("RPL: Moving parent ");
|
||||||
PRINT6ADDR(&parent->addr);
|
PRINT6ADDR(rpl_get_parent_ipaddr(parent));
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
|
|
||||||
list_remove(dag_src->parents, parent);
|
list_remove(dag_src->parents, parent);
|
||||||
|
@ -831,7 +831,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio)
|
||||||
if(of == NULL) {
|
if(of == NULL) {
|
||||||
PRINTF("RPL: DIO for DAG instance %u does not specify a supported OF\n",
|
PRINTF("RPL: DIO for DAG instance %u does not specify a supported OF\n",
|
||||||
dio->instance_id);
|
dio->instance_id);
|
||||||
rpl_remove_parent(dag, p);
|
rpl_remove_parent(p);
|
||||||
instance->used = 0;
|
instance->used = 0;
|
||||||
return;
|
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. */
|
/* Copy prefix information from the DIO into the DAG object. */
|
||||||
memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t));
|
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);
|
instance->of->update_metric_container(instance);
|
||||||
dag->rank = instance->of->calculate_rank(p, 0);
|
dag->rank = instance->of->calculate_rank(p, 0);
|
||||||
/* So far this is the lowest rank we are aware of. */
|
/* 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) {
|
instance->lifetime_unit != dio->lifetime_unit) {
|
||||||
PRINTF("RPL: DIO for DAG instance %u uncompatible with previos DIO\n",
|
PRINTF("RPL: DIO for DAG instance %u uncompatible with previos DIO\n",
|
||||||
dio->instance_id);
|
dio->instance_id);
|
||||||
rpl_remove_parent(dag, p);
|
rpl_remove_parent(p);
|
||||||
dag->used = 0;
|
dag->used = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -958,7 +958,7 @@ rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
|
||||||
/* copy prefix information into the dag */
|
/* copy prefix information into the dag */
|
||||||
memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t));
|
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->rank = instance->of->calculate_rank(p, 0);
|
||||||
dag->min_rank = dag->rank; /* So far this is the lowest rank we know of. */
|
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
|
void
|
||||||
rpl_recalculate_ranks(void)
|
rpl_recalculate_ranks(void)
|
||||||
{
|
{
|
||||||
rpl_instance_t *instance, *end;
|
|
||||||
rpl_parent_t *p;
|
rpl_parent_t *p;
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We recalculate ranks when we receive feedback from the system rather
|
* We recalculate ranks when we receive feedback from the system rather
|
||||||
* than RPL protocol messages. This periodical recalculation is called
|
* than RPL protocol messages. This periodical recalculation is called
|
||||||
* from a timer in order to keep the stack depth reasonably low.
|
* from a timer in order to keep the stack depth reasonably low.
|
||||||
*/
|
*/
|
||||||
for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES;
|
p = nbr_table_head(rpl_parents);
|
||||||
instance < end; ++instance) {
|
while(p != NULL) {
|
||||||
if(instance->used) {
|
if(p->dag != NULL && p->dag->instance && p->updated) {
|
||||||
for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; i++) {
|
p->updated = 0;
|
||||||
if(instance->dag_table[i].used) {
|
if(!rpl_process_parent_event(p->dag->instance, p)) {
|
||||||
for(p = list_head(instance->dag_table[i].parents);
|
PRINTF("RPL: A parent was dropped\n");
|
||||||
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_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
|
/* The candidate parent is no longer valid: the rank increase resulting
|
||||||
from the choice of it as a parent would be too high. */
|
from the choice of it as a parent would be too high. */
|
||||||
PRINTF("RPL: Unacceptable rank %u\n", (unsigned)p->rank);
|
PRINTF("RPL: Unacceptable rank %u\n", (unsigned)p->rank);
|
||||||
|
rpl_nullify_parent(p);
|
||||||
if(p != instance->current_dag->preferred_parent) {
|
if(p != instance->current_dag->preferred_parent) {
|
||||||
rpl_nullify_parent(p->dag, p);
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
rpl_nullify_parent(p->dag, p);
|
|
||||||
return_value = 0;
|
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));
|
DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank, instance));
|
||||||
if(instance->current_dag->rank != INFINITE_RANK) {
|
if(instance->current_dag->rank != INFINITE_RANK) {
|
||||||
PRINTF("RPL: The preferred parent is ");
|
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",
|
PRINTF(" (rank %u)\n",
|
||||||
(unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank, instance));
|
(unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank, instance));
|
||||||
} else {
|
} 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. */
|
/* The DIO sender is on an older version of the DAG. */
|
||||||
PRINTF("RPL: old version received => inconsistency detected\n");
|
PRINTF("RPL: old version received => inconsistency detected\n");
|
||||||
if(dag->joined) {
|
if(dag->joined) {
|
||||||
rpl_reset_dio_timer(instance);
|
rpl_reset_dio_timer(instance);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1196,10 +1179,6 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
||||||
if(p == NULL) {
|
if(p == NULL) {
|
||||||
previous_dag = find_parent_dag(instance, from);
|
previous_dag = find_parent_dag(instance, from);
|
||||||
if(previous_dag == NULL) {
|
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. */
|
/* Add the DIO sender as a candidate parent. */
|
||||||
p = rpl_add_parent(dag, dio, from);
|
p = rpl_add_parent(dag, dio, from);
|
||||||
if(p == NULL) {
|
if(p == NULL) {
|
||||||
|
|
|
@ -664,7 +664,7 @@ dao_input(void)
|
||||||
|
|
||||||
if(lifetime == RPL_ZERO_LIFETIME) {
|
if(lifetime == RPL_ZERO_LIFETIME) {
|
||||||
/* No-Path DAO received; invoke the route purging routine. */
|
/* 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 ");
|
PRINTF("RPL: Setting expiration timer for prefix ");
|
||||||
PRINT6ADDR(&prefix);
|
PRINT6ADDR(&prefix);
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
|
@ -706,7 +706,7 @@ dao_input(void)
|
||||||
PRINTF("RPL: Forwarding DAO to parent ");
|
PRINTF("RPL: Forwarding DAO to parent ");
|
||||||
PRINT6ADDR(&dag->preferred_parent->addr);
|
PRINT6ADDR(&dag->preferred_parent->addr);
|
||||||
PRINTF("\n");
|
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);
|
ICMP6_RPL, RPL_CODE_DAO, buffer_length);
|
||||||
}
|
}
|
||||||
if(flags & RPL_DAO_K_FLAG) {
|
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);
|
PRINT6ADDR(&parent->addr);
|
||||||
PRINTF("\n");
|
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
|
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_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(rpl_dag_t *, uip_ipaddr_t *);
|
||||||
rpl_parent_t *rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr);
|
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_nullify_parent(rpl_parent_t *);
|
||||||
void rpl_remove_parent(rpl_dag_t *, 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);
|
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_parent_t *rpl_select_parent(rpl_dag_t *dag);
|
||||||
rpl_dag_t *rpl_select_dag(rpl_instance_t *instance,rpl_parent_t *parent);
|
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");
|
PRINTF("RPL started\n");
|
||||||
default_instance = NULL;
|
default_instance = NULL;
|
||||||
|
|
||||||
|
rpl_dag_init();
|
||||||
rpl_reset_periodic_timer();
|
rpl_reset_periodic_timer();
|
||||||
neighbor_info_subscribe(rpl_link_neighbor_callback);
|
neighbor_info_subscribe(rpl_link_neighbor_callback);
|
||||||
|
|
||||||
|
|
|
@ -113,9 +113,8 @@ struct rpl_parent {
|
||||||
#if RPL_DAG_MC != RPL_DAG_MC_NONE
|
#if RPL_DAG_MC != RPL_DAG_MC_NONE
|
||||||
rpl_metric_container_t mc;
|
rpl_metric_container_t mc;
|
||||||
#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
|
#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
|
||||||
uip_ipaddr_t addr;
|
|
||||||
rpl_rank_t rank;
|
rpl_rank_t rank;
|
||||||
uint8_t link_metric;
|
uint16_t link_metric;
|
||||||
uint8_t dtsn;
|
uint8_t dtsn;
|
||||||
uint8_t updated;
|
uint8_t updated;
|
||||||
};
|
};
|
||||||
|
@ -243,5 +242,8 @@ int rpl_update_header_final(uip_ipaddr_t *addr);
|
||||||
int rpl_verify_header(int);
|
int rpl_verify_header(int);
|
||||||
void rpl_remove_header(void);
|
void rpl_remove_header(void);
|
||||||
uint8_t rpl_invert_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 */
|
#endif /* RPL_H */
|
||||||
|
|
Loading…
Reference in a new issue