47 #include "net/rpl/rpl-private.h"
49 #include "net/ipv6/uip-nd6.h"
50 #include "net/nbr-table.h"
59 #define DEBUG DEBUG_NONE
65 static rpl_of_t *
const objective_functions[] = {&RPL_OF};
70 #ifndef RPL_CONF_GROUNDED
71 #define RPL_GROUNDED 0
73 #define RPL_GROUNDED RPL_CONF_GROUNDED
78 NBR_TABLE(rpl_parent_t, rpl_parents);
85 nbr_callback(
void *ptr)
87 rpl_remove_parent(ptr);
93 nbr_table_register(rpl_parents, (nbr_table_callback *)nbr_callback);
99 rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)addr);
110 rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (
const linkaddr_t *)addr);
112 return p->link_metric;
119 rpl_get_parent_ipaddr(rpl_parent_t *p)
121 linkaddr_t *lladdr = nbr_table_get_lladdr(rpl_parents, p);
126 rpl_set_preferred_parent(
rpl_dag_t *dag, rpl_parent_t *p)
128 if(dag !=
NULL && dag->preferred_parent != p) {
129 PRINTF(
"RPL: rpl_set_preferred_parent ");
131 PRINT6ADDR(rpl_get_parent_ipaddr(p));
135 PRINTF(
" used to be ");
136 if(dag->preferred_parent !=
NULL) {
137 PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent));
145 nbr_table_unlock(rpl_parents, dag->preferred_parent);
146 nbr_table_lock(rpl_parents, p);
147 dag->preferred_parent = p;
154 lollipop_greater_than(
int a,
int b)
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;
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));
169 remove_parents(
rpl_dag_t *dag, rpl_rank_t minimum_rank)
173 PRINTF(
"RPL: Removing parents (minimum rank %u)\n",
176 p = nbr_table_head(rpl_parents);
178 if(dag == p->dag && p->rank >= minimum_rank) {
179 rpl_remove_parent(p);
181 p = nbr_table_next(rpl_parents, p);
186 nullify_parents(
rpl_dag_t *dag, rpl_rank_t minimum_rank)
190 PRINTF(
"RPL: Nullifying parents (minimum rank %u)\n",
193 p = nbr_table_head(rpl_parents);
195 if(dag == p->dag && p->rank >= minimum_rank) {
196 rpl_nullify_parent(p);
198 p = nbr_table_next(rpl_parents, p);
206 if(instance->mop == RPL_MOP_NO_DOWNWARD_ROUTES) {
210 return p == instance->current_dag->preferred_parent &&
211 (lollipop_greater_than(dio->dtsn, p->dtsn));
215 acceptable_rank(
rpl_dag_t *dag, rpl_rank_t rank)
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));
223 get_dag(uint8_t instance_id, uip_ipaddr_t *dag_id)
229 instance = rpl_get_instance(instance_id);
230 if(instance ==
NULL) {
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)) {
245 rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id)
251 version = RPL_LOLLIPOP_INIT;
252 dag = get_dag(instance_id, dag_id);
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;
263 dag = rpl_alloc_dag(instance_id, dag_id);
265 PRINTF(
"RPL: Failed to allocate a DAG\n");
269 instance = dag->instance;
271 dag->version = version;
273 dag->grounded = RPL_GROUNDED;
274 instance->mop = RPL_MOP_DEFAULT;
275 instance->of = &RPL_OF;
276 rpl_set_preferred_parent(dag,
NULL);
278 memcpy(&dag->dag_id, dag_id,
sizeof(dag->dag_id));
280 instance->dio_intdoubl = RPL_DIO_INTERVAL_DOUBLINGS;
281 instance->dio_intmin = RPL_DIO_INTERVAL_MIN;
284 instance->dio_intcurrent = RPL_DIO_INTERVAL_MIN +
285 RPL_DIO_INTERVAL_DOUBLINGS;
286 instance->dio_redundancy = RPL_DIO_REDUNDANCY;
287 instance->max_rankinc = RPL_MAX_RANKINC;
288 instance->min_hoprankinc = RPL_MIN_HOPRANKINC;
289 instance->default_lifetime = RPL_DEFAULT_LIFETIME;
290 instance->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT;
292 dag->rank = ROOT_RANK(instance);
294 if(instance->current_dag != dag && instance->current_dag !=
NULL) {
296 rpl_remove_routes(instance->current_dag);
298 instance->current_dag->joined = 0;
301 instance->current_dag = dag;
302 instance->dtsn_out = RPL_LOLLIPOP_INIT;
304 default_instance = instance;
306 PRINTF(
"RPL: Node set to be a DAG root with DAG ID ");
307 PRINT6ADDR(&dag->dag_id);
310 ANNOTATE(
"#A root=%u\n", dag->dag_id.u8[
sizeof(dag->dag_id) - 1]);
312 rpl_reset_dio_timer(instance);
318 rpl_repair_root(uint8_t instance_id)
322 instance = rpl_get_instance(instance_id);
323 if(instance ==
NULL ||
324 instance->current_dag->rank != ROOT_RANK(instance)) {
325 PRINTF(
"RPL: rpl_repair_root triggered but not root\n");
329 RPL_LOLLIPOP_INCREMENT(instance->current_dag->version);
330 RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
331 PRINTF(
"RPL: rpl_repair_root initiating global repair with version %d\n", instance->current_dag->version);
332 rpl_reset_dio_timer(instance);
337 set_ip_from_prefix(uip_ipaddr_t *ipaddr,
rpl_prefix_t *prefix)
339 memset(ipaddr, 0,
sizeof(uip_ipaddr_t));
340 memcpy(ipaddr, &prefix->prefix, (prefix->length + 7) / 8);
350 if(last_prefix !=
NULL && new_prefix !=
NULL &&
351 last_prefix->length == new_prefix->length &&
352 uip_ipaddr_prefixcmp(&last_prefix->prefix, &new_prefix->prefix, new_prefix->length) &&
353 last_prefix->flags == new_prefix->flags) {
358 if(last_prefix !=
NULL) {
359 set_ip_from_prefix(&ipaddr, last_prefix);
360 rep = uip_ds6_addr_lookup(&ipaddr);
362 PRINTF(
"RPL: removing global IP address ");
365 uip_ds6_addr_rm(rep);
369 if(new_prefix !=
NULL) {
370 set_ip_from_prefix(&ipaddr, new_prefix);
371 if(uip_ds6_addr_lookup(&ipaddr) ==
NULL) {
372 PRINTF(
"RPL: adding global IP address ");
375 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
381 rpl_set_prefix(
rpl_dag_t *dag, uip_ipaddr_t *prefix,
unsigned len)
384 uint8_t last_len = dag->prefix_info.length;
389 if(dag->prefix_info.length != 0) {
390 memcpy(&last_prefix, &dag->prefix_info,
sizeof(
rpl_prefix_t));
392 memset(&dag->prefix_info.prefix, 0,
sizeof(dag->prefix_info.prefix));
393 memcpy(&dag->prefix_info.prefix, prefix, (len + 7) / 8);
394 dag->prefix_info.length = len;
395 dag->prefix_info.flags = UIP_ND6_RA_FLAG_AUTONOMOUS;
396 PRINTF(
"RPL: Prefix set - will announce this in DIOs\n");
400 PRINTF(
"rpl_set_prefix - prefix NULL\n");
401 check_prefix(
NULL, &dag->prefix_info);
403 PRINTF(
"rpl_set_prefix - prefix NON-NULL\n");
404 check_prefix(&last_prefix, &dag->prefix_info);
410 rpl_set_default_route(
rpl_instance_t *instance, uip_ipaddr_t *from)
412 if(instance->def_route !=
NULL) {
413 PRINTF(
"RPL: Removing default route through ");
414 PRINT6ADDR(&instance->def_route->ipaddr);
417 instance->def_route =
NULL;
421 PRINTF(
"RPL: Adding default route through ");
425 RPL_LIFETIME(instance,
426 instance->default_lifetime));
427 if(instance->def_route ==
NULL) {
431 PRINTF(
"RPL: Removing default route\n");
432 if(instance->def_route !=
NULL) {
435 PRINTF(
"RPL: Not actually removing default route, since instance had no default route\n");
442 rpl_alloc_instance(uint8_t instance_id)
446 for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES;
447 instance < end; ++instance) {
448 if(instance->used == 0) {
449 memset(instance, 0,
sizeof(*instance));
450 instance->instance_id = instance_id;
451 instance->def_route =
NULL;
460 rpl_alloc_dag(uint8_t instance_id, uip_ipaddr_t *dag_id)
465 instance = rpl_get_instance(instance_id);
466 if(instance ==
NULL) {
467 instance = rpl_alloc_instance(instance_id);
468 if(instance ==
NULL) {
469 RPL_STAT(rpl_stats.mem_overflows++);
474 for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
476 memset(dag, 0,
sizeof(*dag));
478 dag->rank = INFINITE_RANK;
479 dag->min_rank = INFINITE_RANK;
480 dag->instance = instance;
485 RPL_STAT(rpl_stats.mem_overflows++);
486 rpl_free_instance(instance);
493 default_instance = instance;
502 PRINTF(
"RPL: Leaving the instance %u\n", instance->instance_id);
505 for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
511 rpl_set_default_route(instance,
NULL);
516 if(default_instance == instance) {
517 default_instance =
NULL;
527 PRINTF(
"RPL: Leaving the DAG ");
528 PRINT6ADDR(&dag->dag_id);
533 rpl_remove_routes(dag);
536 if((dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) {
537 check_prefix(&dag->prefix_info,
NULL);
540 remove_parents(dag, 0);
548 rpl_parent_t *p =
NULL;
553 PRINTF(
"RPL: rpl_add_parent lladdr %p ", lladdr);
558 p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr);
560 PRINTF(
"RPL: rpl_add_parent p NULL\n");
565 p->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR;
566 #if RPL_DAG_MC != RPL_DAG_MC_NONE
567 memcpy(&p->mc, &dio->mc,
sizeof(p->mc));
575 static rpl_parent_t *
576 find_parent_any_dag_any_instance(uip_ipaddr_t *addr)
580 return nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)lladdr);
584 rpl_find_parent(
rpl_dag_t *dag, uip_ipaddr_t *addr)
586 rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
587 if(p !=
NULL && p->dag == dag) {
597 rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
606 rpl_find_parent_any_dag(
rpl_instance_t *instance, uip_ipaddr_t *addr)
608 rpl_parent_t *p = find_parent_any_dag_any_instance(addr);
609 if(p && p->dag && p->dag->instance == instance) {
619 rpl_parent_t *last_parent;
623 old_rank = instance->current_dag->rank;
624 last_parent = instance->current_dag->preferred_parent;
626 best_dag = instance->current_dag;
627 if(best_dag->rank != ROOT_RANK(instance)) {
628 if(rpl_select_parent(p->dag) !=
NULL) {
629 if(p->dag != best_dag) {
630 best_dag = instance->of->
best_dag(best_dag, p->dag);
632 }
else if(p->dag == best_dag) {
634 for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) {
635 if(dag->used && dag->preferred_parent !=
NULL && dag->preferred_parent->rank != INFINITE_RANK) {
636 if(best_dag ==
NULL) {
639 best_dag = instance->of->
best_dag(best_dag, dag);
646 if(best_dag ==
NULL) {
651 if(instance->current_dag != best_dag) {
653 rpl_remove_routes(instance->current_dag);
655 PRINTF(
"RPL: New preferred DAG: ");
656 PRINT6ADDR(&best_dag->dag_id);
659 if(best_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
660 check_prefix(&instance->current_dag->prefix_info, &best_dag->prefix_info);
661 }
else if(instance->current_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
662 check_prefix(&instance->current_dag->prefix_info,
NULL);
665 best_dag->joined = 1;
666 instance->current_dag->joined = 0;
667 instance->current_dag = best_dag;
672 best_dag->rank = instance->of->
calculate_rank(best_dag->preferred_parent, 0);
673 if(last_parent ==
NULL || best_dag->rank < best_dag->min_rank) {
674 best_dag->min_rank = best_dag->rank;
675 }
else if(!acceptable_rank(best_dag, best_dag->rank)) {
676 PRINTF(
"RPL: New rank unacceptable!\n");
677 rpl_set_preferred_parent(instance->current_dag,
NULL);
678 if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES && last_parent !=
NULL) {
680 dao_output(last_parent, RPL_ZERO_LIFETIME);
685 if(best_dag->preferred_parent != last_parent) {
686 rpl_set_default_route(instance, rpl_get_parent_ipaddr(best_dag->preferred_parent));
687 PRINTF(
"RPL: Changed preferred parent, rank changed from %u to %u\n",
688 (
unsigned)old_rank, best_dag->rank);
689 RPL_STAT(rpl_stats.parent_switch++);
690 if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
691 if(last_parent !=
NULL) {
693 dao_output(last_parent, RPL_ZERO_LIFETIME);
696 RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
697 rpl_schedule_dao(instance);
699 rpl_reset_dio_timer(instance);
700 }
else if(best_dag->rank != old_rank) {
701 PRINTF(
"RPL: Preferred parent update, rank changed from %u to %u\n",
702 (
unsigned)old_rank, best_dag->rank);
707 static rpl_parent_t *
710 rpl_parent_t *p, *best;
714 p = nbr_table_head(rpl_parents);
716 if(p->rank == INFINITE_RANK) {
718 }
else if(best ==
NULL) {
723 p = nbr_table_next(rpl_parents, p);
732 rpl_parent_t *best = best_parent(dag);
735 rpl_set_preferred_parent(dag, best);
742 rpl_remove_parent(rpl_parent_t *parent)
744 PRINTF(
"RPL: Removing parent ");
745 PRINT6ADDR(rpl_get_parent_ipaddr(parent));
748 rpl_nullify_parent(parent);
750 nbr_table_remove(rpl_parents, parent);
754 rpl_nullify_parent(rpl_parent_t *parent)
759 if(parent == dag->preferred_parent || dag->preferred_parent ==
NULL) {
760 rpl_set_preferred_parent(dag,
NULL);
761 dag->rank = INFINITE_RANK;
763 if(dag->instance->def_route !=
NULL) {
764 PRINTF(
"RPL: Removing default route ");
765 PRINT6ADDR(rpl_get_parent_ipaddr(parent));
768 dag->instance->def_route =
NULL;
770 dao_output(parent, RPL_ZERO_LIFETIME);
774 PRINTF(
"RPL: Nullifying parent ");
775 PRINT6ADDR(rpl_get_parent_ipaddr(parent));
782 if(parent == dag_src->preferred_parent) {
783 rpl_set_preferred_parent(dag_src,
NULL);
784 dag_src->rank = INFINITE_RANK;
785 if(dag_src->joined && dag_src->instance->def_route !=
NULL) {
786 PRINTF(
"RPL: Removing default route ");
787 PRINT6ADDR(rpl_get_parent_ipaddr(parent));
789 PRINTF(
"rpl_move_parent\n");
791 dag_src->instance->def_route =
NULL;
793 }
else if(dag_src->joined) {
795 rpl_remove_routes_by_nexthop(rpl_get_parent_ipaddr(parent), dag_src);
798 PRINTF(
"RPL: Moving parent ");
799 PRINT6ADDR(rpl_get_parent_ipaddr(parent));
802 parent->dag = dag_dst;
806 rpl_get_any_dag(
void)
810 for(i = 0; i < RPL_MAX_INSTANCES; ++i) {
811 if(instance_table[i].used && instance_table[i].current_dag->joined) {
812 return instance_table[i].current_dag;
819 rpl_get_instance(uint8_t instance_id)
823 for(i = 0; i < RPL_MAX_INSTANCES; ++i) {
824 if(instance_table[i].used && instance_table[i].instance_id == instance_id) {
825 return &instance_table[i];
832 rpl_find_of(rpl_ocp_t ocp)
837 i <
sizeof(objective_functions) /
sizeof(objective_functions[0]);
839 if(objective_functions[i]->ocp == ocp) {
840 return objective_functions[i];
848 rpl_join_instance(uip_ipaddr_t *from,
rpl_dio_t *dio)
855 dag = rpl_alloc_dag(dio->instance_id, &dio->dag_id);
857 PRINTF(
"RPL: Failed to allocate a DAG object!\n");
861 instance = dag->instance;
863 p = rpl_add_parent(dag, dio, from);
864 PRINTF(
"RPL: Adding ");
866 PRINTF(
" as a parent: ");
873 PRINTF(
"succeeded\n");
877 of = rpl_find_of(dio->ocp);
879 PRINTF(
"RPL: DIO for DAG instance %u does not specify a supported OF\n",
881 rpl_remove_parent(p);
888 if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
889 check_prefix(
NULL, &dio->prefix_info);
893 dag->preference = dio->preference;
894 dag->grounded = dio->grounded;
895 dag->version = dio->version;
898 instance->mop = dio->mop;
899 instance->current_dag = dag;
900 instance->dtsn_out = RPL_LOLLIPOP_INIT;
902 instance->max_rankinc = dio->dag_max_rankinc;
903 instance->min_hoprankinc = dio->dag_min_hoprankinc;
904 instance->dio_intdoubl = dio->dag_intdoubl;
905 instance->dio_intmin = dio->dag_intmin;
906 instance->dio_intcurrent = instance->dio_intmin + instance->dio_intdoubl;
907 instance->dio_redundancy = dio->dag_redund;
908 instance->default_lifetime = dio->default_lifetime;
909 instance->lifetime_unit = dio->lifetime_unit;
911 memcpy(&dag->dag_id, &dio->dag_id,
sizeof(dio->dag_id));
914 memcpy(&dag->prefix_info, &dio->prefix_info,
sizeof(
rpl_prefix_t));
916 rpl_set_preferred_parent(dag, p);
920 dag->min_rank = dag->rank;
922 if(default_instance ==
NULL) {
923 default_instance = instance;
926 PRINTF(
"RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ",
927 dio->instance_id, dag->rank);
928 PRINT6ADDR(&dag->dag_id);
931 ANNOTATE(
"#A join=%u\n", dag->dag_id.u8[
sizeof(dag->dag_id) - 1]);
933 rpl_reset_dio_timer(instance);
934 rpl_set_default_route(instance, from);
936 if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
937 rpl_schedule_dao(instance);
939 PRINTF(
"RPL: The DIO does not meet the prerequisites for sending a DAO\n");
945 rpl_add_dag(uip_ipaddr_t *from,
rpl_dio_t *dio)
952 dag = rpl_alloc_dag(dio->instance_id, &dio->dag_id);
954 PRINTF(
"RPL: Failed to allocate a DAG object!\n");
958 instance = dag->instance;
960 previous_dag = find_parent_dag(instance, from);
961 if(previous_dag ==
NULL) {
962 PRINTF(
"RPL: Adding ");
964 PRINTF(
" as a parent: ");
965 p = rpl_add_parent(dag, dio, from);
971 PRINTF(
"succeeded\n");
973 p = rpl_find_parent(previous_dag, from);
975 rpl_move_parent(previous_dag, dag, p);
981 of = rpl_find_of(dio->ocp);
982 if(of != instance->of ||
983 instance->mop != dio->mop ||
984 instance->max_rankinc != dio->dag_max_rankinc ||
985 instance->min_hoprankinc != dio->dag_min_hoprankinc ||
986 instance->dio_intdoubl != dio->dag_intdoubl ||
987 instance->dio_intmin != dio->dag_intmin ||
988 instance->dio_redundancy != dio->dag_redund ||
989 instance->default_lifetime != dio->default_lifetime ||
990 instance->lifetime_unit != dio->lifetime_unit) {
991 PRINTF(
"RPL: DIO for DAG instance %u incompatible with previous DIO\n",
993 rpl_remove_parent(p);
999 dag->grounded = dio->grounded;
1000 dag->preference = dio->preference;
1001 dag->version = dio->version;
1003 memcpy(&dag->dag_id, &dio->dag_id,
sizeof(dio->dag_id));
1006 memcpy(&dag->prefix_info, &dio->prefix_info,
sizeof(
rpl_prefix_t));
1008 rpl_set_preferred_parent(dag, p);
1010 dag->min_rank = dag->rank;
1012 PRINTF(
"RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ",
1013 dio->instance_id, dag->rank);
1014 PRINT6ADDR(&dag->dag_id);
1017 ANNOTATE(
"#A join=%u\n", dag->dag_id.u8[
sizeof(dag->dag_id) - 1]);
1019 rpl_process_parent_event(instance, p);
1020 p->dtsn = dio->dtsn;
1029 remove_parents(dag, 0);
1030 dag->version = dio->version;
1031 dag->instance->of->
reset(dag);
1032 dag->min_rank = INFINITE_RANK;
1033 RPL_LOLLIPOP_INCREMENT(dag->instance->dtsn_out);
1035 p = rpl_add_parent(dag, dio, from);
1037 PRINTF(
"RPL: Failed to add a parent during the global repair\n");
1038 dag->rank = INFINITE_RANK;
1041 dag->min_rank = dag->rank;
1042 PRINTF(
"RPL: rpl_process_parent_event global repair\n");
1043 rpl_process_parent_event(dag->instance, p);
1046 PRINTF(
"RPL: Participating in a global repair (version=%u, rank=%hu)\n",
1047 dag->version, dag->rank);
1049 RPL_STAT(rpl_stats.global_repairs++);
1057 if(instance ==
NULL) {
1058 PRINTF(
"RPL: local repair requested for instance NULL\n");
1061 PRINTF(
"RPL: Starting a local instance repair\n");
1062 for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; i++) {
1063 if(instance->dag_table[i].used) {
1064 instance->dag_table[i].rank = INFINITE_RANK;
1065 nullify_parents(&instance->dag_table[i], 0);
1069 rpl_reset_dio_timer(instance);
1071 RPL_STAT(rpl_stats.local_repairs++);
1075 rpl_recalculate_ranks(
void)
1084 p = nbr_table_head(rpl_parents);
1086 if(p->dag !=
NULL && p->dag->instance && p->updated) {
1088 PRINTF(
"RPL: rpl_process_parent_event recalculate_ranks\n");
1089 if(!rpl_process_parent_event(p->dag->instance, p)) {
1090 PRINTF(
"RPL: A parent was dropped\n");
1093 p = nbr_table_next(rpl_parents, p);
1098 rpl_process_parent_event(
rpl_instance_t *instance, rpl_parent_t *p)
1103 rpl_rank_t old_rank;
1104 old_rank = instance->current_dag->rank;
1109 if(!acceptable_rank(p->dag, p->rank)) {
1112 PRINTF(
"RPL: Unacceptable rank %u\n", (
unsigned)p->rank);
1113 rpl_nullify_parent(p);
1114 if(p != instance->current_dag->preferred_parent) {
1121 if(rpl_select_dag(instance, p) ==
NULL) {
1123 PRINTF(
"RPL: No parents found in any DAG\n");
1124 rpl_local_repair(instance);
1129 if(DAG_RANK(old_rank, instance) != DAG_RANK(instance->current_dag->rank, instance)) {
1130 PRINTF(
"RPL: Moving in the instance from rank %hu to %hu\n",
1131 DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank, instance));
1132 if(instance->current_dag->rank != INFINITE_RANK) {
1133 PRINTF(
"RPL: The preferred parent is ");
1134 PRINT6ADDR(rpl_get_parent_ipaddr(instance->current_dag->preferred_parent));
1135 PRINTF(
" (rank %u)\n",
1136 (
unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank, instance));
1138 PRINTF(
"RPL: We don't have any parent");
1143 return return_value;
1147 rpl_process_dio(uip_ipaddr_t *from,
rpl_dio_t *dio)
1153 #if RPL_CONF_MULTICAST
1156 if(dio->mop < RPL_MOP_STORING_NO_MULTICAST) {
1158 if(dio->mop != RPL_MOP_DEFAULT) {
1160 PRINTF(
"RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop);
1164 dag = get_dag(dio->instance_id, &dio->dag_id);
1165 instance = rpl_get_instance(dio->instance_id);
1167 if(dag !=
NULL && instance !=
NULL) {
1168 if(lollipop_greater_than(dio->version, dag->version)) {
1169 if(dag->rank == ROOT_RANK(instance)) {
1170 PRINTF(
"RPL: Root received inconsistent DIO version number\n");
1171 dag->version = dio->version;
1172 RPL_LOLLIPOP_INCREMENT(dag->version);
1173 rpl_reset_dio_timer(instance);
1175 PRINTF(
"RPL: Global repair\n");
1176 if(dio->prefix_info.length != 0) {
1177 if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
1178 PRINTF(
"RPL : Prefix announced in DIO\n");
1179 rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length);
1182 global_repair(from, dag, dio);
1187 if(lollipop_greater_than(dag->version, dio->version)) {
1189 PRINTF(
"RPL: old version received => inconsistency detected\n");
1191 rpl_reset_dio_timer(instance);
1197 if(instance ==
NULL) {
1198 PRINTF(
"RPL: New instance detected: Joining...\n");
1199 rpl_join_instance(from, dio);
1203 if(instance->current_dag->rank == ROOT_RANK(instance) && instance->current_dag != dag) {
1204 PRINTF(
"RPL: Root ignored DIO for different DAG\n");
1209 PRINTF(
"RPL: Adding new DAG to known instance.\n");
1210 rpl_add_dag(from, dio);
1215 if(dio->rank < ROOT_RANK(instance)) {
1216 PRINTF(
"RPL: Ignoring DIO with too low rank: %u\n",
1217 (
unsigned)dio->rank);
1219 }
else if(dio->rank == INFINITE_RANK && dag->joined) {
1220 rpl_reset_dio_timer(instance);
1224 if(dio->prefix_info.length != 0) {
1225 if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
1226 PRINTF(
"RPL : Prefix announced in DIO\n");
1227 rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length);
1231 if(dag->rank == ROOT_RANK(instance)) {
1232 if(dio->rank != INFINITE_RANK) {
1233 instance->dio_counter++;
1245 p = rpl_find_parent(dag, from);
1247 previous_dag = find_parent_dag(instance, from);
1248 if(previous_dag ==
NULL) {
1250 p = rpl_add_parent(dag, dio, from);
1252 PRINTF(
"RPL: Failed to add a new parent (");
1257 PRINTF(
"RPL: New candidate parent with rank %u: ", (
unsigned)p->rank);
1261 p = rpl_find_parent(previous_dag, from);
1263 rpl_move_parent(previous_dag, dag, p);
1267 if(p->rank == dio->rank) {
1268 PRINTF(
"RPL: Received consistent DIO\n");
1270 instance->dio_counter++;
1277 PRINTF(
"RPL: preferred DAG ");
1278 PRINT6ADDR(&instance->current_dag->dag_id);
1279 PRINTF(
", rank %u, min_rank %u, ",
1280 instance->current_dag->rank, instance->current_dag->min_rank);
1281 PRINTF(
"parent rank %u, parent etx %u, link metric %u, instance etx %u\n",
1282 p->rank, -1, p->link_metric, instance->mc.obj.etx);
1286 #if RPL_DAG_MC != RPL_DAG_MC_NONE
1287 memcpy(&p->mc, &dio->mc,
sizeof(p->mc));
1289 if(rpl_process_parent_event(instance, p) == 0) {
1290 PRINTF(
"RPL: The candidate parent is rejected\n");
1295 if(dag->joined && p == dag->preferred_parent) {
1296 if(should_send_dao(instance, dio, p)) {
1297 RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
1298 rpl_schedule_dao(instance);
1304 p->dtsn = dio->dtsn;
1308 rpl_lock_parent(rpl_parent_t *p)
1310 nbr_table_lock(rpl_parents, p);