/*---------------------------------------------------------------------------*/ void rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) { rpl_instance_t *instance; rpl_dag_t *dag; rpl_parent_t *p; rpl_of_t *of; int tx;//elnaz dag = rpl_alloc_dag(dio->instance_id, &dio->dag_id); if(dag == NULL) { // PRINTF("RPL: Failed to allocate a DAG object!\n"); return; } instance = dag->instance; p = rpl_add_parent(dag, dio, from); // PRINTF("RPL: Adding "); // PRINT6ADDR(from); // PRINTF(" as a parent: "); if(p == NULL) { // PRINTF("failed\n"); instance->used = 0; return; } p->dtsn = dio->dtsn; // PRINTF("succeeded\n"); /* Determine the objective function by using the objective code point of the DIO. */ of = rpl_find_of(dio->ocp); if(of == NULL) { // PRINTF("RPL: DIO for DAG instance %u does not specify a supported OF\n",dio->instance_id); rpl_remove_parent(p); instance->used = 0; return; } /* Autoconfigure an address if this node does not already have an address with this prefix. */ if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { check_prefix(NULL, &dio->prefix_info); } //-----------------elnaz tx =cc2420_get_txpower(); printf("Power=%d \n",tx); switch(tx) { case 3: dag->Tx = 0.003; break; case 7: dag->Tx = 0.03; break; case 11: dag->Tx = 0.1; break; case 15: dag->Tx = 0.2; break; case 19: dag->Tx = 0.3; break; case 23: dag->Tx = 0.5; break; case 27: dag->Tx = 0.8; break; case 31: dag->Tx = 1; } /* float mv = (bateria * 2.500 * 2) / 4096; printf("Battery: (%ld.%03d mV)\n", (long) mv, (unsigned) ((mv - floor(mv)) * 1000)); */ //printf("Test tx=%ld ",(long) (dag->Tx*1000)); //----------------------elnaz dag->joined = 1; dag->preference = dio->preference; dag->grounded = dio->grounded; dag->version = dio->version; instance->of = of; instance->mop = dio->mop; instance->current_dag = dag; instance->dtsn_out = RPL_LOLLIPOP_INIT; instance->max_rankinc = dio->dag_max_rankinc; instance->min_hoprankinc = dio->dag_min_hoprankinc; instance->dio_intdoubl = dio->dag_intdoubl; instance->dio_intmin = dio->dag_intmin; instance->dio_intcurrent = instance->dio_intmin + instance->dio_intdoubl; instance->dio_redundancy = dio->dag_redund; instance->default_lifetime = dio->default_lifetime; instance->lifetime_unit = dio->lifetime_unit; memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id)); /* Copy prefix information from the DIO into the DAG object. */ memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t)); rpl_set_preferred_parent(dag, p); instance->of->update_metric_container(instance); dag->rank = instance->of->calculate_rank(p, 0); /* So far this is the lowest rank we are aware of. */ dag->min_rank = dag->rank; if(default_instance == NULL) { default_instance = instance; } // PRINTF("RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ", dio->instance_id, dag->rank); // PRINT6ADDR(&dag->dag_id); // PRINTF("\n"); ANNOTATE("#A join=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]); rpl_reset_dio_timer(instance); rpl_set_default_route(instance, from); if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { rpl_schedule_dao(instance); } else { // PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); } }
/*---------------------------------------------------------------------------*/ rpl_dag_t * rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) { rpl_parent_t *last_parent; rpl_dag_t *dag, *end, *best_dag; rpl_rank_t old_rank; old_rank = instance->current_dag->rank; last_parent = instance->current_dag->preferred_parent; best_dag = instance->current_dag; if(best_dag->rank != ROOT_RANK(instance)) { if(rpl_select_parent(p->dag) != NULL) { if(p->dag != best_dag) { best_dag = instance->of->best_dag(best_dag, p->dag); } } else if(p->dag == best_dag) { best_dag = NULL; for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DAG_PER_INSTANCE; dag < end; ++dag) { if(dag->used && dag->preferred_parent != NULL && dag->preferred_parent->rank != INFINITE_RANK) { if(best_dag == NULL) { best_dag = dag; } else { best_dag = instance->of->best_dag(best_dag, dag); } } } } } if(best_dag == NULL) { /* No parent found: the calling function handle this problem. */ return NULL; } if(instance->current_dag != best_dag) { /* Remove routes installed by DAOs. */ rpl_remove_routes(instance->current_dag); // PRINTF("RPL: New preferred DAG: "); // PRINT6ADDR(&best_dag->dag_id); // PRINTF("\n"); if(best_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { check_prefix(&instance->current_dag->prefix_info, &best_dag->prefix_info); } else if(instance->current_dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { check_prefix(&instance->current_dag->prefix_info, NULL); } best_dag->joined = 1; instance->current_dag->joined = 0; instance->current_dag = best_dag; } instance->of->update_metric_container(instance); /* Update the DAG rank. */ best_dag->rank = instance->of->calculate_rank(best_dag->preferred_parent, 0); if(last_parent == NULL || best_dag->rank < best_dag->min_rank) { best_dag->min_rank = best_dag->rank; } else if(!acceptable_rank(best_dag, best_dag->rank)) { // PRINTF("RPL: New rank unacceptable!\n"); rpl_set_preferred_parent(instance->current_dag, NULL); if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES && last_parent != NULL) { /* Send a No-Path DAO to the removed preferred parent. */ dao_output(last_parent, RPL_ZERO_LIFETIME); } return NULL; } if(best_dag->preferred_parent != last_parent) { rpl_set_default_route(instance, rpl_get_parent_ipaddr(best_dag->preferred_parent)); // PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n",(unsigned)old_rank, best_dag->rank); RPL_STAT(rpl_stats.parent_switch++); if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { if(last_parent != NULL) { /* Send a No-Path DAO to the removed preferred parent. */ dao_output(last_parent, RPL_ZERO_LIFETIME); } /* The DAO parent set changed - schedule a DAO transmission. */ RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); rpl_schedule_dao(instance); } rpl_reset_dio_timer(instance); } else if(best_dag->rank != old_rank) { // PRINTF("RPL: Preferred parent update, rank changed from %u to %u\n",(unsigned)old_rank, best_dag->rank); } return best_dag; }
/*---------------------------------------------------------------------------*/ rpl_dag_t * rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) { rpl_dag_t *dag; rpl_instance_t *instance; uint8_t version; version = RPL_LOLLIPOP_INIT; dag = get_dag(instance_id, dag_id); if(dag != NULL) { version = dag->version; RPL_LOLLIPOP_INCREMENT(version); // PRINTF("RPL: Dropping a joined DAG when setting this node as root"); if(dag == dag->instance->current_dag) { dag->instance->current_dag = NULL; } rpl_free_dag(dag); } dag = rpl_alloc_dag(instance_id, dag_id); if(dag == NULL) { // PRINTF("RPL: Failed to allocate a DAG\n"); return NULL; } instance = dag->instance; dag->version = version; dag->joined = 1; dag->grounded = RPL_GROUNDED; instance->mop = RPL_MOP_DEFAULT; instance->of = &RPL_OF; rpl_set_preferred_parent(dag, NULL); memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id)); instance->dio_intdoubl = RPL_DIO_INTERVAL_DOUBLINGS; instance->dio_intmin = RPL_DIO_INTERVAL_MIN; /* The current interval must differ from the minimum interval in order to trigger a DIO timer reset. */ instance->dio_intcurrent = RPL_DIO_INTERVAL_MIN + RPL_DIO_INTERVAL_DOUBLINGS; instance->dio_redundancy = RPL_DIO_REDUNDANCY; instance->max_rankinc = RPL_MAX_RANKINC; instance->min_hoprankinc = RPL_MIN_HOPRANKINC; instance->default_lifetime = RPL_DEFAULT_LIFETIME; instance->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; dag->rank = ROOT_RANK(instance); if(instance->current_dag != dag && instance->current_dag != NULL) { /* Remove routes installed by DAOs. */ rpl_remove_routes(instance->current_dag); instance->current_dag->joined = 0; } instance->current_dag = dag; instance->dtsn_out = RPL_LOLLIPOP_INIT; instance->of->update_metric_container(instance); default_instance = instance; // PRINTF("RPL: Node set to be a DAG root with DAG ID "); // PRINT6ADDR(&dag->dag_id); // PRINTF("\n"); ANNOTATE("#A root=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]); rpl_reset_dio_timer(instance); return dag; }
/*---------------------------------------------------------------------------*/ void rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) { rpl_instance_t *instance; rpl_dag_t *dag; rpl_parent_t *p; rpl_of_t *of; dag = rpl_alloc_dag(dio->instance_id, &dio->dag_id); if(dag == NULL) { PRINTF("RPL: Failed to allocate a DAG object!\n"); return; } instance = dag->instance; p = rpl_add_parent(dag, dio, from); PRINTF("RPL: Adding "); PRINT6ADDR(from); PRINTF(" as a parent: "); if(p == NULL) { PRINTF("failed\n"); instance->used = 0; return; } p->dtsn = dio->dtsn; PRINTF("succeeded\n"); /* Determine the objective function by using the objective code point of the DIO. */ of = rpl_find_of(dio->ocp); if(of == NULL) { PRINTF("RPL: DIO for DAG instance %u does not specify a supported OF\n", dio->instance_id); rpl_remove_parent(p); instance->used = 0; return; } /* Autoconfigure an address if this node does not already have an address with this prefix. */ if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { check_prefix(NULL, &dio->prefix_info); } dag->joined = 1; dag->preference = dio->preference; dag->grounded = dio->grounded; dag->version = dio->version; instance->of = of; instance->mop = dio->mop; instance->current_dag = dag; instance->dtsn_out = RPL_LOLLIPOP_INIT; instance->max_rankinc = dio->dag_max_rankinc; instance->min_hoprankinc = dio->dag_min_hoprankinc; instance->dio_intdoubl = dio->dag_intdoubl; instance->dio_intmin = dio->dag_intmin; instance->dio_intcurrent = instance->dio_intmin + instance->dio_intdoubl; instance->dio_redundancy = dio->dag_redund; instance->default_lifetime = dio->default_lifetime; instance->lifetime_unit = dio->lifetime_unit; memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id)); /* Copy prefix information from the DIO into the DAG object. */ memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t)); rpl_set_preferred_parent(dag, p); instance->of->update_metric_container(instance); dag->rank = instance->of->calculate_rank(p, 0); /* So far this is the lowest rank we are aware of. */ dag->min_rank = dag->rank; if(default_instance == NULL) { default_instance = instance; } PRINTF("RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ", dio->instance_id, dag->rank); PRINT6ADDR(&dag->dag_id); PRINTF("\n"); ANNOTATE("#A join=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]); rpl_reset_dio_timer(instance); rpl_set_default_route(instance, from); if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { rpl_schedule_dao(instance); } else { PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); } }
/*---------------------------------------------------------------------------*/ void rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio) { rpl_instance_t *instance; rpl_dag_t *dag, *previous_dag; rpl_parent_t *p; rpl_of_t *of; dag = rpl_alloc_dag(dio->instance_id, &dio->dag_id); if(dag == NULL) { PRINTF("RPL: Failed to allocate a DAG object!\n"); return; } instance = dag->instance; previous_dag = find_parent_dag(instance, from); if(previous_dag == NULL) { PRINTF("RPL: Adding "); PRINT6ADDR(from); PRINTF(" as a parent: "); p = rpl_add_parent(dag, dio, from); if(p == NULL) { PRINTF("failed\n"); dag->used = 0; return; } PRINTF("succeeded\n"); } else { p = rpl_find_parent(previous_dag, from); if(p != NULL) { rpl_move_parent(previous_dag, dag, p); } } /* Determine the objective function by using the objective code point of the DIO. */ of = rpl_find_of(dio->ocp); if(of != instance->of || instance->mop != dio->mop || instance->max_rankinc != dio->dag_max_rankinc || instance->min_hoprankinc != dio->dag_min_hoprankinc || instance->dio_intdoubl != dio->dag_intdoubl || instance->dio_intmin != dio->dag_intmin || instance->dio_redundancy != dio->dag_redund || instance->default_lifetime != dio->default_lifetime || instance->lifetime_unit != dio->lifetime_unit) { PRINTF("RPL: DIO for DAG instance %u incompatible with previous DIO\n", dio->instance_id); rpl_remove_parent(p); dag->used = 0; return; } dag->used = 1; dag->grounded = dio->grounded; dag->preference = dio->preference; dag->version = dio->version; memcpy(&dag->dag_id, &dio->dag_id, sizeof(dio->dag_id)); /* copy prefix information into the dag */ memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t)); rpl_set_preferred_parent(dag, p); dag->rank = instance->of->calculate_rank(p, 0); dag->min_rank = dag->rank; /* So far this is the lowest rank we know of. */ PRINTF("RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ", dio->instance_id, dag->rank); PRINT6ADDR(&dag->dag_id); PRINTF("\n"); ANNOTATE("#A join=%u\n", dag->dag_id.u8[sizeof(dag->dag_id) - 1]); rpl_process_parent_event(instance, p); p->dtsn = dio->dtsn; }
/*---------------------------------------------------------------------------*/ void rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio, int mobility) { rpl_instance_t *instance; rpl_dag_t *dag, *previous_dag; rpl_parent_t *p, *previous_preferred; uint32_t current_t; PRINTF("processing DIO from %u\n", from->u8[15]); if(dio->mop != RPL_MOP_DEFAULT) { PRINTF("RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop); return; } dag = get_dag(dio->instance_id, &dio->dag_id); instance = rpl_get_instance(dio->instance_id); previous_preferred = dag->preferred_parent; if(dag != NULL && instance != NULL) { if(lollipop_greater_than(dio->version, dag->version)) { if(dag->rank == ROOT_RANK(instance)) { PRINTF("RPL: Root received inconsistent DIO version number\n"); dag->version = dio->version; RPL_LOLLIPOP_INCREMENT(dag->version); rpl_reset_dio_timer(instance); } else { PRINTF("RPL: Global Repair\n"); if(dio->prefix_info.length != 0) { if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { PRINTF("RPL : Prefix announced in DIO\n"); rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length); } } global_repair(from, dag, dio); } return; } if(lollipop_greater_than(dag->version, dio->version)) { /* The DIO sender is on an older version of the DAG. */ PRINTF("RPL: old version received => inconsistency detected\n"); if(dag->joined) { rpl_reset_dio_timer(instance); return; } } } if(instance == NULL) { PRINTF("RPL: New instance detected: Joining...\n"); rpl_join_instance(from, dio); return; } if(instance->current_dag->rank == ROOT_RANK(instance) && instance->current_dag != dag) { PRINTF("RPL: Root ignored DIO for different DAG\n"); return; } if(dag == NULL) { PRINTF("RPL: Adding new DAG to known instance.\n"); rpl_add_dag(from, dio); return; } if(dio->rank < ROOT_RANK(instance)) { PRINTF("RPL: Ignoring DIO with too low rank: %u\n", (unsigned)dio->rank); return; } else if(dio->rank == INFINITE_RANK && dag->joined) { rpl_reset_dio_timer(instance); } /* Prefix Information Option treated to add new prefix */ if(dio->prefix_info.length != 0) { if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { PRINTF("RPL : Prefix announced in DIO\n"); rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length); } } if(dag->rank == ROOT_RANK(instance)) { if(dio->rank != INFINITE_RANK) { instance->dio_counter++; } return; } /* * At this point, we know that this DIO pertains to a DAG that * we are already part of. We consider the sender of the DIO to be * a candidate parent, and let rpl_process_parent_event decide * whether to keep it in the set. */ p = rpl_find_parent(dag, from); if(p == NULL) { previous_dag = find_parent_dag(instance, from); if(previous_dag == NULL) { /* Add the DIO sender as a candidate parent. */ p = rpl_add_parent(dag, dio, from); if(p == NULL) { PRINTF("RPL: Failed to add a new parent ("); PRINT6ADDR(from); PRINTF(")\n"); return; } PRINTF("RPL: New candidate parent with rank %u: ", (unsigned)p->rank); PRINT6ADDR(from); PRINTF("\n"); } else { p = rpl_find_parent(previous_dag, from); if(p != NULL) { rpl_move_parent(previous_dag, dag, p); } } } else { if(p->rank == dio->rank) { PRINTF("RPL: Received consistent DIO\n"); if(dag->joined) { instance->dio_counter++; } } else { p->rank = dio->rank; } } PRINTF("RPL: preferred DAG "); PRINT6ADDR(&instance->current_dag->dag_id); PRINTF(", rank %u, min_rank %u, ", instance->current_dag->rank, instance->current_dag->min_rank); PRINTF("parent rank %u, parent etx %u, link metric %u, instance etx %u\n", p->rank, -1 /*p->mc.obj.etx */, p->link_metric, instance->mc.obj.etx); /* * If the DIO being processed came from smart-HOP decision, change default route, * schedule DAO and finish the mobility process. */ if(mobility) { rpl_remove_parent(previous_preferred); rpl_set_preferred_parent(dag, p); RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); /*dao_output(p, 255);*/ /* We received a new DIO from our preferred parent. * Call uip_ds6_defrt_add to set a fresh value for the lifetime counter */ PRINTF("adding default route\n"); current_t = clock_time() * 1000 / CLOCK_SECOND; printf("End %u\n", current_t); rpl_set_default_route(instance, from); rpl_schedule_dao(instance); /*check_dao_ack = 1;*/ process_post(&tcpip_process, RESET_MOBILITY_FLAG, NULL); return; } if(mobility == 0) { #if RPL_DAG_MC != RPL_DAG_MC_NONE memcpy(&p->mc, &dio->mc, sizeof(p->mc)); #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ if(rpl_process_parent_event(instance, p) == 0) { PRINTF("RPL: The candidate parent is rejected\n"); return; } } /* We don't use route control, so we can have only one official parent. */ if(dag->joined && p == dag->preferred_parent) { if(should_send_dao(instance, dio, p)) { RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); rpl_schedule_dao(instance); } /* We received a new DIO from our preferred parent. * Call uip_ds6_defrt_add to set a fresh value for the lifetime counter */ uip_ds6_defrt_add(from, RPL_LIFETIME(instance, instance->default_lifetime)); } p->dtsn = dio->dtsn; }