With an 11s interface and HWMP then this keeps track of a throughput
estimation internally already, as specified by 802.11-2020, section 14.9.2.
The HWMP code even makes use of the Minstrel provided expected throughput
if available and is therefore very close to this expected throughput value,
except the specification adds some constant penalty for:
"Channel access overhead (in μs), which includes frame headers,
training sequences, access protocol frames, etc."
When no expected throughput is available then HWMP keeps track of the
average packet delivery error rate and average phy rate to calculate its
own expected throughput value.
So the 11s airtime link metric should be a slightly better estimate than
the expected throughput provided by Minstrel. And should be significantly
better than our raw PHY rate divided by 3 guestimate fallback.
Therefore this should significantly improve the accuracy for BATMAN V
when using drivers like ath10k/ath11k/ath12k/mt76 which all do not
implement/export an expected throughput information.
Signed-off-by: Linus Lüssing <linus.luessing(a)c0d3.blue>
---
RFC because:
* only tested in a VM with mac80211_hwsim, checked that the value
from sinfo.airtime_link_metric is used and that
"batctl o"/"batctl n" still (nearly) matches the "expected throughput"
in "iw dev wlan0 station dump"
* still needs testing / verification on real devices
* I'm a bit confused about the extra "* 100" I had to apply to make the
values match, not quite sure where that comes from?
net/batman-adv/bat_v_elp.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index 1d704574e6bf..014489f7f947 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -18,6 +18,7 @@
#include <linux/if_ether.h>
#include <linux/jiffies.h>
#include <linux/kref.h>
+#include <linux/limits.h>
#include <linux/minmax.h>
#include <linux/netdevice.h>
#include <linux/nl80211.h>
@@ -56,6 +57,25 @@ static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface)
msecs_to_jiffies(msecs));
}
+/**
+ * batadv_v_elp_get_throughput_from_11s() - get the throughput from 11s link
+ * @airtime: airtime link metric to a neighbor from an 11s link
+ *
+ * Return: The throughput towards the given neighbour in multiples of 100kpbs
+ * (a value of '1' equals 0.1Mbps, '10' equals 1Mbps, etc).
+ */
+static u32 batadv_v_elp_get_throughput_from_11s(u32 airtime)
+{
+ const int tu_to_airtime_unit = 100;
+ const int test_frame_len = 8192;
+ const int tu_to_us = 1024;
+
+ if (!airtime)
+ return U32_MAX;
+
+ return test_frame_len * 100 * tu_to_airtime_unit / (airtime * tu_to_us);
+}
+
/**
* batadv_v_elp_get_throughput() - get the throughput towards a neighbour
* @neigh: the neighbour for which the throughput has to be obtained
@@ -69,7 +89,7 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
struct ethtool_link_ksettings link_settings;
struct net_device *real_netdev;
struct station_info sinfo;
- u32 throughput;
+ u32 throughput, airtime;
int ret;
/* if the user specified a customised value for this interface, then
@@ -109,6 +129,11 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
if (ret)
goto default_throughput;
+ if (sinfo.filled & BIT(NL80211_STA_INFO_AIRTIME_LINK_METRIC)) {
+ airtime = sinfo.airtime_link_metric;
+ return batadv_v_elp_get_throughput_from_11s(airtime);
+ }
+
if (sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT))
return sinfo.expected_throughput / 100;
--
2.47.1