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