/*---------------------------------------------------------------------------*/ static void new_dio_interval(rpl_instance_t *instance) { uint32_t time; clock_time_t ticks; /* TODO: too small timer intervals for many cases */ time = 1UL << instance->dio_intcurrent; /* Convert from milliseconds to CLOCK_TICKS. */ ticks = (time * CLOCK_SECOND) / 1000; instance->dio_next_delay = ticks; /* random number between I/2 and I */ ticks = ticks / 2 + (ticks / 2 * (uint32_t)random_rand()) / RANDOM_RAND_MAX; /* * The intervals must be equally long among the nodes for Trickle to * operate efficiently. Therefore we need to calculate the delay between * the randomized time and the start time of the next interval. */ instance->dio_next_delay -= ticks; instance->dio_send = 1; #if RPL_CONF_STATS /* keep some stats */ instance->dio_totint++; instance->dio_totrecv += instance->dio_counter; ANNOTATE("#A rank=%u.%u(%u),stats=%d %d %d %d,color=%s\n", DAG_RANK(instance->current_dag->rank, instance), (10 * (instance->current_dag->rank % instance->min_hoprankinc)) / instance->min_hoprankinc, instance->current_dag->version, instance->dio_totint, instance->dio_totsend, instance->dio_totrecv,instance->dio_intcurrent, instance->current_dag->rank == ROOT_RANK(instance) ? "BLUE" : "ORANGE"); #endif /* RPL_CONF_STATS */ /* reset the redundancy counter */ instance->dio_counter = 0; /* schedule the timer */ PRINTF("RPL: Scheduling DIO timer %lu ticks in future (Interval)\n", ticks); ctimer_set(&instance->dio_timer, ticks, &handle_dio_timer, instance); }
void rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) { rpl_dag_t *dag; rpl_parent_t *p; if(dio->mop != RPL_MOP_DEFAULT) { PRINTF("RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop); return; } // LVD 24/03/2011 instanceID = dio->instance_id; dag = rpl_get_dag(dio->instance_id); if(dag == NULL) { /* Join the first possible DAG of this RPL instance. */ if(dio->rank != INFINITE_RANK) { join_dag(from, dio); } else { PRINTF("RPL: Ignoring DIO from node with infinite rank: "); PRINT6ADDR(from); PRINTF("\n"); } return; } if(memcmp(&dag->dag_id, &dio->dag_id, sizeof(dag->dag_id))) { PRINTF("RPL: Ignoring DIO for another DAG within our instance\n"); return; } if(dio->version > dag->version) { if(dag->rank == ROOT_RANK(dag)) { PRINTF("RPL: Root received inconsistent DIO version number\n"); dag->version = dio->version + 1; rpl_reset_dio_timer(dag, 1); } else { global_repair(from, dag, dio); } return; } else if(dio->version < dag->version) { /* Inconsistency detected - someone is still on old version */ PRINTF("RPL: old version received => inconsistency detected\n"); rpl_reset_dio_timer(dag, 1); return; } if(dio->rank == INFINITE_RANK) { rpl_reset_dio_timer(dag, 1); } else if(dio->rank < ROOT_RANK(dag)) { PRINTF("RPL: Ignoring DIO with too low rank: %u\n", (unsigned)dio->rank); return; } if(dag->rank == ROOT_RANK(dag)) { if(dio->rank != INFINITE_RANK) { dag->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) { if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS) { /* Make room for a new parent. */ remove_worst_parent(dag, dio->rank); } /* 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 if(DAG_RANK(p->rank, dag) == DAG_RANK(dio->rank, dag)) { PRINTF("RPL: Received consistent DIO\n"); dag->dio_counter++; } /* We have allocated a candidate parent; process the DIO further. */ memcpy(&p->mc, &dio->mc, sizeof(p->mc)); p->rank = dio->rank; if(rpl_process_parent_event(dag, p) == 0) { /* The candidate parent no longer exists. */ return; } if(should_send_dao(dag, dio, p)) { rpl_schedule_dao(dag); } p->dtsn = dio->dtsn; }