Made the remove_parents function more powerful by adding a flag that indicates whether no-DAOs should be sent or not. Fixed some style issues and a possible NULL pointer dereference.
This commit is contained in:
parent
352fb4e74d
commit
f52e97111f
|
@ -32,7 +32,7 @@
|
||||||
*
|
*
|
||||||
* This file is part of the Contiki operating system.
|
* This file is part of the Contiki operating system.
|
||||||
*
|
*
|
||||||
* $Id: rpl-dag.c,v 1.15 2010/06/02 16:54:59 joxe Exp $
|
* $Id: rpl-dag.c,v 1.16 2010/06/03 12:55:09 nvt-se Exp $
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
|
@ -97,20 +97,25 @@ static rpl_of_t *objective_functions[] = {&rpl_of_etx, NULL};
|
||||||
MEMB(parent_memb, struct rpl_parent, RPL_MAX_PARENTS);
|
MEMB(parent_memb, struct rpl_parent, RPL_MAX_PARENTS);
|
||||||
|
|
||||||
static rpl_dag_t dag_table[RPL_MAX_DAG_ENTRIES];
|
static rpl_dag_t dag_table[RPL_MAX_DAG_ENTRIES];
|
||||||
|
|
||||||
|
#define POISON_ROUTES 1
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
static void
|
static void
|
||||||
poison_routes(rpl_dag_t *dag, rpl_parent_t *exception)
|
remove_parents(rpl_dag_t *dag, rpl_parent_t *exception, int poison_routes)
|
||||||
{
|
{
|
||||||
rpl_parent_t *p, *p2;
|
rpl_parent_t *p, *p2;
|
||||||
|
|
||||||
PRINTF("RPL: Poisoning routes\n");
|
PRINTF("RPL: Removing parents %s poisoning routes\n",
|
||||||
|
poison_routes == POISON_ROUTES ? "and" : "without");
|
||||||
|
|
||||||
for(p = list_head(dag->parents); p != NULL;) {
|
for(p = list_head(dag->parents); p != NULL;) {
|
||||||
if(p != exception) {
|
if(p != exception) {
|
||||||
ANNOTATE("#L %u 0\n", p->addr.u8[sizeof(p->addr) - 1]);
|
ANNOTATE("#L %u 0\n", p->addr.u8[sizeof(p->addr) - 1]);
|
||||||
|
|
||||||
/* Send no-DAOs to old parents. */
|
if(poison_routes == POISON_ROUTES) {
|
||||||
dao_output(p, ZERO_LIFETIME);
|
/* Send no-DAOs to old parents. */
|
||||||
|
dao_output(p, ZERO_LIFETIME);
|
||||||
|
}
|
||||||
|
|
||||||
p2 = p->next;
|
p2 = p->next;
|
||||||
rpl_remove_parent(dag, p);
|
rpl_remove_parent(dag, p);
|
||||||
|
@ -162,16 +167,17 @@ rpl_set_root(uip_ipaddr_t *dag_id)
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
int
|
int
|
||||||
rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len) {
|
rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len)
|
||||||
|
{
|
||||||
if(len <= 128) {
|
if(len <= 128) {
|
||||||
memset(&dag->prefix_info.prefix, 0, 16);
|
memset(&dag->prefix_info.prefix, 0, 16);
|
||||||
memcpy(&dag->prefix_info.prefix, prefix, (len + 7)/ 8);
|
memcpy(&dag->prefix_info.prefix, prefix, (len + 7) / 8);
|
||||||
dag->prefix_info.length = len;
|
dag->prefix_info.length = len;
|
||||||
dag->prefix_info.flags = UIP_ND6_RA_FLAG_AUTONOMOUS;
|
dag->prefix_info.flags = UIP_ND6_RA_FLAG_AUTONOMOUS;
|
||||||
PRINTF("RPL: Prefix set - will announce this in DIOs\n");
|
PRINTF("RPL: Prefix set - will announce this in DIOs\n");
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
int
|
int
|
||||||
|
@ -234,7 +240,7 @@ rpl_free_dag(rpl_dag_t *dag)
|
||||||
|
|
||||||
rpl_set_default_route(dag, NULL);
|
rpl_set_default_route(dag, NULL);
|
||||||
|
|
||||||
poison_routes(dag, NULL);
|
remove_parents(dag, NULL, !POISON_ROUTES);
|
||||||
|
|
||||||
ctimer_stop(&dag->dio_timer);
|
ctimer_stop(&dag->dio_timer);
|
||||||
ctimer_stop(&dag->dao_timer);
|
ctimer_stop(&dag->dao_timer);
|
||||||
|
@ -450,7 +456,7 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio)
|
||||||
{
|
{
|
||||||
rpl_parent_t *p;
|
rpl_parent_t *p;
|
||||||
|
|
||||||
poison_routes(dag, NULL);
|
remove_parents(dag, NULL, !POISON_ROUTES);
|
||||||
dag->version = dio->version;
|
dag->version = dio->version;
|
||||||
dag->of->reset(dag);
|
dag->of->reset(dag);
|
||||||
if((p = rpl_add_parent(dag, dio, from)) == NULL) {
|
if((p = rpl_add_parent(dag, dio, from)) == NULL) {
|
||||||
|
@ -461,7 +467,7 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio)
|
||||||
dag->rank = dag->of->increment_rank(dio->dag_rank, p);
|
dag->rank = dag->of->increment_rank(dio->dag_rank, p);
|
||||||
rpl_reset_dio_timer(dag, 1);
|
rpl_reset_dio_timer(dag, 1);
|
||||||
}
|
}
|
||||||
PRINTF("RPL: Participating in a global DAG repair. New DAG version number: %u, new rank: %hu\n",
|
PRINTF("RPL: Participating in a global repair (version=%u, rank=%hu)\n",
|
||||||
dag->version, dag->rank);
|
dag->version, dag->rank);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -482,6 +488,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
||||||
{
|
{
|
||||||
rpl_dag_t *dag;
|
rpl_dag_t *dag;
|
||||||
rpl_parent_t *p;
|
rpl_parent_t *p;
|
||||||
|
rpl_parent_t *preferred_parent;
|
||||||
uint8_t new_rank;
|
uint8_t new_rank;
|
||||||
uint8_t new_parent;
|
uint8_t new_parent;
|
||||||
|
|
||||||
|
@ -529,10 +536,9 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
||||||
/* This DIO pertains to a DAG that we are already part of. */
|
/* This DIO pertains to a DAG that we are already part of. */
|
||||||
p = rpl_find_parent(dag, from);
|
p = rpl_find_parent(dag, from);
|
||||||
if(p != NULL) {
|
if(p != NULL) {
|
||||||
if(dio->dst_adv_supported && dio->dst_adv_trigger) {
|
if(dio->dst_adv_supported && dio->dst_adv_trigger &&
|
||||||
|
p == rpl_preferred_parent(dag)) {
|
||||||
rpl_schedule_dao(dag);
|
rpl_schedule_dao(dag);
|
||||||
} else {
|
|
||||||
PRINTF("RPL: dst_adv_trigger is not set in incoming DIO\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(p->rank > dio->dag_rank) {
|
if(p->rank > dio->dag_rank) {
|
||||||
|
@ -553,14 +559,18 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if(dag->of->increment_rank(dio->dag_rank, p) <= dag->min_rank + dag->max_rankinc) {
|
} else if(dag->of->increment_rank(dio->dag_rank, p) <= dag->min_rank + dag->max_rankinc) {
|
||||||
dag->rank = dag->of->increment_rank(dio->dag_rank, p);
|
preferred_parent = rpl_preferred_parent(dag);
|
||||||
PRINTF("RPL: New rank is %hu, max is %hu\n",
|
if(p == preferred_parent) {
|
||||||
|
new_rank = dag->of->increment_rank(dio->dag_rank, p);
|
||||||
|
PRINTF("RPL: New rank is %hu, max is %hu\n",
|
||||||
dag->rank, dag->min_rank + dag->max_rankinc);
|
dag->rank, dag->min_rank + dag->max_rankinc);
|
||||||
rpl_set_default_route(dag, &p->addr);
|
rpl_set_default_route(dag, &p->addr);
|
||||||
|
dag->rank = new_rank;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
PRINTF("RPL: Cannot find an acceptable preferred parent\n");
|
PRINTF("RPL: Cannot find an acceptable preferred parent\n");
|
||||||
/* do local repair - jump down the DAG */
|
/* do local repair - jump down the DAG */
|
||||||
poison_routes(dag, NULL);
|
remove_parents(dag, NULL, POISON_ROUTES);
|
||||||
dag->rank = INFINITE_RANK;
|
dag->rank = INFINITE_RANK;
|
||||||
}
|
}
|
||||||
rpl_reset_dio_timer(dag, 1);
|
rpl_reset_dio_timer(dag, 1);
|
||||||
|
@ -605,7 +615,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
||||||
rpl_set_default_route(dag, from);
|
rpl_set_default_route(dag, from);
|
||||||
|
|
||||||
if(new_parent) {
|
if(new_parent) {
|
||||||
poison_routes(dag, p);
|
remove_parents(dag, p, POISON_ROUTES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(dio->dag_rank == dag->rank) {
|
} else if(dio->dag_rank == dag->rank) {
|
||||||
|
@ -654,10 +664,14 @@ rpl_ds6_neighbor_callback(uip_ds6_nbr_t *nbr)
|
||||||
if(dag != NULL && dag->def_route != NULL &&
|
if(dag != NULL && dag->def_route != NULL &&
|
||||||
uip_ipaddr_cmp(&dag->def_route->ipaddr, &p->addr)) {
|
uip_ipaddr_cmp(&dag->def_route->ipaddr, &p->addr)) {
|
||||||
p = rpl_preferred_parent(dag);
|
p = rpl_preferred_parent(dag);
|
||||||
acceptable_rank_increase = !dag->max_rankinc ||
|
if(p == NULL) {
|
||||||
dag->of->increment_rank(p->rank, p) <= dag->min_rank + dag->max_rankinc;
|
rpl_free_dag(dag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(p != NULL && acceptable_rank_increase) {
|
acceptable_rank_increase = !dag->max_rankinc ||
|
||||||
|
dag->of->increment_rank(p->rank, p) <= dag->min_rank + dag->max_rankinc;
|
||||||
|
if(acceptable_rank_increase) {
|
||||||
dag->rank = dag->of->increment_rank(p->rank, p);
|
dag->rank = dag->of->increment_rank(p->rank, p);
|
||||||
if(dag->rank < dag->min_rank) {
|
if(dag->rank < dag->min_rank) {
|
||||||
dag->min_rank = dag->rank;
|
dag->min_rank = dag->rank;
|
||||||
|
@ -668,7 +682,7 @@ rpl_ds6_neighbor_callback(uip_ds6_nbr_t *nbr)
|
||||||
} else {
|
} else {
|
||||||
PRINTF("RPL: Cannot select the preferred parent\n");
|
PRINTF("RPL: Cannot select the preferred parent\n");
|
||||||
/* do local repair - jump down the DAG */
|
/* do local repair - jump down the DAG */
|
||||||
poison_routes(dag, NULL);
|
remove_parents(dag, NULL, POISON_ROUTES);
|
||||||
dag->rank = INFINITE_RANK;
|
dag->rank = INFINITE_RANK;
|
||||||
rpl_reset_dio_timer(dag, 1);
|
rpl_reset_dio_timer(dag, 1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue