44 #include "contiki-conf.h"
45 #include "net/rpl/rpl-private.h"
47 #include "lib/random.h"
52 #define DEBUG DEBUG_NONE
56 static struct ctimer periodic_timer;
58 static void handle_periodic_timer(
void *ptr);
59 static void new_dio_interval(rpl_instance_t *instance);
60 static void handle_dio_timer(
void *ptr);
62 static uint16_t next_dis;
65 static uint8_t dio_send_ok;
69 handle_periodic_timer(
void *ptr)
72 rpl_recalculate_ranks();
77 if(rpl_get_any_dag() ==
NULL && next_dis >= RPL_DIS_INTERVAL) {
86 new_dio_interval(rpl_instance_t *instance)
92 time = 1UL << instance->dio_intcurrent;
96 instance->dio_next_delay = ticks;
99 ticks = ticks / 2 + (ticks / 2 * (uint32_t)
random_rand()) / RANDOM_RAND_MAX;
106 instance->dio_next_delay -= ticks;
107 instance->dio_send = 1;
111 instance->dio_totint++;
112 instance->dio_totrecv += instance->dio_counter;
113 ANNOTATE(
"#A rank=%u.%u(%u),stats=%d %d %d %d,color=%s\n",
114 DAG_RANK(instance->current_dag->rank, instance),
115 (10 * (instance->current_dag->rank % instance->min_hoprankinc)) / instance->min_hoprankinc,
116 instance->current_dag->version,
117 instance->dio_totint, instance->dio_totsend,
118 instance->dio_totrecv,instance->dio_intcurrent,
119 instance->current_dag->rank == ROOT_RANK(instance) ?
"BLUE" :
"ORANGE");
123 instance->dio_counter = 0;
126 PRINTF(
"RPL: Scheduling DIO timer %lu ticks in future (Interval)\n", ticks);
127 ctimer_set(&instance->dio_timer, ticks, &handle_dio_timer, instance);
131 handle_dio_timer(
void *ptr)
133 rpl_instance_t *instance;
135 instance = (rpl_instance_t *)ptr;
137 PRINTF(
"RPL: DIO Timer triggered\n");
139 if(uip_ds6_get_link_local(ADDR_PREFERRED) !=
NULL) {
142 PRINTF(
"RPL: Postponing DIO transmission since link local address is not ok\n");
148 if(instance->dio_send) {
150 if(instance->dio_counter < instance->dio_redundancy) {
152 instance->dio_totsend++;
154 dio_output(instance,
NULL);
156 PRINTF(
"RPL: Supressing DIO transmission (%d >= %d)\n",
157 instance->dio_counter, instance->dio_redundancy);
159 instance->dio_send = 0;
160 PRINTF(
"RPL: Scheduling DIO timer %lu ticks in future (sent)\n",
161 instance->dio_next_delay);
162 ctimer_set(&instance->dio_timer, instance->dio_next_delay, handle_dio_timer, instance);
165 if(instance->dio_intcurrent < instance->dio_intmin + instance->dio_intdoubl) {
166 instance->dio_intcurrent++;
167 PRINTF(
"RPL: DIO Timer interval doubled %d\n", instance->dio_intcurrent);
169 new_dio_interval(instance);
174 rpl_reset_periodic_timer(
void)
176 next_dis = RPL_DIS_INTERVAL / 2 +
177 ((uint32_t)RPL_DIS_INTERVAL * (uint32_t)
random_rand()) / RANDOM_RAND_MAX -
184 rpl_reset_dio_timer(rpl_instance_t *instance)
189 if(instance->dio_intcurrent > instance->dio_intmin) {
190 instance->dio_counter = 0;
191 instance->dio_intcurrent = instance->dio_intmin;
192 new_dio_interval(instance);
200 static void handle_dao_timer(
void *ptr);
202 set_dao_lifetime_timer(rpl_instance_t *instance)
210 if(instance->lifetime_unit != 0xffff && instance->default_lifetime != 0xff) {
211 clock_time_t expiration_time;
212 expiration_time = (clock_time_t)instance->default_lifetime *
213 (clock_time_t)instance->lifetime_unit *
215 PRINTF(
"RPL: Scheduling DAO lifetime timer %u ticks in the future\n",
216 (
unsigned)expiration_time);
217 ctimer_set(&instance->dao_lifetime_timer, expiration_time,
218 handle_dao_timer, instance);
223 handle_dao_timer(
void *ptr)
225 rpl_instance_t *instance;
226 #if RPL_CONF_MULTICAST
231 instance = (rpl_instance_t *)ptr;
233 if(!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) ==
NULL) {
234 PRINTF(
"RPL: Postpone DAO transmission\n");
240 if(instance->current_dag->preferred_parent !=
NULL) {
241 PRINTF(
"RPL: handle_dao_timer - sending DAO\n");
243 dao_output(instance->current_dag->preferred_parent, instance->default_lifetime);
245 #if RPL_CONF_MULTICAST
247 if(instance->mop == RPL_MOP_STORING_MULTICAST) {
249 for(i = 0; i < UIP_DS6_MADDR_NB; i++) {
250 if(uip_ds6_if.maddr_list[i].isused
252 dao_output_target(instance->current_dag->preferred_parent,
253 &uip_ds6_if.maddr_list[i].ipaddr, RPL_MCAST_LIFETIME);
258 mcast_route = uip_mcast6_route_list_head();
259 while(mcast_route !=
NULL) {
261 if(uip_ds6_maddr_lookup(&mcast_route->group) ==
NULL) {
262 dao_output_target(instance->current_dag->preferred_parent,
263 &mcast_route->group, RPL_MCAST_LIFETIME);
270 PRINTF(
"RPL: No suitable DAO parent\n");
276 set_dao_lifetime_timer(instance);
281 schedule_dao(rpl_instance_t *instance, clock_time_t latency)
283 clock_time_t expiration_time;
292 PRINTF(
"RPL: DAO timer already scheduled\n");
295 expiration_time = latency / 2 +
300 PRINTF(
"RPL: Scheduling DAO timer %u ticks in the future\n",
301 (
unsigned)expiration_time);
302 ctimer_set(&instance->dao_timer, expiration_time,
303 handle_dao_timer, instance);
305 set_dao_lifetime_timer(instance);
310 rpl_schedule_dao(rpl_instance_t *instance)
312 schedule_dao(instance, RPL_DAO_LATENCY);
316 rpl_schedule_dao_immediately(rpl_instance_t *instance)
318 schedule_dao(instance, 0);
322 rpl_cancel_dao(rpl_instance_t *instance)
clock_time_t etimer_expiration_time(struct etimer *et)
Get the expiration time for the event timer.
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
This header file contains configuration directives for uIPv6 multicast support.
void * list_item_next(void *item)
Get the next item following this item.
#define NULL
The null pointer.
An entry in the multicast routing table.
#define uip_is_addr_mcast_global(a)
is address a global multicast address (FFxE::/16), a is of type uip_ip6addr_t*
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
enum rpl_mode rpl_get_mode(void)
Get the RPL mode.
void ctimer_reset(struct ctimer *c)
Reset a callback timer with the same interval as was previously set.
Header file for the callback timer
A set of debugging macros.
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
unsigned short random_rand(void)
Generate the next state and return the upper part of it.
#define CLOCK_SECOND
A second, measured in system clock time.