release 6.15.2 (preliminary)
This commit is contained in:
34
debian/patches/misc-openwrt/0002-mac80211-avoid-crashing-missing-band.patch
vendored
Normal file
34
debian/patches/misc-openwrt/0002-mac80211-avoid-crashing-missing-band.patch
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
From: David Bauer <mail@david-bauer.net>
|
||||
Date: Thu, 30 Nov 2023 07:32:52 +0100
|
||||
Subject: [PATCH] mac80211: avoid crashing on invalid band info
|
||||
|
||||
Frequent crashes have been observed on MT7916 based platforms. While the
|
||||
root of these crashes are currently unknown, they happen when decoding
|
||||
rate information of connected STAs in AP mode. The rate-information is
|
||||
associated with a band which is not available on the PHY.
|
||||
|
||||
Check for this condition in order to avoid crashing the whole system.
|
||||
This patch should be removed once the roout cause has been found and
|
||||
fixed.
|
||||
|
||||
Link: https://github.com/freifunk-gluon/gluon/issues/2980
|
||||
|
||||
Signed-off-by: David Bauer <mail@david-bauer.net>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/sta_info.c
|
||||
+++ b/net/mac80211/sta_info.c
|
||||
@@ -2474,6 +2474,13 @@ static void sta_stats_decode_rate(struct
|
||||
|
||||
sband = local->hw.wiphy->bands[band];
|
||||
|
||||
+ if (!sband) {
|
||||
+ wiphy_warn(local->hw.wiphy,
|
||||
+ "Invalid band %d\n",
|
||||
+ band);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (WARN_ON_ONCE(!sband->bitrates))
|
||||
break;
|
||||
|
38
debian/patches/misc-openwrt/0003-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch
vendored
Normal file
38
debian/patches/misc-openwrt/0003-mac80211-sta-randomize-BA-session-dialog-token-alloc.patch
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
From b478e06a16a8baa00c5ecc87c1d636981f2206d5 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Berg <johannes.berg@intel.com>
|
||||
Date: Tue, 29 Oct 2019 10:25:25 +0100
|
||||
Subject: [PATCH] mac80211: sta: randomize BA session dialog token allocator
|
||||
|
||||
We currently always start the dialog token generator at zero,
|
||||
so the first dialog token we use is always 1. This would be
|
||||
OK if we had a perfect guarantee that we always do a proper
|
||||
deauth/re-auth handshake, but in IBSS mode this doesn't always
|
||||
happen properly.
|
||||
|
||||
To make problems with block ack (aggregation) sessions getting
|
||||
stuck less likely, randomize the dialog token so if we start a
|
||||
new session but the peer still has old state for us, it can
|
||||
better detect this.
|
||||
|
||||
This is really just a workaround to make things a bit more
|
||||
robust than they are now - a better fix would be to do a full
|
||||
authentication handshake in IBSS mode upon having discovered a
|
||||
new station, and on the receiver resetting the state (removing
|
||||
and re-adding the station) on receiving the authentication
|
||||
packet.
|
||||
|
||||
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
||||
---
|
||||
net/mac80211/sta_info.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/net/mac80211/sta_info.c
|
||||
+++ b/net/mac80211/sta_info.c
|
||||
@@ -583,6 +583,7 @@ __sta_info_alloc(struct ieee80211_sub_if
|
||||
spin_lock_init(&sta->ps_lock);
|
||||
INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
|
||||
wiphy_work_init(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
|
||||
+ sta->ampdu_mlme.dialog_token_allocator = get_random_u32_below(U8_MAX);
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
sta->mesh = kzalloc(sizeof(*sta->mesh), gfp);
|
21
debian/patches/misc-openwrt/0004-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch
vendored
Normal file
21
debian/patches/misc-openwrt/0004-mac80211-minstrel_ht-fix-MINSTREL_FRAC-macro.patch
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Wed, 28 Apr 2021 21:03:13 +0200
|
||||
Subject: [PATCH] mac80211: minstrel_ht: fix MINSTREL_FRAC macro
|
||||
|
||||
Add missing braces to avoid issues with e.g. using additions in the
|
||||
div expression
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.h
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.h
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
/* scaled fraction values */
|
||||
#define MINSTREL_SCALE 12
|
||||
-#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div)
|
||||
+#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / (div))
|
||||
#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE)
|
||||
|
||||
#define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */
|
30
debian/patches/misc-openwrt/0005-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch
vendored
Normal file
30
debian/patches/misc-openwrt/0005-mac80211-minstrel_ht-reduce-fluctuations-in-rate-pro.patch
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Sat, 6 Feb 2021 16:08:01 +0100
|
||||
Subject: [PATCH] mac80211: minstrel_ht: reduce fluctuations in rate
|
||||
probability stats
|
||||
|
||||
In some scenarios when there is a lot of fluctuation in packet error rates,
|
||||
rate switching can be amplified when the statistics get skewed by time slots
|
||||
with very few tries.
|
||||
Make the input data to the moving average more smooth by adding the
|
||||
success/attempts count from the last stats window as well. This has the
|
||||
advantage of smoothing the data without introducing any extra lag to sampling
|
||||
rates.
|
||||
This significantly improves rate stability on a strong test link subjected to
|
||||
periodic noise bursts generated with a SDR
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -769,7 +769,8 @@ minstrel_ht_calc_rate_stats(struct minst
|
||||
unsigned int cur_prob;
|
||||
|
||||
if (unlikely(mrs->attempts > 0)) {
|
||||
- cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts);
|
||||
+ cur_prob = MINSTREL_FRAC(mrs->success + mrs->last_success,
|
||||
+ mrs->attempts + mrs->last_attempts);
|
||||
minstrel_filter_avg_add(&mrs->prob_avg,
|
||||
&mrs->prob_avg_1, cur_prob);
|
||||
mrs->att_hist += mrs->attempts;
|
151
debian/patches/misc-openwrt/0006-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch
vendored
Normal file
151
debian/patches/misc-openwrt/0006-mac80211-minstrel_ht-rework-rate-downgrade-code-and-.patch
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Sat, 6 Feb 2021 16:33:14 +0100
|
||||
Subject: [PATCH] mac80211: minstrel_ht: rework rate downgrade code and
|
||||
max_prob rate selection
|
||||
|
||||
The current fallback code for fast rate switching on potentially failing rates
|
||||
is triggering too often if there is some strong noise on the channel. This can
|
||||
lead to wild fluctuations in the rate selection.
|
||||
Additionally, switching down to max_prob_rate can create a significant gap down
|
||||
in throughput, especially when using only 2 spatial streams, because max_prob_rate
|
||||
is limited to using fewer streams than the max_tp rates.
|
||||
In order to improve throughput without reducing reliability too much, use the
|
||||
rate downgrade code for the max_prob_rate only, and allow the non-downgraded
|
||||
max_prob_rate to use as many spatial streams as the max_tp rates
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -580,6 +580,14 @@ minstrel_ht_set_best_prob_rate(struct mi
|
||||
int cur_tp_avg, cur_group, cur_idx;
|
||||
int max_gpr_group, max_gpr_idx;
|
||||
int max_gpr_tp_avg, max_gpr_prob;
|
||||
+ int min_dur;
|
||||
+
|
||||
+ min_dur = max(minstrel_get_duration(mi->max_tp_rate[0]),
|
||||
+ minstrel_get_duration(mi->max_tp_rate[1]));
|
||||
+
|
||||
+ /* make the rate at least 18% slower than max tp rates */
|
||||
+ if (minstrel_get_duration(index) <= min_dur * 19 / 16)
|
||||
+ return;
|
||||
|
||||
cur_group = MI_RATE_GROUP(index);
|
||||
cur_idx = MI_RATE_IDX(index);
|
||||
@@ -601,11 +609,6 @@ minstrel_ht_set_best_prob_rate(struct mi
|
||||
!minstrel_ht_is_legacy_group(max_tp_group))
|
||||
return;
|
||||
|
||||
- /* skip rates faster than max tp rate with lower prob */
|
||||
- if (minstrel_get_duration(mi->max_tp_rate[0]) > minstrel_get_duration(index) &&
|
||||
- mrs->prob_avg < max_tp_prob)
|
||||
- return;
|
||||
-
|
||||
max_gpr_group = MI_RATE_GROUP(mg->max_group_prob_rate);
|
||||
max_gpr_idx = MI_RATE_IDX(mg->max_group_prob_rate);
|
||||
max_gpr_prob = mi->groups[max_gpr_group].rates[max_gpr_idx].prob_avg;
|
||||
@@ -663,40 +666,6 @@ minstrel_ht_assign_best_tp_rates(struct
|
||||
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Try to increase robustness of max_prob rate by decrease number of
|
||||
- * streams if possible.
|
||||
- */
|
||||
-static inline void
|
||||
-minstrel_ht_prob_rate_reduce_streams(struct minstrel_ht_sta *mi)
|
||||
-{
|
||||
- struct minstrel_mcs_group_data *mg;
|
||||
- int tmp_max_streams, group, tmp_idx, tmp_prob;
|
||||
- int tmp_tp = 0;
|
||||
-
|
||||
- if (!mi->sta->deflink.ht_cap.ht_supported)
|
||||
- return;
|
||||
-
|
||||
- group = MI_RATE_GROUP(mi->max_tp_rate[0]);
|
||||
- tmp_max_streams = minstrel_mcs_groups[group].streams;
|
||||
- for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) {
|
||||
- mg = &mi->groups[group];
|
||||
- if (!mi->supported[group] || group == MINSTREL_CCK_GROUP)
|
||||
- continue;
|
||||
-
|
||||
- tmp_idx = MI_RATE_IDX(mg->max_group_prob_rate);
|
||||
- tmp_prob = mi->groups[group].rates[tmp_idx].prob_avg;
|
||||
-
|
||||
- if (tmp_tp < minstrel_ht_get_tp_avg(mi, group, tmp_idx, tmp_prob) &&
|
||||
- (minstrel_mcs_groups[group].streams < tmp_max_streams)) {
|
||||
- mi->max_prob_rate = mg->max_group_prob_rate;
|
||||
- tmp_tp = minstrel_ht_get_tp_avg(mi, group,
|
||||
- tmp_idx,
|
||||
- tmp_prob);
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
static u16
|
||||
__minstrel_ht_get_sample_rate(struct minstrel_ht_sta *mi,
|
||||
enum minstrel_sample_type type)
|
||||
@@ -1176,8 +1145,6 @@ minstrel_ht_update_stats(struct minstrel
|
||||
|
||||
mi->max_prob_rate = tmp_max_prob_rate;
|
||||
|
||||
- /* Try to increase robustness of max_prob_rate*/
|
||||
- minstrel_ht_prob_rate_reduce_streams(mi);
|
||||
minstrel_ht_refill_sample_rates(mi);
|
||||
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
@@ -1256,7 +1223,7 @@ minstrel_ht_ri_txstat_valid(struct minst
|
||||
}
|
||||
|
||||
static void
|
||||
-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
|
||||
+minstrel_downgrade_prob_rate(struct minstrel_ht_sta *mi, u16 *idx)
|
||||
{
|
||||
int group, orig_group;
|
||||
|
||||
@@ -1271,11 +1238,7 @@ minstrel_downgrade_rate(struct minstrel_
|
||||
minstrel_mcs_groups[orig_group].streams)
|
||||
continue;
|
||||
|
||||
- if (primary)
|
||||
- *idx = mi->groups[group].max_group_tp_rate[0];
|
||||
- else
|
||||
- *idx = mi->groups[group].max_group_tp_rate[1];
|
||||
- break;
|
||||
+ *idx = mi->groups[group].max_group_prob_rate;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1286,7 +1249,7 @@ minstrel_ht_tx_status(void *priv, struct
|
||||
struct ieee80211_tx_info *info = st->info;
|
||||
struct minstrel_ht_sta *mi = priv_sta;
|
||||
struct ieee80211_tx_rate *ar = info->status.rates;
|
||||
- struct minstrel_rate_stats *rate, *rate2;
|
||||
+ struct minstrel_rate_stats *rate;
|
||||
struct minstrel_priv *mp = priv;
|
||||
u32 update_interval = mp->update_interval;
|
||||
bool last, update = false;
|
||||
@@ -1354,18 +1317,13 @@ minstrel_ht_tx_status(void *priv, struct
|
||||
/*
|
||||
* check for sudden death of spatial multiplexing,
|
||||
* downgrade to a lower number of streams if necessary.
|
||||
+ * only do this for the max_prob_rate to prevent spurious
|
||||
+ * rate fluctuations when the link changes suddenly
|
||||
*/
|
||||
- rate = minstrel_get_ratestats(mi, mi->max_tp_rate[0]);
|
||||
+ rate = minstrel_get_ratestats(mi, mi->max_prob_rate);
|
||||
if (rate->attempts > 30 &&
|
||||
rate->success < rate->attempts / 4) {
|
||||
- minstrel_downgrade_rate(mi, &mi->max_tp_rate[0], true);
|
||||
- update = true;
|
||||
- }
|
||||
-
|
||||
- rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate[1]);
|
||||
- if (rate2->attempts > 30 &&
|
||||
- rate2->success < rate2->attempts / 4) {
|
||||
- minstrel_downgrade_rate(mi, &mi->max_tp_rate[1], false);
|
||||
+ minstrel_downgrade_prob_rate(mi, &mi->max_prob_rate);
|
||||
update = true;
|
||||
}
|
||||
}
|
53
debian/patches/misc-openwrt/0007-mac80211-increase-quantum-for-airtime-scheduler.patch
vendored
Normal file
53
debian/patches/misc-openwrt/0007-mac80211-increase-quantum-for-airtime-scheduler.patch
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Sun, 26 Jun 2022 11:43:25 +0200
|
||||
Subject: [PATCH] mac80211: increase quantum for airtime scheduler
|
||||
|
||||
Given the typical AQL budget and queue length, a quantum of 256 with the
|
||||
default station weight often requires iterating over all queues frequently,
|
||||
until one of them becomes eligible.
|
||||
Improve performance by using 8 times station weight as scheduler quantum
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/mac80211/ieee80211_i.h
|
||||
+++ b/net/mac80211/ieee80211_i.h
|
||||
@@ -103,6 +103,8 @@ ieee80211_sta_keep_active(struct sta_inf
|
||||
return time_before_eq(jiffies, sta->airtime[ac].last_active + HZ / 10);
|
||||
}
|
||||
|
||||
+#define AIRTIME_QUANTUM_SHIFT 3
|
||||
+
|
||||
struct ieee80211_bss {
|
||||
u32 device_ts_beacon, device_ts_presp;
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -4084,7 +4084,7 @@ struct ieee80211_txq *ieee80211_next_txq
|
||||
|
||||
if (deficit < 0)
|
||||
sta->airtime[txqi->txq.ac].deficit +=
|
||||
- sta->airtime_weight;
|
||||
+ sta->airtime_weight << AIRTIME_QUANTUM_SHIFT;
|
||||
|
||||
if (deficit < 0 || !aql_check) {
|
||||
list_move_tail(&txqi->schedule_order,
|
||||
@@ -4227,7 +4227,8 @@ bool ieee80211_txq_may_transmit(struct i
|
||||
}
|
||||
sta = container_of(iter->txq.sta, struct sta_info, sta);
|
||||
if (ieee80211_sta_deficit(sta, ac) < 0)
|
||||
- sta->airtime[ac].deficit += sta->airtime_weight;
|
||||
+ sta->airtime[ac].deficit += sta->airtime_weight <<
|
||||
+ AIRTIME_QUANTUM_SHIFT;
|
||||
list_move_tail(&iter->schedule_order, &local->active_txqs[ac]);
|
||||
}
|
||||
|
||||
@@ -4235,7 +4236,7 @@ bool ieee80211_txq_may_transmit(struct i
|
||||
if (sta->airtime[ac].deficit >= 0)
|
||||
goto out;
|
||||
|
||||
- sta->airtime[ac].deficit += sta->airtime_weight;
|
||||
+ sta->airtime[ac].deficit += sta->airtime_weight << AIRTIME_QUANTUM_SHIFT;
|
||||
list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]);
|
||||
spin_unlock_bh(&local->active_txq_lock[ac]);
|
||||
|
293
debian/patches/misc-openwrt/0008-mac80211-add-AQL-support-for-broadcast-packets.patch
vendored
Normal file
293
debian/patches/misc-openwrt/0008-mac80211-add-AQL-support-for-broadcast-packets.patch
vendored
Normal file
@@ -0,0 +1,293 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
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 <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -3464,6 +3464,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
|
||||
@@ -212,11 +212,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);
|
||||
@@ -241,7 +243,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],
|
||||
@@ -249,7 +252,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);
|
||||
}
|
||||
@@ -275,6 +279,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
|
||||
@@ -1368,10 +1368,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
|
||||
@@ -2388,13 +2388,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
|
||||
@@ -2556,7 +2556,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) {
|
||||
@@ -3985,20 +3985,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;
|
||||
@@ -4050,6 +4050,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]);
|
||||
|
||||
@@ -4073,26 +4074,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;
|
||||
|
||||
@@ -4157,7 +4158,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;
|
||||
@@ -4206,15 +4208,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
|
||||
@@ -1238,8 +1238,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);
|
||||
}
|
||||
|
221
debian/patches/misc-openwrt/0009-mac80211-revert-dynamically-set-codel-parameters-per-station.patch
vendored
Normal file
221
debian/patches/misc-openwrt/0009-mac80211-revert-dynamically-set-codel-parameters-per-station.patch
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
This reverts commit 484a54c2e597dbc4ace79c1687022282905afba0. The CoDel
|
||||
parameter change essentially disables CoDel on slow stations, with some
|
||||
questionable assumptions, as Dave pointed out in [0]. Quoting from
|
||||
there:
|
||||
|
||||
But here are my pithy comments as to why this part of mac80211 is so
|
||||
wrong...
|
||||
|
||||
static void sta_update_codel_params(struct sta_info *sta, u32 thr)
|
||||
{
|
||||
- if (thr && thr < STA_SLOW_THRESHOLD * sta->local->num_sta) {
|
||||
|
||||
1) sta->local->num_sta is the number of associated, rather than
|
||||
active, stations. "Active" stations in the last 50ms or so, might have
|
||||
been a better thing to use, but as most people have far more than that
|
||||
associated, we end up with really lousy codel parameters, all the
|
||||
time. Mistake numero uno!
|
||||
|
||||
2) The STA_SLOW_THRESHOLD was completely arbitrary in 2016.
|
||||
|
||||
- sta->cparams.target = MS2TIME(50);
|
||||
|
||||
This, by itself, was probably not too bad. 30ms might have been
|
||||
better, at the time, when we were battling powersave etc, but 20ms was
|
||||
enough, really, to cover most scenarios, even where we had low rate
|
||||
2Ghz multicast to cope with. Even then, codel has a hard time finding
|
||||
any sane drop rate at all, with a target this high.
|
||||
|
||||
- sta->cparams.interval = MS2TIME(300);
|
||||
|
||||
But this was horrible, a total mistake, that is leading to codel being
|
||||
completely ineffective in almost any scenario on clients or APS.
|
||||
100ms, even 80ms, here, would be vastly better than this insanity. I'm
|
||||
seeing 5+seconds of delay accumulated in a bunch of otherwise happily
|
||||
fq-ing APs....
|
||||
|
||||
100ms of observed jitter during a flow is enough. Certainly (in 2016)
|
||||
there were interactions with powersave that I did not understand, and
|
||||
still don't, but if you are transmitting in the first place, powersave
|
||||
shouldn't be a problemmmm.....
|
||||
|
||||
- sta->cparams.ecn = false;
|
||||
|
||||
At the time we were pretty nervous about ecn, I'm kind of sanguine
|
||||
about it now, and reliably indicating ecn seems better than turning it
|
||||
off for any reason.
|
||||
|
||||
[...]
|
||||
|
||||
In production, on p2p wireless, I've had 8ms and 80ms for target and
|
||||
interval for years now, and it works great.
|
||||
|
||||
I think Dave's arguments above are basically sound on the face of it,
|
||||
and various experimentation with tighter CoDel parameters in the OpenWrt
|
||||
community have show promising results[1]. So I don't think there's any
|
||||
reason to keep this parameter fiddling; hence this revert.
|
||||
|
||||
[0] https://lore.kernel.org/linux-wireless/CAA93jw6NJ2cmLmMauz0xAgC2MGbBq6n0ZiZzAdkK0u4b+O2yXg@mail.gmail.com/
|
||||
[1] https://forum.openwrt.org/t/reducing-multiplexing-latencies-still-further-in-wifi/133605/130
|
||||
|
||||
Suggested-By: Dave Taht <dave.taht@gmail.com>
|
||||
In-memory-of: Dave Taht <dave.taht@gmail.com>
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
|
||||
|
||||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -5347,22 +5347,6 @@ void ieee80211_get_tx_rates(struct ieee8
|
||||
int max_rates);
|
||||
|
||||
/**
|
||||
- * ieee80211_sta_set_expected_throughput - set the expected tpt for a station
|
||||
- *
|
||||
- * Call this function to notify mac80211 about a change in expected throughput
|
||||
- * to a station. A driver for a device that does rate control in firmware can
|
||||
- * call this function when the expected throughput estimate towards a station
|
||||
- * changes. The information is used to tune the CoDel AQM applied to traffic
|
||||
- * going towards that station (which can otherwise be too aggressive and cause
|
||||
- * slow stations to starve).
|
||||
- *
|
||||
- * @pubsta: the station to set throughput for.
|
||||
- * @thr: the current expected throughput in kbps.
|
||||
- */
|
||||
-void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
|
||||
- u32 thr);
|
||||
-
|
||||
-/**
|
||||
* ieee80211_tx_rate_update - transmit rate update callback
|
||||
*
|
||||
* Drivers should call this functions with a non-NULL pub sta
|
||||
--- a/net/mac80211/debugfs_sta.c
|
||||
+++ b/net/mac80211/debugfs_sta.c
|
||||
@@ -152,12 +152,6 @@ static ssize_t sta_aqm_read(struct file
|
||||
|
||||
p += scnprintf(p,
|
||||
bufsz + buf - p,
|
||||
- "target %uus interval %uus ecn %s\n",
|
||||
- codel_time_to_us(sta->cparams.target),
|
||||
- codel_time_to_us(sta->cparams.interval),
|
||||
- sta->cparams.ecn ? "yes" : "no");
|
||||
- p += scnprintf(p,
|
||||
- bufsz + buf - p,
|
||||
"tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets flags\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
|
||||
--- a/net/mac80211/rate.c
|
||||
+++ b/net/mac80211/rate.c
|
||||
@@ -990,8 +990,6 @@ int rate_control_set_rates(struct ieee80
|
||||
if (sta->uploaded)
|
||||
drv_sta_rate_tbl_update(hw_to_local(hw), sta->sdata, pubsta);
|
||||
|
||||
- ieee80211_sta_set_expected_throughput(pubsta, sta_get_expected_throughput(sta));
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rate_control_set_rates);
|
||||
--- a/net/mac80211/sta_info.c
|
||||
+++ b/net/mac80211/sta_info.c
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <linux/timer.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
-#include <net/codel.h>
|
||||
#include <net/mac80211.h>
|
||||
#include "ieee80211_i.h"
|
||||
#include "driver-ops.h"
|
||||
@@ -702,13 +701,6 @@ __sta_info_alloc(struct ieee80211_sub_if
|
||||
}
|
||||
}
|
||||
|
||||
- sta->cparams.ce_threshold = CODEL_DISABLED_THRESHOLD;
|
||||
- sta->cparams.target = MS2TIME(20);
|
||||
- sta->cparams.interval = MS2TIME(100);
|
||||
- sta->cparams.ecn = true;
|
||||
- sta->cparams.ce_threshold_selector = 0;
|
||||
- sta->cparams.ce_threshold_mask = 0;
|
||||
-
|
||||
sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
|
||||
|
||||
return sta;
|
||||
@@ -2928,27 +2920,6 @@ unsigned long ieee80211_sta_last_active(
|
||||
return sta->deflink.status_stats.last_ack;
|
||||
}
|
||||
|
||||
-static void sta_update_codel_params(struct sta_info *sta, u32 thr)
|
||||
-{
|
||||
- if (thr && thr < STA_SLOW_THRESHOLD * sta->local->num_sta) {
|
||||
- sta->cparams.target = MS2TIME(50);
|
||||
- sta->cparams.interval = MS2TIME(300);
|
||||
- sta->cparams.ecn = false;
|
||||
- } else {
|
||||
- sta->cparams.target = MS2TIME(20);
|
||||
- sta->cparams.interval = MS2TIME(100);
|
||||
- sta->cparams.ecn = true;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-void ieee80211_sta_set_expected_throughput(struct ieee80211_sta *pubsta,
|
||||
- u32 thr)
|
||||
-{
|
||||
- struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
|
||||
-
|
||||
- sta_update_codel_params(sta, thr);
|
||||
-}
|
||||
-
|
||||
int ieee80211_sta_allocate_link(struct sta_info *sta, unsigned int link_id)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
--- a/net/mac80211/sta_info.h
|
||||
+++ b/net/mac80211/sta_info.h
|
||||
@@ -467,14 +467,6 @@ struct ieee80211_fragment_cache {
|
||||
unsigned int next;
|
||||
};
|
||||
|
||||
-/*
|
||||
- * The bandwidth threshold below which the per-station CoDel parameters will be
|
||||
- * scaled to be more lenient (to prevent starvation of slow stations). This
|
||||
- * value will be scaled by the number of active stations when it is being
|
||||
- * applied.
|
||||
- */
|
||||
-#define STA_SLOW_THRESHOLD 6000 /* 6 Mbps */
|
||||
-
|
||||
/**
|
||||
* struct link_sta_info - Link STA information
|
||||
* All link specific sta info are stored here for reference. This can be
|
||||
@@ -627,7 +619,6 @@ struct link_sta_info {
|
||||
* @sta: station information we share with the driver
|
||||
* @sta_state: duplicates information about station state (for debug)
|
||||
* @rcu_head: RCU head used for freeing this station struct
|
||||
- * @cparams: CoDel parameters for this station.
|
||||
* @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED)
|
||||
* @amsdu_mesh_control: track the mesh A-MSDU format used by the peer:
|
||||
*
|
||||
@@ -718,8 +709,6 @@ struct sta_info {
|
||||
struct dentry *debugfs_dir;
|
||||
#endif
|
||||
|
||||
- struct codel_params cparams;
|
||||
-
|
||||
u8 reserved_tid;
|
||||
s8 amsdu_mesh_control;
|
||||
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1402,16 +1402,9 @@ static struct sk_buff *fq_tin_dequeue_fu
|
||||
|
||||
local = container_of(fq, struct ieee80211_local, fq);
|
||||
txqi = container_of(tin, struct txq_info, tin);
|
||||
+ cparams = &local->cparams;
|
||||
cstats = &txqi->cstats;
|
||||
|
||||
- if (txqi->txq.sta) {
|
||||
- struct sta_info *sta = container_of(txqi->txq.sta,
|
||||
- struct sta_info, sta);
|
||||
- cparams = &sta->cparams;
|
||||
- } else {
|
||||
- cparams = &local->cparams;
|
||||
- }
|
||||
-
|
||||
if (flow == &tin->default_flow)
|
||||
cvars = &txqi->def_cvars;
|
||||
else
|
13
debian/patches/misc-openwrt/0010-mac80211-txq-tune.patch
vendored
Normal file
13
debian/patches/misc-openwrt/0010-mac80211-txq-tune.patch
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
--- a/net/mac80211/tx.c
|
||||
+++ b/net/mac80211/tx.c
|
||||
@@ -1599,8 +1599,8 @@ int ieee80211_txq_setup_flows(struct iee
|
||||
fq->memory_limit = 4 << 20; /* 4 Mbytes */
|
||||
|
||||
codel_params_init(&local->cparams);
|
||||
- local->cparams.interval = MS2TIME(100);
|
||||
- local->cparams.target = MS2TIME(20);
|
||||
+ local->cparams.interval = MS2TIME(50);
|
||||
+ local->cparams.target = MS2TIME(10);
|
||||
local->cparams.ecn = true;
|
||||
|
||||
local->cvars = kvcalloc(fq->flows_cnt, sizeof(local->cvars[0]),
|
18
debian/patches/misc-openwrt/0011-cfg80211-aql-txq-limit.patch
vendored
Normal file
18
debian/patches/misc-openwrt/0011-cfg80211-aql-txq-limit.patch
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -3462,12 +3462,12 @@ enum wiphy_params_flags {
|
||||
#define IEEE80211_DEFAULT_AIRTIME_WEIGHT 256
|
||||
|
||||
/* 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_L 1500
|
||||
+#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 5000
|
||||
#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_BC 50000
|
||||
|
||||
/* The per interface airtime threshold to switch to lower queue limit */
|
||||
-#define IEEE80211_AQL_THRESHOLD 24000
|
||||
+#define IEEE80211_AQL_THRESHOLD 12000
|
||||
|
||||
/**
|
||||
* struct cfg80211_pmksa - PMK Security Association
|
72
debian/patches/misc-openwrt/0101-sched-sch_cake-fix-bulk-flow-accounting-logic-for-host.patch
vendored
Normal file
72
debian/patches/misc-openwrt/0101-sched-sch_cake-fix-bulk-flow-accounting-logic-for-host.patch
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
From 546ea84d07e3e324644025e2aae2d12ea4c5896e Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com>
|
||||
Date: Tue, 3 Sep 2024 18:08:45 +0200
|
||||
Subject: [PATCH] sched: sch_cake: fix bulk flow accounting logic for host
|
||||
fairness
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
In sch_cake, we keep track of the count of active bulk flows per host,
|
||||
when running in dst/src host fairness mode, which is used as the
|
||||
round-robin weight when iterating through flows. The count of active
|
||||
bulk flows is updated whenever a flow changes state.
|
||||
|
||||
This has a peculiar interaction with the hash collision handling: when a
|
||||
hash collision occurs (after the set-associative hashing), the state of
|
||||
the hash bucket is simply updated to match the new packet that collided,
|
||||
and if host fairness is enabled, that also means assigning new per-host
|
||||
state to the flow. For this reason, the bulk flow counters of the
|
||||
host(s) assigned to the flow are decremented, before new state is
|
||||
assigned (and the counters, which may not belong to the same host
|
||||
anymore, are incremented again).
|
||||
|
||||
Back when this code was introduced, the host fairness mode was always
|
||||
enabled, so the decrement was unconditional. When the configuration
|
||||
flags were introduced the *increment* was made conditional, but
|
||||
the *decrement* was not. Which of course can lead to a spurious
|
||||
decrement (and associated wrap-around to U16_MAX).
|
||||
|
||||
AFAICT, when host fairness is disabled, the decrement and wrap-around
|
||||
happens as soon as a hash collision occurs (which is not that common in
|
||||
itself, due to the set-associative hashing). However, in most cases this
|
||||
is harmless, as the value is only used when host fairness mode is
|
||||
enabled. So in order to trigger an array overflow, sch_cake has to first
|
||||
be configured with host fairness disabled, and while running in this
|
||||
mode, a hash collision has to occur to cause the overflow. Then, the
|
||||
qdisc has to be reconfigured to enable host fairness, which leads to the
|
||||
array out-of-bounds because the wrapped-around value is retained and
|
||||
used as an array index. It seems that syzbot managed to trigger this,
|
||||
which is quite impressive in its own right.
|
||||
|
||||
This patch fixes the issue by introducing the same conditional check on
|
||||
decrement as is used on increment.
|
||||
|
||||
The original bug predates the upstreaming of cake, but the commit listed
|
||||
in the Fixes tag touched that code, meaning that this patch won't apply
|
||||
before that.
|
||||
|
||||
Fixes: 712639929912 ("sch_cake: Make the dual modes fairer")
|
||||
Reported-by: syzbot+7fe7b81d602cc1e6b94d@syzkaller.appspotmail.com
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Link: https://patch.msgid.link/20240903160846.20909-1-toke@redhat.com
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
net/sched/sch_cake.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/net/sched/sch_cake.c
|
||||
+++ b/net/sched/sch_cake.c
|
||||
@@ -833,8 +833,10 @@ skip_hash:
|
||||
allocate_dst = cake_ddst(flow_mode);
|
||||
|
||||
if (q->flows[outer_hash + k].set == CAKE_SET_BULK) {
|
||||
- cake_dec_srchost_bulk_flow_count(q, &q->flows[outer_hash + k], flow_mode);
|
||||
- cake_dec_dsthost_bulk_flow_count(q, &q->flows[outer_hash + k], flow_mode);
|
||||
+ if (allocate_src)
|
||||
+ q->hosts[q->flows[reduced_hash].srchost].srchost_bulk_flow_count--;
|
||||
+ if (allocate_dst)
|
||||
+ q->hosts[q->flows[reduced_hash].dsthost].dsthost_bulk_flow_count--;
|
||||
}
|
||||
found:
|
||||
/* reserve queue for future packets in same flow */
|
11
debian/patches/misc-openwrt/0201-fq-adjust-memory-size.patch
vendored
Normal file
11
debian/patches/misc-openwrt/0201-fq-adjust-memory-size.patch
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
--- a/include/net/fq_impl.h
|
||||
+++ b/include/net/fq_impl.h
|
||||
@@ -356,7 +356,7 @@ static int fq_init(struct fq *fq, int fl
|
||||
fq->flows_cnt = max_t(u32, flows_cnt, 1);
|
||||
fq->quantum = 300;
|
||||
fq->limit = 8192;
|
||||
- fq->memory_limit = 16 << 20; /* 16 MBytes */
|
||||
+ fq->memory_limit = 32 << 20; /* 32 MBytes */
|
||||
|
||||
fq->flows = kvcalloc(fq->flows_cnt, sizeof(fq->flows[0]), GFP_KERNEL);
|
||||
if (!fq->flows)
|
Reference in New Issue
Block a user