/*---------------------------------------------------------------------------*/ enum rpl_mode rpl_set_mode(enum rpl_mode m) { enum rpl_mode oldmode = mode; /* We need to do different things depending on what mode we are switching to. */ if(m == RPL_MODE_MESH) { /* If we switch to mesh mode, we should send out a DAO message to inform our parent that we now are reachable. Before we do this, we must set the mode variable, since DAOs will not be sent if we are in feather mode. */ PRINTF("RPL: switching to mesh mode\n"); mode = m; if(default_instance != NULL) { rpl_schedule_dao_immediately(default_instance); } } else if(m == RPL_MODE_FEATHER) { PRINTF("RPL: switching to feather mode\n"); mode = m; if(default_instance != NULL) { rpl_cancel_dao(default_instance); } } else { mode = m; } return oldmode; }
/*---------------------------------------------------------------------------*/ 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; } #if !CONF_6LOWPAN_ND /* 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); } #endif /* !CONF_6LOWPAN_ND */ 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)); #if !CONF_6LOWPAN_ND /* Copy prefix information from the DIO into the DAG object. */ memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t)); #endif /* !CONF_6LOWPAN_ND */ 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_immediately(instance); } else { PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); } }