Contiki-NG
rpl-timers.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  */
31 
32 /**
33  * \addtogroup rpl-lite
34  * @{
35  *
36  * \file
37  * RPL timer management.
38  *
39  * \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>,
40  * Simon Duquennoy <simon.duquennoy@inria.fr>
41  */
42 
43 #include "contiki.h"
44 #include "net/routing/rpl-lite/rpl.h"
45 #include "net/ipv6/uip-sr.h"
46 #include "net/link-stats.h"
47 #include "lib/random.h"
48 #include "sys/ctimer.h"
49 
50 /* Log configuration */
51 #include "sys/log.h"
52 #define LOG_MODULE "RPL"
53 #define LOG_LEVEL LOG_LEVEL_RPL
54 
55 /* A configurable function called after update of the RPL DIO interval */
56 #ifdef RPL_CALLBACK_NEW_DIO_INTERVAL
57 void RPL_CALLBACK_NEW_DIO_INTERVAL(clock_time_t dio_interval);
58 #endif /* RPL_CALLBACK_NEW_DIO_INTERVAL */
59 
60 #ifdef RPL_PROBING_SELECT_FUNC
61 rpl_nbr_t *RPL_PROBING_SELECT_FUNC(void);
62 #endif /* RPL_PROBING_SELECT_FUNC */
63 
64 #ifdef RPL_PROBING_DELAY_FUNC
65 clock_time_t RPL_PROBING_DELAY_FUNC(void);
66 #endif /* RPL_PROBING_DELAY_FUNC */
67 
68 #define PERIODIC_DELAY_SECONDS 60
69 #define PERIODIC_DELAY ((PERIODIC_DELAY_SECONDS) * CLOCK_SECOND)
70 
71 static void handle_dis_timer(void *ptr);
72 static void handle_dio_timer(void *ptr);
73 static void handle_unicast_dio_timer(void *ptr);
74 static void send_new_dao(void *ptr);
75 #if RPL_WITH_DAO_ACK
76 static void resend_dao(void *ptr);
77 static void handle_dao_ack_timer(void *ptr);
78 #endif /* RPL_WITH_DAO_ACK */
79 #if RPL_WITH_PROBING
80 static void handle_probing_timer(void *ptr);
81 #endif /* RPL_WITH_PROBING */
82 static void handle_periodic_timer(void *ptr);
83 static void handle_state_update(void *ptr);
84 
85 /*---------------------------------------------------------------------------*/
86 static struct ctimer dis_timer; /* Not part of a DAG because when not joined */
87 static struct ctimer periodic_timer; /* Not part of a DAG because used for general state maintenance */
88 
89 /*---------------------------------------------------------------------------*/
90 /*------------------------------- DIS -------------------------------------- */
91 /*---------------------------------------------------------------------------*/
92 void
94 {
95  if(ctimer_expired(&dis_timer)) {
96  clock_time_t expiration_time = RPL_DIS_INTERVAL / 2 + (random_rand() % (RPL_DIS_INTERVAL));
97  ctimer_set(&dis_timer, expiration_time, handle_dis_timer, NULL);
98  }
99 }
100 /*---------------------------------------------------------------------------*/
101 static void
102 handle_dis_timer(void *ptr)
103 {
104  if(!rpl_dag_root_is_root() &&
105  (!curr_instance.used ||
106  curr_instance.dag.preferred_parent == NULL ||
107  curr_instance.dag.rank == RPL_INFINITE_RANK)) {
108  /* Send DIS and schedule next */
109  rpl_icmp6_dis_output(NULL);
111  }
112 }
113 /*---------------------------------------------------------------------------*/
114 /*------------------------------- DIO -------------------------------------- */
115 /*---------------------------------------------------------------------------*/
116 static void
117 new_dio_interval(void)
118 {
119  uint32_t time;
120  clock_time_t ticks;
121 
122  time = 1UL << curr_instance.dag.dio_intcurrent;
123 
124  /* Convert from milliseconds to CLOCK_TICKS. */
125  ticks = (time * CLOCK_SECOND) / 1000;
126  curr_instance.dag.dio_next_delay = ticks;
127 
128  /* random number between I/2 and I */
129  ticks = ticks / 2 + (ticks / 2 * (uint32_t)random_rand()) / RANDOM_RAND_MAX;
130 
131  /*
132  * The intervals must be equally long among the nodes for Trickle to
133  * operate efficiently. Therefore we need to calculate the delay between
134  * the randomized time and the start time of the next interval.
135  */
136  curr_instance.dag.dio_next_delay -= ticks;
137  curr_instance.dag.dio_send = 1;
138  /* reset the redundancy counter */
139  curr_instance.dag.dio_counter = 0;
140 
141  /* schedule the timer */
142  ctimer_set(&curr_instance.dag.dio_timer, ticks, &handle_dio_timer, NULL);
143 
144 #ifdef RPL_CALLBACK_NEW_DIO_INTERVAL
145  RPL_CALLBACK_NEW_DIO_INTERVAL((CLOCK_SECOND * 1UL << curr_instance.dag.dio_intcurrent) / 1000);
146 #endif /* RPL_CALLBACK_NEW_DIO_INTERVAL */
147 }
148 /*---------------------------------------------------------------------------*/
149 void
150 rpl_timers_dio_reset(const char *str)
151 {
153  LOG_INFO("reset DIO timer (%s)\n", str);
154  if(!rpl_get_leaf_only()) {
155  curr_instance.dag.dio_counter = 0;
156  curr_instance.dag.dio_intcurrent = curr_instance.dio_intmin;
157  new_dio_interval();
158  }
159  }
160 }
161 /*---------------------------------------------------------------------------*/
162 static void
163 handle_dio_timer(void *ptr)
164 {
166  return; /* We will be scheduled again later */
167  }
168 
169  if(curr_instance.dag.dio_send) {
170  /* send DIO if counter is less than desired redundancy, or if dio_redundancy
171  is set to 0, or if we are the root */
172  if(rpl_dag_root_is_root() || curr_instance.dio_redundancy == 0 ||
173  curr_instance.dag.dio_counter < curr_instance.dio_redundancy) {
174 #if RPL_TRICKLE_REFRESH_DAO_ROUTES
175  if(rpl_dag_root_is_root()) {
176  static int count = 0;
177  if((count++ % RPL_TRICKLE_REFRESH_DAO_ROUTES) == 0) {
178  /* Request new DAO to refresh route. */
179  RPL_LOLLIPOP_INCREMENT(curr_instance.dtsn_out);
180  LOG_INFO("trigger DAO updates with a DTSN increment (%u)\n", curr_instance.dtsn_out);
181  }
182  }
183 #endif /* RPL_TRICKLE_REFRESH_DAO_ROUTES */
184  curr_instance.dag.last_advertised_rank = curr_instance.dag.rank;
185  rpl_icmp6_dio_output(NULL);
186  }
187  curr_instance.dag.dio_send = 0;
188  ctimer_set(&curr_instance.dag.dio_timer, curr_instance.dag.dio_next_delay, handle_dio_timer, NULL);
189  } else {
190  /* check if we need to double interval */
191  if(curr_instance.dag.dio_intcurrent < curr_instance.dio_intmin + curr_instance.dio_intdoubl) {
192  curr_instance.dag.dio_intcurrent++;
193  }
194  new_dio_interval();
195  }
196 }
197 /*---------------------------------------------------------------------------*/
198 /*------------------------------- Unicast DIO ------------------------------ */
199 /*---------------------------------------------------------------------------*/
200 /*---------------------------------------------------------------------------*/
201 void
203 {
204  if(curr_instance.used) {
205  curr_instance.dag.unicast_dio_target = target;
206  ctimer_set(&curr_instance.dag.unicast_dio_timer, 0,
207  handle_unicast_dio_timer, NULL);
208  }
209 }
210 /*---------------------------------------------------------------------------*/
211 static void
212 handle_unicast_dio_timer(void *ptr)
213 {
214  uip_ipaddr_t *target_ipaddr = rpl_neighbor_get_ipaddr(curr_instance.dag.unicast_dio_target);
215  if(target_ipaddr != NULL) {
216  rpl_icmp6_dio_output(target_ipaddr);
217  }
218 }
219 /*---------------------------------------------------------------------------*/
220 /*------------------------------- DAO -------------------------------------- */
221 /*---------------------------------------------------------------------------*/
222 #if RPL_WITH_DAO_ACK
223 /*---------------------------------------------------------------------------*/
224 static void
225 schedule_dao_retransmission(void)
226 {
227  clock_time_t expiration_time = RPL_DAO_RETRANSMISSION_TIMEOUT / 2 + (random_rand() % (RPL_DAO_RETRANSMISSION_TIMEOUT));
228  ctimer_set(&curr_instance.dag.dao_timer, expiration_time, resend_dao, NULL);
229 }
230 #endif /* RPL_WITH_DAO_ACK */
231 /*---------------------------------------------------------------------------*/
232 static void
233 schedule_dao_refresh(void)
234 {
235  if(curr_instance.used && curr_instance.default_lifetime != RPL_INFINITE_LIFETIME) {
236 #if RPL_WITH_DAO_ACK
237  /* DAO-ACK enabled: the last DAO was ACKed, wait until expiration before refresh */
238  clock_time_t target_refresh = CLOCK_SECOND * RPL_LIFETIME(curr_instance.default_lifetime);
239 #else /* RPL_WITH_DAO_ACK */
240  /* DAO-ACK disabled: use half the expiration time to get two chances to refresh per lifetime */
241  clock_time_t target_refresh = (CLOCK_SECOND * RPL_LIFETIME(curr_instance.default_lifetime) / 2);
242 #endif /* RPL_WITH_DAO_ACK */
243 
244  /* Send between 60 and 120 seconds before target refresh */
245  clock_time_t safety_margin = (60 * CLOCK_SECOND) + (random_rand() % (60 * CLOCK_SECOND));
246 
247  if(target_refresh > safety_margin) {
248  target_refresh -= safety_margin;
249  }
250 
251  /* Schedule transmission */
252  ctimer_set(&curr_instance.dag.dao_timer, target_refresh, send_new_dao, NULL);
253  }
254 }
255 /*---------------------------------------------------------------------------*/
256 void
258 {
259  if(curr_instance.used && curr_instance.mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
260  /* No need for DAO aggregation delay as per RFC 6550 section 9.5, as this
261  * only serves storing mode. Use simple delay instead, with the only purpose
262  * to reduce congestion. */
263  clock_time_t expiration_time = RPL_DAO_DELAY / 2 + (random_rand() % (RPL_DAO_DELAY));
264  ctimer_set(&curr_instance.dag.dao_timer, expiration_time, send_new_dao, NULL);
265  }
266 }
267 /*---------------------------------------------------------------------------*/
268 static void
269 send_new_dao(void *ptr)
270 {
271 #if RPL_WITH_DAO_ACK
272  /* We are sending a new DAO here. Prepare retransmissions */
273  curr_instance.dag.dao_transmissions = 1;
274  /* Schedule next retransmission */
275  schedule_dao_retransmission();
276 #else /* RPL_WITH_DAO_ACK */
277  /* No DAO-ACK: assume we are reachable as soon as we send a DAO */
278  if(curr_instance.dag.state == DAG_JOINED) {
279  curr_instance.dag.state = DAG_REACHABLE;
280  }
281  rpl_timers_dio_reset("Reachable");
282  /* There is no DAO-ACK, schedule a refresh. */
283  schedule_dao_refresh();
284 #endif /* !RPL_WITH_DAO_ACK */
285 
286  /* Increment seqno */
287  RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_last_seqno);
288  /* Send a DAO with own prefix as target and default lifetime */
289  rpl_icmp6_dao_output(curr_instance.default_lifetime);
290 }
291 #if RPL_WITH_DAO_ACK
292 /*---------------------------------------------------------------------------*/
293 /*------------------------------- DAO-ACK ---------------------------------- */
294 /*---------------------------------------------------------------------------*/
295 /*---------------------------------------------------------------------------*/
296 void
297 rpl_timers_schedule_dao_ack(uip_ipaddr_t *target, uint16_t sequence)
298 {
299  if(curr_instance.used) {
300  uip_ipaddr_copy(&curr_instance.dag.dao_ack_target, target);
301  curr_instance.dag.dao_ack_sequence = sequence;
302  ctimer_set(&curr_instance.dag.dao_ack_timer, 0, handle_dao_ack_timer, NULL);
303  }
304 }
305 /*---------------------------------------------------------------------------*/
306 static void
307 handle_dao_ack_timer(void *ptr)
308 {
309  rpl_icmp6_dao_ack_output(&curr_instance.dag.dao_ack_target,
310  curr_instance.dag.dao_ack_sequence, RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
311 }
312 /*---------------------------------------------------------------------------*/
313 void
315 {
316  /* The last DAO was ACKed. Schedule refresh to avoid route expiration. This
317  implicitly de-schedules resend_dao, as both share curr_instance.dag.dao_timer */
318  schedule_dao_refresh();
319 }
320 /*---------------------------------------------------------------------------*/
321 static void
322 resend_dao(void *ptr)
323 {
324  /* Increment transmission counter before sending */
325  curr_instance.dag.dao_transmissions++;
326  /* Send a DAO with own prefix as target and default lifetime */
327  rpl_icmp6_dao_output(curr_instance.default_lifetime);
328 
329  /* Schedule next retransmission, or abort */
330  if(curr_instance.dag.dao_transmissions < RPL_DAO_MAX_RETRANSMISSIONS) {
331  schedule_dao_retransmission();
332  } else {
333  /* No more retransmissions. Perform local repair. */
334  rpl_local_repair("DAO max rtx");
335  return;
336  }
337 }
338 #endif /* RPL_WITH_DAO_ACK */
339 /*---------------------------------------------------------------------------*/
340 /*------------------------------- Probing----------------------------------- */
341 /*---------------------------------------------------------------------------*/
342 #if RPL_WITH_PROBING
343 clock_time_t
344 get_probing_delay(void)
345 {
346  return ((RPL_PROBING_INTERVAL) / 2) + random_rand() % (RPL_PROBING_INTERVAL);
347 }
348 /*---------------------------------------------------------------------------*/
349 rpl_nbr_t *
350 get_probing_target(void)
351 {
352  /* Returns the next probing target. The current implementation probes the urgent
353  * probing target if any, or the preferred parent if its link statistics need refresh.
354  * Otherwise, it picks at random between:
355  * (1) selecting the best neighbor with non-fresh link statistics
356  * (2) selecting the least recently updated neighbor
357  */
358 
359  rpl_nbr_t *nbr;
360  rpl_nbr_t *probing_target = NULL;
361  rpl_rank_t probing_target_rank = RPL_INFINITE_RANK;
362  clock_time_t probing_target_age = 0;
363  clock_time_t clock_now = clock_time();
364 
365  if(curr_instance.used == 0) {
366  return NULL;
367  }
368 
369  /* There is an urgent probing target */
370  if(curr_instance.dag.urgent_probing_target != NULL) {
371  return curr_instance.dag.urgent_probing_target;
372  }
373 
374  /* The preferred parent needs probing */
375  if(curr_instance.dag.preferred_parent != NULL && !rpl_neighbor_is_fresh(curr_instance.dag.preferred_parent)) {
376  return curr_instance.dag.preferred_parent;
377  }
378 
379  /* Now consider probing other non-fresh neighbors. With 2/3 proabability,
380  pick the best non-fresh. Otherwise, pick the lest recently updated non-fresh. */
381 
382  if(random_rand() % 3 != 0) {
383  /* Look for best non-fresh */
384  nbr = nbr_table_head(rpl_neighbors);
385  while(nbr != NULL) {
386  if(!rpl_neighbor_is_fresh(nbr)) {
387  /* nbr needs probing */
388  rpl_rank_t nbr_rank = rpl_neighbor_rank_via_nbr(nbr);
389  if(probing_target == NULL
390  || nbr_rank < probing_target_rank) {
391  probing_target = nbr;
392  probing_target_rank = nbr_rank;
393  }
394  }
395  nbr = nbr_table_next(rpl_neighbors, nbr);
396  }
397  } else {
398  /* Look for least recently updated non-fresh */
399  nbr = nbr_table_head(rpl_neighbors);
400  while(nbr != NULL) {
401  if(!rpl_neighbor_is_fresh(nbr)) {
402  /* nbr needs probing */
403  const struct link_stats *stats = rpl_neighbor_get_link_stats(nbr);
404  if(stats != NULL) {
405  if(probing_target == NULL
406  || clock_now - stats->last_tx_time > probing_target_age) {
407  probing_target = nbr;
408  probing_target_age = clock_now - stats->last_tx_time;
409  }
410  }
411  }
412  nbr = nbr_table_next(rpl_neighbors, nbr);
413  }
414  }
415 
416  return probing_target;
417 }
418 /*---------------------------------------------------------------------------*/
419 static void
420 handle_probing_timer(void *ptr)
421 {
422  rpl_nbr_t *probing_target = RPL_PROBING_SELECT_FUNC();
423  uip_ipaddr_t *target_ipaddr = rpl_neighbor_get_ipaddr(probing_target);
424 
425  /* Perform probing */
426  if(target_ipaddr != NULL) {
427  const struct link_stats *stats = rpl_neighbor_get_link_stats(probing_target);
428  (void)stats;
429  LOG_INFO("probing ");
430  LOG_INFO_6ADDR(target_ipaddr);
431  LOG_INFO_(" %s last tx %u min ago\n",
432  curr_instance.dag.urgent_probing_target != NULL ? "(urgent)" : "",
433  stats != NULL ?
434  (unsigned)((clock_time() - stats->last_tx_time) / (60 * CLOCK_SECOND)) : 0
435  );
436  /* Send probe, e.g. unicast DIO or DIS */
437  RPL_PROBING_SEND_FUNC(target_ipaddr);
438  /* urgent_probing_target will be NULLed in the packet_sent callback */
439  } else {
440  LOG_INFO("no neighbor needs probing\n");
441  }
442 
443  /* Schedule next probing */
445 }
446 /*---------------------------------------------------------------------------*/
447 void
449 {
450  if(curr_instance.used) {
451  ctimer_set(&curr_instance.dag.probing_timer, RPL_PROBING_DELAY_FUNC(),
452  handle_probing_timer, NULL);
453  }
454 }
455 /*---------------------------------------------------------------------------*/
456 void
458 {
459  if(curr_instance.used) {
460  ctimer_set(&curr_instance.dag.probing_timer,
461  random_rand() % (CLOCK_SECOND * 4), handle_probing_timer, NULL);
462  }
463 }
464 #endif /* RPL_WITH_PROBING */
465 /*---------------------------------------------------------------------------*/
466 /*------------------------------- Leaving-- -------------------------------- */
467 /*---------------------------------------------------------------------------*/
468 static void
469 handle_leaving_timer(void *ptr)
470 {
471  if(curr_instance.used) {
472  rpl_dag_leave();
473  }
474 }
475 /*---------------------------------------------------------------------------*/
476 void
478 {
479  if(curr_instance.used) {
480  if(!ctimer_expired(&curr_instance.dag.leave)) {
481  ctimer_stop(&curr_instance.dag.leave);
482  }
483  }
484 }
485 /*---------------------------------------------------------------------------*/
486 void
488 {
489  if(curr_instance.used) {
490  if(ctimer_expired(&curr_instance.dag.leave)) {
491  ctimer_set(&curr_instance.dag.leave, RPL_DELAY_BEFORE_LEAVING, handle_leaving_timer, NULL);
492  }
493  }
494 }
495 /*---------------------------------------------------------------------------*/
496 /*------------------------------- Periodic---------------------------------- */
497 /*---------------------------------------------------------------------------*/
498 void
500 {
501  ctimer_set(&periodic_timer, PERIODIC_DELAY, handle_periodic_timer, NULL);
503 }
504 /*---------------------------------------------------------------------------*/
505 static void
506 handle_periodic_timer(void *ptr)
507 {
508  if(curr_instance.used) {
509  rpl_dag_periodic(PERIODIC_DELAY_SECONDS);
510  uip_sr_periodic(PERIODIC_DELAY_SECONDS);
511  }
512 
513  if(!curr_instance.used ||
514  curr_instance.dag.preferred_parent == NULL ||
515  curr_instance.dag.rank == RPL_INFINITE_RANK) {
516  rpl_timers_schedule_periodic_dis(); /* Schedule DIS if needed */
517  }
518 
519  /* Useful because part of the state update is time-dependent, e.g.,
520  the meaning of last_advertised_rank changes with time */
522 
523  if(LOG_INFO_ENABLED) {
524  rpl_neighbor_print_list("Periodic");
525  rpl_dag_root_print_links("Periodic");
526  }
527 
528  ctimer_reset(&periodic_timer);
529 }
530 /*---------------------------------------------------------------------------*/
531 void
533 {
534  /* Stop all timers related to the DAG */
535  ctimer_stop(&curr_instance.dag.state_update);
536  ctimer_stop(&curr_instance.dag.leave);
537  ctimer_stop(&curr_instance.dag.dio_timer);
538  ctimer_stop(&curr_instance.dag.unicast_dio_timer);
539  ctimer_stop(&curr_instance.dag.dao_timer);
540 #if RPL_WITH_PROBING
541  ctimer_stop(&curr_instance.dag.probing_timer);
542 #endif /* RPL_WITH_PROBING */
543 #if RPL_WITH_DAO_ACK
544  ctimer_stop(&curr_instance.dag.dao_ack_timer);
545 #endif /* RPL_WITH_DAO_ACK */
546 }
547 /*---------------------------------------------------------------------------*/
548 void
550 {
551  if(curr_instance.used) {
552  ctimer_stop(&curr_instance.dag.state_update);
553  }
554 }
555 /*---------------------------------------------------------------------------*/
556 void
558 {
559  if(curr_instance.used) {
560  ctimer_set(&curr_instance.dag.state_update, 0, handle_state_update, NULL);
561  }
562 }
563 /*---------------------------------------------------------------------------*/
564 static void
565 handle_state_update(void *ptr)
566 {
568 }
569 
570 /** @}*/
int ctimer_expired(struct ctimer *c)
Check if a callback timer has expired.
Definition: ctimer.c:161
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
uip_ipaddr_t * rpl_neighbor_get_ipaddr(rpl_nbr_t *nbr)
Returns a neighbor&#39;s (link-local) IPv6 address.
Definition: rpl-neighbor.c:252
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
Definition: uip-nd6.c:106
void rpl_timers_schedule_unicast_dio(rpl_nbr_t *target)
Schedule unicast DIO with no delay.
Definition: rpl-timers.c:202
void rpl_timers_notify_dao_ack(void)
Let the rpl-timers module know that the last DAO was ACKed.
void rpl_schedule_probing_now(void)
Schedule probing within a few seconds.
int rpl_neighbor_is_fresh(rpl_nbr_t *nbr)
Tells wether we have fresh link information towards a given neighbor.
Definition: rpl-neighbor.c:266
void rpl_timers_init(void)
Initialize rpl-timers module.
Definition: rpl-timers.c:499
uint8_t rpl_get_leaf_only(void)
Get the value of the rpl_leaf_only flag.
Definition: rpl.c:241
#define RPL_LIFETIME(lifetime)
Compute lifetime, accounting for the lifetime unit.
Definition: rpl-types.h:72
void rpl_dag_root_print_links(const char *str)
Prints a summary of all routing links.
Definition: rpl-dag-root.c:54
void ctimer_reset(struct ctimer *c)
Reset a callback timer with the same interval as was previously set.
Definition: ctimer.c:125
int rpl_dag_root_is_root(void)
Tells whether we are DAG root or not.
Definition: rpl-dag-root.c:152
void rpl_timers_schedule_dao_ack(uip_ipaddr_t *target, uint16_t sequence)
Schedule a DAO-ACK with no delay.
void rpl_icmp6_dao_output(uint8_t lifetime)
Creates an ICMPv6 DAO packet and sends it to the root, advertising the current preferred parent...
Definition: rpl-icmp6.c:543
Source routing support.
void rpl_timers_schedule_state_update(void)
Schedule a state update ASAP.
Definition: rpl-timers.c:557
void rpl_timers_dio_reset(const char *str)
Reset DIO Trickle timer.
Definition: rpl-timers.c:150
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
void rpl_timers_unschedule_leaving(void)
Cancel scheduled leaving if any.
Definition: rpl-timers.c:477
Header file for the callback timer
void uip_sr_periodic(unsigned seconds)
A function called periodically.
Definition: uip-sr.c:206
void rpl_timers_stop_dag_timers(void)
Stop all timers related to the DAG.
Definition: rpl-timers.c:532
void rpl_dag_leave(void)
Leaves the current DAG.
Definition: rpl-dag.c:99
const struct link_stats * rpl_neighbor_get_link_stats(rpl_nbr_t *nbr)
Returns a neighbor&#39;s link statistics.
Definition: rpl-neighbor.c:259
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
All information related to a RPL neighbor.
Definition: rpl-types.h:136
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1015
clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:118
int rpl_dag_ready_to_advertise(void)
Tells whether RPL is ready to advertise the DAG.
Definition: rpl-dag.c:253
void rpl_timers_schedule_periodic_dis(void)
Schedule periodic DIS with a random delay based on RPL_DIS_INTERVAL, until we join a DAG...
Definition: rpl-timers.c:93
void rpl_timers_schedule_dao(void)
Schedule a DAO with random delay based on RPL_DAO_DELAY.
Definition: rpl-timers.c:257
void rpl_dag_periodic(unsigned seconds)
A function called periodically.
Definition: rpl-dag.c:138
void rpl_neighbor_print_list(const char *str)
Prints a summary of all RPL neighbors and their properties.
Definition: rpl-neighbor.c:143
void rpl_icmp6_dao_ack_output(uip_ipaddr_t *dest, uint8_t sequence, uint8_t status)
Creates an ICMPv6 DAO-ACK packet and sends it to the originator of the ACK.
void rpl_dag_update_state(void)
Updates RPL internal state: selects preferred parent, updates rank & metreic container, triggers control traffic accordingly and updates uIP6 internal state.
Definition: rpl-dag.c:264
void rpl_timers_schedule_leaving(void)
Schedule leaving after RPL_DELAY_BEFORE_LEAVING.
Definition: rpl-timers.c:487
void rpl_timers_unschedule_state_update(void)
Cancelled any scheduled state update.
Definition: rpl-timers.c:549
rpl_rank_t rpl_neighbor_rank_via_nbr(rpl_nbr_t *nbr)
Returns our rank if selecting a given parent as preferred parent.
Definition: rpl-neighbor.c:237
void rpl_local_repair(const char *str)
Triggers a RPL local repair.
Definition: rpl-dag.c:238
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Definition: random.c:58
void rpl_icmp6_dio_output(uip_ipaddr_t *uc_addr)
Creates an ICMPv6 DIO packet and sends it.
Definition: rpl-icmp6.c:332
Header file for the logging system
void rpl_icmp6_dis_output(uip_ipaddr_t *addr)
Creates an ICMPv6 DIS packet and sends it.
Definition: rpl-icmp6.c:150
void rpl_schedule_probing(void)
Schedule probing with delay RPL_PROBING_DELAY_FUNC()