Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: Use Airtime-based Queue Limits (AQL) on packet dequeue

The previous commit added the ability to throttle stations when they queue
too much airtime in the hardware. This commit enables the functionality by
calculating the expected airtime usage of each packet that is dequeued from
the TXQs in mac80211, and accounting that as pending airtime.

The estimated airtime for each skb is stored in the tx_info, so we can
subtract the same amount from the running total when the skb is freed or
recycled. The throttling mechanism relies on this accounting to be
accurate (i.e., that we are not freeing skbs without subtracting any
airtime they were accounted for), so we put the subtraction into
ieee80211_report_used_skb(). As an optimisation, we also subtract the
airtime on regular TX completion, zeroing out the value stored in the
packet afterwards, to avoid having to do an expensive lookup of the station
from the packet data on every packet.

This patch does *not* include any mechanism to wake a throttled TXQ again,
on the assumption that this will happen anyway as a side effect of whatever
freed the skb (most commonly a TX completion).

Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/r/20191119060610.76681-5-kyan@google.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Toke Høiland-Jørgensen and committed by
Johannes Berg
7a89233a 3ace10f5

+60
+16
include/net/mac80211.h
··· 1060 1060 }; 1061 1061 }; 1062 1062 1063 + static inline u16 1064 + ieee80211_info_set_tx_time_est(struct ieee80211_tx_info *info, u16 tx_time_est) 1065 + { 1066 + /* We only have 10 bits in tx_time_est, so store airtime 1067 + * in increments of 4us and clamp the maximum to 2**12-1 1068 + */ 1069 + info->tx_time_est = min_t(u16, tx_time_est, 4095) >> 2; 1070 + return info->tx_time_est << 2; 1071 + } 1072 + 1073 + static inline u16 1074 + ieee80211_info_get_tx_time_est(struct ieee80211_tx_info *info) 1075 + { 1076 + return info->tx_time_est << 2; 1077 + } 1078 + 1063 1079 /** 1064 1080 * struct ieee80211_tx_status - extended tx status info for rate control 1065 1081 *
+26
net/mac80211/status.c
··· 670 670 struct sk_buff *skb, bool dropped) 671 671 { 672 672 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 673 + u16 tx_time_est = ieee80211_info_get_tx_time_est(info); 673 674 struct ieee80211_hdr *hdr = (void *)skb->data; 674 675 bool acked = info->flags & IEEE80211_TX_STAT_ACK; 675 676 676 677 if (dropped) 677 678 acked = false; 679 + 680 + if (tx_time_est) { 681 + struct sta_info *sta; 682 + 683 + rcu_read_lock(); 684 + 685 + sta = sta_info_get_by_addrs(local, hdr->addr1, hdr->addr2); 686 + ieee80211_sta_update_pending_airtime(local, sta, 687 + skb_get_queue_mapping(skb), 688 + tx_time_est, 689 + true); 690 + rcu_read_unlock(); 691 + } 678 692 679 693 if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) { 680 694 struct ieee80211_sub_if_data *sdata; ··· 891 877 struct ieee80211_bar *bar; 892 878 int shift = 0; 893 879 int tid = IEEE80211_NUM_TIDS; 880 + u16 tx_time_est; 894 881 895 882 rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); 896 883 ··· 1000 985 NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) 1001 986 ieee80211_sta_register_airtime(&sta->sta, tid, 1002 987 info->status.tx_time, 0); 988 + 989 + if ((tx_time_est = ieee80211_info_get_tx_time_est(info)) > 0) { 990 + /* Do this here to avoid the expensive lookup of the sta 991 + * in ieee80211_report_used_skb(). 992 + */ 993 + ieee80211_sta_update_pending_airtime(local, sta, 994 + skb_get_queue_mapping(skb), 995 + tx_time_est, 996 + true); 997 + ieee80211_info_set_tx_time_est(info, 0); 998 + } 1003 999 1004 1000 if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { 1005 1001 if (info->flags & IEEE80211_TX_STAT_ACK) {
+18
net/mac80211/tx.c
··· 3554 3554 3555 3555 WARN_ON_ONCE(softirq_count() == 0); 3556 3556 3557 + if (!ieee80211_txq_airtime_check(hw, txq)) 3558 + return NULL; 3559 + 3557 3560 begin: 3558 3561 spin_lock_bh(&fq->lock); 3559 3562 ··· 3667 3664 } 3668 3665 3669 3666 IEEE80211_SKB_CB(skb)->control.vif = vif; 3667 + 3668 + if (local->airtime_flags & AIRTIME_USE_AQL) { 3669 + u32 airtime; 3670 + 3671 + airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta, 3672 + skb->len); 3673 + if (airtime) { 3674 + airtime = ieee80211_info_set_tx_time_est(info, airtime); 3675 + ieee80211_sta_update_pending_airtime(local, tx.sta, 3676 + txq->ac, 3677 + airtime, 3678 + false); 3679 + } 3680 + } 3681 + 3670 3682 return skb; 3671 3683 3672 3684 out: