diff --git a/sys/include/net/gnrc/rpl/structs.h b/sys/include/net/gnrc/rpl/structs.h index 2dbad50ba7..fb5301b78e 100644 --- a/sys/include/net/gnrc/rpl/structs.h +++ b/sys/include/net/gnrc/rpl/structs.h @@ -238,7 +238,24 @@ struct gnrc_rpl_parent { typedef struct { uint16_t ocp; /**< objective code point */ uint16_t (*calc_rank)(gnrc_rpl_parent_t *parent, uint16_t base_rank); /**< calculate the rank */ - gnrc_rpl_parent_t *(*which_parent)(gnrc_rpl_parent_t *, gnrc_rpl_parent_t *); /**< compare for parents */ + gnrc_rpl_parent_t *(*which_parent)(gnrc_rpl_parent_t *, gnrc_rpl_parent_t *); /**< retrieve the better parent */ + + /** + * @brief Compare two @ref gnrc_rpl_parent_t. + * + * Compares two parents based on the rank calculated by the objective + * function. This function is used to determine the parent list order. The + * parents are ordered from the preferred parent to the least preferred + * parent. + * + * @param[in] parent1 First parent to compare. + * @param[in] parent2 Second parent to compare. + * + * @return Zero if the parents are of equal preference. + * @return Positive, if the second parent is preferred. + * @return Negative, if the first parent is preferred. + */ + int (*parent_cmp)(gnrc_rpl_parent_t *parent1, gnrc_rpl_parent_t *parent2); gnrc_rpl_dodag_t *(*which_dodag)(gnrc_rpl_dodag_t *, gnrc_rpl_dodag_t *); /**< compare for dodags */ void (*reset)(gnrc_rpl_dodag_t *); /**< resets the OF */ void (*parent_state_callback)(gnrc_rpl_parent_t *, int, int); /**< retrieves the state of a parent*/ diff --git a/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c b/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c index 04cdf16cc7..cefc2d79a8 100644 --- a/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c +++ b/sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c @@ -309,17 +309,14 @@ static gnrc_rpl_parent_t *_gnrc_rpl_find_preferred_parent(gnrc_rpl_dodag_t *doda return NULL; } - LL_FOREACH(dodag->parents, elt) { - new_best = dodag->instance->of->which_parent(new_best, elt); - } + LL_SORT(dodag->parents, dodag->instance->of->parent_cmp); + new_best = dodag->parents; if (new_best->rank == GNRC_RPL_INFINITE_RANK) { return NULL; } if (new_best != old_best) { - LL_DELETE(dodag->parents, new_best); - LL_PREPEND(dodag->parents, new_best); /* no-path DAOs only for the storing mode */ if ((dodag->instance->mop == GNRC_RPL_MOP_STORING_MODE_NO_MC) || (dodag->instance->mop == GNRC_RPL_MOP_STORING_MODE_MC)) { diff --git a/sys/net/gnrc/routing/rpl/of0.c b/sys/net/gnrc/routing/rpl/of0.c index 3bd5d5faee..0fb5e5ddb2 100644 --- a/sys/net/gnrc/routing/rpl/of0.c +++ b/sys/net/gnrc/routing/rpl/of0.c @@ -25,6 +25,7 @@ static uint16_t calc_rank(gnrc_rpl_parent_t *, uint16_t); static gnrc_rpl_parent_t *which_parent(gnrc_rpl_parent_t *, gnrc_rpl_parent_t *); +static int parent_cmp(gnrc_rpl_parent_t *, gnrc_rpl_parent_t *); static gnrc_rpl_dodag_t *which_dodag(gnrc_rpl_dodag_t *, gnrc_rpl_dodag_t *); static void reset(gnrc_rpl_dodag_t *); @@ -32,6 +33,7 @@ static gnrc_rpl_of_t gnrc_rpl_of0 = { 0x0, calc_rank, which_parent, + parent_cmp, which_dodag, reset, NULL, @@ -79,11 +81,21 @@ uint16_t calc_rank(gnrc_rpl_parent_t *parent, uint16_t base_rank) /* We simply return the Parent with lower rank */ gnrc_rpl_parent_t *which_parent(gnrc_rpl_parent_t *p1, gnrc_rpl_parent_t *p2) { - if (p1->rank <= p2->rank) { - return p1; + if (parent_cmp(p1, p2) > 0) { + return p2; } + return p1; +} - return p2; +int parent_cmp(gnrc_rpl_parent_t *parent1, gnrc_rpl_parent_t *parent2) +{ + if (parent1->rank < parent2->rank) { + return -1; + } + else if (parent1->rank > parent2->rank) { + return 1; + } + return 0; } /* Not used yet */