| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- From: Felix Fietkau <[email protected]>
- Date: Fri, 9 Feb 2024 19:43:40 +0100
- Subject: [PATCH] mac80211: add AQL support for broadcast packets
- Excessive broadcast traffic with little competing unicast traffic can easily
- flood hardware queues, leading to throughput issues. Additionally, filling
- the hardware queues with too many packets breaks FQ for broadcast data.
- Fix this by enabling AQL for broadcast packets.
- Signed-off-by: Felix Fietkau <[email protected]>
- ---
- --- a/include/net/cfg80211.h
- +++ b/include/net/cfg80211.h
- @@ -3437,6 +3437,7 @@ enum wiphy_params_flags {
- /* The per TXQ device queue limit in airtime */
- #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L 5000
- #define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 12000
- +#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC 50000
-
- /* The per interface airtime threshold to switch to lower queue limit */
- #define IEEE80211_AQL_THRESHOLD 24000
- --- a/net/mac80211/debugfs.c
- +++ b/net/mac80211/debugfs.c
- @@ -215,11 +215,13 @@ static ssize_t aql_pending_read(struct f
- "VI %u us\n"
- "BE %u us\n"
- "BK %u us\n"
- + "BC/MC %u us\n"
- "total %u us\n",
- atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VO]),
- atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_VI]),
- atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BE]),
- atomic_read(&local->aql_ac_pending_airtime[IEEE80211_AC_BK]),
- + atomic_read(&local->aql_bc_pending_airtime),
- atomic_read(&local->aql_total_pending_airtime));
- return simple_read_from_buffer(user_buf, count, ppos,
- buf, len);
- @@ -245,7 +247,8 @@ static ssize_t aql_txq_limit_read(struct
- "VO %u %u\n"
- "VI %u %u\n"
- "BE %u %u\n"
- - "BK %u %u\n",
- + "BK %u %u\n"
- + "BC/MC %u\n",
- local->aql_txq_limit_low[IEEE80211_AC_VO],
- local->aql_txq_limit_high[IEEE80211_AC_VO],
- local->aql_txq_limit_low[IEEE80211_AC_VI],
- @@ -253,7 +256,8 @@ static ssize_t aql_txq_limit_read(struct
- local->aql_txq_limit_low[IEEE80211_AC_BE],
- local->aql_txq_limit_high[IEEE80211_AC_BE],
- local->aql_txq_limit_low[IEEE80211_AC_BK],
- - local->aql_txq_limit_high[IEEE80211_AC_BK]);
- + local->aql_txq_limit_high[IEEE80211_AC_BK],
- + local->aql_txq_limit_bc);
- return simple_read_from_buffer(user_buf, count, ppos,
- buf, len);
- }
- @@ -279,6 +283,11 @@ static ssize_t aql_txq_limit_write(struc
- else
- buf[count] = '\0';
-
- + if (sscanf(buf, "mcast %u", &q_limit_low) == 1) {
- + local->aql_txq_limit_bc = q_limit_low;
- + return count;
- + }
- +
- if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) != 3)
- return -EINVAL;
-
- --- a/net/mac80211/ieee80211_i.h
- +++ b/net/mac80211/ieee80211_i.h
- @@ -1377,10 +1377,12 @@ struct ieee80211_local {
- spinlock_t handle_wake_tx_queue_lock;
-
- u16 airtime_flags;
- + u32 aql_txq_limit_bc;
- u32 aql_txq_limit_low[IEEE80211_NUM_ACS];
- u32 aql_txq_limit_high[IEEE80211_NUM_ACS];
- u32 aql_threshold;
- atomic_t aql_total_pending_airtime;
- + atomic_t aql_bc_pending_airtime;
- atomic_t aql_ac_pending_airtime[IEEE80211_NUM_ACS];
-
- const struct ieee80211_ops *ops;
- --- a/net/mac80211/main.c
- +++ b/net/mac80211/main.c
- @@ -959,6 +959,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
- spin_lock_init(&local->rx_path_lock);
- spin_lock_init(&local->queue_stop_reason_lock);
-
- + local->aql_txq_limit_bc = IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC;
- for (i = 0; i < IEEE80211_NUM_ACS; i++) {
- INIT_LIST_HEAD(&local->active_txqs[i]);
- spin_lock_init(&local->active_txq_lock[i]);
- --- a/net/mac80211/sta_info.c
- +++ b/net/mac80211/sta_info.c
- @@ -2382,13 +2382,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggre
-
- void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
- struct sta_info *sta, u8 ac,
- - u16 tx_airtime, bool tx_completed)
- + u16 tx_airtime, bool tx_completed,
- + bool mcast)
- {
- int tx_pending;
-
- if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
- return;
-
- + if (mcast) {
- + if (!tx_completed) {
- + atomic_add(tx_airtime, &local->aql_bc_pending_airtime);
- + return;
- + }
- +
- + tx_pending = atomic_sub_return(tx_airtime,
- + &local->aql_bc_pending_airtime);
- + if (tx_pending < 0)
- + atomic_cmpxchg(&local->aql_bc_pending_airtime,
- + tx_pending, 0);
- + return;
- + }
- +
- if (!tx_completed) {
- if (sta)
- atomic_add(tx_airtime,
- --- a/net/mac80211/tx.c
- +++ b/net/mac80211/tx.c
- @@ -2539,7 +2539,7 @@ static u16 ieee80211_store_ack_skb(struc
-
- spin_lock_irqsave(&local->ack_status_lock, flags);
- id = idr_alloc(&local->ack_status_frames, ack_skb,
- - 1, 0x2000, GFP_ATOMIC);
- + 1, 0x1000, GFP_ATOMIC);
- spin_unlock_irqrestore(&local->ack_status_lock, flags);
-
- if (id >= 0) {
- @@ -3967,20 +3967,20 @@ begin:
- encap_out:
- info->control.vif = vif;
-
- - if (tx.sta &&
- - wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
- - bool ampdu = txq->ac != IEEE80211_AC_VO;
- + if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
- + bool ampdu = txq->sta && txq->ac != IEEE80211_AC_VO;
- u32 airtime;
-
- airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
- skb->len, ampdu);
- - if (airtime) {
- - airtime = ieee80211_info_set_tx_time_est(info, airtime);
- - ieee80211_sta_update_pending_airtime(local, tx.sta,
- - txq->ac,
- - airtime,
- - false);
- - }
- + if (!airtime)
- + return skb;
- +
- + airtime = ieee80211_info_set_tx_time_est(info, airtime);
- + info->tx_time_mc = !tx.sta;
- + ieee80211_sta_update_pending_airtime(local, tx.sta, txq->ac,
- + airtime, false,
- + info->tx_time_mc);
- }
-
- return skb;
- @@ -4032,6 +4032,7 @@ struct ieee80211_txq *ieee80211_next_txq
- struct ieee80211_txq *ret = NULL;
- struct txq_info *txqi = NULL, *head = NULL;
- bool found_eligible_txq = false;
- + bool aql_check;
-
- spin_lock_bh(&local->active_txq_lock[ac]);
-
- @@ -4055,26 +4056,26 @@ struct ieee80211_txq *ieee80211_next_txq
- if (!head)
- head = txqi;
-
- + aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
- + if (aql_check)
- + found_eligible_txq = true;
- +
- if (txqi->txq.sta) {
- struct sta_info *sta = container_of(txqi->txq.sta,
- struct sta_info, sta);
- - bool aql_check = ieee80211_txq_airtime_check(hw, &txqi->txq);
- - s32 deficit = ieee80211_sta_deficit(sta, txqi->txq.ac);
- -
- - if (aql_check)
- - found_eligible_txq = true;
- -
- - if (deficit < 0)
- + if (ieee80211_sta_deficit(sta, txqi->txq.ac) < 0) {
- sta->airtime[txqi->txq.ac].deficit +=
- sta->airtime_weight << AIRTIME_QUANTUM_SHIFT;
- -
- - if (deficit < 0 || !aql_check) {
- - list_move_tail(&txqi->schedule_order,
- - &local->active_txqs[txqi->txq.ac]);
- - goto begin;
- + aql_check = false;
- }
- }
-
- + if (!aql_check) {
- + list_move_tail(&txqi->schedule_order,
- + &local->active_txqs[txqi->txq.ac]);
- + goto begin;
- + }
- +
- if (txqi->schedule_round == local->schedule_round[ac])
- goto out;
-
- @@ -4139,7 +4140,8 @@ bool ieee80211_txq_airtime_check(struct
- return true;
-
- if (!txq->sta)
- - return true;
- + return atomic_read(&local->aql_bc_pending_airtime) <
- + local->aql_txq_limit_bc;
-
- if (unlikely(txq->tid == IEEE80211_NUM_TIDS))
- return true;
- @@ -4188,15 +4190,15 @@ bool ieee80211_txq_may_transmit(struct i
-
- spin_lock_bh(&local->active_txq_lock[ac]);
-
- - if (!txqi->txq.sta)
- - goto out;
- -
- if (list_empty(&txqi->schedule_order))
- goto out;
-
- if (!ieee80211_txq_schedule_airtime_check(local, ac))
- goto out;
-
- + if (!txqi->txq.sta)
- + goto out;
- +
- list_for_each_entry_safe(iter, tmp, &local->active_txqs[ac],
- schedule_order) {
- if (iter == txqi)
- --- a/include/net/mac80211.h
- +++ b/include/net/mac80211.h
- @@ -1245,8 +1245,8 @@ struct ieee80211_tx_info {
- status_data_idr:1,
- status_data:13,
- hw_queue:4,
- + tx_time_mc:1,
- tx_time_est:10;
- - /* 1 free bit */
-
- union {
- struct {
- --- a/net/mac80211/sta_info.h
- +++ b/net/mac80211/sta_info.h
- @@ -147,7 +147,8 @@ struct airtime_info {
-
- void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
- struct sta_info *sta, u8 ac,
- - u16 tx_airtime, bool tx_completed);
- + u16 tx_airtime, bool tx_completed,
- + bool mcast);
-
- struct sta_info;
-
- --- a/net/mac80211/status.c
- +++ b/net/mac80211/status.c
- @@ -734,7 +734,7 @@ static void ieee80211_report_used_skb(st
- ieee80211_sta_update_pending_airtime(local, sta,
- skb_get_queue_mapping(skb),
- tx_time_est,
- - true);
- + true, info->tx_time_mc);
- rcu_read_unlock();
- }
-
- @@ -1143,10 +1143,11 @@ void ieee80211_tx_status_ext(struct ieee
- /* Do this here to avoid the expensive lookup of the sta
- * in ieee80211_report_used_skb().
- */
- + bool mcast = IEEE80211_SKB_CB(skb)->tx_time_mc;
- ieee80211_sta_update_pending_airtime(local, sta,
- skb_get_queue_mapping(skb),
- tx_time_est,
- - true);
- + true, mcast);
- ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0);
- }
-
|