00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include "contiki.h"
00045 #include "net/rpl/rpl-private.h"
00046 #include "net/uip.h"
00047 #include "net/uip-nd6.h"
00048 #include "lib/list.h"
00049 #include "lib/memb.h"
00050 #include "sys/ctimer.h"
00051
00052 #include <limits.h>
00053 #include <string.h>
00054
00055 #define DEBUG DEBUG_NONE
00056 #include "net/uip-debug.h"
00057
00058 #include "net/neighbor-info.h"
00059
00060
00061 extern rpl_of_t RPL_OF;
00062 static rpl_of_t * const objective_functions[] = {&RPL_OF};
00063
00064
00065 #ifndef RPL_CONF_MAX_DAG_ENTRIES
00066 #define RPL_MAX_DAG_ENTRIES 2
00067 #else
00068 #define RPL_MAX_DAG_ENTRIES RPL_CONF_MAX_DAG_ENTRIES
00069 #endif
00070
00071 #ifndef RPL_CONF_MAX_PARENTS
00072 #define RPL_MAX_PARENTS 8
00073 #else
00074 #define RPL_MAX_PARENTS RPL_CONF_MAX_PARENTS
00075 #endif
00076
00077
00078
00079 #ifndef RPL_CONF_GROUNDED
00080 #define RPL_GROUNDED 0
00081 #else
00082 #define RPL_GROUNDED RPL_CONF_GROUNDED
00083 #endif
00084
00085 #ifndef RPL_CONF_DIO_INTERVAL_MIN
00086 #define RPL_DIO_INTERVAL_MIN DEFAULT_DIO_INTERVAL_MIN
00087 #else
00088 #define RPL_DIO_INTERVAL_MIN RPL_CONF_DIO_INTERVAL_MIN
00089 #endif
00090
00091 #ifndef RPL_CONF_DIO_INTERVAL_DOUBLINGS
00092 #define RPL_DIO_INTERVAL_DOUBLINGS DEFAULT_DIO_INTERVAL_DOUBLINGS
00093 #else
00094 #define RPL_DIO_INTERVAL_DOUBLINGS RPL_CONF_DIO_INTERVAL_DOUBLINGS
00095 #endif
00096
00097
00098
00099 MEMB(parent_memb, struct rpl_parent, RPL_MAX_PARENTS);
00100
00101 static rpl_dag_t dag_table[RPL_MAX_DAG_ENTRIES];
00102
00103
00104 static void
00105 remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank)
00106 {
00107 rpl_parent_t *p, *p2;
00108
00109 PRINTF("RPL: Removing parents (minimum rank %u)\n",
00110 minimum_rank);
00111
00112 for(p = list_head(dag->parents); p != NULL; p = p2) {
00113 p2 = p->next;
00114 if(p->rank >= minimum_rank) {
00115 rpl_remove_parent(dag, p);
00116 }
00117 }
00118 }
00119
00120 static void
00121 remove_worst_parent(rpl_dag_t *dag, rpl_rank_t min_worst_rank)
00122 {
00123 rpl_parent_t *p, *worst;
00124
00125 PRINTF("RPL: Removing the worst parent\n");
00126
00127
00128 worst = NULL;
00129 for(p = list_head(dag->parents); p != NULL; p = list_item_next(p)) {
00130 if(p != dag->preferred_parent &&
00131 (worst == NULL || p->rank > worst->rank)) {
00132 worst = p;
00133 }
00134 }
00135
00136
00137 if(worst != NULL && worst->rank > min_worst_rank) {
00138 rpl_remove_parent(dag, worst);
00139 }
00140 }
00141
00142 static int
00143 should_send_dao(rpl_dag_t *dag, rpl_dio_t *dio, rpl_parent_t *p)
00144 {
00145
00146 if(dag->mop == RPL_MOP_NO_DOWNWARD_ROUTES) return 0;
00147 return dio->dtsn > p->dtsn && p == dag->preferred_parent;
00148 }
00149
00150 static int
00151 acceptable_rank(rpl_dag_t *dag, rpl_rank_t rank)
00152 {
00153 return rank != INFINITE_RANK &&
00154 (dag->max_rankinc == 0 ||
00155 DAG_RANK(rank, dag) <= DAG_RANK(dag->min_rank + dag->max_rankinc, dag));
00156 }
00157
00158 rpl_dag_t *
00159 rpl_set_root(uip_ipaddr_t *dag_id)
00160 {
00161 rpl_dag_t *dag;
00162 int version;
00163
00164 version = -1;
00165 dag = rpl_get_dag(RPL_DEFAULT_INSTANCE);
00166 if(dag != NULL) {
00167 PRINTF("RPL: Dropping a joined DAG when setting this node as root");
00168 version = dag->version;
00169 rpl_free_dag(dag);
00170 }
00171
00172 dag = rpl_alloc_dag(RPL_DEFAULT_INSTANCE);
00173 if(dag == NULL) {
00174 PRINTF("RPL: Failed to allocate a DAG\n");
00175 return NULL;
00176 }
00177
00178 dag->joined = 1;
00179 dag->version = version + 1;
00180 dag->grounded = RPL_GROUNDED;
00181 dag->mop = RPL_MOP_DEFAULT;
00182 dag->of = &RPL_OF;
00183 dag->preferred_parent = NULL;
00184 dag->dtsn_out = 1;
00185
00186 memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id));
00187
00188 dag->dio_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS;
00189 dag->dio_intmin = DEFAULT_DIO_INTERVAL_MIN;
00190 dag->dio_redundancy = DEFAULT_DIO_REDUNDANCY;
00191 dag->max_rankinc = DEFAULT_MAX_RANKINC;
00192 dag->min_hoprankinc = DEFAULT_MIN_HOPRANKINC;
00193
00194 dag->default_lifetime = DEFAULT_RPL_DEF_LIFETIME;
00195 dag->lifetime_unit = DEFAULT_RPL_LIFETIME_UNIT;
00196
00197 dag->rank = ROOT_RANK(dag);
00198
00199 dag->of->update_metric_container(dag);
00200
00201 PRINTF("RPL: Node set to be a DAG root with DAG ID ");
00202 PRINT6ADDR(&dag->dag_id);
00203 PRINTF("\n");
00204
00205 ANNOTATE("#A root=%u\n",dag->dag_id.u8[sizeof(dag->dag_id) - 1]);
00206
00207
00208 rpl_reset_dio_timer(dag, 1);
00209
00210 return dag;
00211 }
00212
00213 int
00214 rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len)
00215 {
00216 if(len <= 128) {
00217 memset(&dag->prefix_info.prefix, 0, 16);
00218 memcpy(&dag->prefix_info.prefix, prefix, (len + 7) / 8);
00219 dag->prefix_info.length = len;
00220 dag->prefix_info.flags = UIP_ND6_RA_FLAG_AUTONOMOUS;
00221 PRINTF("RPL: Prefix set - will announce this in DIOs\n");
00222 return 1;
00223 }
00224 return 0;
00225 }
00226
00227 int
00228 rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from)
00229 {
00230 if(dag->def_route != NULL) {
00231 PRINTF("RPL: Removing default route through ");
00232 PRINT6ADDR(&dag->def_route->ipaddr);
00233 PRINTF("\n");
00234 uip_ds6_defrt_rm(dag->def_route);
00235 }
00236
00237 if(from != NULL) {
00238 PRINTF("RPL: Adding default route through ");
00239 PRINT6ADDR(from);
00240 PRINTF("\n");
00241 if(DEFAULT_ROUTE_LIFETIME == INFINITE_LIFETIME) {
00242 dag->def_route = uip_ds6_defrt_add(from, 0);
00243 } else {
00244 dag->def_route = uip_ds6_defrt_add(from, DEFAULT_ROUTE_LIFETIME);
00245 }
00246 if(dag->def_route == NULL) {
00247 return 0;
00248 }
00249 }
00250
00251 return 1;
00252 }
00253
00254 rpl_dag_t *
00255 rpl_alloc_dag(uint8_t instance_id)
00256 {
00257 rpl_dag_t *dag;
00258 rpl_dag_t *end;
00259
00260 for(dag = &dag_table[0], end = dag + RPL_MAX_DAG_ENTRIES; dag < end; dag++) {
00261 if(dag->used == 0) {
00262 memset(dag, 0, sizeof(*dag));
00263 dag->parents = &dag->parent_list;
00264 list_init(dag->parents);
00265 dag->instance_id = instance_id;
00266 dag->def_route = NULL;
00267 dag->rank = INFINITE_RANK;
00268 dag->min_rank = INFINITE_RANK;
00269 return dag;
00270 }
00271 }
00272
00273 RPL_STAT(rpl_stats.mem_overflows++);
00274 return NULL;
00275 }
00276
00277 void
00278 rpl_free_dag(rpl_dag_t *dag)
00279 {
00280 PRINTF("RPL: Leaving the DAG ");
00281 PRINT6ADDR(&dag->dag_id);
00282 PRINTF("\n");
00283
00284
00285 rpl_remove_routes(dag);
00286
00287
00288 remove_parents(dag, 0);
00289 rpl_set_default_route(dag, NULL);
00290
00291 ctimer_stop(&dag->dio_timer);
00292 ctimer_stop(&dag->dao_timer);
00293
00294 dag->used = 0;
00295 dag->joined = 0;
00296 }
00297
00298 rpl_parent_t *
00299 rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr)
00300 {
00301 rpl_parent_t *p;
00302
00303 p = memb_alloc(&parent_memb);
00304 if(p == NULL) {
00305 RPL_STAT(rpl_stats.mem_overflows++);
00306 return NULL;
00307 }
00308
00309 memcpy(&p->addr, addr, sizeof(p->addr));
00310 p->dag = dag;
00311 p->rank = dio->rank;
00312 p->link_metric = INITIAL_LINK_METRIC;
00313 p->dtsn = 0;
00314
00315 memcpy(&p->mc, &dio->mc, sizeof(p->mc));
00316
00317 list_add(dag->parents, p);
00318
00319 return p;
00320 }
00321
00322 rpl_parent_t *
00323 rpl_find_parent(rpl_dag_t *dag, uip_ipaddr_t *addr)
00324 {
00325 rpl_parent_t *p;
00326
00327 for(p = list_head(dag->parents); p != NULL; p = p->next) {
00328 if(uip_ipaddr_cmp(&p->addr, addr)) {
00329 return p;
00330 }
00331 }
00332
00333 return NULL;
00334 }
00335
00336
00337 rpl_parent_t *
00338 rpl_select_parent(rpl_dag_t *dag)
00339 {
00340 rpl_parent_t *p;
00341 rpl_parent_t *best;
00342
00343 best = NULL;
00344 for(p = list_head(dag->parents); p != NULL; p = p->next) {
00345 if(p->rank == INFINITE_RANK) {
00346
00347 } else if(best == NULL) {
00348 best = p;
00349 } else {
00350 best = dag->of->best_parent(best, p);
00351 }
00352 }
00353
00354 if(best == NULL) {
00355
00356 return NULL;
00357 }
00358
00359 if(dag->preferred_parent != best) {
00360 dag->preferred_parent = best;
00361 dag->of->update_metric_container(dag);
00362 rpl_set_default_route(dag, &best->addr);
00363
00364 if(dag->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
00365 rpl_schedule_dao(dag);
00366 }
00367 rpl_reset_dio_timer(dag, 1);
00368 PRINTF("RPL: New preferred parent, rank changed from %u to %u\n",
00369 (unsigned)dag->rank, dag->of->calculate_rank(best, 0));
00370 RPL_STAT(rpl_stats.parent_switch++);
00371 }
00372
00373
00374
00375 dag->rank = dag->of->calculate_rank(best, 0);
00376 if(dag->rank < dag->min_rank) {
00377 dag->min_rank = dag->rank;
00378 } else if(!acceptable_rank(dag, best->rank)) {
00379
00380 dao_output(p, ZERO_LIFETIME);
00381
00382 remove_parents(dag, 0);
00383 return NULL;
00384 }
00385
00386 return best;
00387 }
00388
00389 int
00390 rpl_remove_parent(rpl_dag_t *dag, rpl_parent_t *parent)
00391 {
00392 uip_ds6_defrt_t *defrt;
00393
00394
00395 uip_ds6_route_rm_by_nexthop(&parent->addr);
00396 defrt = uip_ds6_defrt_lookup(&parent->addr);
00397 if(defrt != NULL) {
00398 PRINTF("RPL: Removing default route ");
00399 PRINT6ADDR(&parent->addr);
00400 PRINTF("\n");
00401 uip_ds6_defrt_rm(defrt);
00402 dag->def_route = NULL;
00403 }
00404
00405 PRINTF("RPL: Removing parent ");
00406 PRINT6ADDR(&parent->addr);
00407 PRINTF("\n");
00408
00409 if(parent == dag->preferred_parent) {
00410 dag->preferred_parent = NULL;
00411 }
00412
00413 list_remove(dag->parents, parent);
00414 memb_free(&parent_memb, parent);
00415 return 0;
00416 }
00417
00418 rpl_dag_t *
00419 rpl_get_dag(int instance_id)
00420 {
00421 int i;
00422
00423 for(i = 0; i < RPL_MAX_DAG_ENTRIES; i++) {
00424 if(dag_table[i].joined && (instance_id == RPL_ANY_INSTANCE ||
00425 dag_table[i].instance_id == instance_id)) {
00426 return &dag_table[i];
00427 }
00428 }
00429 return NULL;
00430 }
00431
00432 rpl_of_t *
00433 rpl_find_of(rpl_ocp_t ocp)
00434 {
00435 unsigned int i;
00436
00437 for(i = 0;
00438 i < sizeof(objective_functions) / sizeof(objective_functions[0]);
00439 i++) {
00440 if(objective_functions[i]->ocp == ocp) {
00441 return objective_functions[i];
00442 }
00443 }
00444
00445 return NULL;
00446 }
00447
00448 static void
00449 join_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
00450 {
00451 rpl_dag_t *dag;
00452 rpl_parent_t *p;
00453 rpl_of_t *of;
00454
00455 dag = rpl_alloc_dag(dio->instance_id);
00456 if(dag == NULL) {
00457 PRINTF("RPL: Failed to allocate a DAG object!\n");
00458 return;
00459 }
00460
00461 p = rpl_add_parent(dag, dio, from);
00462 PRINTF("RPL: Adding ");
00463 PRINT6ADDR(from);
00464 PRINTF(" as a parent: ");
00465 if(p == NULL) {
00466 PRINTF("failed\n");
00467 return;
00468 }
00469 PRINTF("succeeded\n");
00470
00471
00472
00473 of = rpl_find_of(dio->ocp);
00474 if(of == NULL) {
00475 PRINTF("RPL: DIO for DAG instance %u does not specify a supported OF\n",
00476 dio->instance_id);
00477 return;
00478 }
00479
00480
00481
00482 if((dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) {
00483 uip_ipaddr_t ipaddr;
00484
00485 memcpy(&ipaddr, &dio->prefix_info.prefix, 16);
00486 uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
00487 if(uip_ds6_addr_lookup(&ipaddr) == NULL) {
00488 PRINTF("RPL: adding global IP address ");
00489 PRINT6ADDR(&ipaddr);
00490 PRINTF("\n");
00491 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
00492 }
00493 }
00494
00495 dag->joined = 1;
00496 dag->used = 1;
00497 dag->of = of;
00498 dag->grounded = dio->grounded;
00499 dag->mop = dio->mop;
00500 dag->preference = dio->preference;
00501 dag->instance_id = dio->instance_id;
00502
00503 dag->max_rankinc = dio->dag_max_rankinc;
00504 dag->min_hoprankinc = dio->dag_min_hoprankinc;
00505
00506 dag->version = dio->version;
00507 dag->preferred_parent = p;
00508 dag->of->update_metric_container(dag);
00509
00510 dag->dio_intdoubl = dio->dag_intdoubl;
00511 dag->dio_intmin = dio->dag_intmin;
00512 dag->dio_redundancy = dio->dag_redund;
00513
00514 memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id));
00515
00516
00517 memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t));
00518
00519 dag->rank = dag->of->calculate_rank(p, dio->rank);
00520 dag->min_rank = dag->rank;
00521
00522 PRINTF("RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ",
00523 dio->instance_id, dag->rank);
00524 PRINT6ADDR(&dag->dag_id);
00525 PRINTF("\n");
00526
00527 ANNOTATE("#A join=%u\n",dag->dag_id.u8[sizeof(dag->dag_id) - 1]);
00528
00529
00530 dag->default_lifetime = dio->default_lifetime;
00531 dag->lifetime_unit = dio->lifetime_unit;
00532
00533 rpl_reset_dio_timer(dag, 1);
00534 rpl_set_default_route(dag, from);
00535
00536 if(should_send_dao(dag, dio, p)) {
00537 rpl_schedule_dao(dag);
00538 } else {
00539 PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n");
00540 }
00541 }
00542
00543 static void
00544 global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio)
00545 {
00546 rpl_parent_t *p;
00547
00548 remove_parents(dag, 0);
00549 dag->version = dio->version;
00550 dag->dtsn_out = 1;
00551 dag->of->reset(dag);
00552 if((p = rpl_add_parent(dag, dio, from)) == NULL) {
00553 PRINTF("RPL: Failed to add a parent during the global repair\n");
00554 dag->rank = INFINITE_RANK;
00555 } else {
00556 rpl_set_default_route(dag, from);
00557 dag->rank = dag->of->calculate_rank(NULL, dio->rank);
00558 dag->min_rank = dag->rank;
00559 rpl_reset_dio_timer(dag, 1);
00560 if(should_send_dao(dag, dio, p)) {
00561 rpl_schedule_dao(dag);
00562 }
00563 }
00564 PRINTF("RPL: Participating in a global repair (version=%u, rank=%hu)\n",
00565 dag->version, dag->rank);
00566
00567 RPL_STAT(rpl_stats.global_repairs++);
00568 }
00569
00570 int
00571 rpl_repair_dag(rpl_dag_t *dag)
00572 {
00573 if(dag->rank == ROOT_RANK(dag)) {
00574 dag->version++;
00575 dag->dtsn_out = 1;
00576 rpl_reset_dio_timer(dag, 1);
00577 return 1;
00578 }
00579 return 0;
00580 }
00581
00582 void
00583 rpl_local_repair(rpl_dag_t *dag)
00584 {
00585 PRINTF("RPL: Starting a local DAG repair\n");
00586
00587 dag->rank = INFINITE_RANK;
00588 remove_parents(dag, 0);
00589 rpl_reset_dio_timer(dag, 1);
00590
00591 RPL_STAT(rpl_stats.local_repairs++);
00592 }
00593
00594 void
00595 rpl_recalculate_ranks(void)
00596 {
00597 rpl_dag_t *dag;
00598 rpl_parent_t *p;
00599
00600
00601
00602
00603
00604
00605 dag = rpl_get_dag(RPL_ANY_INSTANCE);
00606 if(dag != NULL) {
00607 for(p = list_head(dag->parents); p != NULL; p = p->next) {
00608 if(p->updated) {
00609 p->updated = 0;
00610 rpl_process_parent_event(dag, p);
00611
00612
00613
00614
00615
00616 break;
00617 }
00618 }
00619 }
00620 }
00621
00622 int
00623 rpl_process_parent_event(rpl_dag_t *dag, rpl_parent_t *p)
00624 {
00625 rpl_rank_t parent_rank;
00626 rpl_rank_t old_rank;
00627
00628
00629 parent_rank = p->rank;
00630 old_rank = dag->rank;
00631
00632 if(rpl_select_parent(dag) == NULL) {
00633
00634 PRINTF("RPL: No parents found in a DAG\n");
00635 rpl_local_repair(dag);
00636 return 1;
00637 }
00638
00639 if(DAG_RANK(old_rank, dag) != DAG_RANK(dag->rank, dag)) {
00640 if(dag->rank < dag->min_rank) {
00641 dag->min_rank = dag->rank;
00642 }
00643 PRINTF("RPL: Moving in the DAG from rank %hu to %hu\n",
00644 DAG_RANK(old_rank, dag), DAG_RANK(dag->rank, dag));
00645 PRINTF("RPL: The preferred parent is ");
00646 PRINT6ADDR(&dag->preferred_parent->addr);
00647 PRINTF(" (rank %u)\n",
00648 (unsigned)DAG_RANK(dag->preferred_parent->rank, dag));
00649 rpl_reset_dio_timer(dag, 1);
00650 }
00651
00652 if(parent_rank == INFINITE_RANK ||
00653 !acceptable_rank(dag, dag->of->calculate_rank(NULL, parent_rank))) {
00654
00655
00656 return 0;
00657 }
00658
00659 return 1;
00660 }
00661
00662 void
00663 rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
00664 {
00665 rpl_dag_t *dag;
00666 rpl_parent_t *p;
00667
00668 if(dio->mop != RPL_MOP_DEFAULT) {
00669 PRINTF("RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop);
00670 return;
00671 }
00672
00673 dag = rpl_get_dag(dio->instance_id);
00674 if(dag == NULL) {
00675
00676 if(dio->rank != INFINITE_RANK) {
00677 join_dag(from, dio);
00678 } else {
00679 PRINTF("RPL: Ignoring DIO from node with infinite rank: ");
00680 PRINT6ADDR(from);
00681 PRINTF("\n");
00682 }
00683 return;
00684 }
00685
00686 if(memcmp(&dag->dag_id, &dio->dag_id, sizeof(dag->dag_id))) {
00687 PRINTF("RPL: Ignoring DIO for another DAG within our instance\n");
00688 return;
00689 }
00690
00691 if(dio->version > dag->version) {
00692 if(dag->rank == ROOT_RANK(dag)) {
00693 PRINTF("RPL: Root received inconsistent DIO version number\n");
00694 dag->version = dio->version + 1;
00695 rpl_reset_dio_timer(dag, 1);
00696 } else {
00697 global_repair(from, dag, dio);
00698 }
00699 return;
00700 } else if(dio->version < dag->version) {
00701
00702 PRINTF("RPL: old version received => inconsistency detected\n");
00703 rpl_reset_dio_timer(dag, 1);
00704 return;
00705 }
00706
00707 if(dio->rank == INFINITE_RANK) {
00708 rpl_reset_dio_timer(dag, 1);
00709 } else if(dio->rank < ROOT_RANK(dag)) {
00710 PRINTF("RPL: Ignoring DIO with too low rank: %u\n",
00711 (unsigned)dio->rank);
00712 return;
00713 }
00714
00715 if(dag->rank == ROOT_RANK(dag)) {
00716 if(dio->rank != INFINITE_RANK) {
00717 dag->dio_counter++;
00718 }
00719 return;
00720 }
00721
00722
00723
00724
00725
00726
00727
00728
00729 p = rpl_find_parent(dag, from);
00730 if(p == NULL) {
00731 if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS) {
00732
00733 remove_worst_parent(dag, dio->rank);
00734 }
00735
00736
00737 p = rpl_add_parent(dag, dio, from);
00738 if(p == NULL) {
00739 PRINTF("RPL: Failed to add a new parent (");
00740 PRINT6ADDR(from);
00741 PRINTF(")\n");
00742 return;
00743 }
00744
00745 PRINTF("RPL: New candidate parent with rank %u: ", (unsigned)p->rank);
00746 PRINT6ADDR(from);
00747 PRINTF("\n");
00748 } else if(DAG_RANK(p->rank, dag) == DAG_RANK(dio->rank, dag)) {
00749 PRINTF("RPL: Received consistent DIO\n");
00750 dag->dio_counter++;
00751 }
00752
00753
00754
00755 memcpy(&p->mc, &dio->mc, sizeof(p->mc));
00756 p->rank = dio->rank;
00757 if(rpl_process_parent_event(dag, p) == 0) {
00758
00759 return;
00760 }
00761
00762 if(should_send_dao(dag, dio, p)) {
00763 rpl_schedule_dao(dag);
00764 }
00765
00766 p->dtsn = dio->dtsn;
00767 }
00768
00769
00770