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