Added support for multiple objective functions.

Extended the objective function API with a callback function that receives link-layer neighbor information.

Throttled DAO transmissions to one per DEFAULT_DAO_LATENCY period.

Added support for an ETX objective function (hysteresis control still lacking though).

Fixed a leak of routes installed by DAOs.

Control that dst_adv_supported is set before sending DAOs.

Improved debugging output.
This commit is contained in:
nvt-se 2010-05-29 22:23:21 +00:00
parent f6e0b46f38
commit f135105567
8 changed files with 172 additions and 32 deletions

View file

@ -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

View file

@ -32,7 +32,7 @@
* *
* This file is part of the Contiki operating system. * 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 * \file
@ -57,12 +57,9 @@
#include "net/uip-debug.h" #include "net/uip-debug.h"
/************************************************************************/ /************************************************************************/
#ifdef RPL_CONF_OBJECTIVE_FUNCTION extern rpl_of_t rpl_of_etx;
#define RPL_OF RPL_CONF_OBJECTIVE_FUNCTION static rpl_of_t *objective_functions[] = {&rpl_of_etx, NULL};
#else /************************************************************************/
extern rpl_of_t rpl_of0;
#define RPL_OF rpl_of0
#endif /* RPL_CONF_OBJECTIVE_FUNCTION */
#ifndef RPL_CONF_MAX_DAG_ENTRIES #ifndef RPL_CONF_MAX_DAG_ENTRIES
#define RPL_MAX_DAG_ENTRIES 2 #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_set_root(uip_ipaddr_t *dag_id)
{ {
rpl_dag_t *dag; rpl_dag_t *dag;
@ -138,7 +135,7 @@ rpl_set_root(uip_ipaddr_t *dag_id)
dag = rpl_alloc_dag(); dag = rpl_alloc_dag();
if(dag == NULL) { if(dag == NULL) {
PRINTF("RPL: Failed to allocate a DAG\n"); PRINTF("RPL: Failed to allocate a DAG\n");
return -1; return NULL;
} }
dag->joined = 1; dag->joined = 1;
@ -159,7 +156,7 @@ rpl_set_root(uip_ipaddr_t *dag_id)
rpl_reset_dio_timer(dag, 1); rpl_reset_dio_timer(dag, 1);
return 0; return dag;
} }
/************************************************************************/ /************************************************************************/
int int
@ -359,9 +356,14 @@ rpl_find_dag(unsigned char aucIndex)
rpl_of_t * rpl_of_t *
rpl_find_of(rpl_ocp_t ocp) rpl_find_of(rpl_ocp_t ocp)
{ {
if(RPL_OF.ocp == ocp) { rpl_of_t *of;
return &RPL_OF;
for(of = objective_functions[0]; of != NULL; of++) {
if(of->ocp == ocp) {
return of;
}
} }
return NULL; return NULL;
} }
/************************************************************************/ /************************************************************************/
@ -438,7 +440,7 @@ join_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
rpl_set_default_route(dag, from); rpl_set_default_route(dag, from);
if(dio->dst_adv_trigger) { if(dio->dst_adv_supported && dio->dst_adv_trigger) {
rpl_schedule_dao(dag); rpl_schedule_dao(dag);
} else { } else {
PRINTF("RPL: dst_adv_trigger not set in incoming DIO!\n"); 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. */ /* This DIO pertains to a DAG that we are already part of. */
p = rpl_find_parent(dag, from); p = rpl_find_parent(dag, from);
if(p != NULL) { if(p != NULL) {
if(dio->dst_adv_trigger) { if(dio->dst_adv_supported && dio->dst_adv_trigger) {
rpl_schedule_dao(dag); rpl_schedule_dao(dag);
} else { } else {
PRINTF("RPL: dst_adv_trigger is not set in incoming DIO\n"); 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. */ node is in the parent list, we just remove it. */
if(p != NULL && p->rank < dio->dag_rank) { if(p != NULL && p->rank < dio->dag_rank) {
PRINTF("RPL: Parent "); PRINTF("RPL: Parent ");
PRINT6ADDR(&n->addr); PRINT6ADDR(&p->addr);
PRINTF(" has increased in rank from %hu to %hu. Removing it.\n", PRINTF(" has increased in rank from %hu to %hu. Removing it.\n",
p->rank, dio->dag_rank); p->rank, dio->dag_rank);
rpl_remove_parent(dag, p); rpl_remove_parent(dag, p);

View file

@ -33,7 +33,7 @@
* *
* This file is part of the Contiki operating system. * 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 * \file
@ -323,8 +323,8 @@ dio_output(rpl_dag_t *dag, uip_ipaddr_t *uc_addr)
buffer[pos++] = RPL_DIO_SUBOPT_OCP; buffer[pos++] = RPL_DIO_SUBOPT_OCP;
buffer[pos++] = 0; buffer[pos++] = 0;
buffer[pos++] = 2; buffer[pos++] = 2;
buffer[pos++] = 0; buffer[pos++] = dag->of->ocp >> 8;
buffer[pos++] = 0; buffer[pos++] = dag->of->ocp & 0xff;
/* alignment here ??? */ /* alignment here ??? */

121
core/net/rpl/rpl-of-etx.c Normal file
View file

@ -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 <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>
*/
#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;
}

View file

@ -32,7 +32,7 @@
* *
* This file is part of the Contiki operating system. * 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 * \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 *); static rpl_rank_t increment_rank(rpl_rank_t, rpl_parent_t *);
rpl_of_t rpl_of0 = { rpl_of_t rpl_of0 = {
NULL,
best_parent, best_parent,
increment_rank, increment_rank,
0 0
@ -82,7 +83,6 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
PRINTF(" (confidence %d, rank %d)\n", PRINTF(" (confidence %d, rank %d)\n",
p2->local_confidence, p2->rank); p2->local_confidence, p2->rank);
/* TODO: Add other rules. */
if(p1->local_confidence > p2->local_confidence) { if(p1->local_confidence > p2->local_confidence) {
return p1; return p1;
} else if(p2->local_confidence > p1->local_confidence) { } else if(p2->local_confidence > p1->local_confidence) {

View file

@ -32,7 +32,7 @@
* *
* This file is part of the Contiki operating system. * 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 * \file
@ -210,14 +210,13 @@ rpl_schedule_dao(rpl_dag_t *dag)
expiration_time = etimer_expiration_time(&dag->dao_timer.etimer); expiration_time = etimer_expiration_time(&dag->dao_timer.etimer);
if(!etimer_expired(&dag->dao_timer.etimer) && if(!etimer_expired(&dag->dao_timer.etimer)) {
(expiration_time - clock_time()) < (DEFAULT_DAO_LATENCY / dag->rank)) {
PRINTF("RPL: DAO timer already scheduled\n"); PRINTF("RPL: DAO timer already scheduled\n");
} else { } else {
PRINTF("RPL: Scheduling DAO timer %u ticks in the future (%u %u)\n", PRINTF("RPL: Scheduling DAO timer %u ticks in the future (%u %u)\n",
(unsigned)DEFAULT_DAO_LATENCY / dag->rank, (unsigned)DEFAULT_DAO_LATENCY / dag->rank,
(unsigned)DEFAULT_DAO_LATENCY, (unsigned)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); handle_dao_timer, dag);
} }
} }

View file

@ -32,7 +32,7 @@
* *
* This file is part of the Contiki operating system. * 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 * \file
@ -59,9 +59,8 @@
#define RPL_MAX_ROUTE_ENTRIES RPL_CONF_MAX_ROUTE_ENTRIES #define RPL_MAX_ROUTE_ENTRIES RPL_CONF_MAX_ROUTE_ENTRIES
#endif /* !RPL_CONF_MAX_ROUTE_ENTRIES */ #endif /* !RPL_CONF_MAX_ROUTE_ENTRIES */
/************************************************************************/
extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB];
/************************************************************************/
void void
rpl_purge_routes(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); PRINTF(" is %sknown. ETX = %d\n", known ? "" : "no longer ", etx);
dag = rpl_get_dag(RPL_DEFAULT_INSTANCE); dag = rpl_get_dag(RPL_DEFAULT_INSTANCE);
if(dag == NULL || (parent = rpl_find_parent(dag, &ipaddr)) == NULL) { if(dag == NULL) {
return; 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) { if(!known) {
PRINTF("RPL: Removing parent "); PRINTF("RPL: Removing parent ");
PRINT6ADDR(&parent->addr); PRINT6ADDR(&parent->addr);
@ -140,6 +154,9 @@ neighbor_callback(const rimeaddr_t *addr, int known, int etx)
/* Select a new default route. */ /* Select a new default route. */
parent = rpl_preferred_parent(dag); parent = rpl_preferred_parent(dag);
if(parent != NULL) { if(parent != NULL) {
PRINTF("RPL: Switching preferred parent to ");
PRINT6ADDR(&parent->addr);
PRINTF("\n");
rpl_set_default_route(dag, &parent->addr); rpl_set_default_route(dag, &parent->addr);
} }
} }

View file

@ -30,7 +30,7 @@
* *
* Author: Joakim Eriksson, Nicolas Tsiftes * 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 #ifndef RPL_H
@ -85,7 +85,7 @@
#define RPL_DEFAULT_INSTANCE 0 #define RPL_DEFAULT_INSTANCE 0
#define RPL_ANY_INSTANCE -1 #define RPL_ANY_INSTANCE -1
#define RPL_DEFAULT_OCP 0 #define RPL_DEFAULT_OCP 1
/* TODO: pick these from OCP later? */ /* TODO: pick these from OCP later? */
#define DEFAULT_MAX_RANKINC 16 #define DEFAULT_MAX_RANKINC 16
@ -138,6 +138,7 @@ struct rpl_parent {
typedef struct rpl_parent rpl_parent_t; typedef struct rpl_parent rpl_parent_t;
struct rpl_of { struct rpl_of {
void (*parent_state_callback)(rpl_parent_t *, int, int);
rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *); rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *);
rpl_rank_t (*increment_rank)(rpl_rank_t, rpl_parent_t *); rpl_rank_t (*increment_rank)(rpl_rank_t, rpl_parent_t *);
rpl_ocp_t ocp; rpl_ocp_t ocp;
@ -231,7 +232,7 @@ void dao_output(rpl_parent_t *, uint32_t lifetime);
void uip_rpl_input(void); void uip_rpl_input(void);
/* RPL logic functions. */ /* 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_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, int len);
int rpl_repair_dag(rpl_dag_t *dag); int rpl_repair_dag(rpl_dag_t *dag);
int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from); int rpl_set_default_route(rpl_dag_t *dag, uip_ipaddr_t *from);