diff --git a/core/net/rpl/Makefile.rpl b/core/net/rpl/Makefile.rpl index 9a69f9513..7c6b33c98 100644 --- a/core/net/rpl/Makefile.rpl +++ b/core/net/rpl/Makefile.rpl @@ -1 +1 @@ -CONTIKI_SOURCEFILES += rpl.c rpl-dag.c rpl-icmp6.c rpl-timers.c rpl-of0.c +CONTIKI_SOURCEFILES += rpl.c rpl-dag.c rpl-icmp6.c rpl-timers.c rpl-of-etx.c diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 3e7c848da..f3c3f63c0 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -32,7 +32,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rpl-dag.c,v 1.9 2010/05/25 21:58:54 nvt-se Exp $ + * $Id: rpl-dag.c,v 1.10 2010/05/29 22:23:21 nvt-se Exp $ */ /** * \file @@ -57,12 +57,9 @@ #include "net/uip-debug.h" /************************************************************************/ -#ifdef RPL_CONF_OBJECTIVE_FUNCTION -#define RPL_OF RPL_CONF_OBJECTIVE_FUNCTION -#else -extern rpl_of_t rpl_of0; -#define RPL_OF rpl_of0 -#endif /* RPL_CONF_OBJECTIVE_FUNCTION */ +extern rpl_of_t rpl_of_etx; +static rpl_of_t *objective_functions[] = {&rpl_of_etx, NULL}; +/************************************************************************/ #ifndef RPL_CONF_MAX_DAG_ENTRIES #define RPL_MAX_DAG_ENTRIES 2 @@ -124,7 +121,7 @@ poison_routes(rpl_dag_t *dag, rpl_parent_t *exception) } } /************************************************************************/ -int +rpl_dag_t * rpl_set_root(uip_ipaddr_t *dag_id) { rpl_dag_t *dag; @@ -138,7 +135,7 @@ rpl_set_root(uip_ipaddr_t *dag_id) dag = rpl_alloc_dag(); if(dag == NULL) { PRINTF("RPL: Failed to allocate a DAG\n"); - return -1; + return NULL; } dag->joined = 1; @@ -159,7 +156,7 @@ rpl_set_root(uip_ipaddr_t *dag_id) rpl_reset_dio_timer(dag, 1); - return 0; + return dag; } /************************************************************************/ int @@ -359,9 +356,14 @@ rpl_find_dag(unsigned char aucIndex) rpl_of_t * rpl_find_of(rpl_ocp_t ocp) { - if(RPL_OF.ocp == ocp) { - return &RPL_OF; + rpl_of_t *of; + + for(of = objective_functions[0]; of != NULL; of++) { + if(of->ocp == ocp) { + return of; + } } + return NULL; } /************************************************************************/ @@ -438,7 +440,7 @@ join_dag(uip_ipaddr_t *from, rpl_dio_t *dio) rpl_set_default_route(dag, from); - if(dio->dst_adv_trigger) { + if(dio->dst_adv_supported && dio->dst_adv_trigger) { rpl_schedule_dao(dag); } else { PRINTF("RPL: dst_adv_trigger not set in incoming DIO!\n"); @@ -511,7 +513,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) /* This DIO pertains to a DAG that we are already part of. */ p = rpl_find_parent(dag, from); if(p != NULL) { - if(dio->dst_adv_trigger) { + if(dio->dst_adv_supported && dio->dst_adv_trigger) { rpl_schedule_dao(dag); } else { PRINTF("RPL: dst_adv_trigger is not set in incoming DIO\n"); @@ -598,7 +600,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) node is in the parent list, we just remove it. */ if(p != NULL && p->rank < dio->dag_rank) { PRINTF("RPL: Parent "); - PRINT6ADDR(&n->addr); + PRINT6ADDR(&p->addr); PRINTF(" has increased in rank from %hu to %hu. Removing it.\n", p->rank, dio->dag_rank); rpl_remove_parent(dag, p); diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 48c75fdd8..bed435bc1 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -33,7 +33,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rpl-icmp6.c,v 1.11 2010/05/25 21:58:54 nvt-se Exp $ + * $Id: rpl-icmp6.c,v 1.12 2010/05/29 22:23:21 nvt-se Exp $ */ /** * \file @@ -323,8 +323,8 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr) buffer[pos++] = RPL_DIO_SUBOPT_OCP; buffer[pos++] = 0; buffer[pos++] = 2; - buffer[pos++] = 0; - buffer[pos++] = 0; + buffer[pos++] = dag->of->ocp >> 8; + buffer[pos++] = dag->of->ocp & 0xff; /* alignment here ??? */ diff --git a/core/net/rpl/rpl-of-etx.c b/core/net/rpl/rpl-of-etx.c new file mode 100644 index 000000000..34b5ed7c8 --- /dev/null +++ b/core/net/rpl/rpl-of-etx.c @@ -0,0 +1,121 @@ +/** + * \addtogroup uip6 + * @{ + */ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: rpl-of-etx.c,v 1.1 2010/05/29 22:23:21 nvt-se Exp $ + */ +/** + * \file + * An implementation of RPL's objective function 1 (ETX). + * + * \author Joakim Eriksson , Nicolas Tsiftes + */ + +#include "net/rpl/rpl.h" + +#define DEBUG DEBUG_ANNOTATE +#include "net/uip-debug.h" + +static void parent_state_callback(rpl_parent_t *, int, int); +static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); +static rpl_rank_t increment_rank(rpl_rank_t, rpl_parent_t *); + +rpl_of_t rpl_of_etx = { + parent_state_callback, + best_parent, + increment_rank, + 1 +}; + +#define LINK_ETX_MIN 1 +#define LINK_ETX_MAX 10 +#define PATH_ETX_MIN 1 +#define PATH_ETX_MAX 200 +#define PARENT_SWITCH_ETX_THRESHOLD 0.5 +#define INFINITY 255 + +typedef unsigned char etx_t; + +static etx_t min_path_etx = INFINITY; + +static void +parent_state_callback(rpl_parent_t *parent, int known, int etx) +{ + rpl_dag_t *dag; + + dag = (rpl_dag_t *)parent->dag; + + if(known) { + if(min_path_etx != INFINITY) { + dag->rank = min_path_etx + etx; + PRINTF("RPL: New path ETX: %u\n", (unsigned)(min_path_etx + etx)); + } + } else { + if(RPL_PARENT_COUNT(dag) == 1) { + /* Our last parent has disappeared, set the path ETX to infinity. */ + min_path_etx = INFINITY; + } + } +} + +static rpl_rank_t +increment_rank(rpl_rank_t rank, rpl_parent_t *parent) +{ + rpl_rank_t new_rank; + + PRINTF("RPL: OF1 increment rank\n"); + + if(parent->rank < min_path_etx) { + min_path_etx = parent->rank; + } + + new_rank = parent->rank + LINK_ETX_MAX; + + if(new_rank < rank) { + return INFINITE_RANK; + } + + PRINTF("RPL: Path ETX %u\n", (unsigned)new_rank); + + return new_rank; +} + +static rpl_parent_t * +best_parent(rpl_parent_t *p1, rpl_parent_t *p2) +{ + if(p1->rank < p2->rank) { + return p1; + } + + return p2; +} diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index d9ad5e4b9..8a924cd7a 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -32,7 +32,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rpl-of0.c,v 1.2 2010/05/25 21:58:54 nvt-se Exp $ + * $Id: rpl-of0.c,v 1.3 2010/05/29 22:23:21 nvt-se Exp $ */ /** * \file @@ -50,6 +50,7 @@ static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); static rpl_rank_t increment_rank(rpl_rank_t, rpl_parent_t *); rpl_of_t rpl_of0 = { + NULL, best_parent, increment_rank, 0 @@ -82,7 +83,6 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2) PRINTF(" (confidence %d, rank %d)\n", p2->local_confidence, p2->rank); - /* TODO: Add other rules. */ if(p1->local_confidence > p2->local_confidence) { return p1; } else if(p2->local_confidence > p1->local_confidence) { diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index 2f6d60b36..d816061f4 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -32,7 +32,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rpl-timers.c,v 1.6 2010/05/25 21:58:54 nvt-se Exp $ + * $Id: rpl-timers.c,v 1.7 2010/05/29 22:23:21 nvt-se Exp $ */ /** * \file @@ -210,14 +210,13 @@ rpl_schedule_dao(rpl_dag_t *dag) expiration_time = etimer_expiration_time(&dag->dao_timer.etimer); - if(!etimer_expired(&dag->dao_timer.etimer) && - (expiration_time - clock_time()) < (DEFAULT_DAO_LATENCY / dag->rank)) { + if(!etimer_expired(&dag->dao_timer.etimer)) { PRINTF("RPL: DAO timer already scheduled\n"); } else { PRINTF("RPL: Scheduling DAO timer %u ticks in the future (%u %u)\n", (unsigned)DEFAULT_DAO_LATENCY / dag->rank, (unsigned)DEFAULT_DAO_LATENCY, (unsigned)dag->rank); - ctimer_set(&dag->dao_timer, DEFAULT_DAO_LATENCY / dag->rank, + ctimer_set(&dag->dao_timer, DEFAULT_DAO_LATENCY, handle_dao_timer, dag); } } diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 789759821..6f2136f74 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -32,7 +32,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rpl.c,v 1.4 2010/05/25 21:58:54 nvt-se Exp $ + * $Id: rpl.c,v 1.5 2010/05/29 22:23:21 nvt-se Exp $ */ /** * \file @@ -59,9 +59,8 @@ #define RPL_MAX_ROUTE_ENTRIES RPL_CONF_MAX_ROUTE_ENTRIES #endif /* !RPL_CONF_MAX_ROUTE_ENTRIES */ -/************************************************************************/ extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; - +/************************************************************************/ void rpl_purge_routes(void) { @@ -125,10 +124,25 @@ neighbor_callback(const rimeaddr_t *addr, int known, int etx) PRINTF(" is %sknown. ETX = %d\n", known ? "" : "no longer ", etx); dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); - if(dag == NULL || (parent = rpl_find_parent(dag, &ipaddr)) == NULL) { + if(dag == NULL) { return; } + 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); + } + return; + } + + if(dag->of->parent_state_callback != NULL) { + dag->of->parent_state_callback(parent, known, etx); + } + if(!known) { PRINTF("RPL: Removing parent "); PRINT6ADDR(&parent->addr); @@ -140,6 +154,9 @@ neighbor_callback(const rimeaddr_t *addr, int known, int etx) /* Select a new default route. */ parent = rpl_preferred_parent(dag); if(parent != NULL) { + PRINTF("RPL: Switching preferred parent to "); + PRINT6ADDR(&parent->addr); + PRINTF("\n"); rpl_set_default_route(dag, &parent->addr); } } diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index b01871259..0d04d12ac 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -30,7 +30,7 @@ * * Author: Joakim Eriksson, Nicolas Tsiftes * - * $Id: rpl.h,v 1.4 2010/05/25 21:58:54 nvt-se Exp $ + * $Id: rpl.h,v 1.5 2010/05/29 22:23:21 nvt-se Exp $ */ #ifndef RPL_H @@ -85,7 +85,7 @@ #define RPL_DEFAULT_INSTANCE 0 #define RPL_ANY_INSTANCE -1 -#define RPL_DEFAULT_OCP 0 +#define RPL_DEFAULT_OCP 1 /* TODO: pick these from OCP later? */ #define DEFAULT_MAX_RANKINC 16 @@ -138,6 +138,7 @@ struct rpl_parent { typedef struct rpl_parent rpl_parent_t; struct rpl_of { + void (*parent_state_callback)(rpl_parent_t *, int, int); rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *); rpl_rank_t (*increment_rank)(rpl_rank_t, rpl_parent_t *); rpl_ocp_t ocp; @@ -231,7 +232,7 @@ void dao_output(rpl_parent_t *, uint32_t lifetime); void uip_rpl_input(void); /* RPL logic functions. */ -int rpl_set_root(uip_ipaddr_t *); +rpl_dag_t *rpl_set_root(uip_ipaddr_t *); 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);