Since the integration of AQL, packet TX airtime estimation is calculated and counted to be used for the dequeue limit. Use this estimated airtime to compute expected throughput for each station. It will be a generic mac80211 implementation. If the driver has get_expected_throughput implementation, it will be used instead. Useful for L2 routing protocols, like B.A.T.M.A.N. Signed-off-by: Baligh Gasmi <gasmibal@xxxxxxxxx> --- net/mac80211/driver-ops.h | 2 ++ net/mac80211/sta_info.c | 39 +++++++++++++++++++++++++++++++++++++++ net/mac80211/sta_info.h | 12 ++++++++++++ net/mac80211/status.c | 3 ++- net/mac80211/tx.c | 8 +++++++- 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 4e2fc1a08681..4331b79647fa 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -1142,6 +1142,8 @@ static inline u32 drv_get_expected_throughput(struct ieee80211_local *local, trace_drv_get_expected_throughput(&sta->sta); if (local->ops->get_expected_throughput && sta->uploaded) ret = local->ops->get_expected_throughput(&local->hw, &sta->sta); + else + ret = ewma_avg_est_tp_read(&sta->status_stats.avg_est_tp); trace_drv_return_u32(local, ret); return ret; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 91fbb1ee5c38..f39d7ec2238d 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1985,6 +1985,45 @@ void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local, tx_pending, 0); } +void ieee80211_sta_update_tp(struct ieee80211_local *local, + struct sta_info *sta, + struct sk_buff *skb, + u16 tx_time_est, + bool ack, int retry) +{ + unsigned long diff = 0; + struct rate_control_ref *ref = NULL; + + if (!skb || !sta || !tx_time_est) + return; + + if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) + ref = sta->rate_ctrl; + + if (ref && ref->ops->get_expected_throughput) + return; + + if (local->ops->get_expected_throughput) + return; + + tx_time_est += ack ? 4 : 0; + tx_time_est += retry ? retry * 2 : 2; + + sta->tx_stats.tp_tx_size += (skb->len * 8) * 1000; + sta->tx_stats.tp_tx_time_est += tx_time_est; + + diff = jiffies - sta->status_stats.last_tp_update; + if (diff > HZ / 10) { + ewma_avg_est_tp_add(&sta->status_stats.avg_est_tp, + sta->tx_stats.tp_tx_size / + sta->tx_stats.tp_tx_time_est); + + sta->tx_stats.tp_tx_size = 0; + sta->tx_stats.tp_tx_time_est = 0; + sta->status_stats.last_tp_update = jiffies; + } +} + int sta_info_move_state(struct sta_info *sta, enum ieee80211_sta_state new_state) { diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 379fd367197f..0c1ebf8d87ef 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -123,6 +123,7 @@ enum ieee80211_sta_info_flags { #define HT_AGG_STATE_STOP_CB 7 #define HT_AGG_STATE_SENT_ADDBA 8 +DECLARE_EWMA(avg_est_tp, 8, 16) DECLARE_EWMA(avg_signal, 10, 8) enum ieee80211_agg_stop_reason { AGG_STOP_DECLINED, @@ -157,6 +158,12 @@ void ieee80211_register_airtime(struct ieee80211_txq *txq, struct sta_info; +void ieee80211_sta_update_tp(struct ieee80211_local *local, + struct sta_info *sta, + struct sk_buff *skb, + u16 tx_time_est, + bool ack, int retry); + /** * struct tid_ampdu_tx - TID aggregation information (Tx). * @@ -567,6 +574,7 @@ struct ieee80211_fragment_cache { * @status_stats.last_ack_signal: last ACK signal * @status_stats.ack_signal_filled: last ACK signal validity * @status_stats.avg_ack_signal: average ACK signal + * @status_stats.avg_est_tp: average expected throughput * @frags: fragment cache */ struct sta_info { @@ -641,6 +649,8 @@ struct sta_info { s8 last_ack_signal; bool ack_signal_filled; struct ewma_avg_signal avg_ack_signal; + struct ewma_avg_est_tp avg_est_tp; + unsigned long last_tp_update; } status_stats; /* Updated from TX path only, no locking requirements */ @@ -650,6 +660,8 @@ struct sta_info { struct ieee80211_tx_rate last_rate; struct rate_info last_rate_info; u64 msdu[IEEE80211_NUM_TIDS + 1]; + u32 tp_tx_size; + u32 tp_tx_time_est; } tx_stats; u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; diff --git a/net/mac80211/status.c b/net/mac80211/status.c index e81e8a5bb774..293a0f14a3ad 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -18,7 +18,6 @@ #include "led.h" #include "wme.h" - void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb) { @@ -1138,6 +1137,8 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw, ack_signal_valid = !!(info->status.flags & IEEE80211_TX_STATUS_ACK_SIGNAL_VALID); + ieee80211_sta_update_tp(local, sta, skb, tx_time_est, acked, retry_count); + if (pubsta) { struct ieee80211_sub_if_data *sdata = sta->sdata; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b6b20f38de0e..364cca1d688e 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3634,6 +3634,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, struct ieee80211_tx_data tx; ieee80211_tx_result r; struct ieee80211_vif *vif = txq->vif; + struct rate_control_ref *ref = NULL; WARN_ON_ONCE(softirq_count() == 0); @@ -3792,8 +3793,13 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, encap_out: IEEE80211_SKB_CB(skb)->control.vif = vif; + if (tx.sta && test_sta_flag(tx.sta, WLAN_STA_RATE_CONTROL)) + ref = tx.sta->rate_ctrl; + if (vif && - wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) { + ((!local->ops->get_expected_throughput && + (!ref || !ref->ops->get_expected_throughput)) || + wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))) { bool ampdu = txq->ac != IEEE80211_AC_VO; u32 airtime; -- 2.36.1