/* Remove DAG parents with a rank that is at least the same as minimum_rank. */ static void remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank) { rpl_parent_t *p, *p2; PRINTF("RPL: Removing parents (minimum rank %u)\n", minimum_rank); for(p = list_head(dag->parents); p != NULL; p = p2) { p2 = p->next; if(p->rank >= minimum_rank) { rpl_remove_parent(dag, p); } } }
/* Remove DAG parents with a rank that is at least the same as minimum_rank. */ static void remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank) { rpl_parent_t *p; PRINTF("RPL: Removing parents (minimum rank %u)\n", minimum_rank); p = nbr_table_head(rpl_parents); while(p != NULL) { if(dag == p->dag && p->rank >= minimum_rank) { rpl_remove_parent(p); } p = nbr_table_next(rpl_parents, p); } }
/* Remove DAG parents with a rank that is at least the same as minimum_rank. */ static void remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank) { rpl_parent_t *p, *p2; PRINTF("RPL: Removing parents (minimum rank %u)\n", minimum_rank); for(p = list_head(dag->parents); p != NULL; p = p2) { p2 = p->next; if(p->rank >= minimum_rank) { rpl_remove_parent(dag, p); ANNOTATE("#L %u 0\n", p->addr.u8[sizeof(uip_ipaddr_t) - 1]); } } }
/*---------------------------------------------------------------------------*/ static void remove_worst_parent(rpl_dag_t *dag, rpl_rank_t min_worst_rank) { rpl_parent_t *p, *worst; PRINTF("RPL: Removing the worst parent\n"); /* Find the parent with the highest rank. */ worst = NULL; for(p = list_head(dag->parents); p != NULL; p = list_item_next(p)) { if(p != dag->preferred_parent && (worst == NULL || p->rank > worst->rank)) { worst = p; } } /* Remove the neighbor if its rank is worse than the minimum worst rank. */ if(worst != NULL && worst->rank > min_worst_rank) { rpl_remove_parent(dag, worst); } }
/*---------------------------------------------------------------------------*/ 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"); } }
/*---------------------------------------------------------------------------*/ static void nbr_callback(void *ptr) { rpl_remove_parent(ptr); }
/*---------------------------------------------------------------------------*/ rpl_dag_t * 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 NULL; } 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 NULL; } PRINTF("succeeded\n"); } else { p = rpl_find_parent(previous_dag, from); if(p != NULL) { rpl_move_parent(previous_dag, dag, p); } } p->rank = dio->rank; /* 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 NULL; } 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; 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; 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"); } }
/*---------------------------------------------------------------------------*/ 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; }