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);