rpl-lite: terminology: use 'neighbor' instead of 'parent', and distinguish candidate neighbors from parent set as per RFC 6550

This commit is contained in:
Simon Duquennoy 2017-06-19 11:35:02 +02:00
parent a6643a9835
commit d4e08fafa6
16 changed files with 344 additions and 324 deletions

View File

@ -156,7 +156,7 @@
/*
* RPL probing. When enabled, probes will be sent periodically to keep
* parent link estimates up to date. Further configurable
* neighbor link estimates up to date. Further configurable
* via RPL_CONF_PROBING_* flags
*/
#ifdef RPL_CONF_WITH_PROBING
@ -166,7 +166,7 @@
#endif
/*
* Function used to select the next parent to be probed.
* Function used to select the next neighbor to be probed.
*/
#ifdef RPL_CONF_PROBING_SELECT_FUNC
#define RPL_PROBING_SELECT_FUNC RPL_CONF_PROBING_SELECT_FUNC

View File

@ -86,8 +86,8 @@ leave_dag(void)
RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno);
rpl_icmp6_dao_output(0);
/* Remove all parents/neighbors */
rpl_parent_remove_all();
/* Remove all neighbors */
rpl_neighbor_remove_all();
rpl_timers_stop_dag_timers();
@ -138,7 +138,7 @@ rpl_global_repair(void)
PRINTF("RPL: initiating global repair (version=%u, rank=%u)\n",
curr_instance.dag.version, curr_instance.dag.rank);
#if DEBUG
rpl_parent_print_list("Global repair");
rpl_neighbor_print_list("Global repair");
#endif
/* Initiate global repair */
@ -155,7 +155,7 @@ global_repair_non_root(rpl_dio_t *dio)
PRINTF("RPL: participating in global repair (version=%u, rank=%u)\n",
curr_instance.dag.version, curr_instance.dag.rank);
#if DEBUG
rpl_parent_print_list("Global repair");
rpl_neighbor_print_list("Global repair");
#endif
/* Re-initialize configuration from DIO */
init_dag_from_dio(dio);
@ -169,7 +169,7 @@ rpl_local_repair(const char *str)
if(curr_instance.used) { /* Check needed because this is a public function */
PRINTF("RPL: local repair (%s)\n", str);
curr_instance.of->reset(); /* Reset OF */
rpl_parent_remove_all(); /* Remove all neighbors/parents */
rpl_neighbor_remove_all(); /* Remove all neighbors */
rpl_timers_dio_reset("Local repair"); /* Reset Trickle timer */
rpl_timers_schedule_state_update();
}
@ -181,16 +181,16 @@ rpl_dag_update_state(void)
{
if(curr_instance.used) {
if(!rpl_dag_root_is_root()) {
rpl_parent_t *old_parent = curr_instance.dag.preferred_parent;
rpl_nbr_t *old_parent = curr_instance.dag.preferred_parent;
rpl_rank_t old_rank = curr_instance.dag.rank;
/* Any scheduled state update is no longer needed */
rpl_timers_unschedule_state_update();
/* Select and set preferred parent */
rpl_parent_set_preferred(rpl_parent_select_best());
rpl_neighbor_set_preferred(rpl_neighbor_select_best());
/* Update rank */
curr_instance.dag.rank = rpl_parent_rank_via_parent(curr_instance.dag.preferred_parent);
curr_instance.dag.rank = rpl_neighbor_rank_via_nbr(curr_instance.dag.preferred_parent);
if(old_parent == NULL || curr_instance.dag.rank < curr_instance.dag.lowest_rank) {
/* This is a slight departure from RFC6550: if we had no preferred parent before,
@ -202,7 +202,7 @@ rpl_dag_update_state(void)
if(curr_instance.dag.preferred_parent != old_parent) {
rpl_timers_schedule_dao();
#if DEBUG
rpl_parent_print_list("Parent switch");
rpl_neighbor_print_list("Parent switch");
#endif
}
@ -217,32 +217,32 @@ rpl_dag_update_state(void)
}
}
/*---------------------------------------------------------------------------*/
static rpl_parent_t *
static rpl_nbr_t *
update_nbr_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
{
rpl_parent_t *p = NULL;
rpl_nbr_t *p = NULL;
const uip_lladdr_t *lladdr;
p = rpl_parent_get_from_ipaddr(from);
/* Neighbor not in RPL parent table, add it */
p = rpl_neighbor_get_from_ipaddr(from);
/* Neighbor not in RPL neighbor table, add it */
if(p == NULL) {
/* Is the parent known by ds6? Drop this request if not.
* Typically, the parent is added upon receiving a DIO. */
/* Is the neighbor known by ds6? Drop this request if not.
* Typically, the neighbor is added upon receiving a DIO. */
lladdr = uip_ds6_nbr_lladdr_from_ipaddr(from);
if(lladdr == NULL) {
return NULL;
}
/* Add neighbor to RPL table */
p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr,
p = nbr_table_add_lladdr(rpl_neighbors, (linkaddr_t *)lladdr,
NBR_TABLE_REASON_RPL_DIO, dio);
if(p == NULL) {
PRINTF("RPL: failed to add parent\n");
PRINTF("RPL: failed to add neighbor\n");
return NULL;
}
}
/* Update parent info from DIO */
/* Update neighbor info from DIO */
p->rank = dio->rank;
p->dtsn = dio->dtsn;
#if RPL_WITH_MC
@ -255,7 +255,7 @@ update_nbr_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
static void
process_dio_from_current_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
{
rpl_parent_t *p;
rpl_nbr_t *p;
uint8_t last_dtsn;
/* Does the rank make sense at all? */
@ -277,8 +277,8 @@ process_dio_from_current_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
}
/* The DIO has a newer version: global repair.
* Must come first, as it might remove all parents, and we then need
* to re-add this source of the DIO to the parent table */
* Must come first, as it might remove all neighbors, and we then need
* to re-add this source of the DIO to the neighbor table */
if(rpl_lollipop_greater_than(dio->version, curr_instance.dag.version)) {
if(curr_instance.dag.rank == ROOT_RANK) { /* The root should not hear newer versions */
PRINTF("RPL: inconsistent DIO version (current: %u, received: %u), initiate global repair\n",
@ -298,12 +298,12 @@ process_dio_from_current_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
return;
}
/* Add neighbor to RPL parent table */
p = rpl_parent_get_from_ipaddr(from);
/* Add neighbor to RPL neighbor table */
p = rpl_neighbor_get_from_ipaddr(from);
last_dtsn = p != NULL ? p->dtsn : RPL_LOLLIPOP_INIT;
if(!update_nbr_from_dio(from, dio)) {
PRINTF("RPL: parent table full, dropping DIO\n");
PRINTF("RPL: neighbor table full, dropping DIO\n");
return;
}
@ -503,7 +503,7 @@ rpl_process_dao_ack(uint8_t sequence, uint8_t status)
#endif /* RPL_WITH_DAO_ACK */
/*---------------------------------------------------------------------------*/
int
rpl_process_hbh(rpl_parent_t *sender, uint16_t sender_rank, int loop_detected, int rank_error_signaled)
rpl_process_hbh(rpl_nbr_t *sender, uint16_t sender_rank, int loop_detected, int rank_error_signaled)
{
int drop = 0;
@ -586,7 +586,7 @@ void
rpl_dag_init(void)
{
memset(&curr_instance, 0, sizeof(curr_instance));
rpl_parent_init();
rpl_neighbor_init();
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -114,7 +114,7 @@ rpl_dag_t *rpl_get_any_dag(void);
* \param rank_error_signaled 1 if the HBH header advertises a rank error, 0 otherwise
* \return 1 if the packet is to be forwarded, 0 if it is to be dropped
*/
int rpl_process_hbh(rpl_parent_t *sender, uint16_t sender_rank, int loop_detected, int rank_error_signaled);
int rpl_process_hbh(rpl_nbr_t *sender, uint16_t sender_rank, int loop_detected, int rank_error_signaled);
/**
* Processes incoming DIS
@ -149,9 +149,8 @@ void rpl_process_dao(uip_ipaddr_t *from, rpl_dao_t *dao);
void rpl_process_dao_ack(uint8_t sequence, uint8_t status);
/**
* Updates RPL interl state from neighbor/parent tables:
* selects preferred parent, updated rank & metreic container,
* triggers control traffic accordingly and updates uIP6 internal state.
* Updates RPL internal state: selects preferred parent, updates rank & metreic
* container, triggers control traffic accordingly and updates uIP6 internal state.
*/
void rpl_dag_update_state(void);

View File

@ -363,7 +363,7 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset)
int loop_detected;
uint16_t sender_rank;
uint8_t sender_closer;
rpl_parent_t *sender;
rpl_nbr_t *sender;
if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
|| UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL
@ -388,7 +388,7 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset)
down = (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) ? 1 : 0;
sender_rank = UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank);
sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER));
sender = nbr_table_get_from_lladdr(rpl_neighbors, packetbuf_addr(PACKETBUF_ADDR_SENDER));
rank_error_signaled = (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) ? 1 : 0;
sender_closer = sender_rank < curr_instance.dag.rank;
loop_detected = (down && !sender_closer) || (!down && sender_closer);

View File

@ -550,7 +550,7 @@ rpl_icmp6_dao_output(uint8_t lifetime)
int pos;
uip_ipaddr_t *dest_ipaddr = NULL;
const uip_ipaddr_t *prefix = rpl_get_global_address();
uip_ipaddr_t *parent_ipaddr = rpl_parent_get_ipaddr(curr_instance.dag.preferred_parent);
uip_ipaddr_t *parent_ipaddr = rpl_neighbor_get_ipaddr(curr_instance.dag.preferred_parent);
/* Make sure we're up-to-date before sending data out */
rpl_dag_update_state();

View File

@ -114,9 +114,8 @@ void rpl_icmp6_dis_output(uip_ipaddr_t *addr);
void rpl_icmp6_dio_output(uip_ipaddr_t *uc_addr);
/**
* Creates an ICMPv6 DAO packet and sends it to the root via the
* current preferred parent, advertising the current preferred parent,
* and with our global address as prefix.
* Creates an ICMPv6 DAO packet and sends it to the root, advertising the
* current preferred parent, and with our global address as prefix.
*
* \param lifetime The DAO lifetime. Use 0 to send a No-path DAO
*/

View File

@ -96,9 +96,9 @@ reset(void)
}
/*---------------------------------------------------------------------------*/
static uint16_t
parent_link_metric(rpl_parent_t *p)
nbr_link_metric(rpl_nbr_t *nbr)
{
const struct link_stats *stats = rpl_parent_get_link_stats(p);
const struct link_stats *stats = rpl_neighbor_get_link_stats(nbr);
if(stats != NULL) {
#if RPL_MRHOF_SQUARED_ETX
uint32_t squared_etx = ((uint32_t)stats->etx * stats->etx) / LINK_STATS_ETX_DIVISOR;
@ -111,11 +111,11 @@ parent_link_metric(rpl_parent_t *p)
}
/*---------------------------------------------------------------------------*/
static uint16_t
parent_path_cost(rpl_parent_t *p)
nbr_path_cost(rpl_nbr_t *nbr)
{
uint16_t base;
if(p == NULL) {
if(nbr == NULL) {
return 0xffff;
}
@ -123,87 +123,86 @@ parent_path_cost(rpl_parent_t *p)
/* Handle the different MC types */
switch(curr_instance.mc.type) {
case RPL_DAG_MC_ETX:
base = p->mc.obj.etx;
base = nbr->mc.obj.etx;
break;
case RPL_DAG_MC_ENERGY:
base = p->mc.obj.energy.energy_est << 8;
base = nbr->mc.obj.energy.energy_est << 8;
break;
default:
base = p->rank;
base = nbr->rank;
break;
}
#else /* RPL_WITH_MC */
base = p->rank;
base = nbr->rank;
#endif /* RPL_WITH_MC */
/* path cost upper bound: 0xffff */
return MIN((uint32_t)base + parent_link_metric(p), 0xffff);
return MIN((uint32_t)base + nbr_link_metric(nbr), 0xffff);
}
/*---------------------------------------------------------------------------*/
static rpl_rank_t
rank_via_parent(rpl_parent_t *p)
rank_via_nbr(rpl_nbr_t *nbr)
{
uint16_t min_hoprankinc;
uint16_t path_cost;
if(p == NULL) {
if(nbr == NULL) {
return RPL_INFINITE_RANK;
}
min_hoprankinc = curr_instance.min_hoprankinc;
path_cost = parent_path_cost(p);
path_cost = nbr_path_cost(nbr);
/* Rank lower-bound: parent rank + min_hoprankinc */
return MAX(MIN((uint32_t)p->rank + min_hoprankinc, RPL_INFINITE_RANK), path_cost);
/* Rank lower-bound: nbr rank + min_hoprankinc */
return MAX(MIN((uint32_t)nbr->rank + min_hoprankinc, RPL_INFINITE_RANK), path_cost);
}
/*---------------------------------------------------------------------------*/
static int
parent_is_acceptable(rpl_parent_t *p)
nbr_has_usable_link(rpl_nbr_t *nbr)
{
uint16_t link_metric = parent_link_metric(p);
uint16_t path_cost = parent_path_cost(p);
/* Exclude links with too high link metrics or path cost (RFC6719, 3.2.2) */
return link_metric <= MAX_LINK_METRIC && path_cost <= MAX_PATH_COST;
}
/*---------------------------------------------------------------------------*/
static int
parent_has_usable_link(rpl_parent_t *p)
{
uint16_t link_metric = parent_link_metric(p);
uint16_t link_metric = nbr_link_metric(nbr);
/* Exclude links with too high link metrics */
return link_metric <= MAX_LINK_METRIC;
}
/*---------------------------------------------------------------------------*/
static rpl_parent_t *
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
static int
nbr_is_acceptable_parent(rpl_nbr_t *nbr)
{
uint16_t p1_cost;
uint16_t p2_cost;
int p1_is_acceptable;
int p2_is_acceptable;
uint16_t path_cost = nbr_path_cost(nbr);
/* Exclude links with too high link metrics or path cost (RFC6719, 3.2.2) */
return nbr_has_usable_link(nbr) && path_cost <= MAX_PATH_COST;
}
/*---------------------------------------------------------------------------*/
static rpl_nbr_t *
best_parent(rpl_nbr_t *nbr1, rpl_nbr_t *nbr2)
{
uint16_t nbr1_cost;
uint16_t nbr2_cost;
int nbr1_is_acceptable;
int nbr2_is_acceptable;
p1_is_acceptable = p1 != NULL && parent_is_acceptable(p1);
p2_is_acceptable = p2 != NULL && parent_is_acceptable(p2);
nbr1_is_acceptable = nbr1 != NULL && nbr_is_acceptable_parent(nbr1);
nbr2_is_acceptable = nbr2 != NULL && nbr_is_acceptable_parent(nbr2);
if(!p1_is_acceptable) {
return p2_is_acceptable ? p2 : NULL;
if(!nbr1_is_acceptable) {
return nbr2_is_acceptable ? nbr2 : NULL;
}
if(!p2_is_acceptable) {
return p1_is_acceptable ? p1 : NULL;
if(!nbr2_is_acceptable) {
return nbr1_is_acceptable ? nbr1 : NULL;
}
p1_cost = parent_path_cost(p1);
p2_cost = parent_path_cost(p2);
nbr1_cost = nbr_path_cost(nbr1);
nbr2_cost = nbr_path_cost(nbr2);
/* Maintain stability of the preferred parent in case of similar ranks. */
if(p1 == curr_instance.dag.preferred_parent || p2 == curr_instance.dag.preferred_parent) {
if(p1_cost < p2_cost + PARENT_SWITCH_THRESHOLD &&
p1_cost > p2_cost - PARENT_SWITCH_THRESHOLD) {
if(nbr1 == curr_instance.dag.preferred_parent || nbr2 == curr_instance.dag.preferred_parent) {
if(nbr1_cost < nbr2_cost + PARENT_SWITCH_THRESHOLD &&
nbr1_cost > nbr2_cost - PARENT_SWITCH_THRESHOLD) {
return curr_instance.dag.preferred_parent;
}
}
return p1_cost < p2_cost ? p1 : p2;
return nbr1_cost < nbr2_cost ? nbr1 : nbr2;
}
/*---------------------------------------------------------------------------*/
#if !RPL_WITH_MC
@ -232,7 +231,7 @@ update_metric_container(void)
curr_instance.mc.prec = 0;
path_cost = curr_instance.dag.rank;
} else {
path_cost = parent_path_cost(curr_instance.dag.preferred_parent);
path_cost = nbr_path_cost(curr_instance.dag.preferred_parent);
}
/* Handle the different MC types */
@ -263,11 +262,11 @@ update_metric_container(void)
/*---------------------------------------------------------------------------*/
rpl_of_t rpl_mrhof = {
reset,
parent_link_metric,
parent_has_usable_link,
parent_is_acceptable,
parent_path_cost,
rank_via_parent,
nbr_link_metric,
nbr_has_usable_link,
nbr_is_acceptable_parent,
nbr_path_cost,
rank_via_nbr,
best_parent,
update_metric_container,
RPL_OCP_MRHOF

View File

@ -66,7 +66,7 @@
static int num_parents; /* all nodes that are possible parents */
static int num_children; /* all children that we have as nexthop */
static int num_free;
static linkaddr_t *worst_rank_nbr; /* the parent that has the worst rank */
static linkaddr_t *worst_rank_nbr; /* the neighbor with the worst rank */
static rpl_rank_t worst_rank;
/*---------------------------------------------------------------------------*/
#if DEBUG == DEBUG_FULL
@ -95,8 +95,8 @@ node_is_child(uip_ipaddr_t *addr) {
static void
update_nbr(void)
{
uip_ds6_nbr_t *nbr;
rpl_parent_t *parent;
uip_ds6_nbr_t *ds6_nbr;
rpl_nbr_t *rpl_nbr;
int num_used;
int is_used;
rpl_rank_t rank;
@ -115,32 +115,32 @@ update_nbr(void)
num_parents = 0;
num_children = 0;
nbr = nbr_table_head(ds6_neighbors);
while(nbr != NULL) {
linkaddr_t *lladdr = nbr_table_get_lladdr(ds6_neighbors, nbr);
ds6_nbr = nbr_table_head(ds6_neighbors);
while(ds6_nbr != NULL) {
linkaddr_t *lladdr = nbr_table_get_lladdr(ds6_neighbors, ds6_nbr);
is_used = 0;
/*
* Check if this neighbor is used as nexthop and therefore being a
* RPL child.
*/
if(node_is_child(&nbr->ipaddr) != 0) {
if(node_is_child(&ds6_nbr->ipaddr) != 0) {
is_used++;
num_children++;
}
parent = rpl_parent_get_from_lladdr((uip_lladdr_t *)lladdr);
if(parent != NULL) {
rpl_nbr = rpl_neighbor_get_from_lladdr((uip_lladdr_t *)lladdr);
if(rpl_nbr != NULL && rpl_neighbor_is_parent(rpl_nbr)) {
num_parents++;
if(curr_instance.dag.preferred_parent == parent) {
if(curr_instance.dag.preferred_parent == rpl_nbr) {
/*
* This is the preferred parent for the DAG and must not be removed
* Note: this assumes that only RPL adds default routes.
*/
} else if(is_used == 0 && worst_rank < RPL_INFINITE_RANK &&
parent->rank > 0 &&
(rank = curr_instance.of->rank_via_parent(parent)) > worst_rank) {
rpl_nbr->rank > 0 &&
(rank = curr_instance.of->rank_via_nbr(rpl_nbr)) > worst_rank) {
/* This is the worst-rank neighbor - this is a good candidate for removal */
worst_rank = rank;
worst_rank_nbr = lladdr;
@ -155,7 +155,7 @@ update_nbr(void)
worst_rank = RPL_INFINITE_RANK;
}
nbr = nbr_table_next(ds6_neighbors, nbr);
ds6_nbr = nbr_table_next(ds6_neighbors, ds6_nbr);
num_used++;
}
/* how many more IP neighbors can be have? */
@ -187,7 +187,7 @@ find_removable_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
return NULL;
}
/* Add the new neighbor only if it is better than the worst parent. */
/* Add the new neighbor only if it is better than the current worst. */
if(dio->rank + curr_instance.min_hoprankinc < worst_rank - curr_instance.min_hoprankinc / 2) {
/* Found *great* neighbor - add! */
PRINTF("RPL nbr-policy: DIO rank %u, worse_rank %u -- add to cache\n",

View File

@ -32,7 +32,7 @@
/**
* \file
* Logic for DAG parents in RPL.
* Logic for DAG neighbors in RPL.
*
* \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>,
* Simon Duquennoy <simon.duquennoy@inria.fr>
@ -54,14 +54,15 @@
/* A configurable function called after every RPL parent switch */
#ifdef RPL_CALLBACK_PARENT_SWITCH
void RPL_CALLBACK_PARENT_SWITCH(rpl_parent_t *old, rpl_parent_t *new);
void RPL_CALLBACK_PARENT_SWITCH(rpl_nbr_t *old, rpl_nbr_t *new);
#endif /* RPL_CALLBACK_PARENT_SWITCH */
/*---------------------------------------------------------------------------*/
/* Per-parent RPL information */
NBR_TABLE_GLOBAL(rpl_parent_t, rpl_parents);
/* Per-neighbor RPL information */
NBR_TABLE_GLOBAL(rpl_nbr_t, rpl_neighbors);
/*---------------------------------------------------------------------------*/
/* As per RFC 6550, section 8.2.2.4 */
static int
acceptable_rank(rpl_rank_t rank)
{
@ -73,31 +74,31 @@ acceptable_rank(rpl_rank_t rank)
}
/*---------------------------------------------------------------------------*/
void
rpl_parent_print_list(const char *str)
rpl_neighbor_print_list(const char *str)
{
if(curr_instance.used) {
int curr_dio_interval = curr_instance.dag.dio_intcurrent;
int curr_rank = curr_instance.dag.rank;
rpl_parent_t *p = nbr_table_head(rpl_parents);
rpl_nbr_t *nbr = nbr_table_head(rpl_neighbors);
clock_time_t clock_now = clock_time();
printf("RPL nbr: MOP %u OCP %u rank %u dioint %u, DS6 nbr count %u (%s)\n",
curr_instance.mop, curr_instance.of->ocp, curr_rank,
curr_dio_interval, uip_ds6_nbr_num(), str);
while(p != NULL) {
const struct link_stats *stats = rpl_parent_get_link_stats(p);
while(nbr != NULL) {
const struct link_stats *stats = rpl_neighbor_get_link_stats(nbr);
printf("RPL nbr: %3u %5u, %5u => %5u -- %2u %c%c%c (last tx %u min ago)\n",
rpl_parent_get_ipaddr(p)->u8[15],
p->rank,
rpl_parent_get_link_metric(p),
rpl_parent_rank_via_parent(p),
rpl_neighbor_get_ipaddr(nbr)->u8[15],
nbr->rank,
rpl_neighbor_get_link_metric(nbr),
rpl_neighbor_rank_via_nbr(nbr),
stats != NULL ? stats->freshness : 0,
(acceptable_rank(rpl_parent_rank_via_parent(p)) && curr_instance.of->parent_is_acceptable(p)) ? 'a' : ' ',
(acceptable_rank(rpl_neighbor_rank_via_nbr(nbr)) && curr_instance.of->nbr_is_acceptable_parent(nbr)) ? 'a' : ' ',
link_stats_is_fresh(stats) ? 'f' : ' ',
p == curr_instance.dag.preferred_parent ? 'p' : ' ',
nbr == curr_instance.dag.preferred_parent ? 'p' : ' ',
(unsigned)((clock_now - stats->last_tx_time) / (60 * CLOCK_SECOND))
);
p = nbr_table_next(rpl_parents, p);
nbr = nbr_table_next(rpl_neighbors, nbr);
}
printf("RPL nbr: end of list\n");
}
@ -105,9 +106,9 @@ rpl_parent_print_list(const char *str)
/*---------------------------------------------------------------------------*/
#if UIP_ND6_SEND_NS
static uip_ds6_nbr_t *
rpl_get_ds6_nbr(rpl_parent_t *parent)
rpl_get_ds6_nbr(rpl_nbr_t *nbr)
{
const linkaddr_t *lladdr = rpl_parent_get_lladdr(parent);
const linkaddr_t *lladdr = rpl_neighbor_get_lladdr(nbr);
if(lladdr != NULL) {
return nbr_table_get_from_lladdr(ds6_neighbors, lladdr);
} else {
@ -117,196 +118,202 @@ rpl_get_ds6_nbr(rpl_parent_t *parent)
#endif /* UIP_ND6_SEND_NS */
/*---------------------------------------------------------------------------*/
static void
remove_parent(rpl_parent_t *parent)
remove_neighbor(rpl_nbr_t *nbr)
{
/* Make sure we don't point to a removed parent. Note that we do not need
/* Make sure we don't point to a removed neighbor. Note that we do not need
to worry about preferred_parent here, as it is locked in the the table
and will never be removed by external modules. */
if(parent == curr_instance.dag.urgent_probing_target) {
if(nbr == curr_instance.dag.urgent_probing_target) {
curr_instance.dag.urgent_probing_target = NULL;
}
if(parent == curr_instance.dag.unicast_dio_target) {
if(nbr == curr_instance.dag.unicast_dio_target) {
curr_instance.dag.unicast_dio_target = NULL;
}
nbr_table_remove(rpl_parents, parent);
nbr_table_remove(rpl_neighbors, nbr);
rpl_timers_schedule_state_update(); /* Updating from here is unsafe; postpone */
}
/*---------------------------------------------------------------------------*/
rpl_parent_t *
rpl_parent_get_from_lladdr(uip_lladdr_t *addr)
rpl_nbr_t *
rpl_neighbor_get_from_lladdr(uip_lladdr_t *addr)
{
return nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)addr);
return nbr_table_get_from_lladdr(rpl_neighbors, (linkaddr_t *)addr);
}
/*---------------------------------------------------------------------------*/
uint16_t
rpl_parent_get_link_metric(rpl_parent_t *p)
rpl_neighbor_get_link_metric(rpl_nbr_t *nbr)
{
if(p != NULL && curr_instance.of->parent_link_metric != NULL) {
return curr_instance.of->parent_link_metric(p);
if(nbr != NULL && curr_instance.of->nbr_link_metric != NULL) {
return curr_instance.of->nbr_link_metric(nbr);
}
return 0xffff;
}
/*---------------------------------------------------------------------------*/
rpl_rank_t
rpl_parent_rank_via_parent(rpl_parent_t *p)
rpl_neighbor_rank_via_nbr(rpl_nbr_t *nbr)
{
if(p != NULL && curr_instance.of->rank_via_parent != NULL) {
return curr_instance.of->rank_via_parent(p);
if(nbr != NULL && curr_instance.of->rank_via_nbr != NULL) {
return curr_instance.of->rank_via_nbr(nbr);
}
return RPL_INFINITE_RANK;
}
/*---------------------------------------------------------------------------*/
const linkaddr_t *
rpl_parent_get_lladdr(rpl_parent_t *p)
rpl_neighbor_get_lladdr(rpl_nbr_t *nbr)
{
return nbr_table_get_lladdr(rpl_parents, p);
return nbr_table_get_lladdr(rpl_neighbors, nbr);
}
/*---------------------------------------------------------------------------*/
uip_ipaddr_t *
rpl_parent_get_ipaddr(rpl_parent_t *p)
rpl_neighbor_get_ipaddr(rpl_nbr_t *nbr)
{
const linkaddr_t *lladdr = rpl_parent_get_lladdr(p);
const linkaddr_t *lladdr = rpl_neighbor_get_lladdr(nbr);
return uip_ds6_nbr_ipaddr_from_lladdr((uip_lladdr_t *)lladdr);
}
/*---------------------------------------------------------------------------*/
const struct link_stats *
rpl_parent_get_link_stats(rpl_parent_t *p)
rpl_neighbor_get_link_stats(rpl_nbr_t *nbr)
{
const linkaddr_t *lladdr = rpl_parent_get_lladdr(p);
const linkaddr_t *lladdr = rpl_neighbor_get_lladdr(nbr);
return link_stats_from_lladdr(lladdr);
}
/*---------------------------------------------------------------------------*/
int
rpl_parent_is_fresh(rpl_parent_t *p)
rpl_neighbor_is_fresh(rpl_nbr_t *nbr)
{
const struct link_stats *stats = rpl_parent_get_link_stats(p);
const struct link_stats *stats = rpl_neighbor_get_link_stats(nbr);
return link_stats_is_fresh(stats);
}
/*---------------------------------------------------------------------------*/
int
rpl_parent_is_reachable(rpl_parent_t *p) {
if(p == NULL) {
rpl_neighbor_is_reachable(rpl_nbr_t *nbr) {
if(nbr == NULL) {
return 0;
} else {
#if UIP_ND6_SEND_NS
uip_ds6_nbr_t *nbr = rpl_get_ds6_nbr(p);
uip_ds6_nbr_t *ds6_nbr = rpl_get_ds6_nbr(nbr);
/* Exclude links to a neighbor that is not reachable at a NUD level */
if(nbr == NULL || nbr->state != NBR_REACHABLE) {
if(ds6_nbr == NULL || ds6_nbr->state != NBR_REACHABLE) {
return 0;
}
#endif /* UIP_ND6_SEND_NS */
/* If we don't have fresh link information, assume the parent is reachable. */
return !rpl_parent_is_fresh(p) || curr_instance.of->parent_has_usable_link(p);
/* If we don't have fresh link information, assume the nbr is reachable. */
return !rpl_neighbor_is_fresh(nbr) || curr_instance.of->nbr_has_usable_link(nbr);
}
}
/*---------------------------------------------------------------------------*/
void
rpl_parent_set_preferred(rpl_parent_t *p)
int
rpl_neighbor_is_parent(rpl_nbr_t *nbr)
{
if(curr_instance.dag.preferred_parent != p) {
return nbr != NULL && nbr->rank < curr_instance.dag.rank;
}
/*---------------------------------------------------------------------------*/
void
rpl_neighbor_set_preferred(rpl_nbr_t *nbr)
{
if(curr_instance.dag.preferred_parent != nbr) {
PRINTF("RPL: parent switch ");
if(p != NULL) {
PRINT6ADDR(rpl_parent_get_ipaddr(p));
if(nbr != NULL) {
PRINT6ADDR(rpl_neighbor_get_ipaddr(nbr));
} else {
PRINTF("NULL");
}
PRINTF(" used to be ");
if(curr_instance.dag.preferred_parent != NULL) {
PRINT6ADDR(rpl_parent_get_ipaddr(curr_instance.dag.preferred_parent));
PRINT6ADDR(rpl_neighbor_get_ipaddr(curr_instance.dag.preferred_parent));
} else {
PRINTF("NULL");
}
PRINTF("\n");
#ifdef RPL_CALLBACK_PARENT_SWITCH
RPL_CALLBACK_PARENT_SWITCH(curr_instance.dag.preferred_parent, p);
RPL_CALLBACK_PARENT_SWITCH(curr_instance.dag.preferred_parent, nbr);
#endif /* RPL_CALLBACK_PARENT_SWITCH */
/* Always keep the preferred parent locked, so it remains in the
* neighbor table. */
nbr_table_unlock(rpl_parents, curr_instance.dag.preferred_parent);
nbr_table_lock(rpl_parents, p);
nbr_table_unlock(rpl_neighbors, curr_instance.dag.preferred_parent);
nbr_table_lock(rpl_neighbors, nbr);
/* Update DS6 default route. Use an infinite lifetime */
uip_ds6_defrt_rm(uip_ds6_defrt_lookup(
rpl_parent_get_ipaddr(curr_instance.dag.preferred_parent)));
uip_ds6_defrt_add(rpl_parent_get_ipaddr(p), 0);
rpl_neighbor_get_ipaddr(curr_instance.dag.preferred_parent)));
uip_ds6_defrt_add(rpl_neighbor_get_ipaddr(nbr), 0);
curr_instance.dag.preferred_parent = p;
curr_instance.dag.preferred_parent = nbr;
}
}
/*---------------------------------------------------------------------------*/
/* Remove DAG parents with a rank that is at least the same as minimum_rank. */
/* Remove DAG neighbors with a rank that is at least the same as minimum_rank. */
void
rpl_parent_remove_all(void)
rpl_neighbor_remove_all(void)
{
rpl_parent_t *p;
rpl_nbr_t *nbr;
PRINTF("RPL: removing all parents\n");
PRINTF("RPL: removing all neighbors\n");
p = nbr_table_head(rpl_parents);
while(p != NULL) {
remove_parent(p);
p = nbr_table_next(rpl_parents, p);
nbr = nbr_table_head(rpl_neighbors);
while(nbr != NULL) {
remove_neighbor(nbr);
nbr = nbr_table_next(rpl_neighbors, nbr);
}
/* Update needed immediately so as to ensure preferred_parent becomes NULL,
* and no longer points to a de-allocated parent. */
* and no longer points to a de-allocated neighbor. */
rpl_dag_update_state();
}
/*---------------------------------------------------------------------------*/
rpl_parent_t *
rpl_parent_get_from_ipaddr(uip_ipaddr_t *addr)
rpl_nbr_t *
rpl_neighbor_get_from_ipaddr(uip_ipaddr_t *addr)
{
uip_ds6_nbr_t *ds6_nbr = uip_ds6_nbr_lookup(addr);
const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(ds6_nbr);
return nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)lladdr);
return nbr_table_get_from_lladdr(rpl_neighbors, (linkaddr_t *)lladdr);
}
/*---------------------------------------------------------------------------*/
static rpl_parent_t *
static rpl_nbr_t *
best_parent(int fresh_only)
{
rpl_parent_t *p;
rpl_parent_t *best = NULL;
rpl_nbr_t *nbr;
rpl_nbr_t *best = NULL;
if(curr_instance.used == 0) {
return NULL;
}
/* Search for the best parent according to the OF */
for(p = nbr_table_head(rpl_parents); p != NULL; p = nbr_table_next(rpl_parents, p)) {
for(nbr = nbr_table_head(rpl_neighbors); nbr != NULL; nbr = nbr_table_next(rpl_neighbors, nbr)) {
if(!acceptable_rank(p->rank) || !curr_instance.of->parent_is_acceptable(p)) {
/* Exclude parents with a rank that is not acceptable) */
if(!acceptable_rank(nbr->rank) || !curr_instance.of->nbr_is_acceptable_parent(nbr)) {
/* Exclude neighbors with a rank that is not acceptable) */
continue;
}
if(fresh_only && !rpl_parent_is_fresh(p)) {
/* Filter out non-fresh parents if fresh_only is set */
if(fresh_only && !rpl_neighbor_is_fresh(nbr)) {
/* Filter out non-fresh nerighbors if fresh_only is set */
continue;
}
#if UIP_ND6_SEND_NS
{
uip_ds6_nbr_t *nbr = rpl_get_ds6_nbr(p);
uip_ds6_nbr_t *ds6_nbr = rpl_get_ds6_nbr(nbr);
/* Exclude links to a neighbor that is not reachable at a NUD level */
if(nbr == NULL || nbr->state != NBR_REACHABLE) {
if(ds6_nbr == NULL || ds6_nbr->state != NBR_REACHABLE) {
continue;
}
}
#endif /* UIP_ND6_SEND_NS */
/* Now we have an acceptable parent, check if it is the new best */
best = curr_instance.of->best_parent(best, p);
best = curr_instance.of->best_parent(best, nbr);
}
return best;
}
/*---------------------------------------------------------------------------*/
rpl_parent_t *
rpl_parent_select_best(void)
rpl_nbr_t *
rpl_neighbor_select_best(void)
{
rpl_parent_t *best;
rpl_nbr_t *best;
if(rpl_dag_root_is_root()) {
return NULL; /* The root has no parent */
@ -317,11 +324,11 @@ rpl_parent_select_best(void)
#if RPL_WITH_PROBING
if(best != NULL) {
if(rpl_parent_is_fresh(best)) {
if(rpl_neighbor_is_fresh(best)) {
return best;
} else {
/* The best is not fresh. Look for the best fresh now. */
rpl_parent_t *best_fresh = best_parent(1);
rpl_nbr_t *best_fresh = best_parent(1);
if(best_fresh == NULL) {
/* No fresh parent around, select best (non-fresh) */
return best;
@ -344,8 +351,8 @@ rpl_parent_select_best(void)
}
/*---------------------------------------------------------------------------*/
void
rpl_parent_init(void)
rpl_neighbor_init(void)
{
nbr_table_register(rpl_parents, (nbr_table_callback *)remove_parent);
nbr_table_register(rpl_neighbors, (nbr_table_callback *)remove_neighbor);
}
/** @} */

View File

@ -29,15 +29,15 @@
* This file is part of the Contiki operating system.
*
* \file
* Header file for rpl-parent module
* Header file for rpl-neighbor module
* \author
* Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>,
* Simon DUquennoy <simon.duquennoy@inria.fr>
*
*/
#ifndef RPL_PARENT_H
#define RPL_PARENT_H
#ifndef RPL_NEIGHBOR_H
#define RPL_NEIGHBOR_H
/********** Includes **********/
@ -54,114 +54,131 @@
/********** Public symbols **********/
/* Per-parent RPL information */
NBR_TABLE_DECLARE(rpl_parents);
/* Per-neighbor RPL information. According to RFC 6550, there exist three
* types of neighbors:
* - Candidate neighbor set: any neighbor, selected in an implementation
* and OF-specific way. The nodes in rpl_neighbors constitute the candidate neighbor set.
* - Parent set: the subset of the candidate neighbor set with rank below our rank
* - Preferred parent: one node of the parent set
*/
NBR_TABLE_DECLARE(rpl_neighbors);
/********** Public functions **********/
/**
* Initialize rpl-dag-parent module
* Initialize rpl-dag-neighbor module
*/
void rpl_parent_init(void);
void rpl_neighbor_init(void);
/**
* Tells whether a neighbor is in the parent set.
*
* \param nbr The neighbor to be tested
* \return 1 if nbr is in the parent set, 0 otherwise
*/
int rpl_neighbor_is_parent(rpl_nbr_t *nbr);
/**
* Set current RPL preferred parent and update DS6 default route accordingly
*
* \param p The new preferred parent
* \param nbr The new preferred parent
*/
void rpl_parent_set_preferred(rpl_parent_t *p);
void rpl_neighbor_set_preferred(rpl_nbr_t *nbr);
/**
* Tells wether we have fresh link information towards a given parent
* Tells wether we have fresh link information towards a given neighbor
*
* \param p The parent
* \param nbr The neighbor
* \return 1 if we have fresh link information, 0 otherwise
*/
int rpl_parent_is_fresh(rpl_parent_t *p);
int rpl_neighbor_is_fresh(rpl_nbr_t *nbr);
/**
* Tells wether we a given parent is reachable
* Tells wether we a given neighbor is reachable
*
* \param p The parent
* \param nbr The neighbor
* \return 1 if the parent is reachable, 0 otherwise
*/
int rpl_parent_is_reachable(rpl_parent_t *p);
int rpl_neighbor_is_reachable(rpl_nbr_t *nbr);
/**
* Returns a parent's link metric
* Returns a neighbor's link metric
*
* \param p The parent
* \param nbr The neighbor
* \return The link metric if any, 0xffff otherwise
*/
uint16_t rpl_parent_get_link_metric(rpl_parent_t *p);
uint16_t rpl_neighbor_get_link_metric(rpl_nbr_t *nbr);
/**
* Returns our rank if selecting a given parent as preferred parent
*
* \param p The parent
* \param nbr The neighbor
* \return The resulting rank if any, RPL_INFINITE_RANK otherwise
*/
rpl_rank_t rpl_parent_rank_via_parent(rpl_parent_t *p);
rpl_rank_t rpl_neighbor_rank_via_nbr(rpl_nbr_t *nbr);
/**
* Returns a parent's link-layer address
* Returns a neighbors's link-layer address
*
* \param p The parent
* \param nbr The neighbor
* \return The link-layer address if any, NULL otherwise
*/
const linkaddr_t *rpl_parent_get_lladdr(rpl_parent_t *p);
const linkaddr_t *rpl_neighbor_get_lladdr(rpl_nbr_t *nbr);
/**
* Returns a parent's link statistics
* Returns a neighbor's link statistics
*
* \param p The parent
* \param nbr The neighbor
* \return The link_stats structure address if any, NULL otherwise
*/
const struct link_stats *rpl_parent_get_link_stats(rpl_parent_t *p);
const struct link_stats *rpl_neighbor_get_link_stats(rpl_nbr_t *nbr);
/**
* Returns a parent's (link-local) IPv6 address
* Returns a neighbor's (link-local) IPv6 address
*
* \param p The parent
* \param nbr The neighbor
* \return The link-local IPv6 address if any, NULL otherwise
*/
uip_ipaddr_t *rpl_parent_get_ipaddr(rpl_parent_t *p);
uip_ipaddr_t *rpl_neighbor_get_ipaddr(rpl_nbr_t *nbr);
/**
* Returns a parent from its link-layer address
* Returns a neighbor from its link-layer address
*
* \param addr The link-layer address
* \return The parent if found, NULL otherwise
* \return Theneighbor if found, NULL otherwise
*/
rpl_parent_t *rpl_parent_get_from_lladdr(uip_lladdr_t *addr);
rpl_nbr_t *rpl_neighbor_get_from_lladdr(uip_lladdr_t *addr);
/**
* Returns a parent from its link-local IPv6 address
* Returns a neighbor from its link-local IPv6 address
*
* \param addr The link-local IPv6 address
* \return The parent if found, NULL otherwise
* \return The neighbor if found, NULL otherwise
*/
rpl_parent_t *rpl_parent_get_from_ipaddr(uip_ipaddr_t *addr);
rpl_nbr_t *rpl_neighbor_get_from_ipaddr(uip_ipaddr_t *addr);
/**
* Prints a summary of all RPL neighbors and their properties
*
* \param str A descriptive text on the caller
*/
void rpl_parent_print_list(const char *str);
void rpl_neighbor_print_list(const char *str);
/**
* Empty the RPL parent table
* Empty the RPL neighbor table
*/
void rpl_parent_remove_all(void);
void rpl_neighbor_remove_all(void);
/**
* Returns the best candidate for preferred parent
*
* \return The best candidate, NULL if no usable parent is found
*/
rpl_parent_t *rpl_parent_select_best(void);
rpl_nbr_t *rpl_neighbor_select_best(void);
typedef rpl_nbr_t rpl_parent_t;
#define rpl_parent_get_from_ipaddr(addr) rpl_neighbor_get_from_ipaddr(addr)
#define rpl_parent_get_ipaddr(nbr) rpl_neighbor_get_ipaddr(nbr)
/** @} */
#endif /* RPL_PARENT_H */
#endif /* RPL_NEIGHBOR_H */

View File

@ -74,13 +74,13 @@
#endif /* RPL_OF0_CONF_SR */
#if RPL_OF0_FIXED_SR
#define STEP_OF_RANK(p) (3)
#define STEP_OF_RANK(nbr) (3)
#endif /* RPL_OF0_FIXED_SR */
#if RPL_OF0_ETX_BASED_SR
/* Numbers suggested by P. Thubert for in the 6TiSCH WG. Anything that maps ETX to
* a step between 1 and 9 works. */
#define STEP_OF_RANK(p) (((3 * parent_link_metric(p)) / LINK_STATS_ETX_DIVISOR) - 2)
#define STEP_OF_RANK(nbr) (((3 * nbr_link_metric(nbr)) / LINK_STATS_ETX_DIVISOR) - 2)
#endif /* RPL_OF0_ETX_BASED_SR */
/*---------------------------------------------------------------------------*/
@ -91,91 +91,91 @@ reset(void)
}
/*---------------------------------------------------------------------------*/
static uint16_t
parent_link_metric(rpl_parent_t *p)
nbr_link_metric(rpl_nbr_t *nbr)
{
/* OF0 operates without metric container; the only metric we have is ETX */
const struct link_stats *stats = rpl_parent_get_link_stats(p);
const struct link_stats *stats = rpl_neighbor_get_link_stats(nbr);
return stats != NULL ? stats->etx : 0xffff;
}
/*---------------------------------------------------------------------------*/
static uint16_t
parent_rank_increase(rpl_parent_t *p)
nbr_rank_increase(rpl_nbr_t *nbr)
{
uint16_t min_hoprankinc;
if(p == NULL) {
if(nbr == NULL) {
return RPL_INFINITE_RANK;
}
min_hoprankinc = curr_instance.min_hoprankinc;
return (RANK_FACTOR * STEP_OF_RANK(p) + RANK_STRETCH) * min_hoprankinc;
return (RANK_FACTOR * STEP_OF_RANK(nbr) + RANK_STRETCH) * min_hoprankinc;
}
/*---------------------------------------------------------------------------*/
static uint16_t
parent_path_cost(rpl_parent_t *p)
nbr_path_cost(rpl_nbr_t *nbr)
{
if(p == NULL) {
if(nbr == NULL) {
return 0xffff;
}
/* path cost upper bound: 0xffff */
return MIN((uint32_t)p->rank + parent_link_metric(p), 0xffff);
return MIN((uint32_t)nbr->rank + nbr_link_metric(nbr), 0xffff);
}
/*---------------------------------------------------------------------------*/
static rpl_rank_t
rank_via_parent(rpl_parent_t *p)
rank_via_nbr(rpl_nbr_t *nbr)
{
if(p == NULL) {
if(nbr == NULL) {
return RPL_INFINITE_RANK;
} else {
return MIN((uint32_t)p->rank + parent_rank_increase(p), RPL_INFINITE_RANK);
return MIN((uint32_t)nbr->rank + nbr_rank_increase(nbr), RPL_INFINITE_RANK);
}
}
/*---------------------------------------------------------------------------*/
static int
parent_is_acceptable(rpl_parent_t *p)
nbr_has_usable_link(rpl_nbr_t *nbr)
{
return STEP_OF_RANK(p) >= MIN_STEP_OF_RANK
&& STEP_OF_RANK(p) <= MAX_STEP_OF_RANK;
return 1;
}
/*---------------------------------------------------------------------------*/
static int
parent_has_usable_link(rpl_parent_t *p)
nbr_is_acceptable_parent(rpl_nbr_t *nbr)
{
return parent_is_acceptable(p);
return STEP_OF_RANK(nbr) >= MIN_STEP_OF_RANK
&& STEP_OF_RANK(nbr) <= MAX_STEP_OF_RANK;
}
/*---------------------------------------------------------------------------*/
static rpl_parent_t *
best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
static rpl_nbr_t *
best_parent(rpl_nbr_t *nbr1, rpl_nbr_t *nbr2)
{
uint16_t p1_cost;
uint16_t p2_cost;
int p1_is_acceptable;
int p2_is_acceptable;
uint16_t nbr1_cost;
uint16_t nbr2_cost;
int nbr1_is_acceptable;
int nbr2_is_acceptable;
p1_is_acceptable = p1 != NULL && parent_is_acceptable(p1);
p2_is_acceptable = p2 != NULL && parent_is_acceptable(p2);
nbr1_is_acceptable = nbr1 != NULL && nbr_is_acceptable_parent(nbr1);
nbr2_is_acceptable = nbr2 != NULL && nbr_is_acceptable_parent(nbr2);
if(!p1_is_acceptable) {
return p2_is_acceptable ? p2 : NULL;
if(!nbr1_is_acceptable) {
return nbr2_is_acceptable ? nbr2 : NULL;
}
if(!p2_is_acceptable) {
return p1_is_acceptable ? p1 : NULL;
if(!nbr2_is_acceptable) {
return nbr1_is_acceptable ? nbr1 : NULL;
}
p1_cost = parent_path_cost(p1);
p2_cost = parent_path_cost(p2);
nbr1_cost = nbr_path_cost(nbr1);
nbr2_cost = nbr_path_cost(nbr2);
/* Paths costs coarse-grained (multiple of min_hoprankinc), we operate without hysteresis */
if(p1_cost != p2_cost) {
/* Pick parent with lowest path cost */
return p1_cost < p2_cost ? p1 : p2;
if(nbr1_cost != nbr2_cost) {
/* Pick nbr with lowest path cost */
return nbr1_cost < nbr2_cost ? nbr1 : nbr2;
} else {
/* We have a tie! */
/* Stik to current preferred parent if possible */
if(p1 == curr_instance.dag.preferred_parent || p2 == curr_instance.dag.preferred_parent) {
if(nbr1 == curr_instance.dag.preferred_parent || nbr2 == curr_instance.dag.preferred_parent) {
return curr_instance.dag.preferred_parent;
}
/* None of the nodes is the current preferred parent,
* choose parent with best link metric */
return parent_link_metric(p1) < parent_link_metric(p2) ? p1 : p2;
* choose nbr with best link metric */
return nbr_link_metric(nbr1) < nbr_link_metric(nbr2) ? nbr1 : nbr2;
}
}
/*---------------------------------------------------------------------------*/
@ -187,11 +187,11 @@ update_metric_container(void)
/*---------------------------------------------------------------------------*/
rpl_of_t rpl_of0 = {
reset,
parent_link_metric,
parent_has_usable_link,
parent_is_acceptable,
parent_path_cost,
rank_via_parent,
nbr_link_metric,
nbr_has_usable_link,
nbr_is_acceptable_parent,
nbr_path_cost,
rank_via_nbr,
best_parent,
update_metric_container,
RPL_OCP_OF0

View File

@ -57,7 +57,7 @@ void RPL_CALLBACK_NEW_DIO_INTERVAL(uint8_t dio_interval);
#endif /* RPL_CALLBACK_NEW_DIO_INTERVAL */
#ifdef RPL_PROBING_SELECT_FUNC
rpl_parent_t *RPL_PROBING_SELECT_FUNC(void);
rpl_nbr_t *RPL_PROBING_SELECT_FUNC(void);
#endif /* RPL_PROBING_SELECT_FUNC */
#ifdef RPL_PROBING_DELAY_FUNC
@ -191,7 +191,7 @@ handle_dio_timer(void *ptr)
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
rpl_timers_schedule_unicast_dio(rpl_parent_t *target)
rpl_timers_schedule_unicast_dio(rpl_nbr_t *target)
{
if(curr_instance.used) {
curr_instance.dag.unicast_dio_target = target;
@ -202,7 +202,7 @@ rpl_timers_schedule_unicast_dio(rpl_parent_t *target)
static void
handle_unicast_dio_timer(void *ptr)
{
uip_ipaddr_t *target_ipaddr = rpl_parent_get_ipaddr(curr_instance.dag.unicast_dio_target);
uip_ipaddr_t *target_ipaddr = rpl_neighbor_get_ipaddr(curr_instance.dag.unicast_dio_target);
if(target_ipaddr != NULL) {
rpl_icmp6_dio_output(target_ipaddr);
}
@ -276,7 +276,7 @@ handle_dao_timer(void *ptr)
}
/* We need to re-send the last DAO */
if(curr_instance.dag.dao_transmissions >= RPL_DAO_MAX_RETRANSMISSIONS) {
/* No more retransmissions. Perform local repair and hope to find another parent. */
/* No more retransmissions. Perform local repair and hope to find another . */
rpl_local_repair("DAO max rtx");
return;
}
@ -334,18 +334,18 @@ get_probing_delay(void)
}
}
/*---------------------------------------------------------------------------*/
rpl_parent_t *
rpl_nbr_t *
get_probing_target(void)
{
/* Returns the next probing target. The current implementation probes the urgent
* probing target if any, or the preferred parent if its link statistics need refresh.
* Otherwise, it picks at random between:
* (1) selecting the best parent with non-fresh link statistics
* (2) selecting the least recently updated parent
* (1) selecting the best neighbor with non-fresh link statistics
* (2) selecting the least recently updated neighbor
*/
rpl_parent_t *p;
rpl_parent_t *probing_target = NULL;
rpl_nbr_t *nbr;
rpl_nbr_t *probing_target = NULL;
rpl_rank_t probing_target_rank = RPL_INFINITE_RANK;
clock_time_t probing_target_age = 0;
clock_time_t clock_now = clock_time();
@ -360,40 +360,40 @@ get_probing_target(void)
}
/* The preferred parent needs probing */
if(curr_instance.dag.preferred_parent != NULL && !rpl_parent_is_fresh(curr_instance.dag.preferred_parent)) {
if(curr_instance.dag.preferred_parent != NULL && !rpl_neighbor_is_fresh(curr_instance.dag.preferred_parent)) {
return curr_instance.dag.preferred_parent;
}
/* With 50% probability: probe best non-fresh parent */
/* With 50% probability: probe best non-fresh neighbor */
if(random_rand() % 2 == 0) {
p = nbr_table_head(rpl_parents);
while(p != NULL) {
if(!rpl_parent_is_fresh(p)) {
nbr = nbr_table_head(rpl_neighbors);
while(nbr != NULL) {
if(!rpl_neighbor_is_fresh(nbr)) {
/* p is in our dag and needs probing */
rpl_rank_t p_rank = rpl_parent_rank_via_parent(p);
rpl_rank_t p_rank = rpl_neighbor_rank_via_nbr(nbr);
if(probing_target == NULL
|| p_rank < probing_target_rank) {
probing_target = p;
probing_target = nbr;
probing_target_rank = p_rank;
}
}
p = nbr_table_next(rpl_parents, p);
nbr = nbr_table_next(rpl_neighbors, nbr);
}
}
/* If we still do not have a probing target: pick the least recently updated parent */
/* If we still do not have a probing target: pick the least recently updated neighbor */
if(probing_target == NULL) {
p = nbr_table_head(rpl_parents);
while(p != NULL) {
const struct link_stats *stats =rpl_parent_get_link_stats(p);
nbr = nbr_table_head(rpl_neighbors);
while(nbr != NULL) {
const struct link_stats *stats =rpl_neighbor_get_link_stats(nbr);
if(stats != NULL) {
if(probing_target == NULL
|| clock_now - stats->last_tx_time > probing_target_age) {
probing_target = p;
probing_target = nbr;
probing_target_age = clock_now - stats->last_tx_time;
}
}
p = nbr_table_next(rpl_parents, p);
nbr = nbr_table_next(rpl_neighbors, nbr);
}
}
@ -403,15 +403,15 @@ get_probing_target(void)
static void
handle_probing_timer(void *ptr)
{
rpl_parent_t *probing_target = RPL_PROBING_SELECT_FUNC();
uip_ipaddr_t *target_ipaddr = rpl_parent_get_ipaddr(probing_target);
rpl_nbr_t *probing_target = RPL_PROBING_SELECT_FUNC();
uip_ipaddr_t *target_ipaddr = rpl_neighbor_get_ipaddr(probing_target);
/* Perform probing */
if(target_ipaddr != NULL) {
const struct link_stats *stats = rpl_parent_get_link_stats(probing_target);
const struct link_stats *stats = rpl_neighbor_get_link_stats(probing_target);
(void)stats;
PRINTF("RPL: probing %u %s last tx %u min ago\n",
rpl_parent_get_lladdr(probing_target)->u8[7],
rpl_neighbor_get_lladdr(probing_target)->u8[7],
curr_instance.dag.urgent_probing_target != NULL ? "(urgent)" : "",
probing_target != NULL ?
(unsigned)((clock_time() - stats->last_tx_time) / (60 * CLOCK_SECOND)) : 0
@ -461,7 +461,7 @@ handle_periodic_timer(void *ptr)
ctimer_reset(&periodic_timer);
#if DEBUG
rpl_parent_print_list("Periodic");
rpl_neighbor_print_list("Periodic");
#endif
}
/*---------------------------------------------------------------------------*/

View File

@ -76,7 +76,7 @@ void rpl_timers_dio_reset(const char *str);
/**
* Schedule unicast DIO with no delay
*/
void rpl_timers_schedule_unicast_dio(rpl_parent_t *target);
void rpl_timers_schedule_unicast_dio(rpl_nbr_t *target);
/**
* Schedule a DAO with random delay based on RPL_DAO_DELAY

View File

@ -130,15 +130,15 @@ struct rpl_prefix {
};
typedef struct rpl_prefix rpl_prefix_t;
/* All information related to a RPL parent */
struct rpl_parent {
/* All information related to a RPL neighbor */
struct rpl_nbr {
#if RPL_WITH_MC
rpl_metric_container_t mc;
#endif /* RPL_WITH_MC */
rpl_rank_t rank;
uint8_t dtsn;
};
typedef struct rpl_parent rpl_parent_t;
typedef struct rpl_nbr rpl_nbr_t;
/*---------------------------------------------------------------------------*/
/*
@ -146,23 +146,22 @@ typedef struct rpl_parent rpl_parent_t;
*
* reset(dag) Resets the objective function state for a specific DAG. This function is
* called when doing a global repair on the DAG.
* parent_link_metric(parent) Returns the link metric of a parent
* parent_has_usable_link(parent) Returns 1 iff we have a usable link to this parent
* parent_is_acceptable(parent) Returns 1 iff the parent has a usable rank/link as defined by the OF
* parent_path_cost(parent) Returns the path cost of a parent
* rank_via_parent(parent) Returns our rank if we select a given parent as preferred parent
* parent_is_acceptable Returns 1 if a parent is usable as preferred parent, 0 otherwise
* best_parent(parent1, parent2) Compares two DAGs and returns the best one, according to the OF.
* update_metric_container() dao_ack_callback(parent, status)
* nbr_link_metric(n) Returns the link metric of a neighbor
* nbr_has_usable_link(n) Returns 1 iff the neighbor has a usable link as defined by the OF
* nbr_is_acceptable_parent(n) Returns 1 iff the neighbor has a usable rank/link as defined by the OF
* nbr_path_cost(n) Returns the path cost of a neighbor
* rank_via_nbr(n) Returns our rank if we select a given neighbor as preferred parent
* best_parent(n1, n2) Compares two neighbors and returns the best one, according to the OF.
* update_metric_container() Updated the DAG metric container from the current OF state
*/
struct rpl_of {
void (*reset)(void);
uint16_t (*parent_link_metric)(rpl_parent_t *);
int (*parent_has_usable_link)(rpl_parent_t *);
int (*parent_is_acceptable)(rpl_parent_t *);
uint16_t (*parent_path_cost)(rpl_parent_t *);
rpl_rank_t (*rank_via_parent)(rpl_parent_t *);
rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *);
uint16_t (*nbr_link_metric)(rpl_nbr_t *);
int (*nbr_has_usable_link)(rpl_nbr_t *);
int (*nbr_is_acceptable_parent)(rpl_nbr_t *);
uint16_t (*nbr_path_cost)(rpl_nbr_t *);
rpl_rank_t (*rank_via_nbr)(rpl_nbr_t *);
rpl_nbr_t *(*best_parent)(rpl_nbr_t *, rpl_nbr_t *);
void (*update_metric_container)(void);
rpl_ocp_t ocp;
};
@ -173,7 +172,7 @@ typedef struct rpl_parent rpl_parent_t;
struct rpl_dag {
uip_ipaddr_t dag_id;
rpl_prefix_t prefix_info;
rpl_parent_t *preferred_parent;
rpl_nbr_t *preferred_parent;
rpl_rank_t lowest_rank; /* The lowest rank seen in the current version */
rpl_rank_t rank; /* The current rank */
uint32_t lifetime;
@ -195,10 +194,10 @@ struct rpl_dag {
struct ctimer dio_timer;
struct ctimer unicast_dio_timer;
struct ctimer dao_timer;
rpl_parent_t *unicast_dio_target;
rpl_nbr_t *unicast_dio_target;
#if RPL_WITH_PROBING
struct ctimer probing_timer;
rpl_parent_t *urgent_probing_target;
rpl_nbr_t *urgent_probing_target;
#endif /* RPL_WITH_PROBING */
#if RPL_WITH_DAO_ACK
uip_ipaddr_t dao_ack_target;

View File

@ -87,8 +87,8 @@ void
rpl_link_neighbor_callback(const linkaddr_t *addr, int status, int numtx)
{
if(curr_instance.used == 1 ) {
rpl_parent_t *parent = rpl_parent_get_from_lladdr((uip_lladdr_t *)addr);
if(parent != NULL) {
rpl_nbr_t *nbr = rpl_neighbor_get_from_lladdr((uip_lladdr_t *)addr);
if(nbr != NULL) {
/* Link stats were updated, and we need to update our internal state.
Updating from here is unsafe; postpone */
rpl_timers_schedule_state_update();
@ -174,7 +174,7 @@ rpl_init(void)
uip_ds6_maddr_add(&rpl_multicast_addr);
rpl_dag_init();
rpl_parent_init();
rpl_neighbor_init();
rpl_timers_init();
rpl_icmp6_init();

View File

@ -49,7 +49,7 @@
#include "rpl-dag.h"
#include "rpl-ns.h"
#include "rpl-dag-root.h"
#include "rpl-parent.h"
#include "rpl-neighbor.h"
#include "rpl-ext-header.h"
#include "rpl-timers.h"