RPL DAO timers and management:

* Added a DAO lifetime timer that sends out a new DAO after half the lifetime of the DAO. This allows implementing DAO route soft state that avoids routing tables in the network keeping stale routes for ever.
* Added ways to schedule a new DAO transmission as well as cancelling an active DAO transmit timer, which makes it possible to do nodes that don't send DAOs.
This commit is contained in:
Adam Dunkels 2013-11-20 14:02:38 +01:00
parent e09ff3ff1e
commit 61ea7fbb1c
3 changed files with 60 additions and 4 deletions

View File

@ -309,6 +309,9 @@ rpl_of_t *rpl_find_of(rpl_ocp_t);
/* Timer functions. */
void rpl_schedule_dao(rpl_instance_t *);
void rpl_schedule_dao_immediately(rpl_instance_t *);
void rpl_cancel_dao(rpl_instance_t *instance);
void rpl_reset_dio_timer(rpl_instance_t *);
void rpl_reset_periodic_timer(void);

View File

@ -194,6 +194,28 @@ rpl_reset_dio_timer(rpl_instance_t *instance)
#endif /* RPL_LEAF_ONLY */
}
/*---------------------------------------------------------------------------*/
static void handle_dao_timer(void *ptr);
static void
set_dao_lifetime_timer(rpl_instance_t *instance)
{
if(rpl_get_mode() == RPL_MODE_FEATHER) {
return;
}
/* Set up another DAO within half the expiration time, if such a
time has been configured */
if(instance->lifetime_unit != 0xffff && instance->default_lifetime != 0xff) {
clock_time_t expiration_time;
expiration_time = (clock_time_t)instance->default_lifetime *
(clock_time_t)instance->lifetime_unit *
CLOCK_SECOND / 2;
PRINTF("RPL: Scheduling DAO lifetime timer %u ticks in the future\n",
(unsigned)expiration_time);
ctimer_set(&instance->dao_lifetime_timer, expiration_time,
handle_dao_timer, instance);
}
}
/*---------------------------------------------------------------------------*/
static void
handle_dao_timer(void *ptr)
{
@ -215,11 +237,16 @@ handle_dao_timer(void *ptr)
} else {
PRINTF("RPL: No suitable DAO parent\n");
}
ctimer_stop(&instance->dao_timer);
if(etimer_expired(&instance->dao_lifetime_timer.etimer)) {
set_dao_lifetime_timer(instance);
}
}
/*---------------------------------------------------------------------------*/
void
rpl_schedule_dao(rpl_instance_t *instance)
static void
schedule_dao(rpl_instance_t *instance, clock_time_t latency)
{
clock_time_t expiration_time;
@ -228,13 +255,38 @@ rpl_schedule_dao(rpl_instance_t *instance)
if(!etimer_expired(&instance->dao_timer.etimer)) {
PRINTF("RPL: DAO timer already scheduled\n");
} else {
expiration_time = RPL_DAO_LATENCY / 2 +
(random_rand() % (RPL_DAO_LATENCY));
if(latency != 0) {
expiration_time = latency / 2 +
(random_rand() % (latency));
} else {
expiration_time = 0;
}
PRINTF("RPL: Scheduling DAO timer %u ticks in the future\n",
(unsigned)expiration_time);
ctimer_set(&instance->dao_timer, expiration_time,
handle_dao_timer, instance);
set_dao_lifetime_timer(instance);
}
}
/*---------------------------------------------------------------------------*/
void
rpl_schedule_dao(rpl_instance_t *instance)
{
schedule_dao(instance, RPL_DAO_LATENCY);
}
/*---------------------------------------------------------------------------*/
void
rpl_schedule_dao_immediately(rpl_instance_t *instance)
{
schedule_dao(instance, 0);
}
/*---------------------------------------------------------------------------*/
void
rpl_cancel_dao(rpl_instance_t *instance)
{
ctimer_stop(&instance->dao_timer);
ctimer_stop(&instance->dao_lifetime_timer);
}
/*---------------------------------------------------------------------------*/
#endif /* UIP_CONF_IPV6 */

View File

@ -225,6 +225,7 @@ struct rpl_instance {
clock_time_t dio_next_delay; /* delay for completion of dio interval */
struct ctimer dio_timer;
struct ctimer dao_timer;
struct ctimer dao_lifetime_timer;
};
/*---------------------------------------------------------------------------*/