From dc9cbe647de747247ecc0404383e572e9ac858d4 Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Mon, 11 Jul 2011 15:50:51 +0200 Subject: [PATCH] Changes in RPL implementation : - Structural modification of RPL data storage. - Support multiple gateways (multiple DODAG-ID with a unique InstanceID) - Use Lollipop counters - Add leaf-only configuration option for RPL Bugfix : - Correctly send "Grounded" flag in DIO --- core/net/rpl/rpl-dag.c | 983 ++++++++++++------ core/net/rpl/rpl-icmp6.c | 206 ++-- core/net/rpl/rpl-of-etx.c | 78 +- core/net/rpl/rpl-of0.c | 32 +- core/net/rpl/rpl-private.h | 51 +- core/net/rpl/rpl-timers.c | 104 +- core/net/rpl/rpl.c | 405 +++++++- core/net/rpl/rpl.h | 161 ++- .../ipv6/rpl-border-router/border-router.c | 4 +- examples/ipv6/rpl-collect/udp-sender.c | 6 +- examples/ipv6/rpl-collect/udp-sink.c | 5 +- examples/ipv6/rpl-udp/udp-server.c | 5 +- platform/avr-ravenusb/cdc_task.c | 4 +- platform/avr-ravenusb/contiki-raven-main.c | 4 +- platform/mb851/contiki-init-net.c | 4 +- 15 files changed, 1497 insertions(+), 555 deletions(-) diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 09b900a54..55dbc83b8 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -60,19 +60,14 @@ /************************************************************************/ extern rpl_of_t RPL_OF; static rpl_of_t * const objective_functions[] = {&RPL_OF}; + /************************************************************************/ - -#ifndef RPL_CONF_MAX_DAG_ENTRIES -#define RPL_MAX_DAG_ENTRIES 2 +#ifndef RPL_CONF_MAX_PARENTS_PER_DODAG +#define RPL_MAX_PARENTS_PER_DODAG 8 #else -#define RPL_MAX_DAG_ENTRIES RPL_CONF_MAX_DAG_ENTRIES -#endif /* !RPL_CONF_MAX_DAG_ENTRIES */ - -#ifndef RPL_CONF_MAX_PARENTS -#define RPL_MAX_PARENTS 8 -#else -#define RPL_MAX_PARENTS RPL_CONF_MAX_PARENTS +#define RPL_MAX_PARENTS_PER_DODAG RPL_CONF_MAX_PARENTS_PER_DODAG #endif /* !RPL_CONF_MAX_PARENTS */ + /************************************************************************/ /* RPL definitions. */ @@ -96,9 +91,12 @@ static rpl_of_t * const objective_functions[] = {&RPL_OF}; /************************************************************************/ /* Allocate parents from the same static MEMB chunk to reduce memory waste. */ -MEMB(parent_memb, struct rpl_parent, RPL_MAX_PARENTS); +MEMB(parent_memb, struct rpl_parent, RPL_MAX_PARENTS_PER_DODAG*RPL_MAX_INSTANCES*RPL_MAX_DODAG_PER_INSTANCE); + +/************************************************************************/ +/* Allocate instance table. */ +rpl_instance_t instance_table[RPL_MAX_INSTANCES]; -static rpl_dag_t dag_table[RPL_MAX_DAG_ENTRIES]; /************************************************************************/ /* Remove DAG parents with a rank that is at least the same as minimum_rank. */ static void @@ -118,6 +116,22 @@ remove_parents(rpl_dag_t *dag, rpl_rank_t minimum_rank) } /************************************************************************/ static void +nullify_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_nullify_parent(dag, p); + } + } +} +/************************************************************************/ +static void remove_worst_parent(rpl_dag_t *dag, rpl_rank_t min_worst_rank) { rpl_parent_t *p, *worst; @@ -140,63 +154,81 @@ remove_worst_parent(rpl_dag_t *dag, rpl_rank_t min_worst_rank) } /************************************************************************/ static int -should_send_dao(rpl_dag_t *dag, rpl_dio_t *dio, rpl_parent_t *p) +should_send_dao(rpl_instance_t *instance, rpl_dio_t *dio, rpl_parent_t *p) { /* if MOP is set to no downward routes no DAO should be sent */ - if(dag->mop == RPL_MOP_NO_DOWNWARD_ROUTES) return 0; - return dio->dtsn > p->dtsn && p == dag->preferred_parent; + if(instance->mop == RPL_MOP_NO_DOWNWARD_ROUTES) return 0; + return (p == instance->current_dag->preferred_parent) && + (RPL_LOLLIPOP_GREATER_THAN(dio->dtsn,p->dtsn) || + ((RPL_LOLLIPOP_GREATER_THAN(p->dtsn,dio->dtsn))&&RPL_LOLLIPOP_IS_INIT(dio->dtsn))); } /************************************************************************/ static int acceptable_rank(rpl_dag_t *dag, rpl_rank_t rank) { return rank != INFINITE_RANK && - (dag->max_rankinc == 0 || - DAG_RANK(rank, dag) <= DAG_RANK(dag->min_rank + dag->max_rankinc, dag)); + ((dag->instance->max_rankinc == 0) || + DAG_RANK(rank, dag->instance) <= DAG_RANK(dag->min_rank + dag->instance->max_rankinc, dag->instance)); + } /************************************************************************/ rpl_dag_t * -rpl_set_root(uip_ipaddr_t *dag_id) +rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) { rpl_dag_t *dag; - int version; + rpl_instance_t *instance; + uint8_t version; - version = -1; - dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); + version = RPL_LOLLIPOP_INIT; + dag = rpl_get_dodag(instance_id, dag_id); if(dag != NULL) { - PRINTF("RPL: Dropping a joined DAG when setting this node as root"); version = dag->version; - rpl_free_dag(dag); + 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_dodag(dag); } - dag = rpl_alloc_dag(RPL_DEFAULT_INSTANCE); + dag = rpl_alloc_dodag(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->version = version + 1; dag->grounded = RPL_GROUNDED; - dag->mop = RPL_MOP_DEFAULT; - dag->of = &RPL_OF; + instance->mop = RPL_MOP_DEFAULT; + instance->of = &RPL_OF; dag->preferred_parent = NULL; - dag->dtsn_out = 1; /* Trigger DAOs from the beginning. */ memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id)); - dag->dio_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS; - dag->dio_intmin = DEFAULT_DIO_INTERVAL_MIN; - dag->dio_redundancy = DEFAULT_DIO_REDUNDANCY; - dag->max_rankinc = DEFAULT_MAX_RANKINC; - dag->min_hoprankinc = DEFAULT_MIN_HOPRANKINC; + instance->dio_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS; + instance->dio_intmin = DEFAULT_DIO_INTERVAL_MIN; + instance->dio_redundancy = DEFAULT_DIO_REDUNDANCY; + instance->max_rankinc = DEFAULT_MAX_RANKINC; + instance->min_hoprankinc = DEFAULT_MIN_HOPRANKINC; + instance->default_lifetime = RPL_DEFAULT_LIFETIME; + instance->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; - dag->default_lifetime = RPL_DEFAULT_LIFETIME; - dag->lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; + dag->rank = ROOT_RANK(instance); - dag->rank = ROOT_RANK(dag); + if(instance->current_dag != dag && instance->current_dag != NULL) { + /* Remove routes installed by DAOs. */ + rpl_remove_routes(instance->current_dag); - dag->of->update_metric_container(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); @@ -204,13 +236,31 @@ rpl_set_root(uip_ipaddr_t *dag_id) ANNOTATE("#A root=%u\n",dag->dag_id.u8[sizeof(dag->dag_id) - 1]); - - rpl_reset_dio_timer(dag, 1); + rpl_reset_dio_timer(instance, 1); return dag; } /************************************************************************/ int +rpl_repair_root(uint8_t instance_id) +{ + rpl_instance_t * instance; + + instance = rpl_get_instance(instance_id); + if(instance == NULL) { + return 0; + } + + if(instance->current_dag->rank == ROOT_RANK(instance)) { + RPL_LOLLIPOP_INCREMENT(instance->current_dag->version); + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); + rpl_reset_dio_timer(instance, 1); + return 1; + } + return 0; +} +/************************************************************************/ +int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len) { if(len <= 128) { @@ -225,72 +275,136 @@ rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len) } /************************************************************************/ int -rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from) +rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from) { - if(dag->def_route != NULL) { - PRINTF("RPL: Removing default route through "); - PRINT6ADDR(&dag->def_route->ipaddr); - PRINTF("\n"); - uip_ds6_defrt_rm(dag->def_route); + if(instance->def_route != NULL) { + if(instance->def_route->isused) { + PRINTF("RPL: Removing default route through "); + PRINT6ADDR(&instance->def_route->ipaddr); + PRINTF("\n"); + uip_ds6_defrt_rm(instance->def_route); + } + instance->def_route = NULL; } if(from != NULL) { PRINTF("RPL: Adding default route through "); PRINT6ADDR(from); PRINTF("\n"); - dag->def_route = uip_ds6_defrt_add(from, - RPL_LIFETIME(dag, - dag->default_lifetime)); - if(dag->def_route == NULL) { + instance->def_route = uip_ds6_defrt_add(from, + RPL_LIFETIME(instance, + instance->default_lifetime)); + if(instance->def_route == NULL) { return 0; } } - return 1; } /************************************************************************/ -rpl_dag_t * -rpl_alloc_dag(uint8_t instance_id) +rpl_instance_t * +rpl_alloc_instance(uint8_t instance_id) { - rpl_dag_t *dag; - rpl_dag_t *end; + rpl_instance_t *instance, *end; - for(dag = &dag_table[0], end = dag + RPL_MAX_DAG_ENTRIES; dag < end; dag++) { - if(dag->used == 0) { + for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if(instance->used == 0) { + memset(instance, 0, sizeof(*instance)); + instance->instance_id = instance_id; + instance->def_route = NULL; + instance->used = 1; + return instance; + } + } + return NULL; +} +/************************************************************************/ +rpl_dag_t * +rpl_alloc_dodag(uint8_t instance_id, uip_ipaddr_t *dag_id) +{ + rpl_dag_t *dag, *end; + rpl_instance_t *instance; + + instance = rpl_get_instance(instance_id); + if(instance == NULL ) { + instance = rpl_alloc_instance(instance_id); + if(instance == NULL ) { + RPL_STAT(rpl_stats.mem_overflows++); + return NULL; + } + dag = &instance->dag_table[0]; + dag->parents = &dag->parent_list; + list_init(dag->parents); + dag->used = 1; + dag->rank = INFINITE_RANK; + dag->min_rank = INFINITE_RANK; + dag->instance = instance; + instance->current_dag = dag; + return dag; + } + + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + if(!dag->used) { memset(dag, 0, sizeof(*dag)); dag->parents = &dag->parent_list; list_init(dag->parents); - dag->instance_id = instance_id; - dag->def_route = NULL; + dag->used = 1; dag->rank = INFINITE_RANK; dag->min_rank = INFINITE_RANK; + dag->instance = instance; return dag; } } - - RPL_STAT(rpl_stats.mem_overflows++); return NULL; } /************************************************************************/ void -rpl_free_dag(rpl_dag_t *dag) +rpl_set_default_instance(rpl_instance_t *instance) { - PRINTF("RPL: Leaving the DAG "); - PRINT6ADDR(&dag->dag_id); - PRINTF("\n"); + default_instance = instance; +} +/************************************************************************/ +void +rpl_free_instance(rpl_instance_t *instance) +{ + rpl_dag_t *dag; + rpl_dag_t *end; - /* Remove routes installed by DAOs. */ - rpl_remove_routes(dag); + PRINTF("RPL: Leaving the instance %u\n", instance->instance_id); - /* Remove parents and the default route. */ - remove_parents(dag, 0); - rpl_set_default_route(dag, NULL); + /* Remove any DODAG inside this instance */ + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + if(dag->used) { + rpl_free_dodag(dag); + } + } - ctimer_stop(&dag->dio_timer); - ctimer_stop(&dag->dao_timer); + rpl_set_default_route(instance, NULL); + ctimer_stop(&instance->dio_timer); + ctimer_stop(&instance->dao_timer); + + if(default_instance == instance) { + default_instance = NULL; + } + + instance->used = 0; +} +/************************************************************************/ +void +rpl_free_dodag(rpl_dag_t *dag) +{ + if(dag->joined) { + PRINTF("RPL: Leaving the DAG "); + PRINT6ADDR(&dag->dag_id); + PRINTF("\n"); + dag->joined = 0; + + /* Remove routes installed by DAOs. */ + rpl_remove_routes(dag); + + remove_parents(dag, 0); + } dag->used = 0; - dag->joined = 0; } /************************************************************************/ rpl_parent_t * @@ -303,17 +417,13 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) RPL_STAT(rpl_stats.mem_overflows++); return NULL; } - memcpy(&p->addr, addr, sizeof(p->addr)); p->dag = dag; p->rank = dio->rank; + p->dtsn = dio->dtsn; p->link_metric = INITIAL_LINK_METRIC; - p->dtsn = 0; - memcpy(&p->mc, &dio->mc, sizeof(p->mc)); - list_add(dag->parents, p); - return p; } /************************************************************************/ @@ -327,16 +437,138 @@ rpl_find_parent(rpl_dag_t *dag, uip_ipaddr_t *addr) return p; } } - return NULL; } +/************************************************************************/ +rpl_dag_t * +rpl_find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr) +{ + rpl_parent_t *p; + rpl_dag_t *dag, *end; + + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + if(dag->used) { + for(p = list_head(dag->parents); p != NULL; p = p->next) { + if(uip_ipaddr_cmp(&p->addr, addr)) { + return dag; + } + } + } + } + return NULL; +} +/************************************************************************/ +rpl_parent_t * +rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr) +{ + rpl_parent_t *p; + rpl_dag_t *dag, *end; + + for(dag = &instance->dag_table[0], end = dag + RPL_MAX_DODAG_PER_INSTANCE; dag < end; ++dag) { + if(dag->used) { + for(p = list_head(dag->parents); p != NULL; p = p->next) { + if(uip_ipaddr_cmp(&p->addr, addr)) { + return p; + } + } + } + } + return NULL; +} +/************************************************************************/ +rpl_dag_t * +rpl_select_dodag(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_DODAG_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 DODAG : "); + PRINT6ADDR(&best_dag->dag_id); + PRINTF("\n"); + + 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(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"); + instance->current_dag->preferred_parent = 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, ZERO_LIFETIME); + } + return NULL; + } + + if(best_dag->preferred_parent != last_parent) { + rpl_set_default_route(instance, &best_dag->preferred_parent->addr); + 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, 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, 1); + } 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); + RPL_STAT(rpl_stats.parent_switch++); + rpl_reset_dio_timer(instance, 1); + } + return best_dag; +} /************************************************************************/ rpl_parent_t * rpl_select_parent(rpl_dag_t *dag) { - rpl_parent_t *p; - rpl_parent_t *best; + rpl_parent_t *p, *best; best = NULL; for(p = list_head(dag->parents); p != NULL; p = p->next) { @@ -345,86 +577,125 @@ rpl_select_parent(rpl_dag_t *dag) } else if(best == NULL) { best = p; } else { - best = dag->of->best_parent(best, p); + best = dag->instance->of->best_parent(best, p); } } - if(best == NULL) { - /* need to handle update of best... */ - return NULL; + if(best != NULL) { + dag->preferred_parent = best; + } else { + /* We should probably do something here .... */ } - - if(dag->preferred_parent != best) { - PRINTF("RPL: Sending a No-Path DAO to old DAO parent\n"); - dao_output(dag->preferred_parent, ZERO_LIFETIME); - - dag->preferred_parent = best; /* Cache the value. */ - dag->of->update_metric_container(dag); - rpl_set_default_route(dag, &best->addr); - /* The DAO parent set changed - schedule a DAO transmission. */ - if(dag->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { - rpl_schedule_dao(dag); - } - rpl_reset_dio_timer(dag, 1); - PRINTF("RPL: New preferred parent, rank changed from %u to %u\n", - (unsigned)dag->rank, dag->of->calculate_rank(best, 0)); - RPL_STAT(rpl_stats.parent_switch++); - } - - /* Update the DAG rank, since link-layer information may have changed - the local confidence. */ - dag->rank = dag->of->calculate_rank(best, 0); - if(dag->rank < dag->min_rank) { - dag->min_rank = dag->rank; - } else if(!acceptable_rank(dag, best->rank)) { - /* Send a No-Path DAO to the soon-to-be-removed preferred parent. */ - dao_output(best, ZERO_LIFETIME); - - remove_parents(dag, 0); - return NULL; - } - return best; } /************************************************************************/ -int +void rpl_remove_parent(rpl_dag_t *dag, rpl_parent_t *parent) { - uip_ds6_defrt_t *defrt; - - /* Remove uIPv6 routes that have this parent as the next hop. **/ - uip_ds6_route_rm_by_nexthop(&parent->addr); - defrt = uip_ds6_defrt_lookup(&parent->addr); - if(defrt != NULL) { - PRINTF("RPL: Removing default route "); - PRINT6ADDR(&parent->addr); - PRINTF("\n"); - uip_ds6_defrt_rm(defrt); - dag->def_route = NULL; - } + rpl_nullify_parent(dag,parent); PRINTF("RPL: Removing parent "); PRINT6ADDR(&parent->addr); PRINTF("\n"); - if(parent == dag->preferred_parent) { - dag->preferred_parent = NULL; - } - list_remove(dag->parents, parent); memb_free(&parent_memb, parent); - return 0; +} +/************************************************************************/ +void +rpl_nullify_parent(rpl_dag_t *dag, rpl_parent_t *parent) +{ + if(parent == dag->preferred_parent) { + dag->preferred_parent = NULL; + dag->rank = INFINITE_RANK; + if(dag->joined) { + if(dag->instance->def_route != NULL) { + if(dag->instance->def_route->isused) { + PRINTF("RPL: Removing default route "); + PRINT6ADDR(&parent->addr); + PRINTF("\n"); + uip_ds6_defrt_rm(dag->instance->def_route); + } + dag->instance->def_route = NULL; + } + dao_output(parent, ZERO_LIFETIME); + } + } + + PRINTF("RPL: Nullifying parent "); + PRINT6ADDR(&parent->addr); + PRINTF("\n"); +} +/************************************************************************/ +void +rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent) +{ + if(parent == dag_src->preferred_parent) { + dag_src->preferred_parent = NULL; + dag_src->rank = INFINITE_RANK; + if(dag_src->joined + && dag_src->instance->def_route != NULL) { + if(dag_src->instance->def_route->isused) { + PRINTF("RPL: Removing default route "); + PRINT6ADDR(&parent->addr); + PRINTF("\n"); + uip_ds6_defrt_rm(dag_src->instance->def_route); + } + dag_src->instance->def_route = NULL; + } + } else if(dag_src->joined) { + /* Remove uIPv6 routes that have this parent as the next hop. */ + rpl_remove_routes_by_nexthop(&parent->addr,dag_src); + } + + PRINTF("RPL: Moving parent "); + PRINT6ADDR(&parent->addr); + PRINTF("\n"); + + list_remove(dag_src->parents, parent); + parent->dag = dag_dst; + list_add(dag_dst->parents, parent); } /************************************************************************/ rpl_dag_t * -rpl_get_dag(int instance_id) +rpl_get_any_dag(void) { int i; - for(i = 0; i < RPL_MAX_DAG_ENTRIES; i++) { - if(dag_table[i].joined && (instance_id == RPL_ANY_INSTANCE || - dag_table[i].instance_id == instance_id)) { - return &dag_table[i]; + for(i = 0; i < RPL_MAX_INSTANCES; ++i) { + if(instance_table[i].used && instance_table[i].current_dag->joined) { + return instance_table[i].current_dag; + } + } + return NULL; +} +/************************************************************************/ +rpl_instance_t * +rpl_get_instance(uint8_t instance_id) +{ + int i; + + for(i = 0; i < RPL_MAX_INSTANCES; ++i) { + if(instance_table[i].used && instance_table[i].instance_id == instance_id) { + return &instance_table[i]; + } + } + return NULL; +} +/************************************************************************/ +rpl_dag_t * +rpl_get_dodag(uint8_t instance_id, uip_ipaddr_t *dag_id) +{ + rpl_instance_t *instance, *end; + int i; + + for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if(instance->used && instance->instance_id == instance_id) { + for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; ++i) { + if(instance->dag_table[i].used && (!memcmp(&instance->dag_table[i].dag_id, dag_id, sizeof(*dag_id)))) { + return &instance->dag_table[i]; + } + } } } return NULL; @@ -436,7 +707,7 @@ rpl_find_of(rpl_ocp_t ocp) unsigned int i; for(i = 0; - i < sizeof(objective_functions) / sizeof(objective_functions[0]); + i < sizeof(objective_functions) / sizeof(objective_functions[0]); i++) { if(objective_functions[i]->ocp == ocp) { return objective_functions[i]; @@ -446,27 +717,32 @@ rpl_find_of(rpl_ocp_t ocp) return NULL; } /************************************************************************/ -static void -join_dag(uip_ipaddr_t *from, rpl_dio_t *dio) +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); + dag = rpl_alloc_dodag(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 @@ -475,6 +751,8 @@ join_dag(uip_ipaddr_t *from, rpl_dio_t *dio) if(of == NULL) { PRINTF("RPL: DIO for DAG instance %u does not specify a supported OF\n", dio->instance_id); + rpl_remove_parent(dag, p); + instance->used = 0; return; } @@ -494,30 +772,119 @@ join_dag(uip_ipaddr_t *from, rpl_dio_t *dio) } dag->joined = 1; - dag->used = 1; - dag->of = of; - dag->grounded = dio->grounded; - dag->mop = dio->mop; dag->preference = dio->preference; - dag->instance_id = dio->instance_id; - - dag->max_rankinc = dio->dag_max_rankinc; - dag->min_hoprankinc = dio->dag_min_hoprankinc; - + dag->grounded = dio->grounded; dag->version = dio->version; - dag->preferred_parent = p; - dag->of->update_metric_container(dag); - dag->dio_intdoubl = dio->dag_intdoubl; - dag->dio_intmin = dio->dag_intmin; - dag->dio_redundancy = dio->dag_redund; + instance->of = of; + instance->mop = dio->mop; + instance->dtsn_out = RPL_LOLLIPOP_INIT; + instance->instance_id = dio->instance_id; + + 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; 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)); - dag->rank = dag->of->calculate_rank(p, dio->rank); + dag->preferred_parent = p; + instance->of->update_metric_container(instance); + dag->rank = instance->of->calculate_rank(p,0); + dag->min_rank = dag->rank; /* So far this is the lowest rank we know of. */ + + 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, 1); + 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_dodag(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_dodag(dio->instance_id,&dio->dag_id); + if(dag == NULL) { + PRINTF("RPL: Failed to allocate a DAG object!\n"); + return; + } + + instance = dag->instance; + + previous_dag = rpl_find_parent_dag(instance, from); + if(previous_dag == NULL) { + p = rpl_add_parent(dag, dio, from); + PRINTF("RPL: Adding "); + PRINT6ADDR(from); + PRINTF(" as a parent: "); + if(p == NULL) { + PRINTF("failed\n"); + dag->used = 0; + return; + } + PRINTF("succeeded\n"); + } else { + p = rpl_find_parent(previous_dag, from); + 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 uncompatible with previos DIO\n", + dio->instance_id); + rpl_remove_parent(dag,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)); + + dag->preferred_parent = 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 ", @@ -527,19 +894,10 @@ join_dag(uip_ipaddr_t *from, rpl_dio_t *dio) ANNOTATE("#A join=%u\n",dag->dag_id.u8[sizeof(dag->dag_id) - 1]); - - dag->default_lifetime = dio->default_lifetime; - dag->lifetime_unit = dio->lifetime_unit; - - rpl_reset_dio_timer(dag, 1); - rpl_set_default_route(dag, from); - - if(should_send_dao(dag, dio, p)) { - rpl_schedule_dao(dag); - } else { - PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); - } + rpl_process_parent_event(instance,p); + p->dtsn = dio->dtsn; } + /************************************************************************/ static void global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) @@ -548,19 +906,16 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) remove_parents(dag, 0); dag->version = dio->version; - dag->dtsn_out = 1; - dag->of->reset(dag); + dag->instance->of->reset(dag); + dag->min_rank = INFINITE_RANK; + RPL_LOLLIPOP_INCREMENT(dag->instance->dtsn_out); if((p = rpl_add_parent(dag, dio, from)) == NULL) { PRINTF("RPL: Failed to add a parent during the global repair\n"); dag->rank = INFINITE_RANK; } else { - rpl_set_default_route(dag, from); - dag->rank = dag->of->calculate_rank(NULL, dio->rank); - dag->min_rank = dag->rank; - rpl_reset_dio_timer(dag, 1); - if(should_send_dao(dag, dio, p)) { - rpl_schedule_dao(dag); - } + dag->rank = dag->instance->of->calculate_rank(p,0); + dag->min_rank = dag->rank ; + rpl_process_parent_event(dag->instance,p); } PRINTF("RPL: Participating in a global repair (version=%u, rank=%hu)\n", dag->version, dag->rank); @@ -568,26 +923,20 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) RPL_STAT(rpl_stats.global_repairs++); } /************************************************************************/ -int -rpl_repair_dag(rpl_dag_t *dag) -{ - if(dag->rank == ROOT_RANK(dag)) { - dag->version++; - dag->dtsn_out = 1; - rpl_reset_dio_timer(dag, 1); - return 1; - } - return 0; -} -/************************************************************************/ void -rpl_local_repair(rpl_dag_t *dag) +rpl_local_repair(rpl_instance_t *instance) { - PRINTF("RPL: Starting a local DAG repair\n"); + int i; - dag->rank = INFINITE_RANK; - remove_parents(dag, 0); - rpl_reset_dio_timer(dag, 1); + PRINTF("RPL: Starting a local instance repair\n"); + for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; i++) { + if(instance->dag_table[i].used) { + instance->dag_table[i].rank = INFINITE_RANK; + nullify_parents(&instance->dag_table[i], 0); + } + } + + rpl_reset_dio_timer(instance,1); RPL_STAT(rpl_stats.local_repairs++); } @@ -595,75 +944,101 @@ rpl_local_repair(rpl_dag_t *dag) void rpl_recalculate_ranks(void) { - rpl_dag_t *dag; + rpl_instance_t *instance, *end; rpl_parent_t *p; + int i; /* * We recalculate ranks when we receive feedback from the system rather * than RPL protocol messages. This periodical recalculation is called * from a timer in order to keep the stack depth reasonably low. */ - dag = rpl_get_dag(RPL_ANY_INSTANCE); - if(dag != NULL) { - for(p = list_head(dag->parents); p != NULL; p = p->next) { - if(p->updated) { - p->updated = 0; - rpl_process_parent_event(dag, p); - /* - * Stop calculating here because the parent list may have changed. - * If more ranks need to be recalculated, it will be taken care of - * in subsequent calls to this functions. - */ - break; + for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if(instance->used) { + for(i = 0; i < RPL_MAX_DODAG_PER_INSTANCE; i++) { + if(instance->dag_table[i].used) { + for(p = list_head(instance->dag_table[i].parents); p != NULL; p = p->next) { + if(p->updated) { + p->updated = 0; + if(!rpl_process_parent_event(instance, p)) { + PRINTF("RPL: A parent was dropped\n"); + } + /* + * Stop calculating here because the parent list may have changed. + * If more ranks need to be recalculated, it will be taken care of + * in subsequent calls to this functions. + */ + break; + } + } + } } } } } /************************************************************************/ int -rpl_process_parent_event(rpl_dag_t *dag, rpl_parent_t *p) +rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p) { - rpl_rank_t parent_rank; rpl_rank_t old_rank; + int return_value; - /* Update the parent rank. */ - parent_rank = p->rank; - old_rank = dag->rank; + old_rank = instance->current_dag->rank; + return_value = 1; - if(rpl_select_parent(dag) == NULL) { - /* No suitable parent; trigger a local repair. */ - PRINTF("RPL: No parents found in a DAG\n"); - rpl_local_repair(dag); - return 1; - } - - if(DAG_RANK(old_rank, dag) != DAG_RANK(dag->rank, dag)) { - if(dag->rank < dag->min_rank) { - dag->min_rank = dag->rank; + if(p->rank == INFINITE_RANK) { + /* This parent is no longer valid */ + PRINTF("RPL: This parent is no longer valid \n"); + if(p != instance->current_dag->preferred_parent) { + rpl_nullify_parent(p->dag, p); + return 0; + } else { + rpl_nullify_parent(p->dag, p); + return_value = 0; } - PRINTF("RPL: Moving in the DAG from rank %hu to %hu\n", - DAG_RANK(old_rank, dag), DAG_RANK(dag->rank, dag)); - PRINTF("RPL: The preferred parent is "); - PRINT6ADDR(&dag->preferred_parent->addr); - PRINTF(" (rank %u)\n", - (unsigned)DAG_RANK(dag->preferred_parent->rank, dag)); - rpl_reset_dio_timer(dag, 1); - } - - if(parent_rank == INFINITE_RANK || - !acceptable_rank(dag, dag->of->calculate_rank(NULL, parent_rank))) { + } else if(!acceptable_rank(p->dag, p->rank)) { /* The candidate parent is no longer valid: the rank increase resulting from the choice of it as a parent would be too high. */ + PRINTF("RPL: Unacceptable rank\n"); + if(p != instance->current_dag->preferred_parent) { + rpl_nullify_parent(p->dag, p); + return 0; + } else { + rpl_nullify_parent(p->dag, p); + return_value = 0; + } + } + + if(rpl_select_dodag(instance, p) == NULL) { + /* No suitable parent; trigger a local repair. */ + PRINTF("RPL: No parents found in any DAG\n"); + rpl_local_repair(instance); return 0; } - return 1; +#if DEBUG + if(DAG_RANK(old_rank, instance) != DAG_RANK(instance->current_dag->rank, instance)) { + PRINTF("RPL: Moving in the Instance from rank %hu to %hu\n", + DAG_RANK(old_rank, instance), DAG_RANK(instance->current_dag->rank, instance)); + if(instance->current_dag->rank != INFINITE_RANK) { + PRINTF("RPL: The preferred parent is "); + PRINT6ADDR(&instance->current_dag->preferred_parent->addr); + PRINTF(" (rank %u)\n", + (unsigned)DAG_RANK(instance->current_dag->preferred_parent->rank, instance)); + } else { + PRINTF("RPL: We don't have any parent"); + } + } +#endif /* DEBUG */ + + return return_value; } /************************************************************************/ void rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) { - rpl_dag_t *dag; + rpl_instance_t *instance; + rpl_dag_t *dag, *previous_dag; rpl_parent_t *p; if(dio->mop != RPL_MOP_DEFAULT) { @@ -671,51 +1046,61 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) return; } - dag = rpl_get_dag(dio->instance_id); + if(dio->rank == INFINITE_RANK) { + PRINTF("RPL: Ignoring DIO from node with infinite rank: "); + PRINT6ADDR(from); + PRINTF("\n"); + return; + } + + instance = rpl_get_instance(dio->instance_id); + if(instance == NULL) { + PRINTF("RPL : New instance detected : Joining...\n"); + rpl_join_instance(from, dio); + return; + } + + dag = rpl_get_dodag(dio->instance_id,&dio->dag_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"); - } + PRINTF("RPL : Adding new dodag to known instance.\n"); + rpl_add_dodag(from,dio); 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)) { + if(RPL_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 + 1; - rpl_reset_dio_timer(dag, 1); + dag->version = dio->version; + RPL_LOLLIPOP_INCREMENT(dag->version); + rpl_reset_dio_timer(instance, 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; + } else { + if(RPL_LOLLIPOP_GREATER_THAN(dag->version,dio->version)) { + /* Inconsistency detected - someone is still on old version */ + PRINTF("RPL: old version received => inconsistency detected\n"); + if(dag->joined) { + rpl_reset_dio_timer(instance, 1); + return; + } + } } if(dio->rank == INFINITE_RANK) { - rpl_reset_dio_timer(dag, 1); - } else if(dio->rank < ROOT_RANK(dag)) { + if(dag->joined) { + rpl_reset_dio_timer(instance, 1); + } + } else if(dio->rank < ROOT_RANK(instance)) { PRINTF("RPL: Ignoring DIO with too low rank: %u\n", (unsigned)dio->rank); return; } - if(dag->rank == ROOT_RANK(dag)) { + if(dag->rank == ROOT_RANK(instance)) { if(dio->rank != INFINITE_RANK) { - dag->dio_counter++; + instance->dio_counter++; } return; } @@ -729,42 +1114,58 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) 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 ("); + previous_dag = rpl_find_parent_dag(instance, from); + if(previous_dag == NULL) { + if(RPL_PARENT_COUNT(dag) == RPL_MAX_PARENTS_PER_DODAG) { + /* 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"); - return; + PRINTF("\n"); + } else { + p = rpl_find_parent(previous_dag, from); + 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: 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++; } - + + PRINTF("RPL current state: Prefered DODAG: "); + PRINT6ADDR(&instance->current_dag->dag_id); + PRINTF(", rank: %u, min_rank: %u, ",instance->current_dag->rank,instance->current_dag->min_rank); + PRINTF("p->rank : %u, p->mc.obj.etx : %u, p->link_metric : %u, instance->mc.obj.etx %u\n", p->rank, p->mc.obj.etx, p->link_metric,instance->mc.obj.etx); + /* 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. */ + memcpy(&p->mc, &dio->mc, sizeof(p->mc)); + if(rpl_process_parent_event(instance, p) == 0) { + PRINTF("RPL: The candidate parent is rejected\n"); return; } - - if(should_send_dao(dag, dio, p)) { - rpl_schedule_dao(dag); + + /* 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); + } } - p->dtsn = dio->dtsn; } /************************************************************************/ - diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 76ae9eb59..f59125391 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -72,7 +72,7 @@ static void dio_input(void); static void dao_input(void); static void dao_ack_input(void); -static uint8_t dao_sequence; +static uint8_t dao_sequence = RPL_LOLLIPOP_INIT; /*---------------------------------------------------------------------------*/ static int get_global_addr(uip_ipaddr_t *addr) @@ -112,21 +112,27 @@ set32(uint8_t *buffer, int pos, uint32_t value) static void dis_input(void) { - rpl_dag_t *dag; + rpl_instance_t *instance; + rpl_instance_t *end; /* DAG Information Solicitation */ PRINTF("RPL: Received a DIS from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); - dag = rpl_get_dag(RPL_ANY_INSTANCE); - if(dag != NULL) { - if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { - PRINTF("RPL: Multicast DIS => reset DIO timer\n"); - rpl_reset_dio_timer(dag, 0); - } else { - PRINTF("RPL: Unicast DIS, reply to sender\n"); - dio_output(dag, &UIP_IP_BUF->srcipaddr); + for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if ( instance->used == 1 ) { +#if RPL_LEAF_ONLY + if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { +#else /* !RPL_LEAF_ONLY */ + if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { + PRINTF("RPL: Multicast DIS => reset DIO timer\n"); + rpl_reset_dio_timer(instance, 0); + } else { +#endif /* !RPL_LEAF_ONLY */ + PRINTF("RPL: Unicast DIS, reply to sender\n"); + dio_output(instance, &UIP_IP_BUF->srcipaddr); + } } } } @@ -199,7 +205,7 @@ dio_input(void) buffer_length = uip_len - uip_l2_l3_icmp_hdr_len; #if RPL_CONF_ADJUST_LLH_LEN - buffer_length+=UIP_LLH_LEN; //Add jackdaw, minimal-net ethernet header + buffer_length += UIP_LLH_LEN; /* Add jackdaw, minimal-net ethernet header */ #endif /* Process the DIO base option. */ @@ -211,6 +217,7 @@ dio_input(void) dio.rank = (buffer[i] << 8) | buffer[i + 1]; i += 2; + PRINTF("RPL: Incoming DIO InstanceID-Version %u-%u\n", (unsigned)dio.instance_id,(unsigned)dio.version); PRINTF("RPL: Incoming DIO rank %u\n", (unsigned)dio.rank); dio.grounded = buffer[i] & RPL_DIO_GROUNDED; @@ -224,6 +231,10 @@ dio_input(void) memcpy(&dio.dag_id, buffer + i, sizeof(dio.dag_id)); i += sizeof(dio.dag_id); + PRINTF("RPL: Incoming DIO DODAG "); + PRINT6ADDR(&dio.dag_id); + PRINTF(" preference : %u\n",dio.preference); + /* Check if there are any DIO suboptions. */ for(; i < buffer_length; i += len) { subopt_type = buffer[i]; @@ -249,7 +260,6 @@ dio_input(void) RPL_STAT(rpl_stats.malformed_msgs++); return; } - dio.mc.type = buffer[i + 2]; dio.mc.flags = buffer[i + 3] << 1; dio.mc.flags |= buffer[i + 4] >> 7; @@ -347,30 +357,50 @@ dio_input(void) } /*---------------------------------------------------------------------------*/ void -dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) +dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) { unsigned char *buffer; int pos; +#if !RPL_LEAF_ONLY uip_ipaddr_t addr; +#endif /* !RPL_LEAF_ONLY */ + +#if RPL_LEAF_ONLY + /* only respond to unicast DIS */ + if(uc_addr == NULL) { + return; + } +#endif /* RPL_LEAF_ONLY */ + + rpl_dag_t *dag = instance->current_dag; /* DAG Information Object */ pos = 0; buffer = UIP_ICMP_PAYLOAD; - buffer[pos++] = dag->instance_id; + buffer[pos++] = instance->instance_id; buffer[pos++] = dag->version; +#if RPL_LEAF_ONLY + buffer[pos++] = INFINITE_RANK >> 8; + buffer[pos++] = INFINITE_RANK & 0xff; +#else /* RPL_LEAF_ONLY */ buffer[pos++] = dag->rank >> 8; buffer[pos++] = dag->rank & 0xff; +#endif /* RPL_LEAF_ONLY */ buffer[pos] = 0; if(dag->grounded) { buffer[pos] |= RPL_DIO_GROUNDED; } - buffer[pos] = dag->mop << RPL_DIO_MOP_SHIFT; + buffer[pos] |= instance->mop << RPL_DIO_MOP_SHIFT; + buffer[pos] |= dag->preference & RPL_DIO_PREFERENCE_MASK; pos++; - buffer[pos++] = ++dag->dtsn_out; + buffer[pos++] = instance->dtsn_out; + + if (RPL_LOLLIPOP_IS_INIT(instance->dtsn_out)) + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); /* reserved 2 bytes */ buffer[pos++] = 0; /* flags */ @@ -379,49 +409,51 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id)); pos += 16; - if(dag->mc.type != RPL_DAG_MC_NONE) { - dag->of->update_metric_container(dag); +#if !RPL_LEAF_ONLY + if(instance->mc.type != RPL_DAG_MC_NONE) { + instance->of->update_metric_container(instance); buffer[pos++] = RPL_DIO_SUBOPT_DAG_METRIC_CONTAINER; buffer[pos++] = 6; - buffer[pos++] = dag->mc.type; - buffer[pos++] = dag->mc.flags >> 1; - buffer[pos] = (dag->mc.flags & 1) << 7; - buffer[pos++] |= (dag->mc.aggr << 4) | dag->mc.prec; - - if(dag->mc.type == RPL_DAG_MC_ETX) { + buffer[pos++] = instance->mc.type; + buffer[pos++] = instance->mc.flags >> 1; + buffer[pos] = (instance->mc.flags & 1) << 7; + buffer[pos++] |= (instance->mc.aggr << 4) | instance->mc.prec; + if(instance->mc.type == RPL_DAG_MC_ETX) { buffer[pos++] = 2; - buffer[pos++] = dag->mc.obj.etx >> 8; - buffer[pos++] = dag->mc.obj.etx & 0xff; - } else if(dag->mc.type == RPL_DAG_MC_ENERGY) { + buffer[pos++] = instance->mc.obj.etx >> 8; + buffer[pos++] = instance->mc.obj.etx & 0xff; + } else if(instance->mc.type == RPL_DAG_MC_ENERGY) { buffer[pos++] = 2; - buffer[pos++] = dag->mc.obj.energy.flags; - buffer[pos++] = dag->mc.obj.energy.energy_est; + buffer[pos++] = instance->mc.obj.energy.flags; + buffer[pos++] = instance->mc.obj.energy.energy_est; } else { PRINTF("RPL: Unable to send DIO because of unhandled DAG MC type %u\n", - (unsigned)dag->mc.type); + (unsigned)instance->mc.type); return; } } - /* Always add a sub-option for DAG configuration. */ +#endif /* RPL_LEAF_ONLY */ + + /* Always add a sub-option for DAG configuration */ buffer[pos++] = RPL_DIO_SUBOPT_DAG_CONF; buffer[pos++] = 14; buffer[pos++] = 0; /* No Auth, PCS = 0 */ - buffer[pos++] = dag->dio_intdoubl; - buffer[pos++] = dag->dio_intmin; - buffer[pos++] = dag->dio_redundancy; - buffer[pos++] = dag->max_rankinc >> 8; - buffer[pos++] = dag->max_rankinc & 0xff; - buffer[pos++] = dag->min_hoprankinc >> 8; - buffer[pos++] = dag->min_hoprankinc & 0xff; + buffer[pos++] = instance->dio_intdoubl; + buffer[pos++] = instance->dio_intmin; + buffer[pos++] = instance->dio_redundancy; + buffer[pos++] = instance->max_rankinc >> 8; + buffer[pos++] = instance->max_rankinc & 0xff; + buffer[pos++] = instance->min_hoprankinc >> 8; + buffer[pos++] = instance->min_hoprankinc & 0xff; /* OCP is in the DAG_CONF option */ - buffer[pos++] = dag->of->ocp >> 8; - buffer[pos++] = dag->of->ocp & 0xff; + buffer[pos++] = instance->of->ocp >> 8; + buffer[pos++] = instance->of->ocp & 0xff; buffer[pos++] = 0; /* reserved */ - buffer[pos++] = dag->default_lifetime; - buffer[pos++] = dag->lifetime_unit >> 8; - buffer[pos++] = dag->lifetime_unit & 0xff; + buffer[pos++] = instance->default_lifetime; + buffer[pos++] = instance->lifetime_unit >> 8; + buffer[pos++] = instance->lifetime_unit & 0xff; /* Check if we have a prefix to send also. */ if(dag->prefix_info.length > 0) { @@ -445,19 +477,27 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) dag->prefix_info.length); } +#if RPL_LEAF_ONLY + PRINTF("RPL: Sending unicast-DIO with rank %u to ", + (unsigned)dag->rank); + PRINT6ADDR(uc_addr); + PRINTF("\n"); + uip_icmp6_send(uc_addr, ICMP6_RPL, RPL_CODE_DIO, pos); +#else /* RPL_LEAF_ONLY */ /* Unicast requests get unicast replies! */ if(uc_addr == NULL) { PRINTF("RPL: Sending a multicast-DIO with rank %u\n", - (unsigned)dag->rank); + (unsigned)instance->current_dag->rank); uip_create_linklocal_rplnodes_mcast(&addr); uip_icmp6_send(&addr, ICMP6_RPL, RPL_CODE_DIO, pos); } else { PRINTF("RPL: Sending unicast-DIO with rank %u to ", - (unsigned)dag->rank); + (unsigned)instance->current_dag->rank); PRINT6ADDR(uc_addr); PRINTF("\n"); uip_icmp6_send(uc_addr, ICMP6_RPL, RPL_CODE_DIO, pos); } +#endif /* RPL_LEAF_ONLY */ } /*---------------------------------------------------------------------------*/ static void @@ -465,10 +505,11 @@ dao_input(void) { uip_ipaddr_t dao_sender_addr; rpl_dag_t *dag; + rpl_instance_t *instance; unsigned char *buffer; uint16_t sequence; uint8_t instance_id; - rpl_lifetime_t lifetime; + uint8_t lifetime; uint8_t prefixlen; uint8_t flags; uint8_t subopt_type; @@ -494,32 +535,37 @@ dao_input(void) buffer = UIP_ICMP_PAYLOAD; buffer_length = uip_len - uip_l2_l3_icmp_hdr_len; + #if RPL_CONF_ADJUST_LLH_LEN buffer_length += UIP_LLH_LEN; /* Add jackdaw, minimal-net ethernet header */ #endif - pos = 0; instance_id = buffer[pos++]; - dag = rpl_get_dag(instance_id); - if(dag == NULL) { - PRINTF("RPL: Ignoring a DAO for a different RPL instance (%u)\n", + instance = rpl_get_instance(instance_id); + if(instance == NULL) { + PRINTF("RPL: Ignoring a DAO for an unknown RPL instance(%u)\n", instance_id); return; } - lifetime = dag->default_lifetime; + lifetime = instance->default_lifetime; flags = buffer[pos++]; /* reserved */ pos++; sequence = buffer[pos++]; + dag = instance->current_dag; /* Is the DAGID present? */ if(flags & RPL_DAO_D_FLAG) { - /* Currently the DAG ID is ignored since we only use global - RPL Instance IDs. */ + if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) { + PRINTF("RPL: Ignoring a DAO for a DODAG different from ours\n"); + return; + } pos += 16; + } else { + /* Perhaps, there are verification to do but ... */ } /* Check if there are any DIO sub-options. */ @@ -529,7 +575,7 @@ dao_input(void) if(subopt_type == RPL_DIO_SUBOPT_PAD1) { len = 1; } else { - /* Sub-option with a two-byte header and payload */ + /* Sub-option with a two-byte header + payload */ len = 2 + buffer[i + 1]; } @@ -551,7 +597,7 @@ dao_input(void) } PRINTF("RPL: DAO lifetime: %u, prefix length: %u prefix: ", - (unsigned)lifetime, (unsigned)prefixlen); + (unsigned)lifetime, (unsigned)prefixlen); PRINT6ADDR(&prefix); PRINTF("\n"); @@ -559,7 +605,7 @@ dao_input(void) if(lifetime == ZERO_LIFETIME) { /* No-Path DAO received; invoke the route purging routine. */ - if(rep != NULL && rep->state.saved_lifetime == 0) { + if(rep != NULL && rep->state.saved_lifetime == 0 && rep->length==prefixlen) { PRINTF("RPL: Setting expiration timer for prefix "); PRINT6ADDR(&prefix); PRINTF("\n"); @@ -575,9 +621,11 @@ dao_input(void) if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { /* Check whether this is a DAO forwarding loop. */ p = rpl_find_parent(dag, &dao_sender_addr); - if(p != NULL && DAG_RANK(p->rank, dag) < DAG_RANK(dag->rank, dag)) { + /* check if this is a new DAO registration with an "illegal" rank */ + /* if we already route to this node it is likely */ + if(p != NULL && DAG_RANK(p->rank, instance) < DAG_RANK(dag->rank, instance)) { PRINTF("RPL: Loop detected when receiving a unicast DAO from a node with a lower rank! (%u < %u)\n", - DAG_RANK(p->rank, dag), DAG_RANK(dag->rank, dag)); + DAG_RANK(p->rank, instance), DAG_RANK(dag->rank, instance)); p->rank = INFINITE_RANK; p->updated = 1; return; @@ -593,7 +641,7 @@ dao_input(void) } } - rep->state.lifetime = RPL_LIFETIME(dag, lifetime); + rep->state.lifetime = RPL_LIFETIME(instance, lifetime); rep->state.learned_from = learned_from; if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { @@ -603,16 +651,18 @@ dao_input(void) PRINTF("\n"); uip_icmp6_send(&dag->preferred_parent->addr, ICMP6_RPL, RPL_CODE_DAO, buffer_length); - } else if(flags & RPL_DAO_K_FLAG) { - dao_ack_output(dag, &dao_sender_addr, sequence); + } + if(flags & RPL_DAO_K_FLAG) { + dao_ack_output(instance, &dao_sender_addr, sequence); } } } /*---------------------------------------------------------------------------*/ void -dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime) +dao_output(rpl_parent_t *n, uint8_t lifetime) { rpl_dag_t *dag; + rpl_instance_t *instance; unsigned char *buffer; uint8_t prefixlen; uip_ipaddr_t addr; @@ -626,7 +676,7 @@ dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime) } if(n == NULL) { - dag = rpl_get_dag(RPL_ANY_INSTANCE); + dag = rpl_get_any_dag(); if(dag == NULL) { PRINTF("RPL: Did not join a DAG before sending DAO\n"); return; @@ -635,19 +685,28 @@ dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime) dag = n->dag; } + instance = dag->instance; + buffer = UIP_ICMP_PAYLOAD; - ++dao_sequence; + RPL_LOLLIPOP_INCREMENT(dao_sequence); pos = 0; - buffer[pos++] = dag->instance_id; + buffer[pos++] = instance->instance_id; + buffer[pos] = 0; +#if RPL_DAO_SPECIFY_DODAG + buffer[pos] |= RPL_DAO_D_FLAG; +#endif /* RPL_DAO_SPECIFY_DODAG */ #if RPL_CONF_DAO_ACK - buffer[pos++] = RPL_DAO_K_FLAG; /* DAO ACK request, no DODAGID */ -#else - buffer[pos++] = 0; /* No DAO ACK request, no DODAGID */ -#endif + buffer[pos] |= RPL_DAO_K_FLAG; +#endif /* RPL_CONF_DAO_ACK */ + ++pos; buffer[pos++] = 0; /* reserved */ - buffer[pos++] = dao_sequence & 0xff; + buffer[pos++] = dao_sequence; +#if RPL_DAO_SPECIFY_DODAG + memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id)); + pos+=sizeof(dag->dag_id); +#endif /* RPL_DAO_SPECIFY_DODAG */ /* create target subopt */ prefixlen = sizeof(prefix) * CHAR_BIT; @@ -696,9 +755,6 @@ dao_ack_input(void) buffer = UIP_ICMP_PAYLOAD; buffer_length = uip_len - uip_l2_l3_icmp_hdr_len; -#if RPL_CONF_ADJUST_LLH_LEN - buffer_length+=UIP_LLH_LEN; //Add jackdaw, minimal-net ethernet header -#endif instance_id = buffer[0]; sequence = buffer[2]; @@ -711,7 +767,7 @@ dao_ack_input(void) } /*---------------------------------------------------------------------------*/ void -dao_ack_output(rpl_dag_t *dag, uip_ipaddr_t *dest, uint8_t sequence) +dao_ack_output(rpl_instance_t *instance, uip_ipaddr_t *dest, uint8_t sequence) { unsigned char *buffer; @@ -721,7 +777,7 @@ dao_ack_output(rpl_dag_t *dag, uip_ipaddr_t *dest, uint8_t sequence) buffer = UIP_ICMP_PAYLOAD; - buffer[0] = dag->instance_id; + buffer[0] = instance->instance_id; buffer[1] = 0; buffer[2] = sequence; buffer[3] = 0; diff --git a/core/net/rpl/rpl-of-etx.c b/core/net/rpl/rpl-of-etx.c index 55bbadca4..dfa7cfbfd 100644 --- a/core/net/rpl/rpl-of-etx.c +++ b/core/net/rpl/rpl-of-etx.c @@ -46,19 +46,21 @@ #include "net/rpl/rpl-private.h" #include "net/neighbor-info.h" -#define DEBUG DEBUG_NONE +#define DEBUG 1 #include "net/uip-debug.h" static void reset(rpl_dag_t *); static void parent_state_callback(rpl_parent_t *, int, int); static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); +static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *); static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t); -static void update_metric_container(rpl_dag_t *); +static void update_metric_container(rpl_instance_t *); rpl_of_t rpl_of_etx = { reset, parent_state_callback, best_parent, + best_dag, calculate_rank, update_metric_container, 1 @@ -86,14 +88,14 @@ typedef uint16_t rpl_path_metric_t; static rpl_path_metric_t calculate_path_metric(rpl_parent_t *p) { - if(p == NULL || (p->mc.obj.etx == 0 && p->rank > ROOT_RANK(p->dag))) { + if(p == NULL || (p->mc.obj.etx == 0 && p->rank > ROOT_RANK(p->dag->instance))) { return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR; } return p->mc.obj.etx + NI_ETX_TO_RPL_ETX(p->link_metric); } static void -reset(rpl_dag_t *dag) +reset(rpl_dag_t *sag) { } @@ -114,7 +116,7 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) } rank_increase = NEIGHBOR_INFO_FIX2ETX(INITIAL_LINK_METRIC) * DEFAULT_MIN_HOPRANKINC; } else { - rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric) * p->dag->min_hoprankinc; + rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric) * p->dag->instance->min_hoprankinc; if(base_rank == 0) { base_rank = p->rank; } @@ -132,6 +134,32 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) return new_rank; } +static rpl_dag_t * +best_dag(rpl_dag_t *d1, rpl_dag_t *d2) +{ + if(d1->grounded) { + if (!d2->grounded) { + return d1; + } + } else if(d2->grounded) { + return d2; + } + + if(d1->preference < d2->preference) { + return d2; + } else { + if(d1->preference > d2->preference) { + return d1; + } + } + + if(d2->rank < d1->rank) { + return d2; + } else { + return d1; + } +} + static rpl_parent_t * best_parent(rpl_parent_t *p1, rpl_parent_t *p2) { @@ -142,7 +170,7 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2) dag = p1->dag; /* Both parents must be in the same DAG. */ - min_diff = RPL_DAG_MC_ETX_DIVISOR / + min_diff = RPL_DAG_MC_ETX_DIVISOR / PARENT_SWITCH_THRESHOLD_DIV; p1_metric = calculate_path_metric(p1); @@ -164,18 +192,26 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2) } static void -update_metric_container(rpl_dag_t *dag) +update_metric_container(rpl_instance_t *instance) { rpl_path_metric_t path_metric; + rpl_dag_t *dag; #if RPL_DAG_MC == RPL_DAG_MC_ENERGY uint8_t type; #endif - dag->mc.flags = RPL_DAG_MC_FLAG_P; - dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE; - dag->mc.prec = 0; + instance->mc.flags = RPL_DAG_MC_FLAG_P; + instance->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE; + instance->mc.prec = 0; - if(dag->rank == ROOT_RANK(dag)) { + dag = instance->current_dag; + + if (!dag->joined) { + /* We should probably do something here */ + return; + } + + if(dag->rank == ROOT_RANK(instance)) { path_metric = 0; } else { path_metric = calculate_path_metric(dag->preferred_parent); @@ -183,27 +219,27 @@ update_metric_container(rpl_dag_t *dag) #if RPL_DAG_MC == RPL_DAG_MC_ETX - dag->mc.type = RPL_DAG_MC_ETX; - dag->mc.length = sizeof(dag->mc.obj.etx); - dag->mc.obj.etx = path_metric; + instance->mc.type = RPL_DAG_MC_ETX; + instance->mc.length = sizeof(instance->mc.obj.etx); + instance->mc.obj.etx = path_metric; PRINTF("RPL: My path ETX to the root is %u.%u\n", - dag->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR, - (dag->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR); + instance->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR, + (instance->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR); #elif RPL_DAG_MC == RPL_DAG_MC_ENERGY - dag->mc.type = RPL_DAG_MC_ENERGY; - dag->mc.length = sizeof(dag->mc.obj.energy); + instance->mc.type = RPL_DAG_MC_ENERGY; + instance->mc.length = sizeof(instance->mc.obj.energy); - if(dag->rank == ROOT_RANK(dag)) { + if(dag->rank == ROOT_RANK(instance)) { type = RPL_DAG_MC_ENERGY_TYPE_MAINS; } else { type = RPL_DAG_MC_ENERGY_TYPE_BATTERY; } - dag->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE; - dag->mc.obj.energy.energy_est = path_metric; + instance->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE; + instance->mc.obj.energy.energy_est = path_metric; #else diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index b9ea90a83..19ea4277c 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -48,6 +48,7 @@ static void reset(rpl_dag_t *); static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); +static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *); static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t); static void update_metric_container(rpl_dag_t *); @@ -55,6 +56,7 @@ rpl_of_t rpl_of0 = { reset, NULL, best_parent, + best_dag, calculate_rank, update_metric_container, 0 @@ -92,6 +94,32 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) } +static rpl_dag_t * +best_dag(rpl_dag_t *d1, rpl_dag_t *d2) +{ + if(d1->grounded) { + if (!d2->grounded) { + return d1; + } + } else if(d2->grounded) { + return d2; + } + + if(d1->preference < d2->preference) { + return d2; + } else { + if(d1->preference > d2->preference) { + return d1; + } + } + + if(d2->rank < d1->rank) { + return d2; + } else { + return d1; + } +} + static rpl_parent_t * best_parent(rpl_parent_t *p1, rpl_parent_t *p2) { @@ -127,7 +155,7 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2) } static void -update_metric_container(rpl_dag_t *dag) +update_metric_container(rpl_instance_t *instance) { - dag->mc.type = RPL_DAG_MC_NONE; + instance->mc.type = RPL_DAG_MC_NONE; } diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index db3ef8515..8d613330b 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -107,8 +107,8 @@ /* Default route lifetime as a multiple of the lifetime unit. */ #define RPL_DEFAULT_LIFETIME 0xff -#define RPL_LIFETIME(dag, lifetime) \ - ((unsigned long)(dag)->lifetime_unit * lifetime) +#define RPL_LIFETIME(instance, lifetime) \ + (((unsigned long)(instance)->lifetime_unit) * lifetime) #ifndef RPL_CONF_MIN_HOPRANKINC #define DEFAULT_MIN_HOPRANKINC 256 @@ -117,13 +117,13 @@ #endif #define DEFAULT_MAX_RANKINC (3 * DEFAULT_MIN_HOPRANKINC) -#define DAG_RANK(fixpt_rank, dag) ((fixpt_rank) / (dag)->min_hoprankinc) +#define DAG_RANK(fixpt_rank, instance) ((fixpt_rank) / (instance)->min_hoprankinc) /* Rank of a virtual root node that coordinates DAG root nodes. */ #define BASE_RANK 0 /* Rank of a root node. */ -#define ROOT_RANK(dag) (dag)->min_hoprankinc +#define ROOT_RANK(instance) (instance)->min_hoprankinc #define INFINITE_RANK 0xffff @@ -207,7 +207,7 @@ struct rpl_dio { uint8_t dag_intdoubl; uint8_t dag_intmin; uint8_t dag_redund; - rpl_lifetime_t default_lifetime; + uint8_t default_lifetime; uint16_t lifetime_unit; rpl_rank_t dag_max_rankinc; rpl_rank_t dag_min_hoprankinc; @@ -240,33 +240,50 @@ extern rpl_stats_t rpl_stats; #define RPL_STAT(code) #endif /* RPL_CONF_STATS */ /*---------------------------------------------------------------------------*/ +/* Instances */ +extern rpl_instance_t instance_table[]; +rpl_instance_t *default_instance; + /* ICMPv6 functions for RPL. */ void dis_output(uip_ipaddr_t *addr); -void dio_output(rpl_dag_t *, uip_ipaddr_t *uc_addr); -void dao_output(rpl_parent_t *, rpl_lifetime_t lifetime); -void dao_ack_output(rpl_dag_t *, uip_ipaddr_t *, uint8_t); +void dio_output(rpl_instance_t *, uip_ipaddr_t *uc_addr); +void dao_output(rpl_parent_t *, uint8_t lifetime); +void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t); void uip_rpl_input(void); +/* RPL Header Option */ +int rpl_verify_header(int uip_ext_opt_offset); +void rpl_update_header_empty(); +int rpl_update_header_final(uip_ipaddr_t *addr); + /* RPL logic functions. */ -void rpl_join_dag(rpl_dag_t *); -void rpl_local_repair(rpl_dag_t *dag); -int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from); +void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio); +void rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio); +void rpl_local_repair(rpl_instance_t *instance); void rpl_process_dio(uip_ipaddr_t *, rpl_dio_t *); -int rpl_process_parent_event(rpl_dag_t *, rpl_parent_t *); +int rpl_process_parent_event(rpl_instance_t *, rpl_parent_t *); /* DAG object management. */ -rpl_dag_t *rpl_alloc_dag(uint8_t); -void rpl_free_dag(rpl_dag_t *); +rpl_dag_t *rpl_alloc_dodag(uint8_t, uip_ipaddr_t *); +rpl_instance_t *rpl_alloc_instance(uint8_t); +void rpl_free_dodag(rpl_dag_t *); +void rpl_free_instance(rpl_instance_t *); /* DAG parent management function. */ rpl_parent_t *rpl_add_parent(rpl_dag_t *, rpl_dio_t *dio, uip_ipaddr_t *); rpl_parent_t *rpl_find_parent(rpl_dag_t *, uip_ipaddr_t *); -int rpl_remove_parent(rpl_dag_t *, rpl_parent_t *); +rpl_parent_t * rpl_find_parent_any_dag(rpl_instance_t *instance, uip_ipaddr_t *addr); +rpl_dag_t * rpl_find_parent_dag(rpl_instance_t *instance, uip_ipaddr_t *addr); +void rpl_nullify_parent(rpl_dag_t *, rpl_parent_t *); +void rpl_remove_parent(rpl_dag_t *, rpl_parent_t *); +void rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent); rpl_parent_t *rpl_select_parent(rpl_dag_t *dag); +rpl_dag_t *rpl_select_dodag(rpl_instance_t *instance,rpl_parent_t *parent); void rpl_recalculate_ranks(void); /* RPL routing table functions. */ void rpl_remove_routes(rpl_dag_t *dag); +void rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag); uip_ds6_route_t *rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, uip_ipaddr_t *next_hop); void rpl_purge_routes(void); @@ -275,8 +292,8 @@ void rpl_purge_routes(void); rpl_of_t *rpl_find_of(rpl_ocp_t); /* Timer functions. */ -void rpl_schedule_dao(rpl_dag_t *); -void rpl_reset_dio_timer(rpl_dag_t *, uint8_t); +void rpl_schedule_dao(rpl_instance_t *); +void rpl_reset_dio_timer(rpl_instance_t *, uint8_t); void rpl_reset_periodic_timer(void); /* Route poisoning. */ diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index dbb7d2392..c86618f3c 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -51,7 +51,7 @@ static struct ctimer periodic_timer; static void handle_periodic_timer(void *ptr); -static void new_dio_interval(rpl_dag_t *dag); +static void new_dio_interval(rpl_instance_t *instance); static void handle_dio_timer(void *ptr); static uint16_t next_dis; @@ -69,7 +69,7 @@ handle_periodic_timer(void *ptr) /* handle DIS */ #ifdef RPL_DIS_SEND next_dis++; - if(rpl_get_dag(RPL_ANY_INSTANCE) == NULL && next_dis >= RPL_DIS_INTERVAL) { + if(rpl_get_any_dag() == NULL && next_dis >= RPL_DIS_INTERVAL) { next_dis = 0; dis_output(NULL); } @@ -78,17 +78,17 @@ handle_periodic_timer(void *ptr) } /************************************************************************/ static void -new_dio_interval(rpl_dag_t *dag) +new_dio_interval(rpl_instance_t *instance) { uint32_t time; /* TODO: too small timer intervals for many cases */ - time = 1UL << dag->dio_intcurrent; + time = 1UL << instance->dio_intcurrent; /* Convert from milliseconds to CLOCK_TICKS. */ time = (time * CLOCK_SECOND) / 1000; - dag->dio_next_delay = time; + instance->dio_next_delay = time; /* random number between I/2 and I */ time = time >> 1; @@ -99,36 +99,36 @@ new_dio_interval(rpl_dag_t *dag) * operate efficiently. Therefore we need to calculate the delay between * the randomized time and the start time of the next interval. */ - dag->dio_next_delay -= time; - dag->dio_send = 1; + instance->dio_next_delay -= time; + instance->dio_send = 1; #if RPL_CONF_STATS /* keep some stats */ - dag->dio_totint++; - dag->dio_totrecv += dag->dio_counter; + 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(dag->rank, dag), - (10 * (dag->rank % dag->min_hoprankinc)) / dag->min_hoprankinc, - dag->version, - dag->dio_totint, dag->dio_totsend, - dag->dio_totrecv,dag->dio_intcurrent, - dag->rank == ROOT_RANK(dag) ? "BLUE" : "ORANGE"); + 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 */ - dag->dio_counter = 0; + instance->dio_counter = 0; /* schedule the timer */ PRINTF("RPL: Scheduling DIO timer %lu ticks in future (Interval)\n", time); - ctimer_set(&dag->dio_timer, time, &handle_dio_timer, dag); + ctimer_set(&instance->dio_timer, time, &handle_dio_timer, instance); } /************************************************************************/ static void handle_dio_timer(void *ptr) { - rpl_dag_t *dag; + rpl_instance_t *instance; - dag = (rpl_dag_t *)ptr; + instance = (rpl_instance_t *)ptr; PRINTF("RPL: DIO Timer triggered\n"); if(!dio_send_ok) { @@ -136,33 +136,33 @@ handle_dio_timer(void *ptr) dio_send_ok = 1; } else { PRINTF("RPL: Postponing DIO transmission since link local address is not ok\n"); - ctimer_set(&dag->dio_timer, CLOCK_SECOND, &handle_dio_timer, dag); + ctimer_set(&instance->dio_timer, CLOCK_SECOND, &handle_dio_timer, instance); return; } } - if(dag->dio_send) { + if(instance->dio_send) { /* send DIO if counter is less than desired redundancy */ - if(dag->dio_counter < dag->dio_redundancy) { + if(instance->dio_counter < instance->dio_redundancy) { #if RPL_CONF_STATS - dag->dio_totsend++; + instance->dio_totsend++; #endif /* RPL_CONF_STATS */ - dio_output(dag, NULL); + dio_output(instance, NULL); } else { PRINTF("RPL: Supressing DIO transmission (%d >= %d)\n", - dag->dio_counter, dag->dio_redundancy); + instance->dio_counter, instance->dio_redundancy); } - dag->dio_send = 0; - PRINTF("RPL: Scheduling DIO timer %u ticks in future (sent)\n", - dag->dio_next_delay); - ctimer_set(&dag->dio_timer, dag->dio_next_delay, handle_dio_timer, dag); + instance->dio_send = 0; + PRINTF("RPL: Scheduling DIO timer %"PRIu32" ticks in future (sent)\n", + instance->dio_next_delay); + ctimer_set(&instance->dio_timer, instance->dio_next_delay, handle_dio_timer, instance); } else { /* check if we need to double interval */ - if(dag->dio_intcurrent < dag->dio_intmin + dag->dio_intdoubl) { - dag->dio_intcurrent++; - PRINTF("RPL: DIO Timer interval doubled %d\n", dag->dio_intcurrent); + if(instance->dio_intcurrent < instance->dio_intmin + instance->dio_intdoubl) { + instance->dio_intcurrent++; + PRINTF("RPL: DIO Timer interval doubled %d\n", instance->dio_intcurrent); } - new_dio_interval(dag); + new_dio_interval(instance); } } /************************************************************************/ @@ -173,61 +173,63 @@ rpl_reset_periodic_timer(void) ctimer_set(&periodic_timer, CLOCK_SECOND, handle_periodic_timer, NULL); } /************************************************************************/ -/* Resets the DIO timer in the DAG to its minimal interval. */ +/* Resets the DIO timer in the instance to its minimal interval. */ void -rpl_reset_dio_timer(rpl_dag_t *dag, uint8_t force) +rpl_reset_dio_timer(rpl_instance_t *instance, uint8_t force) { +#if !RPL_LEAF_ONLY /* only reset if not just reset or started */ - if(force || dag->dio_intcurrent > dag->dio_intmin) { - dag->dio_counter = 0; - dag->dio_intcurrent = dag->dio_intmin; - new_dio_interval(dag); + if(force || instance->dio_intcurrent > instance->dio_intmin) { + instance->dio_counter = 0; + instance->dio_intcurrent = instance->dio_intmin; + new_dio_interval(instance); } #if RPL_CONF_STATS rpl_stats.resets++; -#endif +#endif /* RPL_CONF_STATS */ +#endif /* RPL_LEAF_ONLY */ } /************************************************************************/ static void handle_dao_timer(void *ptr) { - rpl_dag_t *dag; + rpl_instance_t *instance; - dag = (rpl_dag_t *)ptr; + instance = (rpl_instance_t *)ptr; if (!dio_send_ok && uip_ds6_get_link_local(ADDR_PREFERRED) == NULL) { PRINTF("RPL: Postpone DAO transmission... \n"); - ctimer_set(&dag->dao_timer, CLOCK_SECOND, handle_dao_timer, dag); + ctimer_set(&instance->dao_timer, CLOCK_SECOND, handle_dao_timer, instance); return; } /* Send the DAO to the DAO parent set -- the preferred parent in our case. */ - if(dag->preferred_parent != NULL) { + if(instance->current_dag->preferred_parent != NULL) { PRINTF("RPL: handle_dao_timer - sending DAO\n"); /* Set the route lifetime to the default value. */ - dao_output(dag->preferred_parent, dag->default_lifetime); + dao_output(instance->current_dag->preferred_parent, instance->default_lifetime); } else { PRINTF("RPL: No suitable DAO parent\n"); } - ctimer_stop(&dag->dao_timer); + ctimer_stop(&instance->dao_timer); } /************************************************************************/ void -rpl_schedule_dao(rpl_dag_t *dag) +rpl_schedule_dao(rpl_instance_t *instance) { clock_time_t expiration_time; - expiration_time = etimer_expiration_time(&dag->dao_timer.etimer); + expiration_time = etimer_expiration_time(&instance->dao_timer.etimer); - if(!etimer_expired(&dag->dao_timer.etimer)) { + if(!etimer_expired(&instance->dao_timer.etimer)) { PRINTF("RPL: DAO timer already scheduled\n"); } else { expiration_time = DEFAULT_DAO_LATENCY / 2 + (random_rand() % (DEFAULT_DAO_LATENCY)); PRINTF("RPL: Scheduling DAO timer %u ticks in the future\n", (unsigned)expiration_time); - ctimer_set(&dag->dao_timer, expiration_time, - handle_dao_timer, dag); + ctimer_set(&instance->dao_timer, expiration_time, + handle_dao_timer, instance); } } /************************************************************************/ diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 7c5e05d21..271136b62 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -57,6 +57,15 @@ rpl_stats_t rpl_stats; /************************************************************************/ extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_OP_BY_OP_LEN]) +#define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) + /************************************************************************/ void rpl_purge_routes(void) @@ -86,6 +95,23 @@ rpl_remove_routes(rpl_dag_t *dag) } } /************************************************************************/ +void +rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag) +{ + uip_ds6_route_t *locroute; + + for(locroute = uip_ds6_routing_table; + locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; + locroute++) { + if(locroute->isused + && uip_ipaddr_cmp(&locroute->nexthop, nexthop) + && locroute->state.dag == dag) { + locroute->isused = 0; + } + } + ANNOTATE("#L %u 0\n",nexthop->u8[sizeof(uip_ipaddr_t) - 1]); +} +/************************************************************************/ uip_ds6_route_t * rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, uip_ipaddr_t *next_hop) @@ -107,7 +133,7 @@ rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, uip_ipaddr_copy(&rep->nexthop, next_hop); } rep->state.dag = dag; - rep->state.lifetime = RPL_LIFETIME(dag, dag->default_lifetime); + rep->state.lifetime = RPL_LIFETIME(dag->instance, dag->instance->default_lifetime); rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL; PRINTF("RPL: Added a route to "); @@ -123,8 +149,9 @@ static void rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) { uip_ipaddr_t ipaddr; - rpl_dag_t *dag; rpl_parent_t *parent; + rpl_instance_t *instance; + rpl_instance_t *end; uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr); @@ -132,66 +159,55 @@ rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) PRINT6ADDR(&ipaddr); PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx)); - dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); - if(dag == NULL) { - return; - } + for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if ( instance->used == 1 ) { + parent = rpl_find_parent_any_dag(instance, &ipaddr); + if(!(parent == NULL)) { + /* Trigger DAG rank recalculation. */ + parent->updated = 1; + parent->link_metric = etx; - parent = rpl_find_parent(dag, &ipaddr); - if(parent == NULL) { - if(!known) { - PRINTF("RPL: Deleting routes installed by DAOs received from "); - PRINT6ADDR(&ipaddr); - PRINTF("\n"); - uip_ds6_route_rm_by_nexthop(&ipaddr); + if(instance->of->parent_state_callback != NULL) { + instance->of->parent_state_callback(parent, known, etx); + } + if(!known) { + PRINTF("RPL: Removing parent "); + PRINT6ADDR(&parent->addr); + PRINTF(" in instance %u because of bad connectivity (ETX %d)\n", instance->instance_id, etx); + parent->rank = INFINITE_RANK; + } + } } - return; } - /* Trigger DAG rank recalculation. */ - parent->updated = 1; - - parent->link_metric = etx; - - if(dag->of->parent_state_callback != NULL) { - dag->of->parent_state_callback(parent, known, etx); - } - - if(!known) { - PRINTF("RPL: Removing parent "); - PRINT6ADDR(&parent->addr); - PRINTF(" because of bad connectivity (ETX %d)\n", etx); - parent->rank = INFINITE_RANK; + if (!known) { + PRINTF("RPL: Deleting routes installed by DAOs received from "); + PRINT6ADDR(&ipaddr); + PRINTF("\n"); + uip_ds6_route_rm_by_nexthop(&ipaddr); } } /************************************************************************/ void rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr) { - rpl_dag_t *dag; rpl_parent_t *p; - - /* This only handles one DODAG - if multiple we need to check all */ - dag = rpl_get_dag(RPL_ANY_INSTANCE); - if(dag == NULL) { - return; - } - - /* if this is our default route then clean the dag->def_route state */ - if(dag->def_route != NULL && - uip_ipaddr_cmp(&dag->def_route->ipaddr, &nbr->ipaddr)) { - dag->def_route = NULL; - } + rpl_instance_t *instance; + rpl_instance_t *end; if(!nbr->isused) { PRINTF("RPL: Removing neighbor "); PRINT6ADDR(&nbr->ipaddr); PRINTF("\n"); - p = rpl_find_parent(dag, &nbr->ipaddr); - if(p != NULL) { - p->rank = INFINITE_RANK; - /* Trigger DAG rank recalculation. */ - p->updated = 1; + for( instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { + if ( instance->used == 1 ) { + p = rpl_find_parent_any_dag(instance, &nbr->ipaddr); + if(p != NULL) { + p->rank = INFINITE_RANK; + /* Trigger DAG rank recalculation. */ + p->updated = 1; + } + } } } } @@ -201,6 +217,7 @@ rpl_init(void) { uip_ipaddr_t rplmaddr; PRINTF("RPL started\n"); + default_instance=NULL; rpl_reset_periodic_timer(); neighbor_info_subscribe(rpl_link_neighbor_callback); @@ -214,3 +231,299 @@ rpl_init(void) #endif } /************************************************************************/ +int +rpl_verify_header(int uip_ext_opt_offset) +{ + rpl_instance_t *instance; + + if (UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) { + PRINTF("RPL: Bad header option (wrong length) !\n"); + return 1; + } + + if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_FWD_ERR) { + PRINTF("RPL: Forward error !\n"); + /* We should try to repair it, not implemented for the moment */ + return 2; + } + + instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); + + if (instance == NULL) { + PRINTF("RPL : Unknown instance : %u\n",UIP_EXT_HDR_OPT_RPL_BUF->instance); + return 1; + } + + if (!instance->current_dag->joined) { + PRINTF("RPL : No dag in the instance\n"); + return 1; + } + + if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_DOWN) { + PRINTF("RPL: Packet going down :\n"); + if (UIP_EXT_HDR_OPT_RPL_BUF->senderrank>instance->current_dag->rank) { + PRINTF("RPL: Loop detected : Sender rank > our rank\n"); + if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_RANK_ERR) { + PRINTF("RPL: Loop detected !\n"); + /* We should try to repair it, not implemented for the moment */ + return 3; + } + PRINTF("RPL: Single error tolerated\n"); + UIP_EXT_HDR_OPT_RPL_BUF->flags|=RPL_HDR_OPT_RANK_ERR; + return 0; + } + } else { + PRINTF("RPL: Packet going up :"); + if (UIP_EXT_HDR_OPT_RPL_BUF->senderrankcurrent_dag->rank) { + PRINTF("RPL: Rank error : Sender rank < our rank\n"); + if (UIP_EXT_HDR_OPT_RPL_BUF->flags&RPL_HDR_OPT_RANK_ERR) { + PRINTF("RPL: Loop detected !\n"); + /* We should try to repair it, not implemented for the moment */ + return 3; + } + PRINTF("RPL: Single error tolerated\n"); + UIP_EXT_HDR_OPT_RPL_BUF->flags|=RPL_HDR_OPT_RANK_ERR; + return 0; + } + } + PRINTF("RPL: rank Ok\n"); + return 0; +} +/************************************************************************/ +void +rpl_update_header_empty(void) +{ + rpl_instance_t *instance; + int uip_ext_opt_offset; + int last_uip_ext_len; + u8_t temp_len; + + last_uip_ext_len=uip_ext_len; + uip_ext_len=0; + uip_ext_opt_offset = 2; + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto){ + case UIP_PROTO_HBHO: + if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); + uip_ext_len=last_uip_ext_len; + return; + } + instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); + if(instance == NULL || (!instance->used) || (!instance->current_dag->joined) ) { + PRINTF("Unable to add RPL hop-by-hop extension header : incorrect instance\n"); + return; + } + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found, creating it\n"); + if(uip_len + RPL_OP_BY_OP_LEN >UIP_LINK_MTU) { + PRINTF("RPL: Packet too long : impossible to add rpl Hop-by-Hop option\n"); + uip_ext_len=last_uip_ext_len; + return; + } + memmove(UIP_HBHO_NEXT_BUF,UIP_EXT_BUF,uip_len-UIP_IPH_LEN); + memset(UIP_HBHO_BUF,0,RPL_OP_BY_OP_LEN); + UIP_HBHO_BUF->next=UIP_IP_BUF->proto; + UIP_IP_BUF->proto=UIP_PROTO_HBHO; + UIP_HBHO_BUF->len=RPL_OP_BY_OP_LEN - 8; + UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags=0; + UIP_EXT_HDR_OPT_RPL_BUF->instance=0; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=0; + uip_len+=RPL_OP_BY_OP_LEN; + temp_len=UIP_IP_BUF->len[1]; + UIP_IP_BUF->len[1]+=(UIP_HBHO_BUF->len + 8); + if (UIP_IP_BUF->len[1]len[0]+=1; + } + uip_ext_len=last_uip_ext_len+RPL_OP_BY_OP_LEN; + return; + } + switch (UIP_EXT_HDR_OPT_BUF->type) { + case UIP_EXT_HDR_OPT_RPL: + PRINTF("RPL: Updating RPL option\n"); + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; + uip_ext_len=last_uip_ext_len; + return; + default: + PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); + uip_ext_len=last_uip_ext_len; + return; + } +} +/************************************************************************/ +int +rpl_update_header_final(uip_ipaddr_t *addr) +{ + int uip_ext_opt_offset; + int last_uip_ext_len; + + last_uip_ext_len=uip_ext_len; + uip_ext_len=0; + uip_ext_opt_offset = 2; + rpl_parent_t *parent; + + if (UIP_IP_BUF->proto == UIP_PROTO_HBHO){ + if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } + if (UIP_EXT_HDR_OPT_BUF->type == UIP_EXT_HDR_OPT_RPL) { + if (UIP_EXT_HDR_OPT_RPL_BUF->senderrank==0) { + PRINTF("RPL: Updating RPL option\n"); + if(default_instance == NULL || (!default_instance->used) || (!default_instance->current_dag->joined) ) { + PRINTF("Unable to add RPL hop-by-hop extension header : incorrect default instance\n"); + return 1; + } + parent=rpl_find_parent(default_instance->current_dag,addr); + if (parent == NULL || (parent != parent->dag->preferred_parent)) { + UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN; + } + UIP_EXT_HDR_OPT_RPL_BUF->instance=default_instance->instance_id; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=default_instance->current_dag->rank; + uip_ext_len=last_uip_ext_len; + } + } + } + return 0; +} +/************************************************************************/ +int +rpl_add_header(rpl_instance_t *instance,int down) +{ + int uip_ext_opt_offset; + int last_uip_ext_len; + u8_t temp_len; + + last_uip_ext_len = uip_ext_len; + uip_ext_len = 0; + uip_ext_opt_offset = 2; + + if(instance == NULL || (!instance->used) || (!instance->current_dag->joined) ) { + PRINTF("Unable to add RPL hop-by-hop extension header : incorrect instance\n"); + return 0; + } + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto){ + case UIP_PROTO_HBHO: + if (UIP_HBHO_BUF->len != RPL_OP_BY_OP_LEN - 8) { + PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found, creating it\n"); + if(uip_len + RPL_OP_BY_OP_LEN >UIP_LINK_MTU) { + PRINTF("RPL: Packet too long : impossible to add rpl Hop-by-Hop option\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } + memmove(UIP_HBHO_NEXT_BUF,UIP_EXT_BUF,uip_len-UIP_IPH_LEN); + memset(UIP_HBHO_BUF,0,RPL_OP_BY_OP_LEN); + UIP_HBHO_BUF->next=UIP_IP_BUF->proto; + UIP_IP_BUF->proto=UIP_PROTO_HBHO; + UIP_HBHO_BUF->len=RPL_OP_BY_OP_LEN - 8; + UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN&(down<instance=instance->instance_id; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; + uip_len+=RPL_OP_BY_OP_LEN; + temp_len=UIP_IP_BUF->len[1]; + UIP_IP_BUF->len[1]+=(UIP_HBHO_BUF->len + 8); + if (UIP_IP_BUF->len[1]len[0]+=1; + } + uip_ext_len=last_uip_ext_len+RPL_OP_BY_OP_LEN; + return 1; + } + switch (UIP_EXT_HDR_OPT_BUF->type) { + case UIP_EXT_HDR_OPT_RPL: + PRINTF("RPL: Updating RPL option\n"); + UIP_EXT_HDR_OPT_RPL_BUF->opt_type=UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len=RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags=RPL_HDR_OPT_DOWN&(down<instance=instance->instance_id; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; + uip_ext_len=last_uip_ext_len; + return 1; + default: + PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } +} +/************************************************************************/ +int +rpl_add_header_root(void) +{ + return rpl_add_header(default_instance,1); +} +/************************************************************************/ +void +rpl_remove_header() +{ + int last_uip_ext_len; + u8_t temp_len; + + last_uip_ext_len=uip_ext_len; + uip_ext_len=0; + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto){ + case UIP_PROTO_HBHO: + PRINTF("RPL: Removing the present RPL header option\n"); + UIP_IP_BUF->proto=UIP_HBHO_BUF->next; + temp_len=UIP_IP_BUF->len[1]; + uip_len-=UIP_HBHO_BUF->len + 8; + UIP_IP_BUF->len[1]-=(UIP_HBHO_BUF->len + 8); + if (UIP_IP_BUF->len[1]>temp_len) { + UIP_IP_BUF->len[0]-=1; + } + memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN); + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found\n"); + } +} +/************************************************************************/ +u8_t +rpl_invert_header() +{ + u8_t uip_ext_opt_offset; + u8_t last_uip_ext_len; + + last_uip_ext_len=uip_ext_len; + uip_ext_len=0; + uip_ext_opt_offset = 2; + + PRINTF("RPL: Verifying the presence of the RPL header option\n"); + switch(UIP_IP_BUF->proto){ + case UIP_PROTO_HBHO: + break; + default: + PRINTF("RPL: No Hop-by-Hop Option found\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } + switch (UIP_EXT_HDR_OPT_BUF->type) { + case UIP_EXT_HDR_OPT_RPL: + PRINTF("RPL: Updating RPL option (Inverting Up<->Down)\n"); + UIP_EXT_HDR_OPT_RPL_BUF->flags&=RPL_HDR_OPT_DOWN; + UIP_EXT_HDR_OPT_RPL_BUF->flags^=RPL_HDR_OPT_DOWN; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank=rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance)->current_dag->rank; + uip_ext_len=last_uip_ext_len; + return RPL_OP_BY_OP_LEN; + default: + PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); + uip_ext_len=last_uip_ext_len; + return 0; + } +} +/************************************************************************/ diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index bcc600b48..d8f98c780 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -75,17 +75,86 @@ /* This value decides which DAG instance we should participate in by default. */ #define RPL_DEFAULT_INSTANCE 0 -/* This value is used to access an arbitrary DAG. It will likely be - replaced when we support multiple DAGs more. */ -#define RPL_ANY_INSTANCE -1 +/* + * This value decides if this node must stay as a leaf or not + * as allowed by draft-ietf-roll-rpl-19#section-8.5 + */ +#ifdef RPL_CONF_LEAF_ONLY +#define RPL_LEAF_ONLY RPL_CONF_LEAF_ONLY +#else +#define RPL_LEAF_ONLY 0 +#endif + +/* + * Maximum of concurent rpl-instances + */ +#ifndef RPL_CONF_MAX_INSTANCES +#define RPL_MAX_INSTANCES 1 +#else +#define RPL_MAX_INSTANCES RPL_CONF_MAX_INSTANCES +#endif /* !RPL_CONF_MAX_INSTANCES */ + +/* + * Maximum of concurent dodag inside an instance + */ +#ifndef RPL_CONF_MAX_DODAG_PER_INSTANCE +#define RPL_MAX_DODAG_PER_INSTANCE 2 +#else +#define RPL_MAX_DODAG_PER_INSTANCE RPL_CONF_MAX_DODAG_PER_INSTANCE +#endif /* !RPL_CONF_MAX_DODAG_PER_INSTANCE */ + +/* + * + */ +#ifndef RPL_CONF_DAO_SPECIFY_DODAG +#if RPL_MAX_DODAG_PER_INSTANCE > 1 +#define RPL_DAO_SPECIFY_DODAG 1 +#else /* RPL_MAX_DODAG_PER_INSTANCE > 1*/ +#define RPL__DAO_SPECIFY_DODAG 0 +#endif /* RPL_MAX_DODAG_PER_INSTANCE > 1 */ +#else /* RPL_CONF_DAO_SPECIFY_DODAG */ +#define RPL_DAO_SPECIFY_DODAG RPL_CONF_DAO_SPECIFY_DODAG +#endif /* RPL_CONF_DAO_SPECIFY_DODAG */ + + /*---------------------------------------------------------------------------*/ /* The amount of parents that this node has in a particular DAG. */ #define RPL_PARENT_COUNT(dag) list_length((dag)->parents) /*---------------------------------------------------------------------------*/ typedef uint16_t rpl_rank_t; -typedef uint8_t rpl_lifetime_t; typedef uint16_t rpl_ocp_t; +/*---------------------------------------------------------------------------*/ +/* Lollipop counters */ + +#define RPL_LOLLIPOP_MAX_VALUE 255 +#define RPL_LOLLIPOP_CIRCULAR_REGION 127 +#define RPL_LOLLIPOP_SEQUENCE_WINDOWS 16 +#define RPL_LOLLIPOP_INIT RPL_LOLLIPOP_MAX_VALUE - RPL_LOLLIPOP_SEQUENCE_WINDOWS + 1 +#define RPL_LOLLIPOP_INCREMENT(counter) (counter > RPL_LOLLIPOP_CIRCULAR_REGION ?\ + (counter == RPL_LOLLIPOP_MAX_VALUE ? counter=0 : ++counter):\ + (counter == RPL_LOLLIPOP_CIRCULAR_REGION ? counter=0 : ++counter)) +#define RPL_LOLLIPOP_IS_INIT(counter) (counter > RPL_LOLLIPOP_CIRCULAR_REGION) +#define RPL_LOLLIPOP_GREATER_THAN_LOCAL(A,B) (((A < B) && (RPL_LOLLIPOP_CIRCULAR_REGION + 1 - B + A < RPL_LOLLIPOP_SEQUENCE_WINDOWS)) || \ + ((A > B) && (A - B < RPL_LOLLIPOP_SEQUENCE_WINDOWS))) +#define RPL_LOLLIPOP_GREATER_THAN(A,B) ((A > RPL_LOLLIPOP_CIRCULAR_REGION )?\ + ((B > RPL_LOLLIPOP_CIRCULAR_REGION )?\ + RPL_LOLLIPOP_GREATER_THAN_LOCAL(A,B):\ + 0):\ + ((B > RPL_LOLLIPOP_CIRCULAR_REGION )?\ + 1:\ + RPL_LOLLIPOP_GREATER_THAN_LOCAL(A,B))) + +/*---------------------------------------------------------------------------*/ +/* RPL IPv6 extension header option. */ +#define RPL_HDR_OPT_LEN 4 +#define RPL_OP_BY_OP_LEN RPL_HDR_OPT_LEN+2+2 +#define RPL_HDR_OPT_DOWN 0x80 +#define RPL_HDR_OPT_DOWN_SHIFT 7 +#define RPL_HDR_OPT_RANK_ERR 0x40 +#define RPL_HDR_OPT_RANK_ERR_SHIFT 6 +#define RPL_HDR_OPT_FWD_ERR 0x20 +#define RPL_HDR_OPT_FWD_ERR_SHIFT 5 /*---------------------------------------------------------------------------*/ /* DAG Metric Container Object Types, to be confirmed by IANA. */ #define RPL_DAG_MC_NONE 0 /* Local identifier for empty MC */ @@ -139,6 +208,7 @@ struct rpl_metric_container { }; typedef struct rpl_metric_container rpl_metric_container_t; /*---------------------------------------------------------------------------*/ +struct rpl_instance; struct rpl_dag; /*---------------------------------------------------------------------------*/ struct rpl_parent { @@ -153,6 +223,35 @@ struct rpl_parent { }; typedef struct rpl_parent rpl_parent_t; /*---------------------------------------------------------------------------*/ +/* RPL DIO prefix suboption */ +struct rpl_prefix { + uip_ipaddr_t prefix; + uint32_t lifetime; + uint8_t length; + uint8_t flags; +}; +typedef struct rpl_prefix rpl_prefix_t; +/*---------------------------------------------------------------------------*/ +/* Directed Acyclic Graph */ +struct rpl_dag { + uip_ipaddr_t dag_id; + rpl_rank_t min_rank; /* should be reset per DODAG iteration! */ + uint8_t version; + uint8_t grounded; + uint8_t preference; + uint8_t used; + /* live data for the DAG */ + uint8_t joined; + rpl_parent_t *preferred_parent; + rpl_rank_t rank; + struct rpl_instance *instance; + void *parent_list; + list_t parents; + rpl_prefix_t prefix_info; +}; +typedef struct rpl_dag rpl_dag_t; +typedef struct rpl_instance rpl_instance_t; +/*---------------------------------------------------------------------------*/ /* * API for RPL objective functions (OF) * @@ -171,6 +270,10 @@ typedef struct rpl_parent rpl_parent_t; * * Compares two parents and returns the best one, according to the OF. * + * best_dag(dodag1, dodag2) + * + * Compares two dodags and returns the best one, according to the OF. + * * calculate_rank(parent, base_rank) * * Calculates a rank value using the parent rank and a base rank. @@ -188,47 +291,33 @@ struct rpl_of { void (*reset)(struct rpl_dag *); void (*parent_state_callback)(rpl_parent_t *, int, int); rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *); + rpl_dag_t *(*best_dag)(rpl_dag_t *, rpl_dag_t *); rpl_rank_t (*calculate_rank)(rpl_parent_t *, rpl_rank_t); - void (*update_metric_container)(struct rpl_dag *); + void (*update_metric_container)( rpl_instance_t *); rpl_ocp_t ocp; }; typedef struct rpl_of rpl_of_t; /*---------------------------------------------------------------------------*/ -/* RPL DIO prefix suboption */ -struct rpl_prefix { - uip_ipaddr_t prefix; - uint32_t lifetime; - uint8_t length; - uint8_t flags; -}; -typedef struct rpl_prefix rpl_prefix_t; -/*---------------------------------------------------------------------------*/ -/* Directed Acyclic Graph */ -struct rpl_dag { +/* Instance */ +struct rpl_instance { /* DAG configuration */ rpl_metric_container_t mc; rpl_of_t *of; - uip_ipaddr_t dag_id; + uint8_t instance_id; + rpl_dag_t *current_dag; + uint8_t used; + rpl_dag_t dag_table[RPL_MAX_DODAG_PER_INSTANCE]; /* The current default router - used for routing "upwards" */ uip_ds6_defrt_t *def_route; - rpl_rank_t rank; - rpl_rank_t min_rank; /* should be reset per DODAG iteration! */ uint8_t dtsn_out; - uint8_t instance_id; - uint8_t version; - uint8_t grounded; uint8_t mop; - uint8_t preference; uint8_t dio_intdoubl; uint8_t dio_intmin; uint8_t dio_redundancy; rpl_rank_t max_rankinc; rpl_rank_t min_hoprankinc; - uint8_t used; uint8_t default_lifetime; uint16_t lifetime_unit; /* lifetime in seconds = l_u * d_l */ - /* live data for the DAG */ - uint8_t joined; uint8_t dio_intcurrent; uint8_t dio_send; /* for keeping track of which mode the timer is in */ @@ -241,19 +330,21 @@ struct rpl_dag { uint32_t dio_next_delay; /* delay for completion of dio interval */ struct ctimer dio_timer; struct ctimer dao_timer; - rpl_parent_t *preferred_parent; - void *parent_list; - list_t parents; - rpl_prefix_t prefix_info; }; -typedef struct rpl_dag rpl_dag_t; + /*---------------------------------------------------------------------------*/ /* Public RPL functions. */ void rpl_init(void); -rpl_dag_t *rpl_set_root(uip_ipaddr_t *); +rpl_dag_t *rpl_set_root(uint8_t instance_id, uip_ipaddr_t * dag_id); int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len); -int rpl_repair_dag(rpl_dag_t *dag); -int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from); -rpl_dag_t *rpl_get_dag(int instance_id); +int rpl_repair_root(uint8_t instance_id); +int rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from); +rpl_dag_t *rpl_get_any_dag(void); +rpl_dag_t *rpl_get_dodag(uint8_t instance_id,uip_ipaddr_t * dag_id); +rpl_instance_t *rpl_get_instance(uint8_t instance_id); +int rpl_add_header(rpl_instance_t *instance,int down); +int rpl_add_header_root(void); +void rpl_remove_header(void); +u8_t rpl_invert_header(void); /*---------------------------------------------------------------------------*/ #endif /* RPL_H */ diff --git a/examples/ipv6/rpl-border-router/border-router.c b/examples/ipv6/rpl-border-router/border-router.c index a7a31f48e..c3894b22f 100644 --- a/examples/ipv6/rpl-border-router/border-router.c +++ b/examples/ipv6/rpl-border-router/border-router.c @@ -227,7 +227,7 @@ PROCESS_THREAD(border_router_process, ev, data) PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); } - dag = rpl_set_root((uip_ip6addr_t *)dag_id); + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)dag_id); if(dag != NULL) { rpl_set_prefix(dag, &prefix, 64); PRINTF("created a new RPL dag\n"); @@ -245,7 +245,7 @@ PROCESS_THREAD(border_router_process, ev, data) PROCESS_YIELD(); if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiating global repair\n"); - rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); + rpl_repair_root(RPL_DEFAULT_INSTANCE); } } diff --git a/examples/ipv6/rpl-collect/udp-sender.c b/examples/ipv6/rpl-collect/udp-sender.c index 6652f5f0b..0755bf1bb 100644 --- a/examples/ipv6/rpl-collect/udp-sender.c +++ b/examples/ipv6/rpl-collect/udp-sender.c @@ -71,7 +71,8 @@ collect_common_net_print(void) { rpl_dag_t *dag; int i; - dag = rpl_get_dag(RPL_ANY_INSTANCE); + /* Let's suppose we have only one instance */ + dag = rpl_get_any_dag(); if(dag->preferred_parent != NULL) { PRINTF("Preferred parent: "); PRINT6ADDR(&dag->preferred_parent->addr); @@ -128,7 +129,8 @@ collect_common_send(void) rimeaddr_copy(&parent, &rimeaddr_null); parent_etx = 0; - dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); + /* Let's suppose we have only one instance */ + dag = rpl_get_any_dag(); if(dag != NULL) { preferred_parent = dag->preferred_parent; if(preferred_parent != NULL) { diff --git a/examples/ipv6/rpl-collect/udp-sink.c b/examples/ipv6/rpl-collect/udp-sink.c index 11a4f7346..b2251b4ff 100644 --- a/examples/ipv6/rpl-collect/udp-sink.c +++ b/examples/ipv6/rpl-collect/udp-sink.c @@ -151,8 +151,7 @@ PROCESS_THREAD(udp_server_process, ev, data) root_if = uip_ds6_addr_lookup(&ipaddr); if(root_if != NULL) { rpl_dag_t *dag; - rpl_set_root((uip_ip6addr_t *)&ipaddr); - dag = rpl_get_dag(RPL_ANY_INSTANCE); + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &ipaddr, 64); PRINTF("created a new RPL dag\n"); @@ -181,7 +180,7 @@ PROCESS_THREAD(udp_server_process, ev, data) tcpip_handler(); } else if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiaing global repair\n"); - rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); + rpl_repair_root(RPL_DEFAULT_INSTANCE); } } diff --git a/examples/ipv6/rpl-udp/udp-server.c b/examples/ipv6/rpl-udp/udp-server.c index 2ce2a046d..36c9aa4ad 100644 --- a/examples/ipv6/rpl-udp/udp-server.c +++ b/examples/ipv6/rpl-udp/udp-server.c @@ -134,8 +134,7 @@ PROCESS_THREAD(udp_server_process, ev, data) root_if = uip_ds6_addr_lookup(&ipaddr); if(root_if != NULL) { rpl_dag_t *dag; - rpl_set_root((uip_ip6addr_t *)&ipaddr); - dag = rpl_get_dag(RPL_ANY_INSTANCE); + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &ipaddr, 64); PRINTF("created a new RPL dag\n"); @@ -164,7 +163,7 @@ PROCESS_THREAD(udp_server_process, ev, data) tcpip_handler(); } else if (ev == sensors_event && data == &button_sensor) { PRINTF("Initiaing global repair\n"); - rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); + rpl_repair_root(RPL_DEFAULT_INSTANCE); } } diff --git a/platform/avr-ravenusb/cdc_task.c b/platform/avr-ravenusb/cdc_task.c index a53b8e400..c39e6bf27 100644 --- a/platform/avr-ravenusb/cdc_task.c +++ b/platform/avr-ravenusb/cdc_task.c @@ -620,11 +620,11 @@ extern uip_ds6_netif_t uip_ds6_if; } case 'G': - PRINTF_P(PSTR("Global repair returns %d\n\r"),rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE))); + PRINTF_P(PSTR("Global repair returns %d\n\r"),rpl_repair_root(RPL_DEFAULT_INSTANCE)); break; case 'L': - rpl_local_repair(rpl_get_dag(RPL_ANY_INSTANCE)); + rpl_local_repair(rpl_get_any_dag()); PRINTF_P(PSTR("Local repair initiated\n\r")); break; diff --git a/platform/avr-ravenusb/contiki-raven-main.c b/platform/avr-ravenusb/contiki-raven-main.c index 9884a13da..f949765be 100644 --- a/platform/avr-ravenusb/contiki-raven-main.c +++ b/platform/avr-ravenusb/contiki-raven-main.c @@ -164,7 +164,7 @@ PROCESS_THREAD(border_router_process, ev, data) { rpl_dag_t *dag; char buf[sizeof(dag_id)]; memcpy_P(buf,dag_id,sizeof(dag_id)); - dag = rpl_set_root((uip_ip6addr_t *)buf); + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)buf); /* Assign separate addresses to the jackdaw uip stack and the host network interface, but with the same prefix */ /* E.g. bbbb::200 to the jackdaw and bbbb::1 to the host network interface with $ip -6 address add bbbb::1/64 dev usb0 */ @@ -192,8 +192,6 @@ PROCESS_THREAD(border_router_process, ev, data) while(1) { PROCESS_YIELD(); /* Local and global dag repair can be done from the jackdaw menu */ - // rpl_set_prefix(rpl_get_dag(RPL_ANY_INSTANCE), &ipaddr, 64); - // rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); } diff --git a/platform/mb851/contiki-init-net.c b/platform/mb851/contiki-init-net.c index f40513c88..4d81f9c58 100644 --- a/platform/mb851/contiki-init-net.c +++ b/platform/mb851/contiki-init-net.c @@ -120,7 +120,7 @@ void set_net_address(void) print_addresses(); #if RPL_BORDER_ROUTER - dag = rpl_set_root(&ipaddr); + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,&ipaddr); if(dag != NULL) { PRINTF("This node is setted as root of a DAG.\r\n"); } @@ -133,4 +133,4 @@ void set_net_address(void) #endif /* FIXED_GLOBAL_ADDRESS */ -#endif /* UIP_CONF_IPV6 */ \ No newline at end of file +#endif /* UIP_CONF_IPV6 */