Improved logic for processing DIOs
This commit is contained in:
parent
c44cf73e4f
commit
007d4a4001
|
@ -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.29 2010/06/14 18:35:04 nvt-se Exp $
|
* $Id: rpl-dag.c,v 1.30 2010/06/28 14:51:23 nvt-se Exp $
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
|
@ -97,14 +97,9 @@ 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];
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* Remove DAG parents with a rank that is at least the same as minimum_rank.
|
/* Remove DAG parents with a rank that is at least the same as minimum_rank. */
|
||||||
* If the argument poison_routes is non-null, the function also sends
|
|
||||||
* no-DAOs to these parents.
|
|
||||||
*/
|
|
||||||
#define POISON_ROUTES 1
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank, int poison_routes)
|
remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
|
||||||
{
|
{
|
||||||
rpl_parent_t *p, *p2;
|
rpl_parent_t *p, *p2;
|
||||||
|
|
||||||
|
@ -114,11 +109,6 @@ remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank, int poison_routes)
|
||||||
for(p = list_head(dag->parents); p != NULL; p = p2) {
|
for(p = list_head(dag->parents); p != NULL; p = p2) {
|
||||||
p2 = p->next;
|
p2 = p->next;
|
||||||
if(p->rank >= minimum_rank) {
|
if(p->rank >= minimum_rank) {
|
||||||
if(poison_routes == POISON_ROUTES) {
|
|
||||||
/* Send no-DAOs to old parents. */
|
|
||||||
dao_output(p, ZERO_LIFETIME);
|
|
||||||
}
|
|
||||||
|
|
||||||
rpl_remove_parent(dag, p);
|
rpl_remove_parent(dag, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,7 +246,7 @@ rpl_free_dag(rpl_dag_t *dag)
|
||||||
rpl_remove_routes(dag);
|
rpl_remove_routes(dag);
|
||||||
|
|
||||||
/* Remove parents and the default route. */
|
/* Remove parents and the default route. */
|
||||||
remove_parents(dag, 0, !POISON_ROUTES);
|
remove_parents(dag, 0);
|
||||||
rpl_set_default_route(dag, NULL);
|
rpl_set_default_route(dag, NULL);
|
||||||
|
|
||||||
ctimer_stop(&dag->dio_timer);
|
ctimer_stop(&dag->dio_timer);
|
||||||
|
@ -318,7 +308,6 @@ rpl_select_parent(rpl_dag_t *dag)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dag->preferred_parent != best) {
|
if(dag->preferred_parent != best) {
|
||||||
|
|
||||||
/* Visualize the change of the preferred parent in Cooja. */
|
/* Visualize the change of the preferred parent in Cooja. */
|
||||||
ANNOTATE("#L %u 0\n",
|
ANNOTATE("#L %u 0\n",
|
||||||
dag->preferred_parent->addr.u8[sizeof(best->addr) - 1]);
|
dag->preferred_parent->addr.u8[sizeof(best->addr) - 1]);
|
||||||
|
@ -328,6 +317,7 @@ rpl_select_parent(rpl_dag_t *dag)
|
||||||
rpl_set_default_route(dag, &best->addr);
|
rpl_set_default_route(dag, &best->addr);
|
||||||
/* The DAO parent set changed - schedule a DAO transmission. */
|
/* The DAO parent set changed - schedule a DAO transmission. */
|
||||||
rpl_schedule_dao(dag);
|
rpl_schedule_dao(dag);
|
||||||
|
rpl_reset_dio_timer(dag, 1);
|
||||||
PRINTF("RPL: New preferred parent, rank changed from %u to %u\n",
|
PRINTF("RPL: New preferred parent, rank changed from %u to %u\n",
|
||||||
(unsigned)dag->rank, dag->of->calculate_rank(best, 0));
|
(unsigned)dag->rank, dag->of->calculate_rank(best, 0));
|
||||||
}
|
}
|
||||||
|
@ -335,10 +325,13 @@ rpl_select_parent(rpl_dag_t *dag)
|
||||||
/* Update the DAG rank, since link-layer information may have changed
|
/* Update the DAG rank, since link-layer information may have changed
|
||||||
the local confidence. */
|
the local confidence. */
|
||||||
dag->rank = dag->of->calculate_rank(best, 0);
|
dag->rank = dag->of->calculate_rank(best, 0);
|
||||||
if(best->rank < dag->min_rank) {
|
if(dag->rank < dag->min_rank) {
|
||||||
dag->min_rank = best->rank;
|
dag->min_rank = dag->rank;
|
||||||
} else if(!acceptable_rank(dag, best->rank)) {
|
} else if(!acceptable_rank(dag, best->rank)) {
|
||||||
remove_parents(dag, 0, POISON_ROUTES);
|
/* Send a No-Path DAO to the soon-to-be-removed preferred parent. */
|
||||||
|
dao_output(p, ZERO_LIFETIME);
|
||||||
|
|
||||||
|
remove_parents(dag, 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +483,7 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio)
|
||||||
{
|
{
|
||||||
rpl_parent_t *p;
|
rpl_parent_t *p;
|
||||||
|
|
||||||
remove_parents(dag, 0, !POISON_ROUTES);
|
remove_parents(dag, 0);
|
||||||
dag->version = dio->version;
|
dag->version = dio->version;
|
||||||
dag->dtsn_out = 1;
|
dag->dtsn_out = 1;
|
||||||
dag->of->reset(dag);
|
dag->of->reset(dag);
|
||||||
|
@ -630,23 +623,29 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dag->rank == ROOT_RANK) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dio->rank == INFINITE_RANK) {
|
if(dio->rank == INFINITE_RANK) {
|
||||||
rpl_reset_dio_timer(dag, 1);
|
rpl_reset_dio_timer(dag, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dag->rank == ROOT_RANK) {
|
||||||
|
if(dio->rank != INFINITE_RANK) {
|
||||||
|
dag->dio_counter++;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At this point, we know that this DIO pertains to a DAG that
|
/*
|
||||||
we are already part of. */
|
* At this point, we know that this DIO pertains to a DAG that
|
||||||
|
* we are already part of. We consider the sender of the DIO to be
|
||||||
|
* a candidate parent, and let rpl_process_parent_event decide
|
||||||
|
* whether to keep it in the set.
|
||||||
|
*/
|
||||||
|
|
||||||
p = rpl_find_parent(dag, from);
|
p = rpl_find_parent(dag, from);
|
||||||
if(p == NULL) {
|
if(p == NULL) {
|
||||||
if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS && dio->rank >= dag->rank) {
|
if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS && dio->rank >= dag->rank) {
|
||||||
/* Try to make room for a new parent. */
|
/* Try to make room for a new parent. */
|
||||||
remove_parents(dag, dio->rank, !POISON_ROUTES);
|
remove_parents(dag, dio->rank);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the DIO sender as a candidate parent. */
|
/* Add the DIO sender as a candidate parent. */
|
||||||
|
@ -661,19 +660,17 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
|
||||||
PRINTF("RPL: New candidate parent with rank %u: ", (unsigned)p->rank);
|
PRINTF("RPL: New candidate parent with rank %u: ", (unsigned)p->rank);
|
||||||
PRINT6ADDR(from);
|
PRINT6ADDR(from);
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
|
} else if(p->rank == dio->rank) {
|
||||||
|
PRINTF("RPL: Received consistent DIO\n");
|
||||||
|
dag->dio_counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have an allocated candidate parent, process the DIO further. */
|
/* We have an allocated candidate parent, process the DIO further. */
|
||||||
|
|
||||||
if(p->rank != dio->rank) {
|
p->rank = dio->rank;
|
||||||
p->rank = dio->rank;
|
if(rpl_process_parent_event(dag, p) == 0) {
|
||||||
if(rpl_process_parent_event(dag, p) == 0) {
|
/* The candidate parent no longer exists. */
|
||||||
/* The candidate parent no longer exists. */
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
PRINTF("RPL: Received consistent DIO\n");
|
|
||||||
dag->dio_counter++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(should_send_dao(dag, dio, p)) {
|
if(should_send_dao(dag, dio, p)) {
|
||||||
|
|
Loading…
Reference in a new issue