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:
parent
f6e0b46f38
commit
f135105567
8 changed files with 172 additions and 32 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ??? */
|
||||
|
||||
|
|
121
core/net/rpl/rpl-of-etx.c
Normal file
121
core/net/rpl/rpl-of-etx.c
Normal 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;
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue