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:
nvt-se 2010-06-03 12:55:09 +00:00
parent 352fb4e74d
commit f52e97111f

View File

@ -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);
} }