net: rpl: Fix invalid access of IPv6 nbr link metric

Link metric is part IPv6 neighbour data struct. But RPL code is
trying to access it from RPL parent table where link metric doesn't
exist. So provided an api to get IPv6 neighbour data from RPL parent
data.

Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@linux.intel.com>
This commit is contained in:
Ravi kumar Veeramally 2017-07-07 10:49:23 +03:00 committed by Jukka Rissanen
parent d971d26f84
commit ab2dbffc4f
3 changed files with 69 additions and 35 deletions

View File

@ -103,25 +103,18 @@ static int net_rpl_mrhof_neighbor_link_cb(struct net_if *iface,
{
u16_t packet_etx = numtx * NET_RPL_MC_ETX_DIVISOR;
u16_t recorded_etx = 0;
struct net_nbr *nbr = NULL;
struct net_nbr *ipv6_nbr;
struct net_ipv6_nbr_data *data;
u16_t new_etx;
nbr = net_rpl_get_nbr(parent);
if (!nbr) {
/* No neighbor for this parent - something bad has occurred */
data = net_rpl_get_ipv6_nbr_data(parent);
if (!data) {
/* No neighbor data for this parent,
* something bad has occurred.
*/
return -ENOENT;
}
ipv6_nbr = net_ipv6_get_nbr(iface, nbr->idx);
if (!ipv6_nbr) {
/* No neighbor for this index, this definitely should not have
* happened.
*/
return -EINVAL;
}
recorded_etx = net_ipv6_nbr_data(ipv6_nbr)->link_metric;
recorded_etx = data->link_metric;
/* Do not penalize the ETX when collisions or transmission errors
* occur.
@ -157,7 +150,7 @@ static int net_rpl_mrhof_neighbor_link_cb(struct net_if *iface,
packet_etx / NET_RPL_MC_ETX_DIVISOR);
/* Update the link metric for this IPv6 nbr */
net_ipv6_nbr_data(ipv6_nbr)->link_metric = new_etx;
data->link_metric = new_etx;
}
return 0;
@ -170,6 +163,7 @@ int net_rpl_of_neighbor_link_cb(struct net_if *iface,
static u16_t calculate_path_metric(struct net_rpl_parent *parent)
{
struct net_ipv6_nbr_data *data;
struct net_nbr *nbr;
if (!parent) {
@ -181,15 +175,22 @@ static u16_t calculate_path_metric(struct net_rpl_parent *parent)
return MRHOF_MAX_PATH_COST * NET_RPL_MC_ETX_DIVISOR;
}
data = net_rpl_get_ipv6_nbr_data(parent);
if (!data) {
/* No neighbor data for this parent,
* something bad has occurred.
*/
return 0;
}
#if defined(CONFIG_NET_RPL_MC_NONE)
return parent->rank + net_ipv6_nbr_data(nbr)->link_metric;
return parent->rank + data->link_metric;
#elif defined(CONFIG_NET_RPL_MC_ETX)
return parent->mc.obj.etx + net_ipv6_nbr_data(nbr)->link_metric;
return parent->mc.obj.etx + data->link_metric;
#elif defined(CONFIG_NET_RPL_MC_ENERGY)
return parent->mc.obj.energy.estimation +
net_ipv6_nbr_data(nbr)->link_metric;
return parent->mc.obj.energy.estimation + data->link_metric;
#else
#error "Unsupported routing metric configured"
#endif
@ -262,19 +263,24 @@ static u16_t net_rpl_mrhof_calc_rank(struct net_rpl_parent *parent,
u16_t base_rank)
{
u16_t new_rank;
u16_t rank_increase;
struct net_nbr *nbr;
u16_t rank_increase = 0;
struct net_ipv6_nbr_data *data;
nbr = net_rpl_get_nbr(parent);
if (!parent) {
return NET_RPL_INFINITE_RANK;
}
if (!parent || !nbr) {
data = net_rpl_get_ipv6_nbr_data(parent);
if (!data) {
if (base_rank == 0) {
return NET_RPL_INFINITE_RANK;
}
rank_increase = CONFIG_NET_RPL_INIT_LINK_METRIC *
NET_RPL_MC_ETX_DIVISOR;
} else {
rank_increase = net_ipv6_nbr_data(nbr)->link_metric;
rank_increase = data->link_metric;
if (base_rank == 0) {
base_rank = parent->rank;
}

View File

@ -281,6 +281,24 @@ struct net_nbr *net_rpl_get_nbr(struct net_rpl_parent *data)
return NULL;
}
struct net_ipv6_nbr_data *
net_rpl_get_ipv6_nbr_data(struct net_rpl_parent *parent)
{
struct net_nbr *nbr;
nbr = net_rpl_get_nbr(parent);
if (nbr) {
struct net_nbr *ipv6_nbr;
ipv6_nbr = net_ipv6_get_nbr(nbr->iface, nbr->idx);
if (ipv6_nbr) {
return net_ipv6_nbr_data(ipv6_nbr);
}
}
return NULL;
}
static inline void nbr_free(struct net_nbr *nbr)
{
NET_DBG("nbr %p", nbr);
@ -1538,6 +1556,7 @@ static struct net_rpl_parent *net_rpl_add_parent(struct net_if *iface,
struct net_rpl_parent *parent;
struct net_linkaddr lladdr;
struct net_nbr *rpl_nbr;
struct net_nbr *ipv6_nbr;
lladdr_storage = net_nbr_get_lladdr(nbr->idx);
@ -1571,11 +1590,14 @@ static struct net_rpl_parent *net_rpl_add_parent(struct net_if *iface,
/* Check whether we have a neighbor that has not gotten
* a link metric yet.
*/
data = net_ipv6_nbr_data(nbr);
if (data->link_metric == 0) {
data->link_metric = CONFIG_NET_RPL_INIT_LINK_METRIC *
NET_RPL_MC_ETX_DIVISOR;
ipv6_nbr = net_ipv6_get_nbr(iface, nbr->idx);
if (ipv6_nbr) {
data = net_ipv6_nbr_data(ipv6_nbr);
if (data->link_metric == 0) {
data->link_metric =
CONFIG_NET_RPL_INIT_LINK_METRIC *
NET_RPL_MC_ETX_DIVISOR;
}
}
#if !defined(CONFIG_NET_RPL_DAG_MC_NONE)
@ -2109,13 +2131,9 @@ static void global_repair(struct net_if *iface,
#define net_rpl_print_parent_info(parent, instance) \
do { \
struct net_nbr *nbr; \
struct net_ipv6_nbr_data *data = NULL; \
struct net_ipv6_nbr_data *data; \
\
nbr = net_rpl_get_nbr(parent); \
if (nbr->idx != NET_NBR_LLADDR_UNKNOWN) { \
data = net_ipv6_get_nbr_by_index(nbr->idx); \
} \
data = net_rpl_get_ipv6_nbr_data(parent); \
\
NET_DBG("Preferred DAG %s rank %d min_rank %d " \
"parent rank %d parent etx %d link metric %d " \

View File

@ -305,6 +305,16 @@ struct net_rpl_dag {
*/
struct net_nbr *net_rpl_get_nbr(struct net_rpl_parent *data);
/**
* @brief Get related neighbor data from parent pointer.
*
* @param data Pointer to parent.
*
* @return Neighbor data pointer if found, NULL if neighbor is not found.
*/
struct net_ipv6_nbr_data *
net_rpl_get_ipv6_nbr_data(struct net_rpl_parent *parent);
/**
* @brief RPL object function (OF) reset.
*