From 431fb8cae97355109e2496c5921b6d91ce9d510b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 12 Aug 2020 17:12:03 +0200 Subject: [PATCH] mac80211: add AQL improvements Add AQL support for HE drivers. Improve assumed aggregation length based on tx rate Signed-off-by: Felix Fietkau --- ...e-provided-via-status-rate-on-ieee80.patch | 151 ++++++++++++++ ...out-code-to-look-up-the-average-pack.patch | 186 ++++++++++++++++++ ...-AQL-aggregation-estimation-for-low-.patch | 66 +++++++ 3 files changed, 403 insertions(+) create mode 100644 package/kernel/mac80211/patches/subsys/311-mac80211-use-rate-provided-via-status-rate-on-ieee80.patch create mode 100644 package/kernel/mac80211/patches/subsys/312-mac80211-factor-out-code-to-look-up-the-average-pack.patch create mode 100644 package/kernel/mac80211/patches/subsys/313-mac80211-improve-AQL-aggregation-estimation-for-low-.patch 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 +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 +--- + +--- 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 +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 +--- + +--- 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 +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 +--- + +--- 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)