Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
From 83b458f476fdd55ed06e4db50051f17ea4b3f2ba Mon Sep 17 00:00:00 2001
From: Grische <github@grische.xyz>
Date: Thu, 7 Aug 2025 21:53:48 +0200
Subject: [PATCH] patches: mac80211: estimate expected throughput if not
provided by driver/rc

---
...oughput-if-not-provided-by-driver-rc.patch | 213 ++++++++++++++++++
1 file changed, 213 insertions(+)
create mode 100644 patches/openwrt/0010-mac80211-estimate-expected-throughput-if-not-provided-by-driver-rc.patch

diff --git a/patches/openwrt/0010-mac80211-estimate-expected-throughput-if-not-provided-by-driver-rc.patch b/patches/openwrt/0010-mac80211-estimate-expected-throughput-if-not-provided-by-driver-rc.patch
new file mode 100644
index 00000000..51188d06
--- /dev/null
+++ b/patches/openwrt/0010-mac80211-estimate-expected-throughput-if-not-provided-by-driver-rc.patch
@@ -0,0 +1,213 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Wed, 6 Aug 2025 11:09:57 +0200
+Subject: mac80211: estimate expected throughput if not provided by driver/rc
+
+Estimate the tx throughput based on the expected per-packet tx time.
+This is useful for mesh implementations that rely on expected throughput,
+e.g. 802.11s or batman-adv.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+
+diff --git a/package/kernel/mac80211/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch b/package/kernel/mac80211/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch
+new file mode 100644
+index 0000000000000000000000000000000000000000..b5d5a72f87010f0d1d6bcb4ad65267c3f6725b57
+--- /dev/null
++++ b/package/kernel/mac80211/patches/subsys/360-mac80211-factor-out-part-of-ieee80211_calc_expected_.patch
+@@ -0,0 +1,140 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Wed, 6 Aug 2025 10:49:54 +0200
++Subject: [PATCH] mac80211: factor out part of
++ ieee80211_calc_expected_tx_airtime
++
++Create ieee80211_rate_expected_tx_airtime helper function, which returns
++the expected tx airtime for a given rate and packet length in units of
++1024 usec, for more accuracy.
++
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/net/mac80211/airtime.c
+++++ b/net/mac80211/airtime.c
++@@ -685,7 +685,7 @@ static int ieee80211_fill_rx_status(stru
++ if (ieee80211_fill_rate_info(hw, stat, band, ri))
++ return 0;
++
++- if (!ieee80211_rate_valid(rate))
+++ if (!rate || !ieee80211_rate_valid(rate))
++ return -1;
++
++ if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
++@@ -753,6 +753,53 @@ u32 ieee80211_calc_tx_airtime(struct iee
++ }
++ EXPORT_SYMBOL_GPL(ieee80211_calc_tx_airtime);
++
+++u32 ieee80211_rate_expected_tx_airtime(struct ieee80211_hw *hw,
+++ struct ieee80211_tx_rate *tx_rate,
+++ struct rate_info *ri,
+++ enum nl80211_band band,
+++ bool ampdu, int len)
+++{
+++ struct ieee80211_rx_status stat;
+++ u32 duration, overhead;
+++ u8 agg_shift;
+++
+++ if (ieee80211_fill_rx_status(&stat, hw, tx_rate, ri, band, len))
+++ return 0;
+++
+++ if (stat.encoding == RX_ENC_LEGACY || !ampdu)
+++ return ieee80211_calc_rx_airtime(hw, &stat, len) * 1024;
+++
+++ duration = ieee80211_get_rate_duration(hw, &stat, &overhead);
+++
+++ /*
+++ * Assume that HT/VHT transmission on any AC except VO will
+++ * use aggregation. Since we don't have reliable reporting
+++ * of aggregation length, assume an average size based on the
+++ * tx rate.
+++ * This will not be very accurate, but much better than simply
+++ * assuming un-aggregated tx in all cases.
+++ */
+++ if (duration > 400 * 1024) /* <= VHT20 MCS2 1S */
+++ agg_shift = 1;
+++ else if (duration > 250 * 1024) /* <= VHT20 MCS3 1S or MCS1 2S */
+++ agg_shift = 2;
+++ else if (duration > 150 * 1024) /* <= VHT20 MCS5 1S or MCS2 2S */
+++ agg_shift = 3;
+++ else if (duration > 70 * 1024) /* <= VHT20 MCS5 2S */
+++ agg_shift = 4;
+++ else if (stat.encoding != RX_ENC_HE ||
+++ duration > 20 * 1024) /* <= HE40 MCS6 2S */
+++ agg_shift = 5;
+++ else
+++ agg_shift = 6;
+++
+++ duration *= len;
+++ duration /= AVG_PKT_SIZE;
+++ duration += (overhead * 1024 >> agg_shift);
+++
+++ return duration;
+++}
+++
++ u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
++ struct ieee80211_vif *vif,
++ struct ieee80211_sta *pubsta,
++@@ -775,45 +822,13 @@ u32 ieee80211_calc_expected_tx_airtime(s
++ if (pubsta) {
++ struct sta_info *sta = container_of(pubsta, struct sta_info,
++ sta);
++- struct ieee80211_rx_status stat;
++ struct ieee80211_tx_rate *tx_rate = &sta->deflink.tx_stats.last_rate;
++ struct rate_info *ri = &sta->deflink.tx_stats.last_rate_info;
++- u32 duration, overhead;
++- u8 agg_shift;
++-
++- if (ieee80211_fill_rx_status(&stat, hw, tx_rate, ri, band, len))
++- return 0;
++-
++- if (stat.encoding == RX_ENC_LEGACY || !ampdu)
++- return ieee80211_calc_rx_airtime(hw, &stat, len);
++-
++- duration = ieee80211_get_rate_duration(hw, &stat, &overhead);
++- /*
++- * Assume that HT/VHT transmission on any AC except VO will
++- * use aggregation. Since we don't have reliable reporting
++- * of aggregation length, assume an average size based on the
++- * tx rate.
++- * This will not be very accurate, but much better than simply
++- * assuming un-aggregated tx in all cases.
++- */
++- if (duration > 400 * 1024) /* <= VHT20 MCS2 1S */
++- agg_shift = 1;
++- else if (duration > 250 * 1024) /* <= VHT20 MCS3 1S or MCS1 2S */
++- agg_shift = 2;
++- else if (duration > 150 * 1024) /* <= VHT20 MCS5 1S or MCS2 2S */
++- agg_shift = 3;
++- else if (duration > 70 * 1024) /* <= VHT20 MCS5 2S */
++- agg_shift = 4;
++- else if (stat.encoding != RX_ENC_HE ||
++- duration > 20 * 1024) /* <= HE40 MCS6 2S */
++- agg_shift = 5;
++- else
++- agg_shift = 6;
+++ u32 duration;
++
++- duration *= len;
++- duration /= AVG_PKT_SIZE;
+++ duration = ieee80211_rate_expected_tx_airtime(hw, tx_rate, ri,
+++ band, true, len);
++ duration /= 1024;
++- duration += (overhead >> agg_shift);
++
++ return max_t(u32, duration, 4);
++ }
++--- a/net/mac80211/ieee80211_i.h
+++++ b/net/mac80211/ieee80211_i.h
++@@ -2756,6 +2756,11 @@ u8 *ieee80211_get_bssid(struct ieee80211
++
++ extern const struct ethtool_ops ieee80211_ethtool_ops;
++
+++u32 ieee80211_rate_expected_tx_airtime(struct ieee80211_hw *hw,
+++ struct ieee80211_tx_rate *tx_rate,
+++ struct rate_info *ri,
+++ enum nl80211_band band,
+++ bool ampdu, int len);
++ u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
++ struct ieee80211_vif *vif,
++ struct ieee80211_sta *pubsta,
+diff --git a/package/kernel/mac80211/patches/subsys/361-mac80211-estimate-expected-throughput-if-not-provide.patch b/package/kernel/mac80211/patches/subsys/361-mac80211-estimate-expected-throughput-if-not-provide.patch
+new file mode 100644
+index 0000000000000000000000000000000000000000..9bcaf86504170db5b5b77c1c40c96be1cbb5d701
+--- /dev/null
++++ b/package/kernel/mac80211/patches/subsys/361-mac80211-estimate-expected-throughput-if-not-provide.patch
+@@ -0,0 +1,51 @@
++From: Felix Fietkau <nbd@nbd.name>
++Date: Wed, 6 Aug 2025 10:52:03 +0200
++Subject: [PATCH] mac80211: estimate expected throughput if not provided by
++ driver/rc
++
++Estimate the tx throughput based on the expected per-packet tx time.
++This is useful for mesh implementations that rely on expected throughput,
++e.g. 802.11s or batman-adv.
++
++Signed-off-by: Felix Fietkau <nbd@nbd.name>
++---
++
++--- a/net/mac80211/sta_info.c
+++++ b/net/mac80211/sta_info.c
++@@ -2621,6 +2621,27 @@ static inline u64 sta_get_stats_bytes(st
++ return value;
++ }
++
+++static u32 sta_estimate_expected_throughput(struct sta_info *sta,
+++ struct station_info *sinfo)
+++{
+++ struct ieee80211_sub_if_data *sdata = sta->sdata;
+++ struct ieee80211_local *local = sdata->local;
+++ struct rate_info *ri = &sinfo->txrate;
+++ struct ieee80211_hw *hw = &local->hw;
+++ struct ieee80211_chanctx_conf *conf;
+++ u32 duration;
+++ u8 band = 0;
+++
+++ conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
+++ if (conf)
+++ band = conf->def.chan->band;
+++
+++ duration = ieee80211_rate_expected_tx_airtime(hw, NULL, ri, band, true, 1024);
+++ duration += duration >> 4; /* add assumed packet error rate of ~6% */
+++
+++ return ((1024 * USEC_PER_SEC) / duration) * 8;
+++}
+++
++ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
++ bool tidstats)
++ {
++@@ -2865,6 +2886,8 @@ void sta_set_sinfo(struct sta_info *sta,
++ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
++
++ thr = sta_get_expected_throughput(sta);
+++ if (!thr && (sinfo->filled & BIT_ULL(NL80211_STA_INFO_TX_BITRATE)))
+++ thr = sta_estimate_expected_throughput(sta, sinfo);
++
++ if (thr != 0) {
++ sinfo->filled |= BIT_ULL(NL80211_STA_INFO_EXPECTED_THROUGHPUT);
--
2.43.0

Loading