Contiki-NG
rpl-dag.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 /**
34  * \file
35  * Logic for Directed Acyclic Graphs in RPL.
36  *
37  * \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>
38  * Contributors: George Oikonomou <oikonomou@users.sourceforge.net> (multicast)
39  */
40 
41 /**
42  * \addtogroup uip
43  * @{
44  */
45 
46 #include "contiki.h"
47 #include "net/link-stats.h"
48 #include "net/routing/rpl-classic/rpl.h"
49 #include "net/routing/rpl-classic/rpl-private.h"
50 #include "net/routing/rpl-classic/rpl-dag-root.h"
51 #include "net/ipv6/uip.h"
52 #include "net/ipv6/uip-nd6.h"
53 #include "net/ipv6/uip-ds6-nbr.h"
54 #include "net/nbr-table.h"
56 #include "lib/list.h"
57 #include "lib/memb.h"
58 #include "sys/ctimer.h"
59 #include "sys/log.h"
60 
61 #include <limits.h>
62 #include <string.h>
63 
64 #define LOG_MODULE "RPL"
65 #define LOG_LEVEL LOG_LEVEL_RPL
66 
67 /* A configurable function called after every RPL parent switch */
68 #ifdef RPL_CALLBACK_PARENT_SWITCH
69 void RPL_CALLBACK_PARENT_SWITCH(rpl_parent_t *old, rpl_parent_t *new);
70 #endif /* RPL_CALLBACK_PARENT_SWITCH */
71 
72 /*---------------------------------------------------------------------------*/
73 extern rpl_of_t rpl_of0, rpl_mrhof;
74 static rpl_of_t * const objective_functions[] = RPL_SUPPORTED_OFS;
75 
76 /*---------------------------------------------------------------------------*/
77 /* RPL definitions. */
78 
79 #ifndef RPL_CONF_GROUNDED
80 #define RPL_GROUNDED 0
81 #else
82 #define RPL_GROUNDED RPL_CONF_GROUNDED
83 #endif /* !RPL_CONF_GROUNDED */
84 
85 /*---------------------------------------------------------------------------*/
86 /* Per-parent RPL information */
87 NBR_TABLE_GLOBAL(rpl_parent_t, rpl_parents);
88 /*---------------------------------------------------------------------------*/
89 /* Allocate instance table. */
90 rpl_instance_t instance_table[RPL_MAX_INSTANCES];
91 rpl_instance_t *default_instance;
92 
93 /*---------------------------------------------------------------------------*/
94 void
95 rpl_print_neighbor_list(void)
96 {
97  if(default_instance != NULL && default_instance->current_dag != NULL &&
98  default_instance->of != NULL) {
99  int curr_dio_interval = default_instance->dio_intcurrent;
100  int curr_rank = default_instance->current_dag->rank;
101  rpl_parent_t *p = nbr_table_head(rpl_parents);
102  clock_time_t clock_now = clock_time();
103 
104  LOG_DBG("RPL: MOP %u OCP %u rank %u dioint %u, nbr count %u\n",
105  default_instance->mop, default_instance->of->ocp, curr_rank, curr_dio_interval, uip_ds6_nbr_num());
106  while(p != NULL) {
107  const struct link_stats *stats = rpl_get_parent_link_stats(p);
108  uip_ipaddr_t *parent_addr = rpl_parent_get_ipaddr(p);
109  LOG_DBG("RPL: nbr %02x %5u, %5u => %5u -- %2u %c%c (last tx %u min ago)\n",
110  parent_addr != NULL ? parent_addr->u8[15] : 0x0,
111  p->rank,
112  rpl_get_parent_link_metric(p),
113  rpl_rank_via_parent(p),
114  stats != NULL ? stats->freshness : 0,
115  link_stats_is_fresh(stats) ? 'f' : ' ',
116  p == default_instance->current_dag->preferred_parent ? 'p' : ' ',
117  stats != NULL ? (unsigned)((clock_now - stats->last_tx_time) / (60 * CLOCK_SECOND)) : -1u
118  );
119  p = nbr_table_next(rpl_parents, p);
120  }
121  LOG_DBG("RPL: end of list\n");
122  }
123 }
124 /*---------------------------------------------------------------------------*/
126 rpl_get_nbr(rpl_parent_t *parent)
127 {
128  const linkaddr_t *lladdr = rpl_get_parent_lladdr(parent);
129  if(lladdr != NULL) {
130  return uip_ds6_nbr_ll_lookup((const uip_lladdr_t *)lladdr);
131  } else {
132  return NULL;
133  }
134 }
135 /*---------------------------------------------------------------------------*/
136 static void
137 nbr_callback(void *ptr)
138 {
139  rpl_remove_parent(ptr);
140 }
141 
142 void
144 {
145  nbr_table_register(rpl_parents, (nbr_table_callback *)nbr_callback);
146 }
147 /*---------------------------------------------------------------------------*/
148 rpl_parent_t *
149 rpl_get_parent(const uip_lladdr_t *addr)
150 {
151  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (const linkaddr_t *)addr);
152  return p;
153 }
154 /*---------------------------------------------------------------------------*/
155 rpl_rank_t
156 rpl_get_parent_rank(uip_lladdr_t *addr)
157 {
158  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)addr);
159  if(p != NULL) {
160  return p->rank;
161  } else {
162  return RPL_INFINITE_RANK;
163  }
164 }
165 /*---------------------------------------------------------------------------*/
166 uint16_t
167 rpl_get_parent_link_metric(rpl_parent_t *p)
168 {
169  if(p != NULL && p->dag != NULL) {
170  rpl_instance_t *instance = p->dag->instance;
171  if(instance != NULL && instance->of != NULL && instance->of->parent_link_metric != NULL) {
172  return instance->of->parent_link_metric(p);
173  }
174  }
175  return 0xffff;
176 }
177 /*---------------------------------------------------------------------------*/
178 rpl_rank_t
179 rpl_rank_via_parent(rpl_parent_t *p)
180 {
181  if(p != NULL && p->dag != NULL) {
182  rpl_instance_t *instance = p->dag->instance;
183  if(instance != NULL && instance->of != NULL && instance->of->rank_via_parent != NULL) {
184  return instance->of->rank_via_parent(p);
185  }
186  }
187  return RPL_INFINITE_RANK;
188 }
189 /*---------------------------------------------------------------------------*/
190 const linkaddr_t *
191 rpl_get_parent_lladdr(rpl_parent_t *p)
192 {
193  return nbr_table_get_lladdr(rpl_parents, p);
194 }
195 /*---------------------------------------------------------------------------*/
196 uip_ipaddr_t *
197 rpl_parent_get_ipaddr(rpl_parent_t *p)
198 {
199  const linkaddr_t *lladdr = rpl_get_parent_lladdr(p);
200  if(lladdr == NULL) {
201  return NULL;
202  }
203  return uip_ds6_nbr_ipaddr_from_lladdr((uip_lladdr_t *)lladdr);
204 }
205 /*---------------------------------------------------------------------------*/
206 const struct link_stats *
207 rpl_get_parent_link_stats(rpl_parent_t *p)
208 {
209  const linkaddr_t *lladdr = rpl_get_parent_lladdr(p);
210  return link_stats_from_lladdr(lladdr);
211 }
212 /*---------------------------------------------------------------------------*/
213 int
214 rpl_parent_is_fresh(rpl_parent_t *p)
215 {
216  const struct link_stats *stats = rpl_get_parent_link_stats(p);
217  return link_stats_is_fresh(stats);
218 }
219 /*---------------------------------------------------------------------------*/
220 int
221 rpl_parent_is_reachable(rpl_parent_t *p) {
222  if(p == NULL || p->dag == NULL || p->dag->instance == NULL || p->dag->instance->of == NULL) {
223  return 0;
224  } else {
225 #if UIP_ND6_SEND_NS
226  /* Exclude links to a neighbor that is not reachable at a NUD level */
227  if(rpl_get_nbr(p) == NULL) {
228  return 0;
229  }
230 #endif /* UIP_ND6_SEND_NS */
231  /* If we don't have fresh link information, assume the parent is reachable. */
232  return !rpl_parent_is_fresh(p) || p->dag->instance->of->parent_has_usable_link(p);
233  }
234 }
235 /*---------------------------------------------------------------------------*/
236 static void
237 rpl_set_preferred_parent(rpl_dag_t *dag, rpl_parent_t *p)
238 {
239  if(dag != NULL && dag->preferred_parent != p) {
240  LOG_INFO("rpl_set_preferred_parent ");
241  if(p != NULL) {
242  LOG_INFO_6ADDR(rpl_parent_get_ipaddr(p));
243  } else {
244  LOG_INFO_("NULL");
245  }
246  LOG_INFO_(" used to be ");
247  if(dag->preferred_parent != NULL) {
248  LOG_INFO_6ADDR(rpl_parent_get_ipaddr(dag->preferred_parent));
249  } else {
250  LOG_INFO_("NULL");
251  }
252  LOG_INFO_("\n");
253 
254 #ifdef RPL_CALLBACK_PARENT_SWITCH
255  RPL_CALLBACK_PARENT_SWITCH(dag->preferred_parent, p);
256 #endif /* RPL_CALLBACK_PARENT_SWITCH */
257 
258  /* Always keep the preferred parent locked, so it remains in the
259  * neighbor table. */
260  nbr_table_unlock(rpl_parents, dag->preferred_parent);
261  nbr_table_lock(rpl_parents, p);
262  dag->preferred_parent = p;
263  }
264 }
265 /*---------------------------------------------------------------------------*/
266 /* Greater-than function for the lollipop counter. */
267 /*---------------------------------------------------------------------------*/
268 static int
269 lollipop_greater_than(int a, int b)
270 {
271  /* Check if we are comparing an initial value with an old value */
272  if(a > RPL_LOLLIPOP_CIRCULAR_REGION && b <= RPL_LOLLIPOP_CIRCULAR_REGION) {
273  return (RPL_LOLLIPOP_MAX_VALUE + 1 + b - a) > RPL_LOLLIPOP_SEQUENCE_WINDOWS;
274  }
275  /* Otherwise check if a > b and comparable => ok, or
276  if they have wrapped and are still comparable */
277  return (a > b && (a - b) < RPL_LOLLIPOP_SEQUENCE_WINDOWS) ||
278  (a < b && (b - a) > (RPL_LOLLIPOP_CIRCULAR_REGION + 1-
279  RPL_LOLLIPOP_SEQUENCE_WINDOWS));
280 }
281 /*---------------------------------------------------------------------------*/
282 /* Remove DAG parents with a rank that is at least the same as minimum_rank. */
283 static void
284 remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
285 {
286  rpl_parent_t *p;
287 
288  LOG_INFO("Removing parents (minimum rank %u)\n", minimum_rank);
289 
290  p = nbr_table_head(rpl_parents);
291  while(p != NULL) {
292  if(dag == p->dag && p->rank >= minimum_rank) {
293  rpl_remove_parent(p);
294  }
295  p = nbr_table_next(rpl_parents, p);
296  }
297 }
298 /*---------------------------------------------------------------------------*/
299 static void
300 nullify_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
301 {
302  rpl_parent_t *p;
303 
304  LOG_INFO("Nullifying parents (minimum rank %u)\n", minimum_rank);
305 
306  p = nbr_table_head(rpl_parents);
307  while(p != NULL) {
308  if(dag == p->dag && p->rank >= minimum_rank) {
309  rpl_nullify_parent(p);
310  }
311  p = nbr_table_next(rpl_parents, p);
312  }
313 }
314 /*---------------------------------------------------------------------------*/
315 static int
316 should_refresh_routes(rpl_instance_t *instance, rpl_dio_t *dio, rpl_parent_t *p)
317 {
318  /* if MOP is set to no downward routes no DAO should be sent */
319  if(instance->mop == RPL_MOP_NO_DOWNWARD_ROUTES) {
320  return 0;
321  }
322  /* check if the new DTSN is more recent */
323  return p == instance->current_dag->preferred_parent &&
324  (lollipop_greater_than(dio->dtsn, p->dtsn));
325 }
326 /*---------------------------------------------------------------------------*/
327 static int
328 acceptable_rank(rpl_dag_t *dag, rpl_rank_t rank)
329 {
330  return rank != RPL_INFINITE_RANK &&
331  ((dag->instance->max_rankinc == 0) ||
332  DAG_RANK(rank, dag->instance) <= DAG_RANK(dag->min_rank + dag->instance->max_rankinc, dag->instance));
333 }
334 /*---------------------------------------------------------------------------*/
335 static rpl_dag_t *
336 get_dag(uint8_t instance_id, uip_ipaddr_t *dag_id)
337 {
338  rpl_instance_t *instance;
339  rpl_dag_t *dag;
340  int i;
341 
342  instance = rpl_get_instance(instance_id);
343  if(instance == NULL) {
344  return NULL;
345  }
346 
347  for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; ++i) {
348  dag = &instance->dag_table[i];
349  if(dag->used && uip_ipaddr_cmp(&dag->dag_id, dag_id)) {
350  return dag;
351  }
352  }
353 
354  return NULL;
355 }
356 /*---------------------------------------------------------------------------*/
357 rpl_dag_t *
358 rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id)
359 {
360  rpl_dag_t *dag;
361  rpl_instance_t *instance;
362  uint8_t version;
363  int i;
364 
365  version = RPL_LOLLIPOP_INIT;
366  instance = rpl_get_instance(instance_id);
367  if(instance != NULL) {
368  for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; ++i) {
369  dag = &instance->dag_table[i];
370  if(dag->used) {
371  if(uip_ipaddr_cmp(&dag->dag_id, dag_id)) {
372  version = dag->version;
373  RPL_LOLLIPOP_INCREMENT(version);
374  } else {
375  if(dag == dag->instance->current_dag) {
376  LOG_INFO("Dropping a joined DAG when setting this node as root\n");
377  rpl_set_default_route(instance, NULL);
378  dag->instance->current_dag = NULL;
379  } else {
380  LOG_INFO("Dropping a DAG when setting this node as root\n");
381  }
382  rpl_free_dag(dag);
383  }
384  }
385  }
386  }
387 
388  dag = rpl_alloc_dag(instance_id, dag_id);
389  if(dag == NULL) {
390  LOG_ERR("Failed to allocate a DAG\n");
391  return NULL;
392  }
393 
394  instance = dag->instance;
395 
396  dag->version = version;
397  dag->joined = 1;
398  dag->grounded = RPL_GROUNDED;
399  dag->preference = RPL_PREFERENCE;
400  instance->mop = RPL_MOP_DEFAULT;
401  instance->of = rpl_find_of(RPL_OF_OCP);
402  if(instance->of == NULL) {
403  LOG_WARN("OF with OCP %u not supported\n", RPL_OF_OCP);
404  return NULL;
405  }
406 
407  rpl_set_preferred_parent(dag, NULL);
408 
409  memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id));
410 
411  instance->dio_intdoubl = RPL_DIO_INTERVAL_DOUBLINGS;
412  instance->dio_intmin = RPL_DIO_INTERVAL_MIN;
413  /* The current interval must differ from the minimum interval in order to
414  trigger a DIO timer reset. */
415  instance->dio_intcurrent = RPL_DIO_INTERVAL_MIN +
416  RPL_DIO_INTERVAL_DOUBLINGS;
417  instance->dio_redundancy = RPL_DIO_REDUNDANCY;
418  instance->max_rankinc = RPL_MAX_RANKINC;
419  instance->min_hoprankinc = RPL_MIN_HOPRANKINC;
420  instance->default_lifetime = RPL_DEFAULT_LIFETIME;
421  instance->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT;
422 
423  dag->rank = ROOT_RANK(instance);
424 
425  if(instance->current_dag != dag && instance->current_dag != NULL) {
426  /* Remove routes installed by DAOs. */
427  if(RPL_IS_STORING(instance)) {
428  rpl_remove_routes(instance->current_dag);
429  }
430 
431  instance->current_dag->joined = 0;
432  }
433 
434  instance->current_dag = dag;
435  instance->dtsn_out = RPL_LOLLIPOP_INIT;
436  instance->of->update_metric_container(instance);
437  default_instance = instance;
438 
439  LOG_INFO("Node set to be a DAG root with DAG ID ");
440  LOG_INFO_6ADDR(&dag->dag_id);
441  LOG_INFO_("\n");
442 
443  LOG_ANNOTATE("#A root=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]);
444 
445  rpl_reset_dio_timer(instance);
446 
447  return dag;
448 }
449 /*---------------------------------------------------------------------------*/
450 int
451 rpl_repair_root(uint8_t instance_id)
452 {
453  rpl_instance_t *instance;
454 
455  instance = rpl_get_instance(instance_id);
456  if(instance == NULL ||
457  instance->current_dag->rank != ROOT_RANK(instance)) {
458  LOG_WARN("rpl_repair_root triggered but not root\n");
459  return 0;
460  }
461  RPL_STAT(rpl_stats.root_repairs++);
462 
463  RPL_LOLLIPOP_INCREMENT(instance->current_dag->version);
464  RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
465  LOG_INFO("rpl_repair_root initiating global repair with version %d\n", instance->current_dag->version);
466  rpl_reset_dio_timer(instance);
467  return 1;
468 }
469 /*---------------------------------------------------------------------------*/
470 static void
471 set_ip_from_prefix(uip_ipaddr_t *ipaddr, rpl_prefix_t *prefix)
472 {
473  memset(ipaddr, 0, sizeof(uip_ipaddr_t));
474  memcpy(ipaddr, &prefix->prefix, (prefix->length + 7) / 8);
476 }
477 /*---------------------------------------------------------------------------*/
478 static void
479 check_prefix(rpl_prefix_t *last_prefix, rpl_prefix_t *new_prefix)
480 {
481  uip_ipaddr_t ipaddr;
482  uip_ds6_addr_t *rep;
483 
484  if(last_prefix != NULL && new_prefix != NULL &&
485  last_prefix->length == new_prefix->length &&
486  uip_ipaddr_prefixcmp(&last_prefix->prefix, &new_prefix->prefix, new_prefix->length) &&
487  last_prefix->flags == new_prefix->flags) {
488  /* Nothing has changed. */
489  return;
490  }
491 
492  if(last_prefix != NULL) {
493  set_ip_from_prefix(&ipaddr, last_prefix);
494  rep = uip_ds6_addr_lookup(&ipaddr);
495  if(rep != NULL) {
496  LOG_DBG("removing global IP address ");
497  LOG_DBG_6ADDR(&ipaddr);
498  LOG_DBG_("\n");
499  uip_ds6_addr_rm(rep);
500  }
501  }
502 
503  if(new_prefix != NULL) {
504  set_ip_from_prefix(&ipaddr, new_prefix);
505  if(uip_ds6_addr_lookup(&ipaddr) == NULL) {
506  LOG_DBG("adding global IP address ");
507  LOG_DBG_6ADDR(&ipaddr);
508  LOG_DBG_("\n");
509  uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
510  }
511  }
512 }
513 /*---------------------------------------------------------------------------*/
514 int
515 rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, unsigned len)
516 {
517  rpl_prefix_t last_prefix;
518  uint8_t last_len = dag->prefix_info.length;
519 
520  if(len > 128) {
521  return 0;
522  }
523  if(dag->prefix_info.length != 0) {
524  memcpy(&last_prefix, &dag->prefix_info, sizeof(rpl_prefix_t));
525  }
526  memset(&dag->prefix_info.prefix, 0, sizeof(dag->prefix_info.prefix));
527  memcpy(&dag->prefix_info.prefix, prefix, (len + 7) / 8);
528  dag->prefix_info.length = len;
529  dag->prefix_info.flags = UIP_ND6_RA_FLAG_AUTONOMOUS;
530  LOG_INFO("Prefix set - will announce this in DIOs\n");
531  if(dag->rank != ROOT_RANK(dag->instance)) {
532  /* Autoconfigure an address if this node does not already have an address
533  with this prefix. Otherwise, update the prefix */
534  if(last_len == 0) {
535  LOG_INFO("rpl_set_prefix - prefix NULL\n");
536  check_prefix(NULL, &dag->prefix_info);
537  } else {
538  LOG_INFO("rpl_set_prefix - prefix NON-NULL\n");
539  check_prefix(&last_prefix, &dag->prefix_info);
540  }
541  }
542  return 1;
543 }
544 /*---------------------------------------------------------------------------*/
545 int
546 rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from)
547 {
548  if(instance->def_route != NULL) {
549  LOG_DBG("Removing default route through ");
550  LOG_DBG_6ADDR(&instance->def_route->ipaddr);
551  LOG_DBG_("\n");
552  uip_ds6_defrt_rm(instance->def_route);
553  instance->def_route = NULL;
554  }
555 
556  if(from != NULL) {
557  LOG_DBG("Adding default route through ");
558  LOG_DBG_6ADDR(from);
559  LOG_DBG_("\n");
560  instance->def_route = uip_ds6_defrt_add(from,
561  RPL_DEFAULT_ROUTE_INFINITE_LIFETIME ? 0 : RPL_LIFETIME(instance, instance->default_lifetime));
562  if(instance->def_route == NULL) {
563  return 0;
564  }
565  }
566  return 1;
567 }
568 /*---------------------------------------------------------------------------*/
570 rpl_alloc_instance(uint8_t instance_id)
571 {
572  rpl_instance_t *instance, *end;
573 
574  for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES;
575  instance < end; ++instance) {
576  if(instance->used == 0) {
577  memset(instance, 0, sizeof(*instance));
578  instance->instance_id = instance_id;
579  instance->def_route = NULL;
580  instance->used = 1;
581 #if RPL_WITH_PROBING
582  rpl_schedule_probing(instance);
583 #endif /* RPL_WITH_PROBING */
584  return instance;
585  }
586  }
587  return NULL;
588 }
589 /*---------------------------------------------------------------------------*/
590 rpl_dag_t *
591 rpl_alloc_dag(uint8_t instance_id, uip_ipaddr_t *dag_id)
592 {
593  rpl_dag_t *dag, *end;
594  rpl_instance_t *instance;
595 
596  instance = rpl_get_instance(instance_id);
597  if(instance == NULL) {
598  instance = rpl_alloc_instance(instance_id);
599  if(instance == NULL) {
600  RPL_STAT(rpl_stats.mem_overflows++);
601  return NULL;
602  }
603  }
604 
605  for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
606  if(!dag->used) {
607  memset(dag, 0, sizeof(*dag));
608  dag->used = 1;
609  dag->rank = RPL_INFINITE_RANK;
610  dag->min_rank = RPL_INFINITE_RANK;
611  dag->instance = instance;
612  return dag;
613  }
614  }
615 
616  RPL_STAT(rpl_stats.mem_overflows++);
617  return NULL;
618 }
619 /*---------------------------------------------------------------------------*/
620 void
621 rpl_set_default_instance(rpl_instance_t *instance)
622 {
623  default_instance = instance;
624 }
625 /*---------------------------------------------------------------------------*/
628 {
629  return default_instance;
630 }
631 /*---------------------------------------------------------------------------*/
632 void
633 rpl_free_instance(rpl_instance_t *instance)
634 {
635  rpl_dag_t *dag;
636  rpl_dag_t *end;
637 
638  LOG_INFO("Leaving the instance %u\n", instance->instance_id);
639 
640  /* Remove any DAG inside this instance */
641  for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
642  if(dag->used) {
643  rpl_free_dag(dag);
644  }
645  }
646 
647  rpl_set_default_route(instance, NULL);
648 
649 #if RPL_WITH_PROBING
650  ctimer_stop(&instance->probing_timer);
651 #endif /* RPL_WITH_PROBING */
652  ctimer_stop(&instance->dio_timer);
653  ctimer_stop(&instance->dao_timer);
654  ctimer_stop(&instance->dao_lifetime_timer);
655 
656  if(default_instance == instance) {
657  default_instance = NULL;
658  }
659 
660  instance->used = 0;
661 }
662 /*---------------------------------------------------------------------------*/
663 void
664 rpl_free_dag(rpl_dag_t *dag)
665 {
666  if(dag->joined) {
667  LOG_INFO("Leaving the DAG ");
668  LOG_INFO_6ADDR(&dag->dag_id);
669  LOG_INFO_("\n");
670  dag->joined = 0;
671 
672  /* Remove routes installed by DAOs. */
673  if(RPL_IS_STORING(dag->instance)) {
674  rpl_remove_routes(dag);
675  }
676  /* Stop the DAO retransmit timer */
677 #if RPL_WITH_DAO_ACK
678  ctimer_stop(&dag->instance->dao_retransmit_timer);
679 #endif /* RPL_WITH_DAO_ACK */
680 
681  /* Remove autoconfigured address */
682  if((dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) {
683  check_prefix(&dag->prefix_info, NULL);
684  }
685 
686  remove_parents(dag, 0);
687  }
688  dag->used = 0;
689 }
690 /*---------------------------------------------------------------------------*/
691 rpl_parent_t *
692 rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr)
693 {
694  rpl_parent_t *p = NULL;
695  /* Is the parent known by ds6? Drop this request if not.
696  * Typically, the parent is added upon receiving a DIO. */
697  const uip_lladdr_t *lladdr = uip_ds6_nbr_lladdr_from_ipaddr(addr);
698 
699  LOG_DBG("rpl_add_parent lladdr %p ", lladdr);
700  LOG_DBG_6ADDR(addr);
701  LOG_DBG_("\n");
702  if(lladdr != NULL) {
703  /* Add parent in rpl_parents - again this is due to DIO */
704  p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr,
705  NBR_TABLE_REASON_RPL_DIO, dio);
706  if(p == NULL) {
707  LOG_DBG("rpl_add_parent p NULL\n");
708  } else {
709  p->dag = dag;
710  p->rank = dio->rank;
711  p->dtsn = dio->dtsn;
712 #if RPL_WITH_MC
713  memcpy(&p->mc, &dio->mc, sizeof(p->mc));
714 #endif /* RPL_WITH_MC */
715  }
716  }
717 
718  return p;
719 }
720 /*---------------------------------------------------------------------------*/
721 static rpl_parent_t *
722 find_parent_any_dag_any_instance(uip_ipaddr_t *addr)
723 {
724  uip_ds6_nbr_t *ds6_nbr = uip_ds6_nbr_lookup(addr);
725  const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(ds6_nbr);
726  return nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)lladdr);
727 }
728 /*---------------------------------------------------------------------------*/
729 rpl_parent_t *
730 rpl_find_parent(rpl_dag_t *dag, uip_ipaddr_t *addr)
731 {
732  rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
733  if(p != NULL && p->dag == dag) {
734  return p;
735  } else {
736  return NULL;
737  }
738 }
739 /*---------------------------------------------------------------------------*/
740 static rpl_dag_t *
741 find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr)
742 {
743  rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
744  if(p != NULL) {
745  return p->dag;
746  } else {
747  return NULL;
748  }
749 }
750 /*---------------------------------------------------------------------------*/
751 rpl_parent_t *
752 rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr)
753 {
754  rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
755  if(p && p->dag && p->dag->instance == instance) {
756  return p;
757  } else {
758  return NULL;
759  }
760 }
761 /*---------------------------------------------------------------------------*/
762 rpl_dag_t *
763 rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p)
764 {
765  rpl_parent_t *last_parent;
766  rpl_dag_t *dag, *end, *best_dag;
767  rpl_rank_t old_rank;
768 
769  old_rank = instance->current_dag->rank;
770  last_parent = instance->current_dag->preferred_parent;
771 
772  if(instance->current_dag->rank != ROOT_RANK(instance)) {
773  rpl_select_parent(p->dag);
774  }
775 
776  best_dag = NULL;
777  for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
778  if(dag->used && dag->preferred_parent != NULL && dag->preferred_parent->rank != RPL_INFINITE_RANK) {
779  if(best_dag == NULL) {
780  best_dag = dag;
781  } else {
782  best_dag = instance->of->best_dag(best_dag, dag);
783  }
784  }
785  }
786 
787  if(best_dag == NULL) {
788  /* No parent found: the calling function handle this problem. */
789  return NULL;
790  }
791 
792  if(instance->current_dag != best_dag) {
793  /* Remove routes installed by DAOs. */
794  if(RPL_IS_STORING(instance)) {
795  rpl_remove_routes(instance->current_dag);
796  }
797 
798  LOG_INFO("New preferred DAG: ");
799  LOG_INFO_6ADDR(&best_dag->dag_id);
800  LOG_INFO_("\n");
801 
802  if(best_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
803  check_prefix(&instance->current_dag->prefix_info, &best_dag->prefix_info);
804  } else if(instance->current_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
805  check_prefix(&instance->current_dag->prefix_info, NULL);
806  }
807 
808  best_dag->joined = 1;
809  instance->current_dag->joined = 0;
810  instance->current_dag = best_dag;
811  }
812 
813  instance->of->update_metric_container(instance);
814  /* Update the DAG rank. */
815  best_dag->rank = rpl_rank_via_parent(best_dag->preferred_parent);
816  if(last_parent == NULL || best_dag->rank < best_dag->min_rank) {
817  /* This is a slight departure from RFC6550: if we had no preferred parent before,
818  * reset min_rank. This helps recovering from temporary bad link conditions. */
819  best_dag->min_rank = best_dag->rank;
820  }
821 
822  if(!acceptable_rank(best_dag, best_dag->rank)) {
823  LOG_WARN("New rank unacceptable!\n");
824  rpl_set_preferred_parent(instance->current_dag, NULL);
825  if(RPL_IS_STORING(instance) && last_parent != NULL) {
826  /* Send a No-Path DAO to the removed preferred parent. */
827  dao_output(last_parent, RPL_ZERO_LIFETIME);
828  }
829  return NULL;
830  }
831 
832  if(best_dag->preferred_parent != last_parent) {
833  rpl_set_default_route(instance, rpl_parent_get_ipaddr(best_dag->preferred_parent));
834  LOG_INFO("Changed preferred parent, rank changed from %u to %u\n",
835  (unsigned)old_rank, best_dag->rank);
836  RPL_STAT(rpl_stats.parent_switch++);
837  if(RPL_IS_STORING(instance)) {
838  if(last_parent != NULL) {
839  /* Send a No-Path DAO to the removed preferred parent. */
840  dao_output(last_parent, RPL_ZERO_LIFETIME);
841  }
842  /* Trigger DAO transmission from immediate children.
843  * Only for storing mode, see RFC6550 section 9.6. */
844  RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
845  }
846  /* The DAO parent set changed - schedule a DAO transmission. */
847  rpl_schedule_dao(instance);
848  rpl_reset_dio_timer(instance);
849  if(LOG_DBG_ENABLED) {
850  rpl_print_neighbor_list();
851  }
852  } else if(best_dag->rank != old_rank) {
853  LOG_DBG("RPL: Preferred parent update, rank changed from %u to %u\n",
854  (unsigned)old_rank, best_dag->rank);
855  }
856  return best_dag;
857 }
858 /*---------------------------------------------------------------------------*/
859 static rpl_parent_t *
860 best_parent(rpl_dag_t *dag, int fresh_only)
861 {
862  rpl_parent_t *p;
863  rpl_of_t *of;
864  rpl_parent_t *best = NULL;
865 
866  if(dag == NULL || dag->instance == NULL || dag->instance->of == NULL) {
867  return NULL;
868  }
869 
870  of = dag->instance->of;
871  /* Search for the best parent according to the OF */
872  for(p = nbr_table_head(rpl_parents); p != NULL; p = nbr_table_next(rpl_parents, p)) {
873 
874  /* Exclude parents from other DAGs or announcing an infinite rank */
875  if(p->dag != dag || p->rank == RPL_INFINITE_RANK || p->rank < ROOT_RANK(dag->instance)) {
876  if(p->rank < ROOT_RANK(dag->instance)) {
877  LOG_WARN("Parent has invalid rank\n");
878  }
879  continue;
880  }
881 
882  if(fresh_only && !rpl_parent_is_fresh(p)) {
883  /* Filter out non-fresh parents if fresh_only is set */
884  continue;
885  }
886 
887 #if UIP_ND6_SEND_NS
888  /* Exclude links to a neighbor that is not reachable at a NUD level */
889  if(rpl_get_nbr(p) == NULL) {
890  continue;
891  }
892 #endif /* UIP_ND6_SEND_NS */
893 
894  /* Now we have an acceptable parent, check if it is the new best */
895  best = of->best_parent(best, p);
896  }
897 
898  return best;
899 }
900 /*---------------------------------------------------------------------------*/
901 rpl_parent_t *
902 rpl_select_parent(rpl_dag_t *dag)
903 {
904  /* Look for best parent (regardless of freshness) */
905  rpl_parent_t *best = best_parent(dag, 0);
906 
907  if(best != NULL) {
908 #if RPL_WITH_PROBING
909  if(rpl_parent_is_fresh(best)) {
910  rpl_set_preferred_parent(dag, best);
911  /* Unschedule any already scheduled urgent probing */
912  dag->instance->urgent_probing_target = NULL;
913  } else {
914  /* The best is not fresh. Look for the best fresh now. */
915  rpl_parent_t *best_fresh = best_parent(dag, 1);
916  if(best_fresh == NULL) {
917  /* No fresh parent around, use best (non-fresh) */
918  rpl_set_preferred_parent(dag, best);
919  } else {
920  /* Use best fresh */
921  rpl_set_preferred_parent(dag, best_fresh);
922  }
923  /* Probe the best parent shortly in order to get a fresh estimate */
924  dag->instance->urgent_probing_target = best;
925  rpl_schedule_probing_now(dag->instance);
926  }
927 #else /* RPL_WITH_PROBING */
928  rpl_set_preferred_parent(dag, best);
929  dag->rank = rpl_rank_via_parent(dag->preferred_parent);
930 #endif /* RPL_WITH_PROBING */
931  } else {
932  rpl_set_preferred_parent(dag, NULL);
933  }
934 
935  dag->rank = rpl_rank_via_parent(dag->preferred_parent);
936  return dag->preferred_parent;
937 }
938 /*---------------------------------------------------------------------------*/
939 void
940 rpl_remove_parent(rpl_parent_t *parent)
941 {
942  LOG_INFO("Removing parent ");
943  LOG_INFO_6ADDR(rpl_parent_get_ipaddr(parent));
944  LOG_INFO_("\n");
945 
946  rpl_nullify_parent(parent);
947 
948  nbr_table_remove(rpl_parents, parent);
949 }
950 /*---------------------------------------------------------------------------*/
951 void
952 rpl_nullify_parent(rpl_parent_t *parent)
953 {
954  rpl_dag_t *dag = parent->dag;
955  /* This function can be called when the preferred parent is NULL, so we
956  need to handle this condition in order to trigger uip_ds6_defrt_rm. */
957  if(parent == dag->preferred_parent || dag->preferred_parent == NULL) {
958  dag->rank = RPL_INFINITE_RANK;
959  if(dag->joined) {
960  if(dag->instance->def_route != NULL) {
961  LOG_DBG("Removing default route ");
962  LOG_DBG_6ADDR(rpl_parent_get_ipaddr(parent));
963  LOG_DBG_("\n");
964  uip_ds6_defrt_rm(dag->instance->def_route);
965  dag->instance->def_route = NULL;
966  }
967  /* Send No-Path DAO only when nullifying preferred parent */
968  if(parent == dag->preferred_parent) {
969  if(RPL_IS_STORING(dag->instance)) {
970  dao_output(parent, RPL_ZERO_LIFETIME);
971  }
972  rpl_set_preferred_parent(dag, NULL);
973  }
974  }
975  }
976 
977  LOG_INFO("Nullifying parent ");
978  LOG_INFO_6ADDR(rpl_parent_get_ipaddr(parent));
979  LOG_INFO_("\n");
980 }
981 /*---------------------------------------------------------------------------*/
982 void
983 rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent)
984 {
985  if(parent == dag_src->preferred_parent) {
986  rpl_set_preferred_parent(dag_src, NULL);
987  dag_src->rank = RPL_INFINITE_RANK;
988  if(dag_src->joined && dag_src->instance->def_route != NULL) {
989  LOG_DBG("Removing default route ");
990  LOG_DBG_6ADDR(rpl_parent_get_ipaddr(parent));
991  LOG_DBG_("\n");
992  LOG_DBG("rpl_move_parent\n");
993  uip_ds6_defrt_rm(dag_src->instance->def_route);
994  dag_src->instance->def_route = NULL;
995  }
996  } else if(dag_src->joined) {
997  if(RPL_IS_STORING(dag_src->instance)) {
998  /* Remove uIPv6 routes that have this parent as the next hop. */
999  rpl_remove_routes_by_nexthop(rpl_parent_get_ipaddr(parent), dag_src);
1000  }
1001  }
1002 
1003  LOG_INFO("Moving parent ");
1004  LOG_INFO_6ADDR(rpl_parent_get_ipaddr(parent));
1005  LOG_INFO_("\n");
1006 
1007  parent->dag = dag_dst;
1008 }
1009 /*---------------------------------------------------------------------------*/
1010 static rpl_dag_t *
1011 rpl_get_any_dag_with_parent(bool requires_parent)
1012 {
1013  int i;
1014 
1015  for(i = 0; i < RPL_MAX_INSTANCES; ++i) {
1016  if(instance_table[i].used
1017  && instance_table[i].current_dag->joined
1018  && (!requires_parent || instance_table[i].current_dag->preferred_parent != NULL)) {
1019  return instance_table[i].current_dag;
1020  }
1021  }
1022  return NULL;
1023 }
1024 /*---------------------------------------------------------------------------*/
1025 int
1027 {
1028  if(rpl_dag_root_is_root()) {
1029  return 1;
1030  }
1031  return rpl_get_any_dag_with_parent(true) != NULL;
1032 }
1033 /*---------------------------------------------------------------------------*/
1034 int
1036 {
1037  int i;
1038  if(rpl_dag_root_is_root()) {
1039  return 1; /* We are the root, and know the route to ourself */
1040  }
1041  for(i = 0; i < RPL_MAX_INSTANCES; ++i) {
1042  if(instance_table[i].used && instance_table[i].has_downward_route) {
1043  return 1;
1044  }
1045  }
1046  return 0;
1047 }
1048 /*---------------------------------------------------------------------------*/
1049 rpl_dag_t *
1050 rpl_get_dag(const uip_ipaddr_t *addr)
1051 {
1052  int i, j;
1053 
1054  for(i = 0; i < RPL_MAX_INSTANCES; ++i) {
1055  if(instance_table[i].used) {
1056  for(j = 0; j < RPL_MAX_DAG_PER_INSTANCE; ++j) {
1057  if(instance_table[i].dag_table[j].joined
1058  && uip_ipaddr_prefixcmp(&instance_table[i].dag_table[j].dag_id, addr,
1059  instance_table[i].dag_table[j].prefix_info.length)) {
1060  return &instance_table[i].dag_table[j];
1061  }
1062  }
1063  }
1064  }
1065  return NULL;
1066 }
1067 /*---------------------------------------------------------------------------*/
1068 rpl_dag_t *
1070 {
1071  return rpl_get_any_dag_with_parent(false);
1072 }
1073 /*---------------------------------------------------------------------------*/
1075 rpl_get_instance(uint8_t instance_id)
1076 {
1077  int i;
1078 
1079  for(i = 0; i < RPL_MAX_INSTANCES; ++i) {
1080  if(instance_table[i].used && instance_table[i].instance_id == instance_id) {
1081  return &instance_table[i];
1082  }
1083  }
1084  return NULL;
1085 }
1086 /*---------------------------------------------------------------------------*/
1087 rpl_of_t *
1088 rpl_find_of(rpl_ocp_t ocp)
1089 {
1090  unsigned int i;
1091 
1092  for(i = 0;
1093  i < sizeof(objective_functions) / sizeof(objective_functions[0]);
1094  i++) {
1095  if(objective_functions[i]->ocp == ocp) {
1096  return objective_functions[i];
1097  }
1098  }
1099 
1100  return NULL;
1101 }
1102 /*---------------------------------------------------------------------------*/
1103 void
1104 rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio)
1105 {
1106  rpl_instance_t *instance;
1107  rpl_dag_t *dag;
1108  rpl_parent_t *p;
1109  rpl_of_t *of;
1110 
1111  if((!RPL_WITH_NON_STORING && dio->mop == RPL_MOP_NON_STORING)
1112  || (!RPL_WITH_STORING && (dio->mop == RPL_MOP_STORING_NO_MULTICAST
1113  || dio->mop == RPL_MOP_STORING_MULTICAST))) {
1114  LOG_WARN("DIO advertising a non-supported MOP %u\n", dio->mop);
1115  return;
1116  }
1117 
1118  /* Determine the objective function by using the
1119  objective code point of the DIO. */
1120  of = rpl_find_of(dio->ocp);
1121  if(of == NULL) {
1122  LOG_WARN("DIO for DAG instance %u does not specify a supported OF: %u\n",
1123  dio->instance_id, dio->ocp);
1124  return;
1125  }
1126 
1127  dag = rpl_alloc_dag(dio->instance_id, &dio->dag_id);
1128  if(dag == NULL) {
1129  LOG_ERR("Failed to allocate a DAG object!\n");
1130  return;
1131  }
1132 
1133  instance = dag->instance;
1134 
1135  p = rpl_add_parent(dag, dio, from);
1136  LOG_DBG("Adding ");
1137  LOG_DBG_6ADDR(from);
1138  LOG_DBG_(" as a parent: ");
1139  if(p == NULL) {
1140  LOG_DBG_("failed\n");
1141  instance->used = 0;
1142  return;
1143  }
1144  p->dtsn = dio->dtsn;
1145  LOG_DBG_("succeeded\n");
1146 
1147  /* Autoconfigure an address if this node does not already have an address
1148  with this prefix. */
1149  if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
1150  check_prefix(NULL, &dio->prefix_info);
1151  }
1152 
1153  dag->joined = 1;
1154  dag->preference = dio->preference;
1155  dag->grounded = dio->grounded;
1156  dag->version = dio->version;
1157 
1158  instance->of = of;
1159  instance->mop = dio->mop;
1160  instance->mc.type = dio->mc.type;
1161  instance->mc.flags = dio->mc.flags;
1162  instance->mc.aggr = dio->mc.aggr;
1163  instance->mc.prec = dio->mc.prec;
1164  instance->current_dag = dag;
1165  instance->dtsn_out = RPL_LOLLIPOP_INIT;
1166 
1167  instance->max_rankinc = dio->dag_max_rankinc;
1168  instance->min_hoprankinc = dio->dag_min_hoprankinc;
1169  instance->dio_intdoubl = dio->dag_intdoubl;
1170  instance->dio_intmin = dio->dag_intmin;
1171  instance->dio_intcurrent = instance->dio_intmin + instance->dio_intdoubl;
1172  instance->dio_redundancy = dio->dag_redund;
1173  instance->default_lifetime = dio->default_lifetime;
1174  instance->lifetime_unit = dio->lifetime_unit;
1175 
1176  memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id));
1177 
1178  /* Copy prefix information from the DIO into the DAG object. */
1179  memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t));
1180 
1181  rpl_set_preferred_parent(dag, p);
1182  instance->of->update_metric_container(instance);
1183  dag->rank = rpl_rank_via_parent(p);
1184  /* So far this is the lowest rank we are aware of. */
1185  dag->min_rank = dag->rank;
1186 
1187  if(default_instance == NULL) {
1188  default_instance = instance;
1189  }
1190 
1191  LOG_INFO("Joined DAG with instance ID %u, rank %hu, DAG ID ",
1192  dio->instance_id, dag->rank);
1193  LOG_INFO_6ADDR(&dag->dag_id);
1194  LOG_INFO_("\n");
1195 
1196  LOG_ANNOTATE("#A join=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]);
1197 
1198  rpl_reset_dio_timer(instance);
1199  rpl_set_default_route(instance, from);
1200 
1201  if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
1202  rpl_schedule_dao(instance);
1203  } else {
1204  LOG_WARN("The DIO does not meet the prerequisites for sending a DAO\n");
1205  }
1206 
1207  instance->of->reset(dag);
1208 }
1209 
1210 #if RPL_MAX_DAG_PER_INSTANCE > 1
1211 /*---------------------------------------------------------------------------*/
1212 rpl_dag_t *
1213 rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
1214 {
1215  rpl_instance_t *instance;
1216  rpl_dag_t *dag, *previous_dag;
1217  rpl_parent_t *p;
1218  rpl_of_t *of;
1219 
1220  dag = rpl_alloc_dag(dio->instance_id, &dio->dag_id);
1221  if(dag == NULL) {
1222  LOG_ERR("Failed to allocate a DAG object!\n");
1223  return NULL;
1224  }
1225 
1226  instance = dag->instance;
1227 
1228  previous_dag = find_parent_dag(instance, from);
1229  if(previous_dag == NULL) {
1230  LOG_DBG("Adding ");
1231  LOG_DBG_6ADDR(from);
1232  LOG_DBG_(" as a parent: ");
1233  p = rpl_add_parent(dag, dio, from);
1234  if(p == NULL) {
1235  LOG_DBG_("failed\n");
1236  dag->used = 0;
1237  return NULL;
1238  }
1239  LOG_DBG_("succeeded\n");
1240  } else {
1241  p = rpl_find_parent(previous_dag, from);
1242  if(p != NULL) {
1243  rpl_move_parent(previous_dag, dag, p);
1244  }
1245  }
1246  p->rank = dio->rank;
1247 
1248  /* Determine the objective function by using the
1249  objective code point of the DIO. */
1250  of = rpl_find_of(dio->ocp);
1251  if(of != instance->of ||
1252  instance->mop != dio->mop ||
1253  instance->max_rankinc != dio->dag_max_rankinc ||
1254  instance->min_hoprankinc != dio->dag_min_hoprankinc ||
1255  instance->dio_intdoubl != dio->dag_intdoubl ||
1256  instance->dio_intmin != dio->dag_intmin ||
1257  instance->dio_redundancy != dio->dag_redund ||
1258  instance->default_lifetime != dio->default_lifetime ||
1259  instance->lifetime_unit != dio->lifetime_unit) {
1260  LOG_WARN("DIO for DAG instance %u incompatible with previous DIO\n",
1261  dio->instance_id);
1262  rpl_remove_parent(p);
1263  dag->used = 0;
1264  return NULL;
1265  }
1266 
1267  dag->used = 1;
1268  dag->grounded = dio->grounded;
1269  dag->preference = dio->preference;
1270  dag->version = dio->version;
1271 
1272  memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id));
1273 
1274  /* copy prefix information into the dag */
1275  memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t));
1276 
1277  rpl_set_preferred_parent(dag, p);
1278  dag->rank = rpl_rank_via_parent(p);
1279  dag->min_rank = dag->rank; /* So far this is the lowest rank we know of. */
1280 
1281  LOG_INFO("Joined DAG with instance ID %u, rank %hu, DAG ID ",
1282  dio->instance_id, dag->rank);
1283  LOG_INFO_6ADDR(&dag->dag_id);
1284  LOG_INFO_("\n");
1285 
1286  LOG_ANNOTATE("#A join=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]);
1287 
1288  rpl_process_parent_event(instance, p);
1289  p->dtsn = dio->dtsn;
1290 
1291  return dag;
1292 }
1293 #endif /* RPL_MAX_DAG_PER_INSTANCE > 1 */
1294 
1295 /*---------------------------------------------------------------------------*/
1296 static void
1297 global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio)
1298 {
1299  rpl_parent_t *p;
1300 
1301  remove_parents(dag, 0);
1302  dag->version = dio->version;
1303 
1304  /* copy parts of the configuration so that it propagates in the network */
1305  dag->instance->dio_intdoubl = dio->dag_intdoubl;
1306  dag->instance->dio_intmin = dio->dag_intmin;
1307  dag->instance->dio_redundancy = dio->dag_redund;
1308  dag->instance->default_lifetime = dio->default_lifetime;
1309  dag->instance->lifetime_unit = dio->lifetime_unit;
1310 
1311  dag->instance->of->reset(dag);
1312  dag->min_rank = RPL_INFINITE_RANK;
1313  RPL_LOLLIPOP_INCREMENT(dag->instance->dtsn_out);
1314 
1315  p = rpl_add_parent(dag, dio, from);
1316  if(p == NULL) {
1317  LOG_ERR("Failed to add a parent during the global repair\n");
1318  dag->rank = RPL_INFINITE_RANK;
1319  } else {
1320  dag->rank = rpl_rank_via_parent(p);
1321  dag->min_rank = dag->rank;
1322  LOG_DBG("rpl_process_parent_event global repair\n");
1323  rpl_process_parent_event(dag->instance, p);
1324  }
1325 
1326  LOG_DBG("Participating in a global repair (version=%u, rank=%hu)\n",
1327  dag->version, dag->rank);
1328 
1329  RPL_STAT(rpl_stats.global_repairs++);
1330 }
1331 
1332 /*---------------------------------------------------------------------------*/
1333 void
1335 {
1336  int i;
1337 
1338  if(instance == NULL) {
1339  LOG_WARN("local repair requested for instance NULL\n");
1340  return;
1341  }
1342  LOG_INFO("Starting a local instance repair\n");
1343  for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; i++) {
1344  if(instance->dag_table[i].used) {
1345  instance->dag_table[i].rank = RPL_INFINITE_RANK;
1346  nullify_parents(&instance->dag_table[i], 0);
1347  }
1348  }
1349 
1350  /* no downward route anymore */
1351  instance->has_downward_route = 0;
1352 #if RPL_WITH_DAO_ACK
1353  ctimer_stop(&instance->dao_retransmit_timer);
1354 #endif /* RPL_WITH_DAO_ACK */
1355 
1356  rpl_reset_dio_timer(instance);
1357  if(RPL_IS_STORING(instance)) {
1358  /* Request refresh of DAO registrations next DIO. Only for storing mode. In
1359  * non-storing mode, non-root nodes increment DTSN only on when their parent do,
1360  * or on global repair (see RFC6550 section 9.6.) */
1361  RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
1362  }
1363 
1364  RPL_STAT(rpl_stats.local_repairs++);
1365 }
1366 /*---------------------------------------------------------------------------*/
1367 void
1368 rpl_recalculate_ranks(void)
1369 {
1370  rpl_parent_t *p;
1371 
1372  /*
1373  * We recalculate ranks when we receive feedback from the system rather
1374  * than RPL protocol messages. This periodical recalculation is called
1375  * from a timer in order to keep the stack depth reasonably low.
1376  */
1377  p = nbr_table_head(rpl_parents);
1378  while(p != NULL) {
1379  if(p->dag != NULL && p->dag->instance && (p->flags & RPL_PARENT_FLAG_UPDATED)) {
1380  p->flags &= ~RPL_PARENT_FLAG_UPDATED;
1381  LOG_DBG("rpl_process_parent_event recalculate_ranks\n");
1382  if(!rpl_process_parent_event(p->dag->instance, p)) {
1383  LOG_DBG("A parent was dropped\n");
1384  }
1385  }
1386  p = nbr_table_next(rpl_parents, p);
1387  }
1388 }
1389 /*---------------------------------------------------------------------------*/
1390 int
1391 rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p)
1392 {
1393  int return_value;
1394  rpl_parent_t *last_parent = instance->current_dag->preferred_parent;
1395 
1396 #if LOG_DBG_ENABLED
1397  rpl_rank_t old_rank;
1398  old_rank = instance->current_dag->rank;
1399 #endif /* LOG_DBG_ENABLED */
1400 
1401  return_value = 1;
1402 
1403  if(RPL_IS_STORING(instance)
1404  && uip_ds6_route_is_nexthop(rpl_parent_get_ipaddr(p))
1405  && !rpl_parent_is_reachable(p) && instance->mop > RPL_MOP_NON_STORING) {
1406  LOG_WARN("Unacceptable link %u, removing routes via: ", rpl_get_parent_link_metric(p));
1407  LOG_WARN_6ADDR(rpl_parent_get_ipaddr(p));
1408  LOG_WARN_("\n");
1409  rpl_remove_routes_by_nexthop(rpl_parent_get_ipaddr(p), p->dag);
1410  }
1411 
1412  if(!acceptable_rank(p->dag, rpl_rank_via_parent(p))) {
1413  /* The candidate parent is no longer valid: the rank increase resulting
1414  from the choice of it as a parent would be too high. */
1415  LOG_WARN("Unacceptable rank %u (Current min %u, MaxRankInc %u)\n", (unsigned)p->rank,
1416  p->dag->min_rank, p->dag->instance->max_rankinc);
1417  rpl_nullify_parent(p);
1418  if(p != instance->current_dag->preferred_parent) {
1419  return 0;
1420  } else {
1421  return_value = 0;
1422  }
1423  }
1424 
1425  if(rpl_select_dag(instance, p) == NULL) {
1426  if(last_parent != NULL) {
1427  /* No suitable parent anymore; trigger a local repair. */
1428  LOG_ERR("No parents found in any DAG\n");
1429  rpl_local_repair(instance);
1430  return 0;
1431  }
1432  }
1433 
1434 #if LOG_DBG_ENABLED
1435  if(DAG_RANK(old_rank, instance) != DAG_RANK(instance->current_dag->rank, instance)) {
1436  LOG_INFO("Moving in the instance from rank %hu to %hu\n",
1437  DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank, instance));
1438  if(instance->current_dag->rank != RPL_INFINITE_RANK) {
1439  LOG_DBG("The preferred parent is ");
1440  LOG_DBG_6ADDR(rpl_parent_get_ipaddr(instance->current_dag->preferred_parent));
1441  LOG_DBG_(" (rank %u)\n",
1442  (unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank, instance));
1443  } else {
1444  LOG_WARN("We don't have any parent");
1445  }
1446  }
1447 #endif /* LOG_DBG_ENABLED */
1448 
1449  return return_value;
1450 }
1451 /*---------------------------------------------------------------------------*/
1452 static int
1453 add_nbr_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
1454 {
1455  /* add this to the neighbor cache if not already there */
1456  if(rpl_icmp6_update_nbr_table(from, NBR_TABLE_REASON_RPL_DIO, dio) == NULL) {
1457  LOG_ERR("Out of memory, dropping DIO from ");
1458  LOG_ERR_6ADDR(from);
1459  LOG_ERR_("\n");
1460  return 0;
1461  }
1462  return 1;
1463 }
1464 /*---------------------------------------------------------------------------*/
1465 void
1466 rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
1467 {
1468  rpl_instance_t *instance;
1469  rpl_dag_t *dag, *previous_dag;
1470  rpl_parent_t *p;
1471 
1472 #if RPL_WITH_MULTICAST
1473  /* If the root is advertising MOP 2 but we support MOP 3 we can still join
1474  * In that scenario, we suppress DAOs for multicast targets */
1475  if(dio->mop < RPL_MOP_STORING_NO_MULTICAST) {
1476 #else
1477  if(dio->mop != RPL_MOP_DEFAULT) {
1478 #endif
1479  LOG_ERR("Ignoring a DIO with an unsupported MOP: %d\n", dio->mop);
1480  return;
1481  }
1482 
1483  dag = get_dag(dio->instance_id, &dio->dag_id);
1484  instance = rpl_get_instance(dio->instance_id);
1485 
1486  if(dag != NULL && instance != NULL) {
1487  if(lollipop_greater_than(dio->version, dag->version)) {
1488  if(dag->rank == ROOT_RANK(instance)) {
1489  LOG_WARN("Root received inconsistent DIO version number (current: %u, received: %u)\n", dag->version, dio->version);
1490  dag->version = dio->version;
1491  RPL_LOLLIPOP_INCREMENT(dag->version);
1492  rpl_reset_dio_timer(instance);
1493  } else {
1494  LOG_DBG("Global repair\n");
1495  if(dio->prefix_info.length != 0) {
1496  if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
1497  LOG_DBG("Prefix announced in DIO\n");
1498  rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length);
1499  }
1500  }
1501  global_repair(from, dag, dio);
1502  }
1503  return;
1504  }
1505 
1506  if(lollipop_greater_than(dag->version, dio->version)) {
1507  /* The DIO sender is on an older version of the DAG. */
1508  LOG_WARN("old version received => inconsistency detected\n");
1509  if(dag->joined) {
1510  rpl_reset_dio_timer(instance);
1511  return;
1512  }
1513  }
1514  }
1515 
1516  if(instance == NULL) {
1517  LOG_INFO("New instance detected (ID=%u): Joining...\n", dio->instance_id);
1518  if(add_nbr_from_dio(from, dio)) {
1519  rpl_join_instance(from, dio);
1520  } else {
1521  LOG_WARN("Not joining since could not add parent\n");
1522  }
1523  return;
1524  }
1525 
1526  if(instance->current_dag->rank == ROOT_RANK(instance) && instance->current_dag != dag) {
1527  LOG_WARN("Root ignored DIO for different DAG\n");
1528  return;
1529  }
1530 
1531  if(dag == NULL) {
1532 #if RPL_MAX_DAG_PER_INSTANCE > 1
1533  LOG_INFO("Adding new DAG to known instance.\n");
1534  if(!add_nbr_from_dio(from, dio)) {
1535  LOG_WARN("Could not add new DAG, could not add parent\n");
1536  return;
1537  }
1538  dag = rpl_add_dag(from, dio);
1539  if(dag == NULL) {
1540  LOG_WARN("Failed to add DAG.\n");
1541  return;
1542  }
1543 #else /* RPL_MAX_DAG_PER_INSTANCE > 1 */
1544  LOG_WARN("Only one instance supported.\n");
1545  return;
1546 #endif /* RPL_MAX_DAG_PER_INSTANCE > 1 */
1547  }
1548 
1549 
1550  if(dio->rank < ROOT_RANK(instance)) {
1551  LOG_INFO("Ignoring DIO with too low rank: %u\n",
1552  (unsigned)dio->rank);
1553  return;
1554  }
1555 
1556  /* Prefix Information Option treated to add new prefix */
1557  if(dio->prefix_info.length != 0) {
1558  if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
1559  LOG_DBG("Prefix announced in DIO\n");
1560  rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length);
1561  }
1562  }
1563 
1564  if(!add_nbr_from_dio(from, dio)) {
1565  LOG_WARN("Could not add parent based on DIO\n");
1566  return;
1567  }
1568 
1569  if(dag->rank == ROOT_RANK(instance)) {
1570  if(dio->rank != RPL_INFINITE_RANK) {
1571  instance->dio_counter++;
1572  }
1573  return;
1574  }
1575 
1576  /* The DIO comes from a valid DAG, we can refresh its lifetime */
1577  dag->lifetime = (1UL << (instance->dio_intmin + instance->dio_intdoubl)) * RPL_DAG_LIFETIME / 1000;
1578  LOG_INFO("Set dag ");
1579  LOG_INFO_6ADDR(&dag->dag_id);
1580  LOG_INFO_(" lifetime to %ld\n", (long int) dag->lifetime);
1581 
1582  /*
1583  * At this point, we know that this DIO pertains to a DAG that
1584  * we are already part of. We consider the sender of the DIO to be
1585  * a candidate parent, and let rpl_process_parent_event decide
1586  * whether to keep it in the set.
1587  */
1588 
1589  p = rpl_find_parent(dag, from);
1590  if(p == NULL) {
1591  previous_dag = find_parent_dag(instance, from);
1592  if(previous_dag == NULL) {
1593  /* Add the DIO sender as a candidate parent. */
1594  p = rpl_add_parent(dag, dio, from);
1595  if(p == NULL) {
1596  LOG_WARN("Failed to add a new parent (");
1597  LOG_WARN_6ADDR(from);
1598  LOG_WARN_(")\n");
1599  return;
1600  }
1601  LOG_INFO("New candidate parent with rank %u: ", (unsigned)p->rank);
1602  LOG_INFO_6ADDR(from);
1603  LOG_INFO_("\n");
1604  } else {
1605  p = rpl_find_parent(previous_dag, from);
1606  if(p != NULL) {
1607  rpl_move_parent(previous_dag, dag, p);
1608  }
1609  }
1610  } else {
1611  if(p->rank == dio->rank) {
1612  LOG_INFO("Received consistent DIO\n");
1613  if(dag->joined) {
1614  instance->dio_counter++;
1615  }
1616  }
1617  }
1618  p->rank = dio->rank;
1619 
1620  if(dio->rank == RPL_INFINITE_RANK && p == dag->preferred_parent) {
1621  /* Our preferred parent advertised an infinite rank, reset DIO timer */
1622  rpl_reset_dio_timer(instance);
1623  }
1624 
1625  /* Parent info has been updated, trigger rank recalculation */
1626  p->flags |= RPL_PARENT_FLAG_UPDATED;
1627 
1628  LOG_INFO("preferred DAG ");
1629  LOG_INFO_6ADDR(&instance->current_dag->dag_id);
1630  LOG_INFO_(", rank %u, min_rank %u, ",
1631  instance->current_dag->rank, instance->current_dag->min_rank);
1632  LOG_INFO_("parent rank %u, link metric %u\n",
1633  p->rank, rpl_get_parent_link_metric(p));
1634 
1635  /* We have allocated a candidate parent; process the DIO further. */
1636 
1637 #if RPL_WITH_MC
1638  memcpy(&p->mc, &dio->mc, sizeof(p->mc));
1639 #endif /* RPL_WITH_MC */
1640  if(rpl_process_parent_event(instance, p) == 0) {
1641  LOG_WARN("The candidate parent is rejected\n");
1642  return;
1643  }
1644 
1645  /* We don't use route control, so we can have only one official parent. */
1646  if(dag->joined && p == dag->preferred_parent) {
1647  if(should_refresh_routes(instance, dio, p)) {
1648  /* Our parent is requesting a new DAO. Increment DTSN in turn,
1649  * in both storing and non-storing mode (see RFC6550 section 9.6.) */
1650  RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
1651  rpl_schedule_dao(instance);
1652  }
1653  /* We received a new DIO from our preferred parent.
1654  * Call uip_ds6_defrt_add to set a fresh value for the lifetime counter */
1655  uip_ds6_defrt_add(from, RPL_DEFAULT_ROUTE_INFINITE_LIFETIME ? 0 : RPL_LIFETIME(instance, instance->default_lifetime));
1656  }
1657  p->dtsn = dio->dtsn;
1658 }
1659 /*---------------------------------------------------------------------------*/
1660 /** @} */
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:107
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
RPL DAG structure.
Definition: rpl.h:135
RPL instance structure.
Definition: rpl.h:219
#define ROOT_RANK
Rank of a root node.
Definition: rpl-types.h:78
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
void rpl_schedule_probing_now(void)
Schedule probing within a few seconds.
IPv6 Neighbor cache (link-layer/IPv6 address mapping)
#define RPL_LIFETIME(lifetime)
Compute lifetime, accounting for the lifetime unit.
Definition: rpl-types.h:72
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
Definition: uip-ds6.c:576
RPL prefix information.
Definition: rpl.h:126
int rpl_dag_root_is_root(void)
Tells whether we are DAG root or not.
Definition: rpl-dag-root.c:153
int uip_ds6_nbr_num(void)
Return the number of neighbor caches.
Definition: uip-ds6-nbr.c:406
API for RPL objective functions (OF)
Definition: rpl.h:201
This header file contains configuration directives for uIPv6 multicast support.
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
#define DAG_RANK(fixpt_rank)
Return DAG RANK as per RFC 6550 (rank divided by min_hoprankinc)
Definition: rpl-types.h:81
int rpl_has_downward_route(void)
Get the RPL&#39;s best guess on if we have downward route or not.
Definition: rpl-dag.c:1035
Header file for the callback timer
uip_ipaddr_t * uip_ds6_nbr_ipaddr_from_lladdr(const uip_lladdr_t *lladdr)
Get an IPv6 address associated with a specified link-layer address.
Definition: uip-ds6-nbr.c:505
Linked list manipulation routines.
uip_ds6_nbr_t * uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
Get the neighbor cache associated with a specified IPv6 address.
Definition: uip-ds6-nbr.c:467
Unicast address structure.
Definition: uip-ds6.h:205
rpl_dag_t * rpl_get_any_dag(void)
Returns pointer to any DAG (for compatibility with legagy RPL code)
Definition: rpl-dag.c:1069
clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:118
const uip_lladdr_t * uip_ds6_nbr_lladdr_from_ipaddr(const uip_ipaddr_t *ipaddr)
Get the link-layer address associated with a specified IPv6 address.
Definition: uip-ds6-nbr.c:513
Memory block allocation routines.
uip_ds6_addr_t * uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
Add a unicast address to the interface.
Definition: uip-ds6.c:360
uip_ds6_nbr_t * rpl_icmp6_update_nbr_table(uip_ipaddr_t *from, nbr_table_reason_t reason, void *data)
Updates IPv6 neighbor cache on incoming link-local RPL ICMPv6 messages.
Definition: rpl-icmp6.c:194
Header file for the uIP TCP/IP stack.
Header file for IPv6 Neighbor discovery (RFC 4861)
void rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
Processes incoming DIO.
Definition: rpl-dag.c:1466
int rpl_has_joined(void)
Tells whether the node has joined a network or not.
Definition: rpl-dag.c:1026
uip_ds6_nbr_t * uip_ds6_nbr_ll_lookup(const uip_lladdr_t *lladdr)
Get the neighbor cache associated with a specified link-layer address.
Definition: uip-ds6-nbr.c:482
const uip_lladdr_t * uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr)
Get the link-layer address associated with a specified nbr cache.
Definition: uip-ds6-nbr.c:392
void rpl_local_repair(const char *str)
Triggers a RPL local repair.
Definition: rpl-dag.c:240
Header file for the logging system
rpl_instance_t * rpl_get_default_instance(void)
Returns pointer to the default instance (for compatibility with legagy RPL code)
Definition: rpl-dag.c:627
void rpl_dag_init(void)
Initializes rpl-dag module.
Definition: rpl-dag.c:143
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...
Definition: uip-ds6-nbr.h:105
void rpl_schedule_probing(void)
Schedule probing with delay RPL_PROBING_DELAY_FUNC()