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  (curr_instance.dag.dio_intcurrent == 0 ||
154  curr_instance.dag.dio_intcurrent > curr_instance.dio_intmin)) {
155  /*
156  * don't reset the DIO timer if the current interval is Imin; see
157  * Section 4.2, RFC 6206.
158  */
159  LOG_INFO("reset DIO timer (%s)\n", str);
160  if(!rpl_get_leaf_only()) {
161  curr_instance.dag.dio_counter = 0;
162  curr_instance.dag.dio_intcurrent = curr_instance.dio_intmin;
163  new_dio_interval();
164  }
165  }
166 }
167 /*---------------------------------------------------------------------------*/
168 static void
169 handle_dio_timer(void *ptr)
170 {
172  return; /* We will be scheduled again later */
173  }
174 
175  if(curr_instance.dag.dio_send) {
176  /* send DIO if counter is less than desired redundancy, or if dio_redundancy
177  is set to 0, or if we are the root */
178  if(rpl_dag_root_is_root() || curr_instance.dio_redundancy == 0 ||
179  curr_instance.dag.dio_counter < curr_instance.dio_redundancy) {
180 #if RPL_TRICKLE_REFRESH_DAO_ROUTES
181  if(rpl_dag_root_is_root()) {
182  static int count = 0;
183  if((count++ % RPL_TRICKLE_REFRESH_DAO_ROUTES) == 0) {
184  /* Request new DAO to refresh route. */
185  RPL_LOLLIPOP_INCREMENT(curr_instance.dtsn_out);
186  LOG_INFO("trigger DAO updates with a DTSN increment (%u)\n", curr_instance.dtsn_out);
187  }
188  }
189 #endif /* RPL_TRICKLE_REFRESH_DAO_ROUTES */
190  curr_instance.dag.last_advertised_rank = curr_instance.dag.rank;
191  rpl_icmp6_dio_output(NULL);
192  }
193  curr_instance.dag.dio_send = 0;
194  ctimer_set(&curr_instance.dag.dio_timer, curr_instance.dag.dio_next_delay, handle_dio_timer, NULL);
195  } else {
196  /* check if we need to double interval */
197  if(curr_instance.dag.dio_intcurrent < curr_instance.dio_intmin + curr_instance.dio_intdoubl) {
198  curr_instance.dag.dio_intcurrent++;
199  }
200  new_dio_interval();
201  }
202 }
203 /*---------------------------------------------------------------------------*/
204 /*------------------------------- Unicast DIO ------------------------------ */
205 /*---------------------------------------------------------------------------*/
206 /*---------------------------------------------------------------------------*/
207 void
209 {
210  if(curr_instance.used) {
211  curr_instance.dag.unicast_dio_target = target;
212  ctimer_set(&curr_instance.dag.unicast_dio_timer, 0,
213  handle_unicast_dio_timer, NULL);
214  }
215 }
216 /*---------------------------------------------------------------------------*/
217 static void
218 handle_unicast_dio_timer(void *ptr)
219 {
220  uip_ipaddr_t *target_ipaddr = rpl_neighbor_get_ipaddr(curr_instance.dag.unicast_dio_target);
221  if(target_ipaddr != NULL) {
222  rpl_icmp6_dio_output(target_ipaddr);
223  }
224 }
225 /*---------------------------------------------------------------------------*/
226 /*------------------------------- DAO -------------------------------------- */
227 /*---------------------------------------------------------------------------*/
228 #if RPL_WITH_DAO_ACK
229 /*---------------------------------------------------------------------------*/
230 static void
231 schedule_dao_retransmission(void)
232 {
233  clock_time_t expiration_time = RPL_DAO_RETRANSMISSION_TIMEOUT / 2 + (random_rand() % (RPL_DAO_RETRANSMISSION_TIMEOUT));
234  ctimer_set(&curr_instance.dag.dao_timer, expiration_time, resend_dao, NULL);
235 }
236 #endif /* RPL_WITH_DAO_ACK */
237 /*---------------------------------------------------------------------------*/
238 static void
239 schedule_dao_refresh(void)
240 {
241  if(curr_instance.used && curr_instance.default_lifetime != RPL_INFINITE_LIFETIME) {
242 #if RPL_WITH_DAO_ACK
243  /* DAO-ACK enabled: the last DAO was ACKed, wait until expiration before refresh */
244  clock_time_t target_refresh = CLOCK_SECOND * RPL_LIFETIME(curr_instance.default_lifetime);
245 #else /* RPL_WITH_DAO_ACK */
246  /* DAO-ACK disabled: use half the expiration time to get two chances to refresh per lifetime */
247  clock_time_t target_refresh = (CLOCK_SECOND * RPL_LIFETIME(curr_instance.default_lifetime) / 2);
248 #endif /* RPL_WITH_DAO_ACK */
249 
250  /* Send between 60 and 120 seconds before target refresh */
251  clock_time_t safety_margin = (60 * CLOCK_SECOND) + (random_rand() % (60 * CLOCK_SECOND));
252 
253  if(target_refresh > safety_margin) {
254  target_refresh -= safety_margin;
255  }
256 
257  /* Schedule transmission */
258  ctimer_set(&curr_instance.dag.dao_timer, target_refresh, send_new_dao, NULL);
259  }
260 }
261 /*---------------------------------------------------------------------------*/
262 void
264 {
265  if(curr_instance.used && curr_instance.mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
266  /* No need for DAO aggregation delay as per RFC 6550 section 9.5, as this
267  * only serves storing mode. Use simple delay instead, with the only purpose
268  * to reduce congestion. */
269  clock_time_t expiration_time = RPL_DAO_DELAY / 2 + (random_rand() % (RPL_DAO_DELAY));
270  ctimer_set(&curr_instance.dag.dao_timer, expiration_time, send_new_dao, NULL);
271  }
272 }
273 /*---------------------------------------------------------------------------*/
274 static void
275 send_new_dao(void *ptr)
276 {
277 #if RPL_WITH_DAO_ACK
278  /* We are sending a new DAO here. Prepare retransmissions */
279  curr_instance.dag.dao_transmissions = 1;
280  /* Schedule next retransmission */
281  schedule_dao_retransmission();
282 #else /* RPL_WITH_DAO_ACK */
283  /* No DAO-ACK: assume we are reachable as soon as we send a DAO */
284  if(curr_instance.dag.state == DAG_JOINED) {
285  curr_instance.dag.state = DAG_REACHABLE;
286  }
287  rpl_timers_dio_reset("Reachable");
288  /* There is no DAO-ACK, schedule a refresh. */
289  schedule_dao_refresh();
290 #endif /* !RPL_WITH_DAO_ACK */
291 
292  /* Increment seqno */
293  RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_last_seqno);
294  /* Send a DAO with own prefix as target and default lifetime */
295  rpl_icmp6_dao_output(curr_instance.default_lifetime);
296 }
297 #if RPL_WITH_DAO_ACK
298 /*---------------------------------------------------------------------------*/
299 /*------------------------------- DAO-ACK ---------------------------------- */
300 /*---------------------------------------------------------------------------*/
301 /*---------------------------------------------------------------------------*/
302 void
303 rpl_timers_schedule_dao_ack(uip_ipaddr_t *target, uint16_t sequence)
304 {
305  if(curr_instance.used) {
306  uip_ipaddr_copy(&curr_instance.dag.dao_ack_target, target);
307  curr_instance.dag.dao_ack_sequence = sequence;
308  ctimer_set(&curr_instance.dag.dao_ack_timer, 0, handle_dao_ack_timer, NULL);
309  }
310 }
311 /*---------------------------------------------------------------------------*/
312 static void
313 handle_dao_ack_timer(void *ptr)
314 {
315  rpl_icmp6_dao_ack_output(&curr_instance.dag.dao_ack_target,
316  curr_instance.dag.dao_ack_sequence, RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
317 }
318 /*---------------------------------------------------------------------------*/
319 void
321 {
322  /* The last DAO was ACKed. Schedule refresh to avoid route expiration. This
323  implicitly de-schedules resend_dao, as both share curr_instance.dag.dao_timer */
324  schedule_dao_refresh();
325 }
326 /*---------------------------------------------------------------------------*/
327 static void
328 resend_dao(void *ptr)
329 {
330  /* Increment transmission counter before sending */
331  curr_instance.dag.dao_transmissions++;
332  /* Send a DAO with own prefix as target and default lifetime */
333  rpl_icmp6_dao_output(curr_instance.default_lifetime);
334 
335  /* Schedule next retransmission, or abort */
336  if(curr_instance.dag.dao_transmissions < RPL_DAO_MAX_RETRANSMISSIONS) {
337  schedule_dao_retransmission();
338  } else {
339  /* No more retransmissions. Perform local repair. */
340  rpl_local_repair("DAO max rtx");
341  return;
342  }
343 }
344 #endif /* RPL_WITH_DAO_ACK */
345 /*---------------------------------------------------------------------------*/
346 /*------------------------------- Probing----------------------------------- */
347 /*---------------------------------------------------------------------------*/
348 #if RPL_WITH_PROBING
349 clock_time_t
350 get_probing_delay(void)
351 {
352  return ((RPL_PROBING_INTERVAL) / 2) + random_rand() % (RPL_PROBING_INTERVAL);
353 }
354 /*---------------------------------------------------------------------------*/
355 rpl_nbr_t *
356 get_probing_target(void)
357 {
358  /* Returns the next probing target. The current implementation probes the urgent
359  * probing target if any, or the preferred parent if its link statistics need refresh.
360  * Otherwise, it picks at random between:
361  * (1) selecting the best neighbor with non-fresh link statistics
362  * (2) selecting the least recently updated neighbor
363  */
364 
365  rpl_nbr_t *nbr;
366  rpl_nbr_t *probing_target = NULL;
367  rpl_rank_t probing_target_rank = RPL_INFINITE_RANK;
368  clock_time_t probing_target_age = 0;
369  clock_time_t clock_now = clock_time();
370 
371  if(curr_instance.used == 0) {
372  return NULL;
373  }
374 
375  /* There is an urgent probing target */
376  if(curr_instance.dag.urgent_probing_target != NULL) {
377  return curr_instance.dag.urgent_probing_target;
378  }
379 
380  /* The preferred parent needs probing */
381  if(curr_instance.dag.preferred_parent != NULL && !rpl_neighbor_is_fresh(curr_instance.dag.preferred_parent)) {
382  return curr_instance.dag.preferred_parent;
383  }
384 
385  /* Now consider probing other non-fresh neighbors. With 2/3 proabability,
386  pick the best non-fresh. Otherwise, pick the lest recently updated non-fresh. */
387 
388  if(random_rand() % 3 != 0) {
389  /* Look for best non-fresh */
390  nbr = nbr_table_head(rpl_neighbors);
391  while(nbr != NULL) {
392  if(!rpl_neighbor_is_fresh(nbr)) {
393  /* nbr needs probing */
394  rpl_rank_t nbr_rank = rpl_neighbor_rank_via_nbr(nbr);
395  if(probing_target == NULL
396  || nbr_rank < probing_target_rank) {
397  probing_target = nbr;
398  probing_target_rank = nbr_rank;
399  }
400  }
401  nbr = nbr_table_next(rpl_neighbors, nbr);
402  }
403  } else {
404  /* Look for least recently updated non-fresh */
405  nbr = nbr_table_head(rpl_neighbors);
406  while(nbr != NULL) {
407  if(!rpl_neighbor_is_fresh(nbr)) {
408  /* nbr needs probing */
409  const struct link_stats *stats = rpl_neighbor_get_link_stats(nbr);
410  if(stats != NULL) {
411  if(probing_target == NULL
412  || clock_now - stats->last_tx_time > probing_target_age) {
413  probing_target = nbr;
414  probing_target_age = clock_now - stats->last_tx_time;
415  }
416  }
417  }
418  nbr = nbr_table_next(rpl_neighbors, nbr);
419  }
420  }
421 
422  return probing_target;
423 }
424 /*---------------------------------------------------------------------------*/
425 static void
426 handle_probing_timer(void *ptr)
427 {
428  rpl_nbr_t *probing_target = RPL_PROBING_SELECT_FUNC();
429  uip_ipaddr_t *target_ipaddr = rpl_neighbor_get_ipaddr(probing_target);
430 
431  /* Perform probing */
432  if(target_ipaddr != NULL) {
433  const struct link_stats *stats = rpl_neighbor_get_link_stats(probing_target);
434  (void)stats;
435  LOG_INFO("probing ");
436  LOG_INFO_6ADDR(target_ipaddr);
437  LOG_INFO_(" %s last tx %u min ago\n",
438  curr_instance.dag.urgent_probing_target != NULL ? "(urgent)" : "",
439  stats != NULL ?
440  (unsigned)((clock_time() - stats->last_tx_time) / (60 * CLOCK_SECOND)) : 0
441  );
442  /* Send probe, e.g. unicast DIO or DIS */
443  RPL_PROBING_SEND_FUNC(target_ipaddr);
444  /* urgent_probing_target will be NULLed in the packet_sent callback */
445  } else {
446  LOG_INFO("no neighbor needs probing\n");
447  }
448 
449  /* Schedule next probing */
451 }
452 /*---------------------------------------------------------------------------*/
453 void
455 {
456  if(curr_instance.used) {
457  ctimer_set(&curr_instance.dag.probing_timer, RPL_PROBING_DELAY_FUNC(),
458  handle_probing_timer, NULL);
459  }
460 }
461 /*---------------------------------------------------------------------------*/
462 void
464 {
465  if(curr_instance.used) {
466  ctimer_set(&curr_instance.dag.probing_timer,
467  random_rand() % (CLOCK_SECOND * 4), handle_probing_timer, NULL);
468  }
469 }
470 #endif /* RPL_WITH_PROBING */
471 /*---------------------------------------------------------------------------*/
472 /*------------------------------- Leaving-- -------------------------------- */
473 /*---------------------------------------------------------------------------*/
474 static void
475 handle_leaving_timer(void *ptr)
476 {
477  if(curr_instance.used) {
478  rpl_dag_leave();
479  }
480 }
481 /*---------------------------------------------------------------------------*/
482 void
484 {
485  if(curr_instance.used) {
486  if(!ctimer_expired(&curr_instance.dag.leave)) {
487  ctimer_stop(&curr_instance.dag.leave);
488  }
489  }
490 }
491 /*---------------------------------------------------------------------------*/
492 void
494 {
495  if(curr_instance.used) {
496  if(ctimer_expired(&curr_instance.dag.leave)) {
497  ctimer_set(&curr_instance.dag.leave, RPL_DELAY_BEFORE_LEAVING, handle_leaving_timer, NULL);
498  }
499  }
500 }
501 /*---------------------------------------------------------------------------*/
502 /*------------------------------- Periodic---------------------------------- */
503 /*---------------------------------------------------------------------------*/
504 void
506 {
507  ctimer_set(&periodic_timer, PERIODIC_DELAY, handle_periodic_timer, NULL);
509 }
510 /*---------------------------------------------------------------------------*/
511 static void
512 handle_periodic_timer(void *ptr)
513 {
514  if(curr_instance.used) {
515  rpl_dag_periodic(PERIODIC_DELAY_SECONDS);
516  uip_sr_periodic(PERIODIC_DELAY_SECONDS);
517  }
518 
519  if(!curr_instance.used ||
520  curr_instance.dag.preferred_parent == NULL ||
521  curr_instance.dag.rank == RPL_INFINITE_RANK) {
522  rpl_timers_schedule_periodic_dis(); /* Schedule DIS if needed */
523  }
524 
525  /* Useful because part of the state update is time-dependent, e.g.,
526  the meaning of last_advertised_rank changes with time */
528 
529  if(LOG_INFO_ENABLED) {
530  rpl_neighbor_print_list("Periodic");
531  rpl_dag_root_print_links("Periodic");
532  }
533 
534  ctimer_reset(&periodic_timer);
535 }
536 /*---------------------------------------------------------------------------*/
537 void
539 {
540  /* Stop all timers related to the DAG */
541  ctimer_stop(&curr_instance.dag.state_update);
542  ctimer_stop(&curr_instance.dag.leave);
543  ctimer_stop(&curr_instance.dag.dio_timer);
544  ctimer_stop(&curr_instance.dag.unicast_dio_timer);
545  ctimer_stop(&curr_instance.dag.dao_timer);
546 #if RPL_WITH_PROBING
547  ctimer_stop(&curr_instance.dag.probing_timer);
548 #endif /* RPL_WITH_PROBING */
549 #if RPL_WITH_DAO_ACK
550  ctimer_stop(&curr_instance.dag.dao_ack_timer);
551 #endif /* RPL_WITH_DAO_ACK */
552 }
553 /*---------------------------------------------------------------------------*/
554 void
556 {
557  if(curr_instance.used) {
558  ctimer_stop(&curr_instance.dag.state_update);
559  }
560 }
561 /*---------------------------------------------------------------------------*/
562 void
564 {
565  if(curr_instance.used) {
566  ctimer_set(&curr_instance.dag.state_update, 0, handle_state_update, NULL);
567  }
568 }
569 /*---------------------------------------------------------------------------*/
570 static void
571 handle_state_update(void *ptr)
572 {
574 }
575 
576 /** @}*/
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:208
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:505
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:153
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:563
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:483
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:538
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:255
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:263
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:266
void rpl_timers_schedule_leaving(void)
Schedule leaving after RPL_DELAY_BEFORE_LEAVING.
Definition: rpl-timers.c:493
void rpl_timers_unschedule_state_update(void)
Cancelled any scheduled state update.
Definition: rpl-timers.c:555
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:240
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()