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 handle_dao_timer(void *ptr);
75 #if RPL_WITH_DAO_ACK
76 static void handle_dao_ack_timer(void *ptr);
77 #endif /* RPL_WITH_DAO_ACK */
78 #if RPL_WITH_PROBING
79 static void handle_probing_timer(void *ptr);
80 #endif /* RPL_WITH_PROBING */
81 static void handle_periodic_timer(void *ptr);
82 static void handle_state_update(void *ptr);
83 
84 /*---------------------------------------------------------------------------*/
85 static struct ctimer dis_timer; /* Not part of a DAG because when not joined */
86 static struct ctimer periodic_timer; /* Not part of a DAG because used for general state maintenance */
87 
88 /*---------------------------------------------------------------------------*/
89 /*------------------------------- DIS -------------------------------------- */
90 /*---------------------------------------------------------------------------*/
91 void
93 {
94  if(ctimer_expired(&dis_timer)) {
95  clock_time_t expiration_time = RPL_DIS_INTERVAL / 2 + (random_rand() % (RPL_DIS_INTERVAL));
96  ctimer_set(&dis_timer, expiration_time, handle_dis_timer, NULL);
97  }
98 }
99 /*---------------------------------------------------------------------------*/
100 static void
101 handle_dis_timer(void *ptr)
102 {
103  if(!rpl_dag_root_is_root() &&
104  (!curr_instance.used ||
105  curr_instance.dag.preferred_parent == NULL ||
106  curr_instance.dag.rank == RPL_INFINITE_RANK)) {
107  /* Send DIS and schedule next */
108  rpl_icmp6_dis_output(NULL);
110  }
111 }
112 /*---------------------------------------------------------------------------*/
113 /*------------------------------- DIO -------------------------------------- */
114 /*---------------------------------------------------------------------------*/
115 static void
116 new_dio_interval(void)
117 {
118  uint32_t time;
119  clock_time_t ticks;
120 
121  time = 1UL << curr_instance.dag.dio_intcurrent;
122 
123  /* Convert from milliseconds to CLOCK_TICKS. */
124  ticks = (time * CLOCK_SECOND) / 1000;
125  curr_instance.dag.dio_next_delay = ticks;
126 
127  /* random number between I/2 and I */
128  ticks = ticks / 2 + (ticks / 2 * (uint32_t)random_rand()) / RANDOM_RAND_MAX;
129 
130  /*
131  * The intervals must be equally long among the nodes for Trickle to
132  * operate efficiently. Therefore we need to calculate the delay between
133  * the randomized time and the start time of the next interval.
134  */
135  curr_instance.dag.dio_next_delay -= ticks;
136  curr_instance.dag.dio_send = 1;
137  /* reset the redundancy counter */
138  curr_instance.dag.dio_counter = 0;
139 
140  /* schedule the timer */
141  ctimer_set(&curr_instance.dag.dio_timer, ticks, &handle_dio_timer, NULL);
142 
143 #ifdef RPL_CALLBACK_NEW_DIO_INTERVAL
144  RPL_CALLBACK_NEW_DIO_INTERVAL((CLOCK_SECOND * 1UL << curr_instance.dag.dio_intcurrent) / 1000);
145 #endif /* RPL_CALLBACK_NEW_DIO_INTERVAL */
146 }
147 /*---------------------------------------------------------------------------*/
148 void
149 rpl_timers_dio_reset(const char *str)
150 {
152  LOG_INFO("reset DIO timer (%s)\n", str);
153  if(!rpl_get_leaf_only()) {
154  curr_instance.dag.dio_counter = 0;
155  curr_instance.dag.dio_intcurrent = curr_instance.dio_intmin;
156  new_dio_interval();
157  }
158  }
159 }
160 /*---------------------------------------------------------------------------*/
161 static void
162 handle_dio_timer(void *ptr)
163 {
165  return; /* We will be scheduled again later */
166  }
167 
168  if(curr_instance.dag.dio_send) {
169  /* send DIO if counter is less than desired redundancy, or if dio_redundancy
170  is set to 0, or if we are the root */
171  if(rpl_dag_root_is_root() || curr_instance.dio_redundancy == 0 ||
172  curr_instance.dag.dio_counter < curr_instance.dio_redundancy) {
173 #if RPL_TRICKLE_REFRESH_DAO_ROUTES
174  if(rpl_dag_root_is_root()) {
175  static int count = 0;
176  if((count++ % RPL_TRICKLE_REFRESH_DAO_ROUTES) == 0) {
177  /* Request new DAO to refresh route. */
178  RPL_LOLLIPOP_INCREMENT(curr_instance.dtsn_out);
179  LOG_INFO("trigger DAO updates with a DTSN increment (%u)\n", curr_instance.dtsn_out);
180  }
181  }
182 #endif /* RPL_TRICKLE_REFRESH_DAO_ROUTES */
183  curr_instance.dag.last_advertised_rank = curr_instance.dag.rank;
184  rpl_icmp6_dio_output(NULL);
185  }
186  curr_instance.dag.dio_send = 0;
187  ctimer_set(&curr_instance.dag.dio_timer, curr_instance.dag.dio_next_delay, handle_dio_timer, NULL);
188  } else {
189  /* check if we need to double interval */
190  if(curr_instance.dag.dio_intcurrent < curr_instance.dio_intmin + curr_instance.dio_intdoubl) {
191  curr_instance.dag.dio_intcurrent++;
192  }
193  new_dio_interval();
194  }
195 }
196 /*---------------------------------------------------------------------------*/
197 /*------------------------------- Unicast DIO ------------------------------ */
198 /*---------------------------------------------------------------------------*/
199 /*---------------------------------------------------------------------------*/
200 void
202 {
203  if(curr_instance.used) {
204  curr_instance.dag.unicast_dio_target = target;
205  ctimer_set(&curr_instance.dag.unicast_dio_timer, 0,
206  handle_unicast_dio_timer, NULL);
207  }
208 }
209 /*---------------------------------------------------------------------------*/
210 static void
211 handle_unicast_dio_timer(void *ptr)
212 {
213  uip_ipaddr_t *target_ipaddr = rpl_neighbor_get_ipaddr(curr_instance.dag.unicast_dio_target);
214  if(target_ipaddr != NULL) {
215  rpl_icmp6_dio_output(target_ipaddr);
216  }
217 }
218 /*---------------------------------------------------------------------------*/
219 /*------------------------------- DAO -------------------------------------- */
220 /*---------------------------------------------------------------------------*/
221 #if RPL_WITH_DAO_ACK
222 /*---------------------------------------------------------------------------*/
223 static void
224 schedule_dao_retransmission(void)
225 {
226  clock_time_t expiration_time = RPL_DAO_RETRANSMISSION_TIMEOUT / 2 + (random_rand() % (RPL_DAO_RETRANSMISSION_TIMEOUT));
227  ctimer_set(&curr_instance.dag.dao_timer, expiration_time, handle_dao_timer, NULL);
228 }
229 #endif /* RPL_WITH_DAO_ACK */
230 /*---------------------------------------------------------------------------*/
231 static void
232 schedule_dao_refresh(void)
233 {
234  if(curr_instance.used && curr_instance.default_lifetime != RPL_INFINITE_LIFETIME) {
235 #if RPL_WITH_DAO_ACK
236  /* DAO-ACK enabled: the last DAO was ACKed, wait until expiration before refresh */
237  clock_time_t target_refresh = CLOCK_SECOND * RPL_LIFETIME(curr_instance.default_lifetime);
238 #else /* RPL_WITH_DAO_ACK */
239  /* DAO-ACK disabled: use half the expiration time to get two chances to refresh per lifetime */
240  clock_time_t target_refresh = (CLOCK_SECOND * RPL_LIFETIME(curr_instance.default_lifetime) / 2);
241 #endif /* RPL_WITH_DAO_ACK */
242 
243  /* Send between 60 and 120 seconds before target refresh */
244  clock_time_t safety_margin = (60 * CLOCK_SECOND) + (random_rand() % (60 * CLOCK_SECOND));
245 
246  if(target_refresh > safety_margin) {
247  target_refresh -= safety_margin;
248  }
249 
250  /* Increment next sequno */
251  RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno);
252  ctimer_set(&curr_instance.dag.dao_timer, target_refresh, handle_dao_timer, 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  /* Increment next seqno */
265  RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno);
266  ctimer_set(&curr_instance.dag.dao_timer, expiration_time, handle_dao_timer, NULL);
267  }
268 }
269 /*---------------------------------------------------------------------------*/
270 static void
271 handle_dao_timer(void *ptr)
272 {
273 #if RPL_WITH_DAO_ACK
274  if(rpl_lollipop_greater_than(curr_instance.dag.dao_curr_seqno,
275  curr_instance.dag.dao_last_seqno)) {
276  /* We are sending a new DAO here. Prepare retransmissions */
277  curr_instance.dag.dao_transmissions = 0;
278  } else {
279  /* We are called for the same DAO again */
280  if(curr_instance.dag.dao_last_acked_seqno == curr_instance.dag.dao_last_seqno) {
281  /* The last seqno sent is ACKed! Schedule refresh to avoid route expiration */
282  schedule_dao_refresh();
283  return;
284  }
285  /* We need to re-send the last DAO */
286  if(curr_instance.dag.dao_transmissions >= RPL_DAO_MAX_RETRANSMISSIONS) {
287  /* No more retransmissions. Perform local repair and hope to find another . */
288  rpl_local_repair("DAO max rtx");
289  return;
290  }
291  }
292  /* Increment transmission counter before sending */
293  curr_instance.dag.dao_transmissions++;
294  /* Schedule next retransmission */
295  schedule_dao_retransmission();
296 #else /* RPL_WITH_DAO_ACK */
297  /* No DAO-ACK: assume we are reachable as soon as we send a DAO */
298  if(curr_instance.dag.state == DAG_JOINED) {
299  curr_instance.dag.state = DAG_REACHABLE;
300  }
301  rpl_timers_dio_reset("Reachable");
302 #endif /* !RPL_WITH_DAO_ACK */
303 
304  curr_instance.dag.dao_last_seqno = curr_instance.dag.dao_curr_seqno;
305  /* Send a DAO with own prefix as target and default lifetime */
306  rpl_icmp6_dao_output(curr_instance.default_lifetime);
307 
308 #if !RPL_WITH_DAO_ACK
309  /* There is no DAO-ACK, schedule a refresh. Must be done after rpl_icmp6_dao_output,
310  because we increment curr_instance.dag.dao_curr_seqno for the next DAO (refresh).
311  Where there is DAO-ACK, the refresh is scheduled after reception of the ACK.
312  Happens when handle_dao_timer is called again next. */
313  schedule_dao_refresh();
314 #endif /* !RPL_WITH_DAO_ACK */
315 }
316 #if RPL_WITH_DAO_ACK
317 /*---------------------------------------------------------------------------*/
318 /*------------------------------- DAO-ACK ---------------------------------- */
319 /*---------------------------------------------------------------------------*/
320 /*---------------------------------------------------------------------------*/
321 void
322 rpl_timers_schedule_dao_ack(uip_ipaddr_t *target, uint16_t sequence)
323 {
324  if(curr_instance.used) {
325  uip_ipaddr_copy(&curr_instance.dag.dao_ack_target, target);
326  curr_instance.dag.dao_ack_sequence = sequence;
327  ctimer_set(&curr_instance.dag.dao_ack_timer, 0, handle_dao_ack_timer, NULL);
328  }
329 }
330 /*---------------------------------------------------------------------------*/
331 static void
332 handle_dao_ack_timer(void *ptr)
333 {
334  rpl_icmp6_dao_ack_output(&curr_instance.dag.dao_ack_target,
335  curr_instance.dag.dao_ack_sequence, RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
336 }
337 #endif /* RPL_WITH_DAO_ACK */
338 /*---------------------------------------------------------------------------*/
339 /*------------------------------- Probing----------------------------------- */
340 /*---------------------------------------------------------------------------*/
341 #if RPL_WITH_PROBING
342 clock_time_t
343 get_probing_delay(void)
344 {
345  return ((RPL_PROBING_INTERVAL) / 2) + random_rand() % (RPL_PROBING_INTERVAL);
346 }
347 /*---------------------------------------------------------------------------*/
348 rpl_nbr_t *
349 get_probing_target(void)
350 {
351  /* Returns the next probing target. The current implementation probes the urgent
352  * probing target if any, or the preferred parent if its link statistics need refresh.
353  * Otherwise, it picks at random between:
354  * (1) selecting the best neighbor with non-fresh link statistics
355  * (2) selecting the least recently updated neighbor
356  */
357 
358  rpl_nbr_t *nbr;
359  rpl_nbr_t *probing_target = NULL;
360  rpl_rank_t probing_target_rank = RPL_INFINITE_RANK;
361  clock_time_t probing_target_age = 0;
362  clock_time_t clock_now = clock_time();
363 
364  if(curr_instance.used == 0) {
365  return NULL;
366  }
367 
368  /* There is an urgent probing target */
369  if(curr_instance.dag.urgent_probing_target != NULL) {
370  return curr_instance.dag.urgent_probing_target;
371  }
372 
373  /* The preferred parent needs probing */
374  if(curr_instance.dag.preferred_parent != NULL && !rpl_neighbor_is_fresh(curr_instance.dag.preferred_parent)) {
375  return curr_instance.dag.preferred_parent;
376  }
377 
378  /* Now consider probing other non-fresh neighbors. With 2/3 proabability,
379  pick the best non-fresh. Otherwise, pick the lest recently updated non-fresh. */
380 
381  if(random_rand() % 3 != 0) {
382  /* Look for best non-fresh */
383  nbr = nbr_table_head(rpl_neighbors);
384  while(nbr != NULL) {
385  if(!rpl_neighbor_is_fresh(nbr)) {
386  /* nbr needs probing */
387  rpl_rank_t nbr_rank = rpl_neighbor_rank_via_nbr(nbr);
388  if(probing_target == NULL
389  || nbr_rank < probing_target_rank) {
390  probing_target = nbr;
391  probing_target_rank = nbr_rank;
392  }
393  }
394  nbr = nbr_table_next(rpl_neighbors, nbr);
395  }
396  } else {
397  /* Look for least recently updated non-fresh */
398  nbr = nbr_table_head(rpl_neighbors);
399  while(nbr != NULL) {
400  if(!rpl_neighbor_is_fresh(nbr)) {
401  /* nbr needs probing */
402  const struct link_stats *stats = rpl_neighbor_get_link_stats(nbr);
403  if(stats != NULL) {
404  if(probing_target == NULL
405  || clock_now - stats->last_tx_time > probing_target_age) {
406  probing_target = nbr;
407  probing_target_age = clock_now - stats->last_tx_time;
408  }
409  }
410  }
411  nbr = nbr_table_next(rpl_neighbors, nbr);
412  }
413  }
414 
415  return probing_target;
416 }
417 /*---------------------------------------------------------------------------*/
418 static void
419 handle_probing_timer(void *ptr)
420 {
421  rpl_nbr_t *probing_target = RPL_PROBING_SELECT_FUNC();
422  uip_ipaddr_t *target_ipaddr = rpl_neighbor_get_ipaddr(probing_target);
423 
424  /* Perform probing */
425  if(target_ipaddr != NULL) {
426  const struct link_stats *stats = rpl_neighbor_get_link_stats(probing_target);
427  (void)stats;
428  LOG_INFO("probing ");
429  LOG_INFO_6ADDR(target_ipaddr);
430  LOG_INFO_(" %s last tx %u min ago\n",
431  curr_instance.dag.urgent_probing_target != NULL ? "(urgent)" : "",
432  stats != NULL ?
433  (unsigned)((clock_time() - stats->last_tx_time) / (60 * CLOCK_SECOND)) : 0
434  );
435  /* Send probe, e.g. unicast DIO or DIS */
436  RPL_PROBING_SEND_FUNC(target_ipaddr);
437  /* urgent_probing_target will be NULLed in the packet_sent callback */
438  } else {
439  LOG_INFO("no neighbor needs probing\n");
440  }
441 
442  /* Schedule next probing */
444 }
445 /*---------------------------------------------------------------------------*/
446 void
448 {
449  if(curr_instance.used) {
450  ctimer_set(&curr_instance.dag.probing_timer, RPL_PROBING_DELAY_FUNC(),
451  handle_probing_timer, NULL);
452  }
453 }
454 /*---------------------------------------------------------------------------*/
455 void
457 {
458  if(curr_instance.used) {
459  ctimer_set(&curr_instance.dag.probing_timer,
460  random_rand() % (CLOCK_SECOND * 4), handle_probing_timer, NULL);
461  }
462 }
463 #endif /* RPL_WITH_PROBING */
464 /*---------------------------------------------------------------------------*/
465 /*------------------------------- Leaving-- -------------------------------- */
466 /*---------------------------------------------------------------------------*/
467 static void
468 handle_leaving_timer(void *ptr)
469 {
470  if(curr_instance.used) {
471  rpl_dag_leave();
472  }
473 }
474 /*---------------------------------------------------------------------------*/
475 void
477 {
478  if(curr_instance.used) {
479  if(!ctimer_expired(&curr_instance.dag.leave)) {
480  ctimer_stop(&curr_instance.dag.leave);
481  }
482  }
483 }
484 /*---------------------------------------------------------------------------*/
485 void
487 {
488  if(curr_instance.used) {
489  if(ctimer_expired(&curr_instance.dag.leave)) {
490  ctimer_set(&curr_instance.dag.leave, RPL_DELAY_BEFORE_LEAVING, handle_leaving_timer, NULL);
491  }
492  }
493 }
494 /*---------------------------------------------------------------------------*/
495 /*------------------------------- Periodic---------------------------------- */
496 /*---------------------------------------------------------------------------*/
497 void
499 {
500  ctimer_set(&periodic_timer, PERIODIC_DELAY, handle_periodic_timer, NULL);
502 }
503 /*---------------------------------------------------------------------------*/
504 static void
505 handle_periodic_timer(void *ptr)
506 {
507  if(curr_instance.used) {
508  rpl_dag_periodic(PERIODIC_DELAY_SECONDS);
509  uip_sr_periodic(PERIODIC_DELAY_SECONDS);
510  }
511 
512  if(!curr_instance.used ||
513  curr_instance.dag.preferred_parent == NULL ||
514  curr_instance.dag.rank == RPL_INFINITE_RANK) {
515  rpl_timers_schedule_periodic_dis(); /* Schedule DIS if needed */
516  }
517 
518  /* Useful because part of the state update is time-dependent, e.g.,
519  the meaning of last_advertised_rank changes with time */
521 
522  if(LOG_INFO_ENABLED) {
523  rpl_neighbor_print_list("Periodic");
524  rpl_dag_root_print_links("Periodic");
525  }
526 
527  ctimer_reset(&periodic_timer);
528 }
529 /*---------------------------------------------------------------------------*/
530 void
532 {
533  /* Stop all timers related to the DAG */
534  ctimer_stop(&curr_instance.dag.state_update);
535  ctimer_stop(&curr_instance.dag.leave);
536  ctimer_stop(&curr_instance.dag.dio_timer);
537  ctimer_stop(&curr_instance.dag.unicast_dio_timer);
538  ctimer_stop(&curr_instance.dag.dao_timer);
539 #if RPL_WITH_PROBING
540  ctimer_stop(&curr_instance.dag.probing_timer);
541 #endif /* RPL_WITH_PROBING */
542 #if RPL_WITH_DAO_ACK
543  ctimer_stop(&curr_instance.dag.dao_ack_timer);
544 #endif /* RPL_WITH_DAO_ACK */
545 }
546 /*---------------------------------------------------------------------------*/
547 void
549 {
550  if(curr_instance.used) {
551  ctimer_stop(&curr_instance.dag.state_update);
552  }
553 }
554 /*---------------------------------------------------------------------------*/
555 void
557 {
558  if(curr_instance.used) {
559  ctimer_set(&curr_instance.dag.state_update, 0, handle_state_update, NULL);
560  }
561 }
562 /*---------------------------------------------------------------------------*/
563 static void
564 handle_state_update(void *ptr)
565 {
567 }
568 
569 /** @}*/
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:249
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
Definition: uip-nd6.c:115
void rpl_timers_schedule_unicast_dio(rpl_nbr_t *target)
Schedule unicast DIO with no delay.
Definition: rpl-timers.c:201
int rpl_lollipop_greater_than(int a, int b)
Greater-than function for a lollipop counter.
Definition: rpl.c:57
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:263
void rpl_timers_init(void)
Initialize rpl-timers module.
Definition: rpl-timers.c:498
uint8_t rpl_get_leaf_only(void)
Get the value of the rpl_leaf_only flag.
Definition: rpl.c:239
#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:147
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:547
Source routing support.
void rpl_timers_schedule_state_update(void)
Schedule a state update ASAP.
Definition: rpl-timers.c:556
void rpl_timers_dio_reset(const char *str)
Reset DIO Trickle timer.
Definition: rpl-timers.c:149
#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:476
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:531
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:256
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:1018
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:92
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:486
void rpl_timers_unschedule_state_update(void)
Cancelled any scheduled state update.
Definition: rpl-timers.c:548
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:234
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:336
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:154
void rpl_schedule_probing(void)
Schedule probing with delay RPL_PROBING_DELAY_FUNC()