mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
batman-adv: Ignore neighbor throughput metrics in error case
commit e7e34ffc976aaae4f465b7898303241b81ceefc3 upstream. If a temporary error happened in the evaluation of the neighbor throughput information, then the invalid throughput result should not be stored in the throughtput EWMA. Cc: stable@vger.kernel.org Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
7eb5dd2016
commit
792a14c90d
@@ -60,11 +60,13 @@ static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface)
|
|||||||
/**
|
/**
|
||||||
* batadv_v_elp_get_throughput() - get the throughput towards a neighbour
|
* batadv_v_elp_get_throughput() - get the throughput towards a neighbour
|
||||||
* @neigh: the neighbour for which the throughput has to be obtained
|
* @neigh: the neighbour for which the throughput has to be obtained
|
||||||
|
* @pthroughput: calculated throughput towards the given neighbour in multiples
|
||||||
|
* of 100kpbs (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
|
||||||
*
|
*
|
||||||
* Return: The throughput towards the given neighbour in multiples of 100kpbs
|
* Return: true when value behind @pthroughput was set
|
||||||
* (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
|
|
||||||
*/
|
*/
|
||||||
static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh,
|
||||||
|
u32 *pthroughput)
|
||||||
{
|
{
|
||||||
struct batadv_hard_iface *hard_iface = neigh->if_incoming;
|
struct batadv_hard_iface *hard_iface = neigh->if_incoming;
|
||||||
struct net_device *soft_iface = hard_iface->soft_iface;
|
struct net_device *soft_iface = hard_iface->soft_iface;
|
||||||
@@ -78,14 +80,16 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
|||||||
* batman-adv interface
|
* batman-adv interface
|
||||||
*/
|
*/
|
||||||
if (!soft_iface)
|
if (!soft_iface)
|
||||||
return BATADV_THROUGHPUT_DEFAULT_VALUE;
|
return false;
|
||||||
|
|
||||||
/* if the user specified a customised value for this interface, then
|
/* if the user specified a customised value for this interface, then
|
||||||
* return it directly
|
* return it directly
|
||||||
*/
|
*/
|
||||||
throughput = atomic_read(&hard_iface->bat_v.throughput_override);
|
throughput = atomic_read(&hard_iface->bat_v.throughput_override);
|
||||||
if (throughput != 0)
|
if (throughput != 0) {
|
||||||
return throughput;
|
*pthroughput = throughput;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* if this is a wireless device, then ask its throughput through
|
/* if this is a wireless device, then ask its throughput through
|
||||||
* cfg80211 API
|
* cfg80211 API
|
||||||
@@ -112,19 +116,24 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
|||||||
* possible to delete this neighbor. For now set
|
* possible to delete this neighbor. For now set
|
||||||
* the throughput metric to 0.
|
* the throughput metric to 0.
|
||||||
*/
|
*/
|
||||||
return 0;
|
*pthroughput = 0;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (ret)
|
if (ret)
|
||||||
goto default_throughput;
|
goto default_throughput;
|
||||||
|
|
||||||
if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT))
|
if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT)) {
|
||||||
return sinfo.expected_throughput / 100;
|
*pthroughput = sinfo.expected_throughput / 100;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* try to estimate the expected throughput based on reported tx
|
/* try to estimate the expected throughput based on reported tx
|
||||||
* rates
|
* rates
|
||||||
*/
|
*/
|
||||||
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))
|
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) {
|
||||||
return cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
|
*pthroughput = cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
goto default_throughput;
|
goto default_throughput;
|
||||||
}
|
}
|
||||||
@@ -143,8 +152,10 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
|||||||
hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
|
hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
|
||||||
|
|
||||||
throughput = link_settings.base.speed;
|
throughput = link_settings.base.speed;
|
||||||
if (throughput && throughput != SPEED_UNKNOWN)
|
if (throughput && throughput != SPEED_UNKNOWN) {
|
||||||
return throughput * 10;
|
*pthroughput = throughput * 10;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default_throughput:
|
default_throughput:
|
||||||
@@ -158,7 +169,8 @@ default_throughput:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* if none of the above cases apply, return the base_throughput */
|
/* if none of the above cases apply, return the base_throughput */
|
||||||
return BATADV_THROUGHPUT_DEFAULT_VALUE;
|
*pthroughput = BATADV_THROUGHPUT_DEFAULT_VALUE;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -170,15 +182,21 @@ void batadv_v_elp_throughput_metric_update(struct work_struct *work)
|
|||||||
{
|
{
|
||||||
struct batadv_hardif_neigh_node_bat_v *neigh_bat_v;
|
struct batadv_hardif_neigh_node_bat_v *neigh_bat_v;
|
||||||
struct batadv_hardif_neigh_node *neigh;
|
struct batadv_hardif_neigh_node *neigh;
|
||||||
|
u32 throughput;
|
||||||
|
bool valid;
|
||||||
|
|
||||||
neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v,
|
neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v,
|
||||||
metric_work);
|
metric_work);
|
||||||
neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node,
|
neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node,
|
||||||
bat_v);
|
bat_v);
|
||||||
|
|
||||||
ewma_throughput_add(&neigh->bat_v.throughput,
|
valid = batadv_v_elp_get_throughput(neigh, &throughput);
|
||||||
batadv_v_elp_get_throughput(neigh));
|
if (!valid)
|
||||||
|
goto put_neigh;
|
||||||
|
|
||||||
|
ewma_throughput_add(&neigh->bat_v.throughput, throughput);
|
||||||
|
|
||||||
|
put_neigh:
|
||||||
/* decrement refcounter to balance increment performed before scheduling
|
/* decrement refcounter to balance increment performed before scheduling
|
||||||
* this task
|
* this task
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user