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/rpl/rpl-private.h"
48 #include "net/ip/uip.h"
49 #include "net/ipv6/uip-nd6.h"
50 #include "net/nbr-table.h"
52 #include "lib/list.h"
53 #include "lib/memb.h"
54 #include "sys/ctimer.h"
55 
56 #include <limits.h>
57 #include <string.h>
58 
59 #define DEBUG DEBUG_NONE
60 #include "net/ip/uip-debug.h"
61 
62 #if UIP_CONF_IPV6
63 /*---------------------------------------------------------------------------*/
64 extern rpl_of_t RPL_OF;
65 static rpl_of_t * const objective_functions[] = {&RPL_OF};
66 
67 /*---------------------------------------------------------------------------*/
68 /* RPL definitions. */
69 
70 #ifndef RPL_CONF_GROUNDED
71 #define RPL_GROUNDED 0
72 #else
73 #define RPL_GROUNDED RPL_CONF_GROUNDED
74 #endif /* !RPL_CONF_GROUNDED */
75 
76 /*---------------------------------------------------------------------------*/
77 /* Per-parent RPL information */
78 NBR_TABLE(rpl_parent_t, rpl_parents);
79 /*---------------------------------------------------------------------------*/
80 /* Allocate instance table. */
81 rpl_instance_t instance_table[RPL_MAX_INSTANCES];
82 rpl_instance_t *default_instance;
83 /*---------------------------------------------------------------------------*/
84 static void
85 nbr_callback(void *ptr)
86 {
87  rpl_remove_parent(ptr);
88 }
89 
90 void
91 rpl_dag_init(void)
92 {
93  nbr_table_register(rpl_parents, (nbr_table_callback *)nbr_callback);
94 }
95 /*---------------------------------------------------------------------------*/
96 rpl_rank_t
97 rpl_get_parent_rank(uip_lladdr_t *addr)
98 {
99  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)addr);
100  if(p != NULL) {
101  return p->rank;
102  } else {
103  return 0;
104  }
105 }
106 /*---------------------------------------------------------------------------*/
107 uint16_t
108 rpl_get_parent_link_metric(const uip_lladdr_t *addr)
109 {
110  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (const linkaddr_t *)addr);
111  if(p != NULL) {
112  return p->link_metric;
113  } else {
114  return 0;
115  }
116 }
117 /*---------------------------------------------------------------------------*/
118 uip_ipaddr_t *
119 rpl_get_parent_ipaddr(rpl_parent_t *p)
120 {
121  linkaddr_t *lladdr = nbr_table_get_lladdr(rpl_parents, p);
122  return uip_ds6_nbr_ipaddr_from_lladdr((uip_lladdr_t *)lladdr);
123 }
124 /*---------------------------------------------------------------------------*/
125 static void
126 rpl_set_preferred_parent(rpl_dag_t *dag, rpl_parent_t *p)
127 {
128  if(dag != NULL && dag->preferred_parent != p) {
129  PRINTF("RPL: rpl_set_preferred_parent ");
130  if(p != NULL) {
131  PRINT6ADDR(rpl_get_parent_ipaddr(p));
132  } else {
133  PRINTF("NULL");
134  }
135  PRINTF(" used to be ");
136  if(dag->preferred_parent != NULL) {
137  PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent));
138  } else {
139  PRINTF("NULL");
140  }
141  PRINTF("\n");
142 
143  /* Always keep the preferred parent locked, so it remains in the
144  * neighbor table. */
145  nbr_table_unlock(rpl_parents, dag->preferred_parent);
146  nbr_table_lock(rpl_parents, p);
147  dag->preferred_parent = p;
148  }
149 }
150 /*---------------------------------------------------------------------------*/
151 /* Greater-than function for the lollipop counter. */
152 /*---------------------------------------------------------------------------*/
153 static int
154 lollipop_greater_than(int a, int b)
155 {
156  /* Check if we are comparing an initial value with an old value */
157  if(a > RPL_LOLLIPOP_CIRCULAR_REGION && b <= RPL_LOLLIPOP_CIRCULAR_REGION) {
158  return (RPL_LOLLIPOP_MAX_VALUE + 1 + b - a) > RPL_LOLLIPOP_SEQUENCE_WINDOWS;
159  }
160  /* Otherwise check if a > b and comparable => ok, or
161  if they have wrapped and are still comparable */
162  return (a > b && (a - b) < RPL_LOLLIPOP_SEQUENCE_WINDOWS) ||
163  (a < b && (b - a) > (RPL_LOLLIPOP_CIRCULAR_REGION + 1-
164  RPL_LOLLIPOP_SEQUENCE_WINDOWS));
165 }
166 /*---------------------------------------------------------------------------*/
167 /* Remove DAG parents with a rank that is at least the same as minimum_rank. */
168 static void
169 remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
170 {
171  rpl_parent_t *p;
172 
173  PRINTF("RPL: Removing parents (minimum rank %u)\n",
174  minimum_rank);
175 
176  p = nbr_table_head(rpl_parents);
177  while(p != NULL) {
178  if(dag == p->dag && p->rank >= minimum_rank) {
179  rpl_remove_parent(p);
180  }
181  p = nbr_table_next(rpl_parents, p);
182  }
183 }
184 /*---------------------------------------------------------------------------*/
185 static void
186 nullify_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
187 {
188  rpl_parent_t *p;
189 
190  PRINTF("RPL: Nullifying parents (minimum rank %u)\n",
191  minimum_rank);
192 
193  p = nbr_table_head(rpl_parents);
194  while(p != NULL) {
195  if(dag == p->dag && p->rank >= minimum_rank) {
196  rpl_nullify_parent(p);
197  }
198  p = nbr_table_next(rpl_parents, p);
199  }
200 }
201 /*---------------------------------------------------------------------------*/
202 static int
203 should_send_dao(rpl_instance_t *instance, rpl_dio_t *dio, rpl_parent_t *p)
204 {
205  /* if MOP is set to no downward routes no DAO should be sent */
206  if(instance->mop == RPL_MOP_NO_DOWNWARD_ROUTES) {
207  return 0;
208  }
209  /* check if the new DTSN is more recent */
210  return p == instance->current_dag->preferred_parent &&
211  (lollipop_greater_than(dio->dtsn, p->dtsn));
212 }
213 /*---------------------------------------------------------------------------*/
214 static int
215 acceptable_rank(rpl_dag_t *dag, rpl_rank_t rank)
216 {
217  return rank != INFINITE_RANK &&
218  ((dag->instance->max_rankinc == 0) ||
219  DAG_RANK(rank, dag->instance) <= DAG_RANK(dag->min_rank + dag->instance->max_rankinc, dag->instance));
220 }
221 /*---------------------------------------------------------------------------*/
222 static rpl_dag_t *
223 get_dag(uint8_t instance_id, uip_ipaddr_t *dag_id)
224 {
225  rpl_instance_t *instance;
226  rpl_dag_t *dag;
227  int i;
228 
229  instance = rpl_get_instance(instance_id);
230  if(instance == NULL) {
231  return NULL;
232  }
233 
234  for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; ++i) {
235  dag = &instance->dag_table[i];
236  if(dag->used && uip_ipaddr_cmp(&dag->dag_id, dag_id)) {
237  return dag;
238  }
239  }
240 
241  return NULL;
242 }
243 /*---------------------------------------------------------------------------*/
244 rpl_dag_t *
245 rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id)
246 {
247  rpl_dag_t *dag;
248  rpl_instance_t *instance;
249  uint8_t version;
250 
251  version = RPL_LOLLIPOP_INIT;
252  dag = get_dag(instance_id, dag_id);
253  if(dag != NULL) {
254  version = dag->version;
255  RPL_LOLLIPOP_INCREMENT(version);
256  PRINTF("RPL: Dropping a joined DAG when setting this node as root");
257  if(dag == dag->instance->current_dag) {
258  dag->instance->current_dag = NULL;
259  }
260  rpl_free_dag(dag);
261  }
262 
263  dag = rpl_alloc_dag(instance_id, dag_id);
264  if(dag == NULL) {
265  PRINTF("RPL: Failed to allocate a DAG\n");
266  return NULL;
267  }
268 
269  instance = dag->instance;
270 
271  dag->version = version;
272  dag->joined = 1;
273  dag->grounded = RPL_GROUNDED;
274  dag->preference = RPL_PREFERENCE;
275  instance->mop = RPL_MOP_DEFAULT;
276  instance->of = &RPL_OF;
277  rpl_set_preferred_parent(dag, NULL);
278 
279  memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id));
280 
281  instance->dio_intdoubl = RPL_DIO_INTERVAL_DOUBLINGS;
282  instance->dio_intmin = RPL_DIO_INTERVAL_MIN;
283  /* The current interval must differ from the minimum interval in order to
284  trigger a DIO timer reset. */
285  instance->dio_intcurrent = RPL_DIO_INTERVAL_MIN +
286  RPL_DIO_INTERVAL_DOUBLINGS;
287  instance->dio_redundancy = RPL_DIO_REDUNDANCY;
288  instance->max_rankinc = RPL_MAX_RANKINC;
289  instance->min_hoprankinc = RPL_MIN_HOPRANKINC;
290  instance->default_lifetime = RPL_DEFAULT_LIFETIME;
291  instance->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT;
292 
293  dag->rank = ROOT_RANK(instance);
294 
295  if(instance->current_dag != dag && instance->current_dag != NULL) {
296  /* Remove routes installed by DAOs. */
297  rpl_remove_routes(instance->current_dag);
298 
299  instance->current_dag->joined = 0;
300  }
301 
302  instance->current_dag = dag;
303  instance->dtsn_out = RPL_LOLLIPOP_INIT;
304  instance->of->update_metric_container(instance);
305  default_instance = instance;
306 
307  PRINTF("RPL: Node set to be a DAG root with DAG ID ");
308  PRINT6ADDR(&dag->dag_id);
309  PRINTF("\n");
310 
311  ANNOTATE("#A root=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]);
312 
313  rpl_reset_dio_timer(instance);
314 
315  return dag;
316 }
317 /*---------------------------------------------------------------------------*/
318 int
319 rpl_repair_root(uint8_t instance_id)
320 {
321  rpl_instance_t *instance;
322 
323  instance = rpl_get_instance(instance_id);
324  if(instance == NULL ||
325  instance->current_dag->rank != ROOT_RANK(instance)) {
326  PRINTF("RPL: rpl_repair_root triggered but not root\n");
327  return 0;
328  }
329 
330  RPL_LOLLIPOP_INCREMENT(instance->current_dag->version);
331  RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
332  PRINTF("RPL: rpl_repair_root initiating global repair with version %d\n", instance->current_dag->version);
333  rpl_reset_dio_timer(instance);
334  return 1;
335 }
336 /*---------------------------------------------------------------------------*/
337 static void
338 set_ip_from_prefix(uip_ipaddr_t *ipaddr, rpl_prefix_t *prefix)
339 {
340  memset(ipaddr, 0, sizeof(uip_ipaddr_t));
341  memcpy(ipaddr, &prefix->prefix, (prefix->length + 7) / 8);
343 }
344 /*---------------------------------------------------------------------------*/
345 static void
346 check_prefix(rpl_prefix_t *last_prefix, rpl_prefix_t *new_prefix)
347 {
348  uip_ipaddr_t ipaddr;
349  uip_ds6_addr_t *rep;
350 
351  if(last_prefix != NULL && new_prefix != NULL &&
352  last_prefix->length == new_prefix->length &&
353  uip_ipaddr_prefixcmp(&last_prefix->prefix, &new_prefix->prefix, new_prefix->length) &&
354  last_prefix->flags == new_prefix->flags) {
355  /* Nothing has changed. */
356  return;
357  }
358 
359  if(last_prefix != NULL) {
360  set_ip_from_prefix(&ipaddr, last_prefix);
361  rep = uip_ds6_addr_lookup(&ipaddr);
362  if(rep != NULL) {
363  PRINTF("RPL: removing global IP address ");
364  PRINT6ADDR(&ipaddr);
365  PRINTF("\n");
366  uip_ds6_addr_rm(rep);
367  }
368  }
369 
370  if(new_prefix != NULL) {
371  set_ip_from_prefix(&ipaddr, new_prefix);
372  if(uip_ds6_addr_lookup(&ipaddr) == NULL) {
373  PRINTF("RPL: adding global IP address ");
374  PRINT6ADDR(&ipaddr);
375  PRINTF("\n");
376  uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
377  }
378  }
379 }
380 /*---------------------------------------------------------------------------*/
381 int
382 rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, unsigned len)
383 {
384  rpl_prefix_t last_prefix;
385  uint8_t last_len = dag->prefix_info.length;
386 
387  if(len > 128) {
388  return 0;
389  }
390  if(dag->prefix_info.length != 0) {
391  memcpy(&last_prefix, &dag->prefix_info, sizeof(rpl_prefix_t));
392  }
393  memset(&dag->prefix_info.prefix, 0, sizeof(dag->prefix_info.prefix));
394  memcpy(&dag->prefix_info.prefix, prefix, (len + 7) / 8);
395  dag->prefix_info.length = len;
396  dag->prefix_info.flags = UIP_ND6_RA_FLAG_AUTONOMOUS;
397  PRINTF("RPL: Prefix set - will announce this in DIOs\n");
398  /* Autoconfigure an address if this node does not already have an address
399  with this prefix. Otherwise, update the prefix */
400  if(last_len == 0) {
401  PRINTF("rpl_set_prefix - prefix NULL\n");
402  check_prefix(NULL, &dag->prefix_info);
403  } else {
404  PRINTF("rpl_set_prefix - prefix NON-NULL\n");
405  check_prefix(&last_prefix, &dag->prefix_info);
406  }
407  return 1;
408 }
409 /*---------------------------------------------------------------------------*/
410 int
411 rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from)
412 {
413  if(instance->def_route != NULL) {
414  PRINTF("RPL: Removing default route through ");
415  PRINT6ADDR(&instance->def_route->ipaddr);
416  PRINTF("\n");
417  uip_ds6_defrt_rm(instance->def_route);
418  instance->def_route = NULL;
419  }
420 
421  if(from != NULL) {
422  PRINTF("RPL: Adding default route through ");
423  PRINT6ADDR(from);
424  PRINTF("\n");
425  instance->def_route = uip_ds6_defrt_add(from,
426  RPL_LIFETIME(instance,
427  instance->default_lifetime));
428  if(instance->def_route == NULL) {
429  return 0;
430  }
431  } else {
432  PRINTF("RPL: Removing default route\n");
433  if(instance->def_route != NULL) {
434  uip_ds6_defrt_rm(instance->def_route);
435  } else {
436  PRINTF("RPL: Not actually removing default route, since instance had no default route\n");
437  }
438  }
439  return 1;
440 }
441 /*---------------------------------------------------------------------------*/
442 rpl_instance_t *
443 rpl_alloc_instance(uint8_t instance_id)
444 {
445  rpl_instance_t *instance, *end;
446 
447  for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES;
448  instance < end; ++instance) {
449  if(instance->used == 0) {
450  memset(instance, 0, sizeof(*instance));
451  instance->instance_id = instance_id;
452  instance->def_route = NULL;
453  instance->used = 1;
454  return instance;
455  }
456  }
457  return NULL;
458 }
459 /*---------------------------------------------------------------------------*/
460 rpl_dag_t *
461 rpl_alloc_dag(uint8_t instance_id, uip_ipaddr_t *dag_id)
462 {
463  rpl_dag_t *dag, *end;
464  rpl_instance_t *instance;
465 
466  instance = rpl_get_instance(instance_id);
467  if(instance == NULL) {
468  instance = rpl_alloc_instance(instance_id);
469  if(instance == NULL) {
470  RPL_STAT(rpl_stats.mem_overflows++);
471  return NULL;
472  }
473  }
474 
475  for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
476  if(!dag->used) {
477  memset(dag, 0, sizeof(*dag));
478  dag->used = 1;
479  dag->rank = INFINITE_RANK;
480  dag->min_rank = INFINITE_RANK;
481  dag->instance = instance;
482  return dag;
483  }
484  }
485 
486  RPL_STAT(rpl_stats.mem_overflows++);
487  rpl_free_instance(instance);
488  return NULL;
489 }
490 /*---------------------------------------------------------------------------*/
491 void
492 rpl_set_default_instance(rpl_instance_t *instance)
493 {
494  default_instance = instance;
495 }
496 /*---------------------------------------------------------------------------*/
497 void
498 rpl_free_instance(rpl_instance_t *instance)
499 {
500  rpl_dag_t *dag;
501  rpl_dag_t *end;
502 
503  PRINTF("RPL: Leaving the instance %u\n", instance->instance_id);
504 
505  /* Remove any DAG inside this instance */
506  for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
507  if(dag->used) {
508  rpl_free_dag(dag);
509  }
510  }
511 
512  rpl_set_default_route(instance, NULL);
513 
514  ctimer_stop(&instance->dio_timer);
515  ctimer_stop(&instance->dao_timer);
516 
517  if(default_instance == instance) {
518  default_instance = NULL;
519  }
520 
521  instance->used = 0;
522 }
523 /*---------------------------------------------------------------------------*/
524 void
525 rpl_free_dag(rpl_dag_t *dag)
526 {
527  if(dag->joined) {
528  PRINTF("RPL: Leaving the DAG ");
529  PRINT6ADDR(&dag->dag_id);
530  PRINTF("\n");
531  dag->joined = 0;
532 
533  /* Remove routes installed by DAOs. */
534  rpl_remove_routes(dag);
535 
536  /* Remove autoconfigured address */
537  if((dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) {
538  check_prefix(&dag->prefix_info, NULL);
539  }
540 
541  remove_parents(dag, 0);
542  }
543  dag->used = 0;
544 }
545 /*---------------------------------------------------------------------------*/
546 rpl_parent_t *
547 rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr)
548 {
549  rpl_parent_t *p = NULL;
550  /* Is the parent known by ds6? Drop this request if not.
551  * Typically, the parent is added upon receiving a DIO. */
552  const uip_lladdr_t *lladdr = uip_ds6_nbr_lladdr_from_ipaddr(addr);
553 
554  PRINTF("RPL: rpl_add_parent lladdr %p ", lladdr);
555  PRINT6ADDR(addr);
556  PRINTF("\n");
557  if(lladdr != NULL) {
558  /* Add parent in rpl_parents */
559  p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr);
560  if(p == NULL) {
561  PRINTF("RPL: rpl_add_parent p NULL\n");
562  } else {
563  p->dag = dag;
564  p->rank = dio->rank;
565  p->dtsn = dio->dtsn;
566  p->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
567 #if RPL_DAG_MC != RPL_DAG_MC_NONE
568  memcpy(&p->mc, &dio->mc, sizeof(p->mc));
569 #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
570  }
571  }
572 
573  return p;
574 }
575 /*---------------------------------------------------------------------------*/
576 static rpl_parent_t *
577 find_parent_any_dag_any_instance(uip_ipaddr_t *addr)
578 {
579  uip_ds6_nbr_t *ds6_nbr = uip_ds6_nbr_lookup(addr);
580  const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(ds6_nbr);
581  return nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)lladdr);
582 }
583 /*---------------------------------------------------------------------------*/
584 rpl_parent_t *
585 rpl_find_parent(rpl_dag_t *dag, uip_ipaddr_t *addr)
586 {
587  rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
588  if(p != NULL && p->dag == dag) {
589  return p;
590  } else {
591  return NULL;
592  }
593 }
594 /*---------------------------------------------------------------------------*/
595 static rpl_dag_t *
596 find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr)
597 {
598  rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
599  if(p != NULL) {
600  return p->dag;
601  } else {
602  return NULL;
603  }
604 }
605 /*---------------------------------------------------------------------------*/
606 rpl_parent_t *
607 rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr)
608 {
609  rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
610  if(p && p->dag && p->dag->instance == instance) {
611  return p;
612  } else {
613  return NULL;
614  }
615 }
616 /*---------------------------------------------------------------------------*/
617 rpl_dag_t *
618 rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p)
619 {
620  rpl_parent_t *last_parent;
621  rpl_dag_t *dag, *end, *best_dag;
622  rpl_rank_t old_rank;
623 
624  old_rank = instance->current_dag->rank;
625  last_parent = instance->current_dag->preferred_parent;
626 
627  best_dag = instance->current_dag;
628  if(best_dag->rank != ROOT_RANK(instance)) {
629  if(rpl_select_parent(p->dag) != NULL) {
630  if(p->dag != best_dag) {
631  best_dag = instance->of->best_dag(best_dag, p->dag);
632  }
633  } else if(p->dag == best_dag) {
634  best_dag = NULL;
635  for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
636  if(dag->used && dag->preferred_parent != NULL && dag->preferred_parent->rank != INFINITE_RANK) {
637  if(best_dag == NULL) {
638  best_dag = dag;
639  } else {
640  best_dag = instance->of->best_dag(best_dag, dag);
641  }
642  }
643  }
644  }
645  }
646 
647  if(best_dag == NULL) {
648  /* No parent found: the calling function handle this problem. */
649  return NULL;
650  }
651 
652  if(instance->current_dag != best_dag) {
653  /* Remove routes installed by DAOs. */
654  rpl_remove_routes(instance->current_dag);
655 
656  PRINTF("RPL: New preferred DAG: ");
657  PRINT6ADDR(&best_dag->dag_id);
658  PRINTF("\n");
659 
660  if(best_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
661  check_prefix(&instance->current_dag->prefix_info, &best_dag->prefix_info);
662  } else if(instance->current_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
663  check_prefix(&instance->current_dag->prefix_info, NULL);
664  }
665 
666  best_dag->joined = 1;
667  instance->current_dag->joined = 0;
668  instance->current_dag = best_dag;
669  }
670 
671  instance->of->update_metric_container(instance);
672  /* Update the DAG rank. */
673  best_dag->rank = instance->of->calculate_rank(best_dag->preferred_parent, 0);
674  if(last_parent == NULL || best_dag->rank < best_dag->min_rank) {
675  best_dag->min_rank = best_dag->rank;
676  } else if(!acceptable_rank(best_dag, best_dag->rank)) {
677  PRINTF("RPL: New rank unacceptable!\n");
678  rpl_set_preferred_parent(instance->current_dag, NULL);
679  if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES && last_parent != NULL) {
680  /* Send a No-Path DAO to the removed preferred parent. */
681  dao_output(last_parent, RPL_ZERO_LIFETIME);
682  }
683  return NULL;
684  }
685 
686  if(best_dag->preferred_parent != last_parent) {
687  rpl_set_default_route(instance, rpl_get_parent_ipaddr(best_dag->preferred_parent));
688  PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n",
689  (unsigned)old_rank, best_dag->rank);
690  RPL_STAT(rpl_stats.parent_switch++);
691  if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
692  if(last_parent != NULL) {
693  /* Send a No-Path DAO to the removed preferred parent. */
694  dao_output(last_parent, RPL_ZERO_LIFETIME);
695  }
696  /* The DAO parent set changed - schedule a DAO transmission. */
697  RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
698  rpl_schedule_dao(instance);
699  }
700  rpl_reset_dio_timer(instance);
701  } else if(best_dag->rank != old_rank) {
702  PRINTF("RPL: Preferred parent update, rank changed from %u to %u\n",
703  (unsigned)old_rank, best_dag->rank);
704  }
705  return best_dag;
706 }
707 /*---------------------------------------------------------------------------*/
708 static rpl_parent_t *
709 best_parent(rpl_dag_t *dag)
710 {
711  rpl_parent_t *p, *best;
712 
713  best = NULL;
714 
715  p = nbr_table_head(rpl_parents);
716  while(p != NULL) {
717  if(p->dag != dag || p->rank == INFINITE_RANK) {
718  /* ignore this neighbor */
719  } else if(best == NULL) {
720  best = p;
721  } else {
722  best = dag->instance->of->best_parent(best, p);
723  }
724  p = nbr_table_next(rpl_parents, p);
725  }
726 
727  return best;
728 }
729 /*---------------------------------------------------------------------------*/
730 rpl_parent_t *
731 rpl_select_parent(rpl_dag_t *dag)
732 {
733  rpl_parent_t *best = best_parent(dag);
734 
735  if(best != NULL) {
736  rpl_set_preferred_parent(dag, best);
737  }
738 
739  return best;
740 }
741 /*---------------------------------------------------------------------------*/
742 void
743 rpl_remove_parent(rpl_parent_t *parent)
744 {
745  PRINTF("RPL: Removing parent ");
746  PRINT6ADDR(rpl_get_parent_ipaddr(parent));
747  PRINTF("\n");
748 
749  rpl_nullify_parent(parent);
750 
751  nbr_table_remove(rpl_parents, parent);
752 }
753 /*---------------------------------------------------------------------------*/
754 void
755 rpl_nullify_parent(rpl_parent_t *parent)
756 {
757  rpl_dag_t *dag = parent->dag;
758  /* This function can be called when the preferred parent is NULL, so we
759  need to handle this condition in order to trigger uip_ds6_defrt_rm. */
760  if(parent == dag->preferred_parent || dag->preferred_parent == NULL) {
761  rpl_set_preferred_parent(dag, NULL);
762  dag->rank = INFINITE_RANK;
763  if(dag->joined) {
764  if(dag->instance->def_route != NULL) {
765  PRINTF("RPL: Removing default route ");
766  PRINT6ADDR(rpl_get_parent_ipaddr(parent));
767  PRINTF("\n");
768  uip_ds6_defrt_rm(dag->instance->def_route);
769  dag->instance->def_route = NULL;
770  }
771  dao_output(parent, RPL_ZERO_LIFETIME);
772  }
773  }
774 
775  PRINTF("RPL: Nullifying parent ");
776  PRINT6ADDR(rpl_get_parent_ipaddr(parent));
777  PRINTF("\n");
778 }
779 /*---------------------------------------------------------------------------*/
780 void
781 rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent)
782 {
783  if(parent == dag_src->preferred_parent) {
784  rpl_set_preferred_parent(dag_src, NULL);
785  dag_src->rank = INFINITE_RANK;
786  if(dag_src->joined && dag_src->instance->def_route != NULL) {
787  PRINTF("RPL: Removing default route ");
788  PRINT6ADDR(rpl_get_parent_ipaddr(parent));
789  PRINTF("\n");
790  PRINTF("rpl_move_parent\n");
791  uip_ds6_defrt_rm(dag_src->instance->def_route);
792  dag_src->instance->def_route = NULL;
793  }
794  } else if(dag_src->joined) {
795  /* Remove uIPv6 routes that have this parent as the next hop. */
796  rpl_remove_routes_by_nexthop(rpl_get_parent_ipaddr(parent), dag_src);
797  }
798 
799  PRINTF("RPL: Moving parent ");
800  PRINT6ADDR(rpl_get_parent_ipaddr(parent));
801  PRINTF("\n");
802 
803  parent->dag = dag_dst;
804 }
805 /*---------------------------------------------------------------------------*/
806 rpl_dag_t *
807 rpl_get_any_dag(void)
808 {
809  int i;
810 
811  for(i = 0; i < RPL_MAX_INSTANCES; ++i) {
812  if(instance_table[i].used && instance_table[i].current_dag->joined) {
813  return instance_table[i].current_dag;
814  }
815  }
816  return NULL;
817 }
818 /*---------------------------------------------------------------------------*/
819 rpl_instance_t *
820 rpl_get_instance(uint8_t instance_id)
821 {
822  int i;
823 
824  for(i = 0; i < RPL_MAX_INSTANCES; ++i) {
825  if(instance_table[i].used && instance_table[i].instance_id == instance_id) {
826  return &instance_table[i];
827  }
828  }
829  return NULL;
830 }
831 /*---------------------------------------------------------------------------*/
832 rpl_of_t *
833 rpl_find_of(rpl_ocp_t ocp)
834 {
835  unsigned int i;
836 
837  for(i = 0;
838  i < sizeof(objective_functions) / sizeof(objective_functions[0]);
839  i++) {
840  if(objective_functions[i]->ocp == ocp) {
841  return objective_functions[i];
842  }
843  }
844 
845  return NULL;
846 }
847 /*---------------------------------------------------------------------------*/
848 void
849 rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio)
850 {
851  rpl_instance_t *instance;
852  rpl_dag_t *dag;
853  rpl_parent_t *p;
854  rpl_of_t *of;
855 
856  dag = rpl_alloc_dag(dio->instance_id, &dio->dag_id);
857  if(dag == NULL) {
858  PRINTF("RPL: Failed to allocate a DAG object!\n");
859  return;
860  }
861 
862  instance = dag->instance;
863 
864  p = rpl_add_parent(dag, dio, from);
865  PRINTF("RPL: Adding ");
866  PRINT6ADDR(from);
867  PRINTF(" as a parent: ");
868  if(p == NULL) {
869  PRINTF("failed\n");
870  instance->used = 0;
871  return;
872  }
873  p->dtsn = dio->dtsn;
874  PRINTF("succeeded\n");
875 
876  /* Determine the objective function by using the
877  objective code point of the DIO. */
878  of = rpl_find_of(dio->ocp);
879  if(of == NULL) {
880  PRINTF("RPL: DIO for DAG instance %u does not specify a supported OF\n",
881  dio->instance_id);
882  rpl_remove_parent(p);
883  instance->used = 0;
884  return;
885  }
886 
887  /* Autoconfigure an address if this node does not already have an address
888  with this prefix. */
889  if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
890  check_prefix(NULL, &dio->prefix_info);
891  }
892 
893  dag->joined = 1;
894  dag->preference = dio->preference;
895  dag->grounded = dio->grounded;
896  dag->version = dio->version;
897 
898  instance->of = of;
899  instance->mop = dio->mop;
900  instance->current_dag = dag;
901  instance->dtsn_out = RPL_LOLLIPOP_INIT;
902 
903  instance->max_rankinc = dio->dag_max_rankinc;
904  instance->min_hoprankinc = dio->dag_min_hoprankinc;
905  instance->dio_intdoubl = dio->dag_intdoubl;
906  instance->dio_intmin = dio->dag_intmin;
907  instance->dio_intcurrent = instance->dio_intmin + instance->dio_intdoubl;
908  instance->dio_redundancy = dio->dag_redund;
909  instance->default_lifetime = dio->default_lifetime;
910  instance->lifetime_unit = dio->lifetime_unit;
911 
912  memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id));
913 
914  /* Copy prefix information from the DIO into the DAG object. */
915  memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t));
916 
917  rpl_set_preferred_parent(dag, p);
918  instance->of->update_metric_container(instance);
919  dag->rank = instance->of->calculate_rank(p, 0);
920  /* So far this is the lowest rank we are aware of. */
921  dag->min_rank = dag->rank;
922 
923  if(default_instance == NULL) {
924  default_instance = instance;
925  }
926 
927  PRINTF("RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ",
928  dio->instance_id, dag->rank);
929  PRINT6ADDR(&dag->dag_id);
930  PRINTF("\n");
931 
932  ANNOTATE("#A join=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]);
933 
934  rpl_reset_dio_timer(instance);
935  rpl_set_default_route(instance, from);
936 
937  if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
938  rpl_schedule_dao(instance);
939  } else {
940  PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n");
941  }
942 }
943 
944 /*---------------------------------------------------------------------------*/
945 void
946 rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
947 {
948  rpl_instance_t *instance;
949  rpl_dag_t *dag, *previous_dag;
950  rpl_parent_t *p;
951  rpl_of_t *of;
952 
953  dag = rpl_alloc_dag(dio->instance_id, &dio->dag_id);
954  if(dag == NULL) {
955  PRINTF("RPL: Failed to allocate a DAG object!\n");
956  return;
957  }
958 
959  instance = dag->instance;
960 
961  previous_dag = find_parent_dag(instance, from);
962  if(previous_dag == NULL) {
963  PRINTF("RPL: Adding ");
964  PRINT6ADDR(from);
965  PRINTF(" as a parent: ");
966  p = rpl_add_parent(dag, dio, from);
967  if(p == NULL) {
968  PRINTF("failed\n");
969  dag->used = 0;
970  return;
971  }
972  PRINTF("succeeded\n");
973  } else {
974  p = rpl_find_parent(previous_dag, from);
975  if(p != NULL) {
976  rpl_move_parent(previous_dag, dag, p);
977  }
978  }
979 
980  /* Determine the objective function by using the
981  objective code point of the DIO. */
982  of = rpl_find_of(dio->ocp);
983  if(of != instance->of ||
984  instance->mop != dio->mop ||
985  instance->max_rankinc != dio->dag_max_rankinc ||
986  instance->min_hoprankinc != dio->dag_min_hoprankinc ||
987  instance->dio_intdoubl != dio->dag_intdoubl ||
988  instance->dio_intmin != dio->dag_intmin ||
989  instance->dio_redundancy != dio->dag_redund ||
990  instance->default_lifetime != dio->default_lifetime ||
991  instance->lifetime_unit != dio->lifetime_unit) {
992  PRINTF("RPL: DIO for DAG instance %u incompatible with previous DIO\n",
993  dio->instance_id);
994  rpl_remove_parent(p);
995  dag->used = 0;
996  return;
997  }
998 
999  dag->used = 1;
1000  dag->grounded = dio->grounded;
1001  dag->preference = dio->preference;
1002  dag->version = dio->version;
1003 
1004  memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id));
1005 
1006  /* copy prefix information into the dag */
1007  memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t));
1008 
1009  rpl_set_preferred_parent(dag, p);
1010  dag->rank = instance->of->calculate_rank(p, 0);
1011  dag->min_rank = dag->rank; /* So far this is the lowest rank we know of. */
1012 
1013  PRINTF("RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ",
1014  dio->instance_id, dag->rank);
1015  PRINT6ADDR(&dag->dag_id);
1016  PRINTF("\n");
1017 
1018  ANNOTATE("#A join=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]);
1019 
1020  rpl_process_parent_event(instance, p);
1021  p->dtsn = dio->dtsn;
1022 }
1023 
1024 /*---------------------------------------------------------------------------*/
1025 static void
1026 global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio)
1027 {
1028  rpl_parent_t *p;
1029 
1030  remove_parents(dag, 0);
1031  dag->version = dio->version;
1032  dag->instance->of->reset(dag);
1033  dag->min_rank = INFINITE_RANK;
1034  RPL_LOLLIPOP_INCREMENT(dag->instance->dtsn_out);
1035 
1036  p = rpl_add_parent(dag, dio, from);
1037  if(p == NULL) {
1038  PRINTF("RPL: Failed to add a parent during the global repair\n");
1039  dag->rank = INFINITE_RANK;
1040  } else {
1041  dag->rank = dag->instance->of->calculate_rank(p, 0);
1042  dag->min_rank = dag->rank;
1043  PRINTF("RPL: rpl_process_parent_event global repair\n");
1044  rpl_process_parent_event(dag->instance, p);
1045  }
1046 
1047  PRINTF("RPL: Participating in a global repair (version=%u, rank=%hu)\n",
1048  dag->version, dag->rank);
1049 
1050  RPL_STAT(rpl_stats.global_repairs++);
1051 }
1052 /*---------------------------------------------------------------------------*/
1053 void
1054 rpl_local_repair(rpl_instance_t *instance)
1055 {
1056  int i;
1057 
1058  if(instance == NULL) {
1059  PRINTF("RPL: local repair requested for instance NULL\n");
1060  return;
1061  }
1062  PRINTF("RPL: Starting a local instance repair\n");
1063  for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; i++) {
1064  if(instance->dag_table[i].used) {
1065  instance->dag_table[i].rank = INFINITE_RANK;
1066  nullify_parents(&instance->dag_table[i], 0);
1067  }
1068  }
1069 
1070  rpl_reset_dio_timer(instance);
1071 
1072  RPL_STAT(rpl_stats.local_repairs++);
1073 }
1074 /*---------------------------------------------------------------------------*/
1075 void
1076 rpl_recalculate_ranks(void)
1077 {
1078  rpl_parent_t *p;
1079 
1080  /*
1081  * We recalculate ranks when we receive feedback from the system rather
1082  * than RPL protocol messages. This periodical recalculation is called
1083  * from a timer in order to keep the stack depth reasonably low.
1084  */
1085  p = nbr_table_head(rpl_parents);
1086  while(p != NULL) {
1087  if(p->dag != NULL && p->dag->instance && (p->flags & RPL_PARENT_FLAG_UPDATED)) {
1088  p->flags &= ~RPL_PARENT_FLAG_UPDATED;
1089  PRINTF("RPL: rpl_process_parent_event recalculate_ranks\n");
1090  if(!rpl_process_parent_event(p->dag->instance, p)) {
1091  PRINTF("RPL: A parent was dropped\n");
1092  }
1093  }
1094  p = nbr_table_next(rpl_parents, p);
1095  }
1096 }
1097 /*---------------------------------------------------------------------------*/
1098 int
1099 rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p)
1100 {
1101  int return_value;
1102 
1103 #if DEBUG
1104  rpl_rank_t old_rank;
1105  old_rank = instance->current_dag->rank;
1106 #endif /* DEBUG */
1107 
1108  return_value = 1;
1109 
1110  if(!acceptable_rank(p->dag, p->rank)) {
1111  /* The candidate parent is no longer valid: the rank increase resulting
1112  from the choice of it as a parent would be too high. */
1113  PRINTF("RPL: Unacceptable rank %u\n", (unsigned)p->rank);
1114  rpl_nullify_parent(p);
1115  if(p != instance->current_dag->preferred_parent) {
1116  return 0;
1117  } else {
1118  return_value = 0;
1119  }
1120  }
1121 
1122  if(rpl_select_dag(instance, p) == NULL) {
1123  /* No suitable parent; trigger a local repair. */
1124  PRINTF("RPL: No parents found in any DAG\n");
1125  rpl_local_repair(instance);
1126  return 0;
1127  }
1128 
1129 #if DEBUG
1130  if(DAG_RANK(old_rank, instance) != DAG_RANK(instance->current_dag->rank, instance)) {
1131  PRINTF("RPL: Moving in the instance from rank %hu to %hu\n",
1132  DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank, instance));
1133  if(instance->current_dag->rank != INFINITE_RANK) {
1134  PRINTF("RPL: The preferred parent is ");
1135  PRINT6ADDR(rpl_get_parent_ipaddr(instance->current_dag->preferred_parent));
1136  PRINTF(" (rank %u)\n",
1137  (unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank, instance));
1138  } else {
1139  PRINTF("RPL: We don't have any parent");
1140  }
1141  }
1142 #endif /* DEBUG */
1143 
1144  return return_value;
1145 }
1146 /*---------------------------------------------------------------------------*/
1147 void
1148 rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
1149 {
1150  rpl_instance_t *instance;
1151  rpl_dag_t *dag, *previous_dag;
1152  rpl_parent_t *p;
1153 
1154 #if RPL_CONF_MULTICAST
1155  /* If the root is advertising MOP 2 but we support MOP 3 we can still join
1156  * In that scenario, we suppress DAOs for multicast targets */
1157  if(dio->mop < RPL_MOP_STORING_NO_MULTICAST) {
1158 #else
1159  if(dio->mop != RPL_MOP_DEFAULT) {
1160 #endif
1161  PRINTF("RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop);
1162  return;
1163  }
1164 
1165  dag = get_dag(dio->instance_id, &dio->dag_id);
1166  instance = rpl_get_instance(dio->instance_id);
1167 
1168  if(dag != NULL && instance != NULL) {
1169  if(lollipop_greater_than(dio->version, dag->version)) {
1170  if(dag->rank == ROOT_RANK(instance)) {
1171  PRINTF("RPL: Root received inconsistent DIO version number\n");
1172  dag->version = dio->version;
1173  RPL_LOLLIPOP_INCREMENT(dag->version);
1174  rpl_reset_dio_timer(instance);
1175  } else {
1176  PRINTF("RPL: Global repair\n");
1177  if(dio->prefix_info.length != 0) {
1178  if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
1179  PRINTF("RPL : Prefix announced in DIO\n");
1180  rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length);
1181  }
1182  }
1183  global_repair(from, dag, dio);
1184  }
1185  return;
1186  }
1187 
1188  if(lollipop_greater_than(dag->version, dio->version)) {
1189  /* The DIO sender is on an older version of the DAG. */
1190  PRINTF("RPL: old version received => inconsistency detected\n");
1191  if(dag->joined) {
1192  rpl_reset_dio_timer(instance);
1193  return;
1194  }
1195  }
1196  }
1197 
1198  if(instance == NULL) {
1199  PRINTF("RPL: New instance detected: Joining...\n");
1200  rpl_join_instance(from, dio);
1201  return;
1202  }
1203 
1204  if(instance->current_dag->rank == ROOT_RANK(instance) && instance->current_dag != dag) {
1205  PRINTF("RPL: Root ignored DIO for different DAG\n");
1206  return;
1207  }
1208 
1209  if(dag == NULL) {
1210  PRINTF("RPL: Adding new DAG to known instance.\n");
1211  rpl_add_dag(from, dio);
1212  return;
1213  }
1214 
1215 
1216  if(dio->rank < ROOT_RANK(instance)) {
1217  PRINTF("RPL: Ignoring DIO with too low rank: %u\n",
1218  (unsigned)dio->rank);
1219  return;
1220  } else if(dio->rank == INFINITE_RANK && dag->joined) {
1221  rpl_reset_dio_timer(instance);
1222  }
1223 
1224  /* Prefix Information Option treated to add new prefix */
1225  if(dio->prefix_info.length != 0) {
1226  if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
1227  PRINTF("RPL : Prefix announced in DIO\n");
1228  rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length);
1229  }
1230  }
1231 
1232  if(dag->rank == ROOT_RANK(instance)) {
1233  if(dio->rank != INFINITE_RANK) {
1234  instance->dio_counter++;
1235  }
1236  return;
1237  }
1238 
1239  /*
1240  * At this point, we know that this DIO pertains to a DAG that
1241  * we are already part of. We consider the sender of the DIO to be
1242  * a candidate parent, and let rpl_process_parent_event decide
1243  * whether to keep it in the set.
1244  */
1245 
1246  p = rpl_find_parent(dag, from);
1247  if(p == NULL) {
1248  previous_dag = find_parent_dag(instance, from);
1249  if(previous_dag == NULL) {
1250  /* Add the DIO sender as a candidate parent. */
1251  p = rpl_add_parent(dag, dio, from);
1252  if(p == NULL) {
1253  PRINTF("RPL: Failed to add a new parent (");
1254  PRINT6ADDR(from);
1255  PRINTF(")\n");
1256  return;
1257  }
1258  PRINTF("RPL: New candidate parent with rank %u: ", (unsigned)p->rank);
1259  PRINT6ADDR(from);
1260  PRINTF("\n");
1261  } else {
1262  p = rpl_find_parent(previous_dag, from);
1263  if(p != NULL) {
1264  rpl_move_parent(previous_dag, dag, p);
1265  }
1266  }
1267  } else {
1268  if(p->rank == dio->rank) {
1269  PRINTF("RPL: Received consistent DIO\n");
1270  if(dag->joined) {
1271  instance->dio_counter++;
1272  }
1273  } else {
1274  p->rank=dio->rank;
1275  }
1276  }
1277 
1278  PRINTF("RPL: preferred DAG ");
1279  PRINT6ADDR(&instance->current_dag->dag_id);
1280  PRINTF(", rank %u, min_rank %u, ",
1281  instance->current_dag->rank, instance->current_dag->min_rank);
1282  PRINTF("parent rank %u, parent etx %u, link metric %u, instance etx %u\n",
1283  p->rank, -1/*p->mc.obj.etx*/, p->link_metric, instance->mc.obj.etx);
1284 
1285  /* We have allocated a candidate parent; process the DIO further. */
1286 
1287 #if RPL_DAG_MC != RPL_DAG_MC_NONE
1288  memcpy(&p->mc, &dio->mc, sizeof(p->mc));
1289 #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */
1290  if(rpl_process_parent_event(instance, p) == 0) {
1291  PRINTF("RPL: The candidate parent is rejected\n");
1292  return;
1293  }
1294 
1295  /* We don't use route control, so we can have only one official parent. */
1296  if(dag->joined && p == dag->preferred_parent) {
1297  if(should_send_dao(instance, dio, p)) {
1298  RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
1299  rpl_schedule_dao(instance);
1300  }
1301  /* We received a new DIO from our preferred parent.
1302  * Call uip_ds6_defrt_add to set a fresh value for the lifetime counter */
1303  uip_ds6_defrt_add(from, RPL_LIFETIME(instance, instance->default_lifetime));
1304  }
1305  p->dtsn = dio->dtsn;
1306 }
1307 /*---------------------------------------------------------------------------*/
1308 void
1309 rpl_lock_parent(rpl_parent_t *p)
1310 {
1311  nbr_table_lock(rpl_parents, p);
1312 }
1313 /*---------------------------------------------------------------------------*/
1314 #endif /* UIP_CONF_IPV6 */
1315 /** @} */
Linked list manipulation routines.
Neighbor discovery (RFC 4861)
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:115
This header file contains configuration directives for uIPv6 multicast support.
Unicast address structure.
Definition: uip-ds6.h:172
Header file for the uIP TCP/IP stack.
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:535
#define NULL
The null pointer.
802.3 address
Definition: uip.h:135
Header file for the callback timer
A set of debugging macros.
Memory block allocation routines.
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:142
An entry in the nbr cache.
Definition: uip-ds6-nbr.h:70