diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index bc307e459..a78e1dd8b 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -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); diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index 51f440f3f..02c3e00ba 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -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 */ diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index b83e140ed..5dc1f6e1c 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -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; }; /*---------------------------------------------------------------------------*/