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
57void RPL_CALLBACK_NEW_DIO_INTERVAL(clock_time_t dio_interval);
58#endif /* RPL_CALLBACK_NEW_DIO_INTERVAL */
59
60#ifdef RPL_PROBING_SELECT_FUNC
61rpl_nbr_t *RPL_PROBING_SELECT_FUNC(void);
62#endif /* RPL_PROBING_SELECT_FUNC */
63
64#ifdef RPL_PROBING_DELAY_FUNC
65clock_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
71static void handle_dis_timer(void *ptr);
72static void handle_dio_timer(void *ptr);
73static void handle_unicast_dio_timer(void *ptr);
74static void send_new_dao(void *ptr);
75#if RPL_WITH_DAO_ACK
76static void resend_dao(void *ptr);
77static void handle_dao_ack_timer(void *ptr);
78#endif /* RPL_WITH_DAO_ACK */
79#if RPL_WITH_PROBING
80static void handle_probing_timer(void *ptr);
81#endif /* RPL_WITH_PROBING */
82static void handle_periodic_timer(void *ptr);
83static void handle_state_update(void *ptr);
84
85/*---------------------------------------------------------------------------*/
86static struct ctimer dis_timer; /* Not part of a DAG because when not joined */
87static struct ctimer periodic_timer; /* Not part of a DAG because used for general state maintenance */
88
89/*---------------------------------------------------------------------------*/
90/*------------------------------- DIS -------------------------------------- */
91/*---------------------------------------------------------------------------*/
92void
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/*---------------------------------------------------------------------------*/
101static void
102handle_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 */
111 }
112}
113/*---------------------------------------------------------------------------*/
114/*------------------------------- DIO -------------------------------------- */
115/*---------------------------------------------------------------------------*/
116static void
117new_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/*---------------------------------------------------------------------------*/
149void
150rpl_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/*---------------------------------------------------------------------------*/
168static void
169handle_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
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;
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/*---------------------------------------------------------------------------*/
207void
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/*---------------------------------------------------------------------------*/
217static void
218handle_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/*---------------------------------------------------------------------------*/
230static void
231schedule_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/*---------------------------------------------------------------------------*/
238static void
239schedule_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/*---------------------------------------------------------------------------*/
262void
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/*---------------------------------------------------------------------------*/
274static void
275send_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/*---------------------------------------------------------------------------*/
302void
303rpl_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/*---------------------------------------------------------------------------*/
312static void
313handle_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/*---------------------------------------------------------------------------*/
319void
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/*---------------------------------------------------------------------------*/
327static void
328resend_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
349clock_time_t
350get_probing_delay(void)
351{
352 return ((RPL_PROBING_INTERVAL) / 2) + random_rand() % (RPL_PROBING_INTERVAL);
353}
354/*---------------------------------------------------------------------------*/
355rpl_nbr_t *
356get_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) {
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) {
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/*---------------------------------------------------------------------------*/
425static void
426handle_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/*---------------------------------------------------------------------------*/
453void
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/*---------------------------------------------------------------------------*/
462void
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/*---------------------------------------------------------------------------*/
474static void
475handle_leaving_timer(void *ptr)
476{
477 if(curr_instance.used) {
479 }
480}
481/*---------------------------------------------------------------------------*/
482void
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/*---------------------------------------------------------------------------*/
492void
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/*---------------------------------------------------------------------------*/
504void
506{
507 ctimer_set(&periodic_timer, PERIODIC_DELAY, handle_periodic_timer, NULL);
509}
510/*---------------------------------------------------------------------------*/
511static void
512handle_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/*---------------------------------------------------------------------------*/
537void
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/*---------------------------------------------------------------------------*/
554void
556{
557 if(curr_instance.used) {
558 ctimer_stop(&curr_instance.dag.state_update);
559 }
560}
561/*---------------------------------------------------------------------------*/
562void
564{
565 if(curr_instance.used) {
566 ctimer_set(&curr_instance.dag.state_update, 0, handle_state_update, NULL);
567 }
568}
569/*---------------------------------------------------------------------------*/
570static void
571handle_state_update(void *ptr)
572{
574}
575
576/** @}*/
Header file for the callback timer.
clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:118
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Definition: random.c:58
static volatile uint64_t count
Num.
Definition: clock.c:50
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
int ctimer_expired(struct ctimer *c)
Check if a callback timer has expired.
Definition: ctimer.c:161
void ctimer_reset(struct ctimer *c)
Reset a callback timer with the same interval as was previously set.
Definition: ctimer.c:125
void rpl_timers_stop_dag_timers(void)
Stop all timers related to the DAG.
Definition: rpl-timers.c:538
void rpl_schedule_probing(void)
Schedule probing with delay RPL_PROBING_DELAY_FUNC()
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_icmp6_dis_output(uip_ipaddr_t *addr)
Creates an ICMPv6 DIS packet and sends it.
Definition: rpl-icmp6.c:151
void rpl_schedule_probing_now(void)
Schedule probing within a few seconds.
uint8_t rpl_get_leaf_only(void)
Get the value of the rpl_leaf_only flag.
Definition: rpl.c:242
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_icmp6_dio_output(uip_ipaddr_t *uc_addr)
Creates an ICMPv6 DIO packet and sends it.
Definition: rpl-icmp6.c:352
void rpl_dag_root_print_links(const char *str)
Prints a summary of all routing links.
Definition: rpl-dag-root.c:54
void rpl_dag_update_state(void)
Updates RPL internal state: selects preferred parent, updates rank & metreic container,...
Definition: rpl-dag.c:266
void rpl_dag_periodic(unsigned seconds)
A function called periodically.
Definition: rpl-dag.c:138
void rpl_timers_notify_dao_ack(void)
Let the rpl-timers module know that the last DAO was ACKed.
void rpl_timers_unschedule_state_update(void)
Cancelled any scheduled state update.
Definition: rpl-timers.c:555
void rpl_timers_schedule_dao(void)
Schedule a DAO with random delay based on RPL_DAO_DELAY.
Definition: rpl-timers.c:263
#define RPL_LIFETIME(lifetime)
Compute lifetime, accounting for the lifetime unit.
Definition: rpl-types.h:72
void rpl_timers_schedule_leaving(void)
Schedule leaving after RPL_DELAY_BEFORE_LEAVING.
Definition: rpl-timers.c:493
const struct link_stats * rpl_neighbor_get_link_stats(rpl_nbr_t *nbr)
Returns a neighbor's link statistics.
Definition: rpl-neighbor.c:259
void rpl_timers_dio_reset(const char *str)
Reset DIO Trickle timer.
Definition: rpl-timers.c:150
void rpl_timers_init(void)
Initialize rpl-timers module.
Definition: rpl-timers.c:505
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:597
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_dao_ack(uip_ipaddr_t *target, uint16_t sequence)
Schedule a DAO-ACK with no delay.
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_timers_unschedule_leaving(void)
Cancel scheduled leaving if any.
Definition: rpl-timers.c:483
uip_ipaddr_t * rpl_neighbor_get_ipaddr(rpl_nbr_t *nbr)
Returns a neighbor's (link-local) IPv6 address.
Definition: rpl-neighbor.c:252
void rpl_dag_leave(void)
Leaves the current DAG.
Definition: rpl-dag.c:99
void rpl_local_repair(const char *str)
Triggers a RPL local repair.
Definition: rpl-dag.c:240
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_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_state_update(void)
Schedule a state update ASAP.
Definition: rpl-timers.c:563
void rpl_timers_schedule_unicast_dio(rpl_nbr_t *target)
Schedule unicast DIO with no delay.
Definition: rpl-timers.c:208
int rpl_dag_root_is_root(void)
Tells whether we are DAG root or not.
Definition: rpl-dag-root.c:152
void uip_sr_periodic(unsigned seconds)
A function called periodically.
Definition: uip-sr.c:211
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:969
Header file for the logging system.
All information related to a RPL neighbor.
Definition: rpl-types.h:136
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
Definition: uip-nd6.c:106
Source routing support.