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:
parent
072b278732
commit
96405e2c49
|
@ -59,11 +59,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
|
||||
* @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
|
||||
* (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
|
||||
* Return: true when value behind @pthroughput was set
|
||||
*/
|
||||
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 net_device *soft_iface = hard_iface->soft_iface;
|
||||
|
@ -77,14 +79,16 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
|||
* batman-adv interface
|
||||
*/
|
||||
if (!soft_iface)
|
||||
return BATADV_THROUGHPUT_DEFAULT_VALUE;
|
||||
return false;
|
||||
|
||||
/* if the user specified a customised value for this interface, then
|
||||
* return it directly
|
||||
*/
|
||||
throughput = atomic_read(&hard_iface->bat_v.throughput_override);
|
||||
if (throughput != 0)
|
||||
return throughput;
|
||||
if (throughput != 0) {
|
||||
*pthroughput = throughput;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* if this is a wireless device, then ask its throughput through
|
||||
* cfg80211 API
|
||||
|
@ -111,19 +115,24 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
|||
* possible to delete this neighbor. For now set
|
||||
* the throughput metric to 0.
|
||||
*/
|
||||
return 0;
|
||||
*pthroughput = 0;
|
||||
return true;
|
||||
}
|
||||
if (ret)
|
||||
goto default_throughput;
|
||||
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT))
|
||||
return sinfo.expected_throughput / 100;
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT)) {
|
||||
*pthroughput = sinfo.expected_throughput / 100;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* try to estimate the expected throughput based on reported tx
|
||||
* rates
|
||||
*/
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE))
|
||||
return cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)) {
|
||||
*pthroughput = cfg80211_calculate_bitrate(&sinfo.txrate) / 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
goto default_throughput;
|
||||
}
|
||||
|
@ -142,8 +151,10 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
|
|||
hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
|
||||
|
||||
throughput = link_settings.base.speed;
|
||||
if (throughput && throughput != SPEED_UNKNOWN)
|
||||
return throughput * 10;
|
||||
if (throughput && throughput != SPEED_UNKNOWN) {
|
||||
*pthroughput = throughput * 10;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
default_throughput:
|
||||
|
@ -157,7 +168,8 @@ default_throughput:
|
|||
}
|
||||
|
||||
/* if none of the above cases apply, return the base_throughput */
|
||||
return BATADV_THROUGHPUT_DEFAULT_VALUE;
|
||||
*pthroughput = BATADV_THROUGHPUT_DEFAULT_VALUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,15 +181,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 *neigh;
|
||||
u32 throughput;
|
||||
bool valid;
|
||||
|
||||
neigh_bat_v = container_of(work, struct batadv_hardif_neigh_node_bat_v,
|
||||
metric_work);
|
||||
neigh = container_of(neigh_bat_v, struct batadv_hardif_neigh_node,
|
||||
bat_v);
|
||||
|
||||
ewma_throughput_add(&neigh->bat_v.throughput,
|
||||
batadv_v_elp_get_throughput(neigh));
|
||||
valid = batadv_v_elp_get_throughput(neigh, &throughput);
|
||||
if (!valid)
|
||||
goto put_neigh;
|
||||
|
||||
ewma_throughput_add(&neigh->bat_v.throughput, throughput);
|
||||
|
||||
put_neigh:
|
||||
/* decrement refcounter to balance increment performed before scheduling
|
||||
* this task
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue