[openwrt/openwrt] mac80211: add AQL improvements

LEDE Commits lede-commits at lists.infradead.org
Thu Aug 13 11:57:43 EDT 2020


nbd pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/431fb8cae97355109e2496c5921b6d91ce9d510b

commit 431fb8cae97355109e2496c5921b6d91ce9d510b
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Wed Aug 12 17:12:03 2020 +0200

    mac80211: add AQL improvements
    
    Add AQL support for HE drivers.
    Improve assumed aggregation length based on tx rate
    
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 ...e-rate-provided-via-status-rate-on-ieee80.patch | 151 +++++++++++++++++
 ...ctor-out-code-to-look-up-the-average-pack.patch | 186 +++++++++++++++++++++
 ...prove-AQL-aggregation-estimation-for-low-.patch |  66 ++++++++
 3 files changed, 403 insertions(+)

diff --git a/package/kernel/mac80211/patches/subsys/311-mac80211-use-rate-provided-via-status-rate-on-ieee80.patch b/package/kernel/mac80211/patches/subsys/311-mac80211-use-rate-provided-via-status-rate-on-ieee80.patch
new file mode 100644
index 0000000000..ee1db716e0
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/311-mac80211-use-rate-provided-via-status-rate-on-ieee80.patch
@@ -0,0 +1,151 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 12 Aug 2020 17:04:22 +0200
+Subject: [PATCH] mac80211: use rate provided via status->rate on
+ ieee80211_tx_status_ext for AQL
+
+Since ieee80211_tx_info does not have enough room to encode HE rates, HE
+drivers use status->rate to provide rate info.
+Store it in struct sta_info and use it for AQL.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/airtime.c
++++ b/net/mac80211/airtime.c
+@@ -487,14 +487,61 @@ u32 ieee80211_calc_rx_airtime(struct iee
+ }
+ EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime);
+ 
++static bool ieee80211_fill_rate_info(struct ieee80211_hw *hw,
++				     struct ieee80211_rx_status *stat, u8 band,
++				     struct rate_info *ri)
++{
++	struct ieee80211_supported_band *sband = hw->wiphy->bands[band];
++	int i;
++
++	if (!ri || !sband)
++	    return false;
++
++	stat->bw = ri->bw;
++	stat->nss = ri->nss;
++	stat->rate_idx = ri->mcs;
++
++	if (ri->flags & RATE_INFO_FLAGS_HE_MCS)
++		stat->encoding = RX_ENC_HE;
++	else if (ri->flags & RATE_INFO_FLAGS_VHT_MCS)
++		stat->encoding = RX_ENC_VHT;
++	else if (ri->flags & RATE_INFO_FLAGS_MCS)
++		stat->encoding = RX_ENC_HT;
++	else
++		stat->encoding = RX_ENC_LEGACY;
++
++	if (ri->flags & RATE_INFO_FLAGS_SHORT_GI)
++		stat->enc_flags |= RX_ENC_FLAG_SHORT_GI;
++
++	stat->he_gi = ri->he_gi;
++
++	if (stat->encoding != RX_ENC_LEGACY)
++		return true;
++
++	stat->rate_idx = 0;
++	for (i = 0; i < sband->n_bitrates; i++) {
++		if (ri->legacy != sband->bitrates[i].bitrate)
++			continue;
++
++		stat->rate_idx = i;
++		return true;
++	}
++
++	return false;
++}
++
+ static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
+ 					  struct ieee80211_tx_rate *rate,
++					  struct rate_info *ri,
+ 					  u8 band, int len)
+ {
+ 	struct ieee80211_rx_status stat = {
+ 		.band = band,
+ 	};
+ 
++	if (ieee80211_fill_rate_info(hw, &stat, band, ri))
++		goto out;
++
+ 	if (rate->idx < 0 || !rate->count)
+ 		return 0;
+ 
+@@ -522,6 +569,7 @@ static u32 ieee80211_calc_tx_airtime_rat
+ 		stat.encoding = RX_ENC_LEGACY;
+ 	}
+ 
++out:
+ 	return ieee80211_calc_rx_airtime(hw, &stat, len);
+ }
+ 
+@@ -536,7 +584,7 @@ u32 ieee80211_calc_tx_airtime(struct iee
+ 		struct ieee80211_tx_rate *rate = &info->status.rates[i];
+ 		u32 cur_duration;
+ 
+-		cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate,
++		cur_duration = ieee80211_calc_tx_airtime_rate(hw, rate, NULL,
+ 							      info->band, len);
+ 		if (!cur_duration)
+ 			break;
+@@ -573,6 +621,7 @@ u32 ieee80211_calc_expected_tx_airtime(s
+ 		struct sta_info *sta = container_of(pubsta, struct sta_info,
+ 						    sta);
+ 		struct ieee80211_tx_rate *rate = &sta->tx_stats.last_rate;
++		struct rate_info *ri = &sta->tx_stats.last_rate_info;
+ 		u32 airtime;
+ 
+ 		if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS |
+@@ -586,7 +635,7 @@ u32 ieee80211_calc_expected_tx_airtime(s
+ 		 * This will not be very accurate, but much better than simply
+ 		 * assuming un-aggregated tx.
+ 		 */
+-		airtime = ieee80211_calc_tx_airtime_rate(hw, rate, band,
++		airtime = ieee80211_calc_tx_airtime_rate(hw, rate, ri, band,
+ 							 ampdu ? len * 16 : len);
+ 		if (ampdu)
+ 			airtime /= 16;
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -609,6 +609,7 @@ struct sta_info {
+ 		u64 packets[IEEE80211_NUM_ACS];
+ 		u64 bytes[IEEE80211_NUM_ACS];
+ 		struct ieee80211_tx_rate last_rate;
++		struct rate_info last_rate_info;
+ 		u64 msdu[IEEE80211_NUM_TIDS + 1];
+ 	} tx_stats;
+ 	u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -1147,9 +1147,17 @@ void ieee80211_tx_status_ext(struct ieee
+ 	struct ieee80211_tx_info *info = status->info;
+ 	struct ieee80211_sta *pubsta = status->sta;
+ 	struct ieee80211_supported_band *sband;
++	struct sta_info *sta;
+ 	int retry_count;
+ 	bool acked, noack_success;
+ 
++	if (pubsta) {
++		sta = container_of(pubsta, struct sta_info, sta);
++
++		if (status->rate)
++			sta->tx_stats.last_rate_info = *status->rate;
++	}
++
+ 	if (status->skb)
+ 		return __ieee80211_tx_status(hw, status);
+ 
+@@ -1164,10 +1172,6 @@ void ieee80211_tx_status_ext(struct ieee
+ 	noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
+ 
+ 	if (pubsta) {
+-		struct sta_info *sta;
+-
+-		sta = container_of(pubsta, struct sta_info, sta);
+-
+ 		if (!acked && !noack_success)
+ 			sta->status_stats.retry_failed++;
+ 		sta->status_stats.retry_count += retry_count;
diff --git a/package/kernel/mac80211/patches/subsys/312-mac80211-factor-out-code-to-look-up-the-average-pack.patch b/package/kernel/mac80211/patches/subsys/312-mac80211-factor-out-code-to-look-up-the-average-pack.patch
new file mode 100644
index 0000000000..105bbe2529
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/312-mac80211-factor-out-code-to-look-up-the-average-pack.patch
@@ -0,0 +1,186 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 12 Aug 2020 17:06:12 +0200
+Subject: [PATCH] mac80211: factor out code to look up the average packet
+ length duration for a rate
+
+This will be used to enhance AQL estimated aggregation length
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/airtime.c
++++ b/net/mac80211/airtime.c
+@@ -405,18 +405,14 @@ ieee80211_calc_legacy_rate_duration(u16
+ 	return duration;
+ }
+ 
+-u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
+-			      struct ieee80211_rx_status *status,
+-			      int len)
++static u32 ieee80211_get_rate_duration(struct ieee80211_hw *hw,
++				       struct ieee80211_rx_status *status,
++				       u32 *overhead)
+ {
+-	struct ieee80211_supported_band *sband;
+-	const struct ieee80211_rate *rate;
+ 	bool sgi = status->enc_flags & RX_ENC_FLAG_SHORT_GI;
+-	bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE;
+ 	int bw, streams;
+ 	int group, idx;
+ 	u32 duration;
+-	bool cck;
+ 
+ 	switch (status->bw) {
+ 	case RATE_INFO_BW_20:
+@@ -437,20 +433,6 @@ u32 ieee80211_calc_rx_airtime(struct iee
+ 	}
+ 
+ 	switch (status->encoding) {
+-	case RX_ENC_LEGACY:
+-		if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ))
+-			return 0;
+-
+-		sband = hw->wiphy->bands[status->band];
+-		if (!sband || status->rate_idx >= sband->n_bitrates)
+-			return 0;
+-
+-		rate = &sband->bitrates[status->rate_idx];
+-		cck = rate->flags & IEEE80211_RATE_MANDATORY_B;
+-
+-		return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp,
+-							   cck, len);
+-
+ 	case RX_ENC_VHT:
+ 		streams = status->nss;
+ 		idx = status->rate_idx;
+@@ -477,13 +459,47 @@ u32 ieee80211_calc_rx_airtime(struct iee
+ 
+ 	duration = airtime_mcs_groups[group].duration[idx];
+ 	duration <<= airtime_mcs_groups[group].shift;
++	*overhead = 36 + (streams << 2);
++
++	return duration;
++}
++
++
++u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
++			      struct ieee80211_rx_status *status,
++			      int len)
++{
++	struct ieee80211_supported_band *sband;
++	u32 duration, overhead = 0;
++
++	if (status->encoding == RX_ENC_LEGACY) {
++		const struct ieee80211_rate *rate;
++		bool sp = status->enc_flags & RX_ENC_FLAG_SHORTPRE;
++		bool cck;
++
++		if (WARN_ON_ONCE(status->band > NL80211_BAND_5GHZ))
++			return 0;
++
++		sband = hw->wiphy->bands[status->band];
++		if (!sband || status->rate_idx >= sband->n_bitrates)
++			return 0;
++
++		rate = &sband->bitrates[status->rate_idx];
++		cck = rate->flags & IEEE80211_RATE_MANDATORY_B;
++
++		return ieee80211_calc_legacy_rate_duration(rate->bitrate, sp,
++							   cck, len);
++	}
++
++	duration = ieee80211_get_rate_duration(hw, status, &overhead);
++	if (!duration)
++		return 0;
++
+ 	duration *= len;
+ 	duration /= AVG_PKT_SIZE;
+ 	duration /= 1024;
+ 
+-	duration += 36 + (streams << 2);
+-
+-	return duration;
++	return duration + overhead;
+ }
+ EXPORT_SYMBOL_GPL(ieee80211_calc_rx_airtime);
+ 
+@@ -530,46 +546,56 @@ static bool ieee80211_fill_rate_info(str
+ 	return false;
+ }
+ 
+-static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
+-					  struct ieee80211_tx_rate *rate,
+-					  struct rate_info *ri,
+-					  u8 band, int len)
++static int ieee80211_fill_rx_status(struct ieee80211_rx_status *stat,
++				    struct ieee80211_hw *hw,
++				    struct ieee80211_tx_rate *rate,
++				    struct rate_info *ri, u8 band, int len)
+ {
+-	struct ieee80211_rx_status stat = {
+-		.band = band,
+-	};
++	memset(stat, 0, sizeof(*stat));
++	stat->band = band;
+ 
+-	if (ieee80211_fill_rate_info(hw, &stat, band, ri))
+-		goto out;
++	if (ieee80211_fill_rate_info(hw, stat, band, ri))
++		return 0;
+ 
+ 	if (rate->idx < 0 || !rate->count)
+-		return 0;
++		return -1;
+ 
+ 	if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+-		stat.bw = RATE_INFO_BW_80;
++		stat->bw = RATE_INFO_BW_80;
+ 	else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+-		stat.bw = RATE_INFO_BW_40;
++		stat->bw = RATE_INFO_BW_40;
+ 	else
+-		stat.bw = RATE_INFO_BW_20;
++		stat->bw = RATE_INFO_BW_20;
+ 
+-	stat.enc_flags = 0;
++	stat->enc_flags = 0;
+ 	if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+-		stat.enc_flags |= RX_ENC_FLAG_SHORTPRE;
++		stat->enc_flags |= RX_ENC_FLAG_SHORTPRE;
+ 	if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+-		stat.enc_flags |= RX_ENC_FLAG_SHORT_GI;
++		stat->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+ 
+-	stat.rate_idx = rate->idx;
++	stat->rate_idx = rate->idx;
+ 	if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
+-		stat.encoding = RX_ENC_VHT;
+-		stat.rate_idx = ieee80211_rate_get_vht_mcs(rate);
+-		stat.nss = ieee80211_rate_get_vht_nss(rate);
++		stat->encoding = RX_ENC_VHT;
++		stat->rate_idx = ieee80211_rate_get_vht_mcs(rate);
++		stat->nss = ieee80211_rate_get_vht_nss(rate);
+ 	} else if (rate->flags & IEEE80211_TX_RC_MCS) {
+-		stat.encoding = RX_ENC_HT;
++		stat->encoding = RX_ENC_HT;
+ 	} else {
+-		stat.encoding = RX_ENC_LEGACY;
++		stat->encoding = RX_ENC_LEGACY;
+ 	}
+ 
+-out:
++	return 0;
++}
++
++static u32 ieee80211_calc_tx_airtime_rate(struct ieee80211_hw *hw,
++					  struct ieee80211_tx_rate *rate,
++					  struct rate_info *ri,
++					  u8 band, int len)
++{
++	struct ieee80211_rx_status stat;
++
++	ieee80211_fill_rx_status(&stat, hw, rate, ri, band, len);
++
+ 	return ieee80211_calc_rx_airtime(hw, &stat, len);
+ }
+ 
diff --git a/package/kernel/mac80211/patches/subsys/313-mac80211-improve-AQL-aggregation-estimation-for-low-.patch b/package/kernel/mac80211/patches/subsys/313-mac80211-improve-AQL-aggregation-estimation-for-low-.patch
new file mode 100644
index 0000000000..565d9bec43
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/313-mac80211-improve-AQL-aggregation-estimation-for-low-.patch
@@ -0,0 +1,66 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Wed, 12 Aug 2020 17:07:10 +0200
+Subject: [PATCH] mac80211: improve AQL aggregation estimation for low data
+ rates
+
+Links with low data rates use much smaller aggregates and are much more
+sensitive to latency added by bufferbloat.
+Tune the assumed aggregation length based on the tx rate duration.
+
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/mac80211/airtime.c
++++ b/net/mac80211/airtime.c
+@@ -646,27 +646,40 @@ 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 *rate = &sta->tx_stats.last_rate;
+ 		struct rate_info *ri = &sta->tx_stats.last_rate_info;
+-		u32 airtime;
++		u32 duration, overhead;
++		u8 agg_shift;
+ 
+-		if (!(rate->flags & (IEEE80211_TX_RC_VHT_MCS |
+-				     IEEE80211_TX_RC_MCS)))
+-			ampdu = false;
++		ieee80211_fill_rx_status(&stat, hw, rate, ri, band, len);
++
++		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 of 16.
++		 * 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.
++		 * assuming un-aggregated tx in all cases.
+ 		 */
+-		airtime = ieee80211_calc_tx_airtime_rate(hw, rate, ri, band,
+-							 ampdu ? len * 16 : len);
+-		if (ampdu)
+-			airtime /= 16;
++		if (duration > 400) /* <= VHT20 MCS2 1S */
++			agg_shift = 1;
++		else if (duration > 250) /* <= VHT20 MCS3 1S or MCS1 2S */
++			agg_shift = 2;
++		else if (duration > 150) /* <= VHT20 MCS5 1S or MCS3 2S */
++			agg_shift = 3;
++		else
++			agg_shift = 4;
+ 
+-		return airtime;
++		duration *= len;
++		duration /= AVG_PKT_SIZE;
++		duration /= 1024;
++
++		return duration + (overhead >> agg_shift);
+ 	}
+ 
+ 	if (!conf)



More information about the lede-commits mailing list