From 31b65059a8fe2eb30c2eafde94a76648558b5eec Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Thu, 21 Feb 2013 18:25:35 +0100 Subject: [PATCH] preparing for changing how parent selection/updates work in rpl, since the way it is implemented now goes against the spec --- sys/net/sixlowpan/rpl/of_mrhof.c | 188 ++++++++++++++++++++++++++----- sys/net/sixlowpan/rpl/of_mrhof.h | 27 ++++- 2 files changed, 180 insertions(+), 35 deletions(-) diff --git a/sys/net/sixlowpan/rpl/of_mrhof.c b/sys/net/sixlowpan/rpl/of_mrhof.c index 801a9ebf7c..91b5978cf4 100644 --- a/sys/net/sixlowpan/rpl/of_mrhof.c +++ b/sys/net/sixlowpan/rpl/of_mrhof.c @@ -1,56 +1,182 @@ #include +#include #include "of_mrhof.h" +static char is_initialised = 0; + +uint16_t cur_min_path_cost = MAX_PATH_COST; +static mrhof_candidate_info_t candidate_info[RPL_MAX_CANDIDATE_NEIGHBORS]; + rpl_of_t rpl_of_mrhof = { - 0x1, - calc_rank, - which_parent, - which_dodag, - reset, - NULL + 0x1, + calc_rank, + which_parent, + which_dodag, + reset, + init, + NULL }; -rpl_of_t *rpl_get_of_mrhof(){ +rpl_of_t *rpl_get_of_mrhof() { return &rpl_of_mrhof; } -void reset(rpl_dodag_t *dodag){ - if(PARENT_SET_SIZE > 3){ - //do stuff +void init() { + //TODO implement OF-specific init of timers/functions/structs/whatever + if (!is_initialised) { + //blabla init this node } + is_initialised = 1; +} + +void reset(rpl_dodag_t *dodag) { //todo implement if necessary } -uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank){ - if(base_rank == 0) { - if(parent == NULL) { - return INFINITE_RANK; - } - base_rank = parent->rank; +void calc_path_cost() { + /* + * Calculates the path cost through all candidate neighbours and sets + * cur_min_path_cost to the lowest value? + */ + + if(i_am_root){ + //Since for now we only support ETX, the pastcost that computes to + //a rank of minhoprankincrease IS minhoprankincrease + cur_min_path_cost = rpl_get_my_dodag()->minhoprankincrease; + return; } - uint16_t add; - if(parent != NULL){ - add = parent->dodag->minhoprankincrease; + /* + * This is the boolean describing if I need to do a parent selection. + * This happens always when the past cost for a candidate neighbor OR a + * parent changes. + */ + char do_parent_selection = 0; + uint16_t path_cost = 0; + for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + if(candidates[i].used){ + if(candidate_info[i].cur_etx != 0){ + /* The RFC specifies this computation a bit ambiguously, this is + * what I understood: + * + * (ETX_for_link_to_neighbor * 128) + Rank_of_that_neighbor + * + * This means I get the rank of that neighbor (which is the etx + * of the whole path from him to the root node) plus my ETX to + * that neighbor*128, which would be the 'rank' of the single link + * from me to that neighbor + * + */ + path_cost = candidate_info[i].cur_etx*ETX_RANK_MULTIPLIER + (candidates[i].dodag->my_rank); + if(candidate_info[i].cur_path_cost == path_cost){ + //nothing changed + continue; + } + do_parent_selection = 1; + candidate_info[i].cur_path_cost = path_cost; + }else{ + //if it is 0, the value has not been computed yet, so we can't + //compute a path cost + if(candidate_info[i].cur_path_cost == MAX_PATH_COST){ + //nothing changed + continue; + } + do_parent_selection = 1; + candidate_info[i].cur_path_cost = MAX_PATH_COST; + } + } } - else{ - add = DEFAULT_MIN_HOP_RANK_INCREASE; + if(do_parent_selection){ + parent_selection(); } - if( base_rank + add < base_rank ){ - return INFINITE_RANK; - } - return base_rank + add; + } -//We simply return the Parent with lower rank -rpl_parent_t * which_parent(rpl_parent_t *p1, rpl_parent_t *p2){ - if(p1->rank < p2->rank){ - return p1; +uint16_t calc_rank() { + /* + * Return the rank for this node (calculated from path cost). + * There will be 3 values calculated, the highest of those 3 values will be + * used as the noderank. + * + * For now, there is no metric-selection or specification, so the rank com- + * putation will always be assumed to be done for the ETX metric. + */ + uint16_t result = INFINITE_RANK; + + //Holds the 3 computed values for the nodes rank from which the max value + //will be the nodes actual rank + uint16_t rankarray[3] = {0,0,0}; + + //TODO finish this + //rankarray[0] = (rpl_find_preferred_parent()->rank > ; + + if (i_am_root) { + result = rpl_get_my_dodag()->minhoprankincrease; + return result; } - return p2; + + //Check which parent has the highest advertised rank + for (uint8_t i = 0; i < RPL_MAX_PARENTS; i++) { + if (parents[i].used) { + if (parents[i].rank == INFINITE_RANK){ + // parent not useful, should be deleted //TODO check if deletion + // should be triggered from here + continue; + } + else if (parents[i].rank > rankarray[2]) { + //store it away + rankarray[2] = parents[i].rank; + } + } + } + + //Compute 2nd rankvalue and store it in 2nd place in the array + if(rpl_get_my_dodag()->minhoprankincrease * (1 + (rankarray[2]/rpl_get_my_dodag()->minhoprankincrease)) < rankarray[2]){ + //overflow + rankarray[1] = INFINITE_RANK; + }else{ + rankarray[1] = rpl_get_my_dodag()->minhoprankincrease * (1 + (rankarray[2]/rpl_get_my_dodag()->minhoprankincrease)); + } + + //Compute the 3rd rankvalue and store it in the 3rd place + if(rankarray[2] - rpl_get_my_dodag()->maxrankincrease ) + + + return result; +} + +void parent_selection(){ + /* + * Select a candidate neighbor as preferred parent. + * + * Note: + * If we allow floating roots, a node may have no parents + */ + + /* + * Might be faster to set the node directly? + */ + uint8_t cur_min_path_neighbor_index = 0; + uint16_t min_path_cost = MAX_PATH_COST; + + for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + /* + * Go through all Candidate Neighbors, compare their path cost with cur- + * rent minimum path cost and change cur_min_path_neighbor_index + * to the index of the current neighbor if his path is 'shorter' + */ + if(candidates[i].used && (candidate_info[i].cur_path_cost < MAX_LINK_METRIC)){ + if(candidate_info[i].cur_path_cost < min_path_cost){ + cur_min_path_neighbor_index = i; + } + } + } + + //TODO finish this. + //rpl_find_preferred_parent() } //Not used yet, as the implementation only makes use of one dodag for now. -rpl_dodag_t * which_dodag(rpl_dodag_t *d1, rpl_dodag_t *d2){ +rpl_dodag_t * which_dodag(rpl_dodag_t *d1, rpl_dodag_t *d2) { return d1; } diff --git a/sys/net/sixlowpan/rpl/of_mrhof.h b/sys/net/sixlowpan/rpl/of_mrhof.h index 846da62128..ed4aa04377 100644 --- a/sys/net/sixlowpan/rpl/of_mrhof.h +++ b/sys/net/sixlowpan/rpl/of_mrhof.h @@ -6,23 +6,42 @@ // Disallow paths with greater than 256 // expected transmission counts. -#define MAX_PATH_COST (32768) +#define MAX_PATH_COST (0x8000) // Switch to a new path only if it is // expected to require at least 1.5 fewer transmissions than the // current path. #define PARENT_SWITCH_THRESHOLD (192) -// If the preferred parent is not available, two +// If the preferred parent is not available, some more // candidate parents are still available without triggering a new // round of route discovery. -#define PARENT_SET_SIZE (3) +#define PARENT_SET_SIZE (RPL_MAX_PARENTS) // Do not allow a node to become a floating root. #define ALLOW_FLOATING_ROOT (0) +// While assigning Rank when using ETX, use the representation of ETX described +// in [RFC6551], i.e., assign Rank equal to ETX * 128. +#define ETX_RANK_MULTIPLIER (0x80) + rpl_of_t *rpl_get_of_mrhof(); -uint16_t calc_rank(rpl_parent_t *, uint16_t); +uint16_t calc_rank(); +uint16_t calc_path_cost(); +uint16_t calc_etx_value(); rpl_parent_t *which_parent(rpl_parent_t *, rpl_parent_t *); rpl_dodag_t *which_dodag(rpl_dodag_t *, rpl_dodag_t *); void reset(rpl_dodag_t *); + +//############################ +// OF specific structs ####### +//############################ + +//neighbour struct for etx path calculation +typedef struct mrhof_candidate_info_t { + ipv6_addr_t addr; + uint16_t packet_snt; + uint16_t packet_rec; + uint16_t cur_path_cost; + uint16_t cur_etx; +} mrhof_candidate_info_t;