8b356aa11f
Replaces the 13 broken DKMS-path -danctnix mirrors from PR #17 + adds 9 new series-dirs for the c-stack patches that were never split (Patches A/B/C-v3/F/D/E/C2/G/H) + retires the cumulative-c5x-danctnix single-file interim from fleet/ohm.yaml. Mechanism: cd marfrit/bes2600-dkms-mobian git format-patch fe73571..cleanups --no-merges -o /tmp/cleanups/ git format-patch cleanups..bes2600/bh-c-fossil-cleanup --no-merges -o /tmp/h/ for each commit: route to series-dir, sed-rewrite a/bes2600/foo.c -> a/drivers/staging/bes2600/foo.c The 29 cleanups commits + 1 Patch H commit map to 25 series-dirs (a few series-dirs get multiple commits: lmac-recover gets c5.2 + c5.2.1 as 0001+0002; cw1200-fix-backports gets F3+F2+F1 as 0001-0003; factory-series gets request_firmware + STANDARD_FACTORY_EFUSE_FLAG as 0001+0002). fleet/ohm.yaml apply order matches cleanups commit chronology, which is what produced the working c5x interim. cumulative.patch from ka-promote ohm now has 32 resolved patches (29 cleanups + 1 Patch H + scan-filter-5ghz + xor-neon SCS + besser#18-fix), 276 079 bytes, b2sum 7418db5ddf8fe938b130bc9d0e9f7dc9060f3a13703cd50757835ac43140a13... Apply order in cleanups + bh-c-fossil-cleanup: 1 factory-series (c1 + factory-no-efuse-flag) 3 factory-thread-dev 4 pm-gate-on-handshake 5 remove-chardev-user-interface 6 enable-testmode 7 tx-sdio-dma-oob-danctnix (was 'staging-prep-series') 8 factory-drop-kernel-write-danctnix 9 drop-dpd-file-paths-danctnix 10 drop-orphan-file-io-danctnix 11 pm-timeout-silence-danctnix 12 scan-defer-on-reject-danctnix (c5.1) 13 scan-defer-backoff-tune-danctnix (c5.1.1) 14 lmac-recover-via-mmc-hw-reset-danctnix (c5.2 + c5.2.1) 16 pm-state-resync-danctnix (c6.1) 17 pm-wake-consume-state-danctnix (c6.2) 18 pm-detect-firmware-unsupported-danctnix (c7) 19 decrypt-storm-fast-recover-danctnix (Patch A) 20 connection-loss-fast-recover-danctnix (Patch B) 21 cw1200-fix-backports-danctnix (Patches F3 + F2 + F1) 24 sdio-rx-no-relay-danctnix (Patch C v3) 25 license-spdx-restore-attribution-danctnix (Patch G) 26 ba-lock-atomic-danctnix (Patch D) 27 ps-state-lock-skip-pm-disabled-danctnix (Patch E) 28 rx-list-batch-delivery-danctnix (Patch C2) 29 bh-c-fossil-cleanup-danctnix (Patch H) 30 scan-filter-5ghz-danctnix (besser#1) 31 arch/arm64/xor-neon-... (GCC 15 SCS) 32 queue-pending-record-lock-bh-danctnix (besser#18) Verification: pkgrel=6 build from this manifest in progress; if srcversion == 26B0003FE9F2B05DCE838C4 (pkgrel=5's), source-tree is byte-equivalent to the c5x interim + scan-filter + besser#18 stack that's currently running on ohm. Refs: #17 (the broken mirror), #28 (the interim PR that landed cumulative-c5x), #31 (ka-promote trailer normalisation followup).
222 lines
9.0 KiB
Diff
222 lines
9.0 KiB
Diff
From d0f14e3ba7408e81ed4c76941b8a4c7abda0c61b Mon Sep 17 00:00:00 2001
|
|
From: "Claude (noether)" <claude@reauktion.de>
|
|
Date: Wed, 6 May 2026 19:50:52 +0200
|
|
Subject: [PATCH 20/29] bes2600: pre-empt AP-deauth-6 with mac80211 reassoc on
|
|
decrypt-fail storm
|
|
|
|
When the BES2600 firmware reports WSM_STATUS_DECRYPTFAILURE for a burst
|
|
of received frames (typically because the host's PTK or GTK has fallen
|
|
out of sync with the AP), the AP eventually concludes that the STA is
|
|
not authenticated and emits an unprotected deauth-reason-6 ("Class 2
|
|
frame received from non-authenticated station"). On the deployed
|
|
pinetab2 + bes2600 stack this AP-initiated deauth has been observed to
|
|
leave the link blackholed for up to 109 s before userspace finds a
|
|
different SSID/channel to recover on. (Receipts at
|
|
https://git.reauktion.de/marfrit/besser, notes/phase5-2026-05-06.md.)
|
|
|
|
Add a sliding-window counter on each bes2600_vif: when 5 decrypt
|
|
failures fire within 5 s, schedule a worker that calls
|
|
ieee80211_connection_loss(vif). mac80211 then performs immediate
|
|
disassociation; userspace (NetworkManager / wpa_supplicant) reconnects
|
|
with fresh keys before the AP gets a chance to fire its unprotected
|
|
deauth.
|
|
|
|
Predicted Phase 7 delta vs the unpatched baseline:
|
|
- decrypt-burst rate: unchanged (this does not address root cause)
|
|
- AP-deauth-6 rate: <= 0.2 of baseline
|
|
- conditional probability of >5s blackhole given a burst:
|
|
100% -> <= 10%
|
|
- worst-case recovery time: 109s -> <5s
|
|
|
|
Contract pin: ieee80211_connection_loss() per
|
|
include/net/mac80211.h: "may also be called if the connection needs to
|
|
be terminated for some other reason... will cause immediate change to
|
|
disassociated state, without connection recovery attempts." Userspace
|
|
recovery is the existing NM/wpa_supplicant path. The worker context
|
|
satisfies the implicit process-context expectation.
|
|
|
|
Files touched:
|
|
- bes2600/bes2600.h: 4 new fields on struct bes2600_vif + 2 prototypes
|
|
- bes2600/txrx.c: new helpers + the call site at the existing
|
|
WSM_STATUS_DECRYPTFAILURE log point (the unconditional "goto drop"
|
|
branch in bes2600_rx_cb)
|
|
- bes2600/sta.c: bes2600_decrypt_storm_init() in bes2600_vif_setup;
|
|
cancel_work_sync() in bes2600_remove_interface, alongside the
|
|
existing per-vif cancel_*_work_sync block. Safe under the kernel
|
|
cancel_work_sync contract: the work_struct is INIT_WORK'd in setup,
|
|
so the call is valid; it blocks until any in-flight handler returns,
|
|
ensuring no use-after-free of priv when mac80211 frees the vif; and
|
|
it is idempotent (subsequent calls just return false).
|
|
- bes2600/debug.c: DecryptStormRecoveries seq_printf in the per-vif
|
|
status seq_file output
|
|
|
|
Threshold (5/5s) is set well above the steady-state per-vif decrypt-
|
|
fail rate observed in measurement (~1/min even under sustained 1 MB/s
|
|
load), so a true storm is required to trip it. The cw1200/cw1260
|
|
ancestor has no equivalent storm-recovery; this is a clean addition.
|
|
|
|
checkpatch.pl --no-tree --strict: clean (0/0/0).
|
|
|
|
Signed-off-by: Claude (noether) <claude@reauktion.de>
|
|
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
---
|
|
bes2600/bes2600.h | 9 ++++++
|
|
bes2600/debug.c | 2 ++
|
|
bes2600/sta.c | 2 ++
|
|
bes2600/txrx.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
4 files changed, 87 insertions(+)
|
|
|
|
diff --git a/drivers/staging/bes2600/bes2600.h b/drivers/staging/bes2600/bes2600.h
|
|
index 0e60960..66482f7 100644
|
|
--- a/drivers/staging/bes2600/bes2600.h
|
|
+++ b/drivers/staging/bes2600/bes2600.h
|
|
@@ -596,6 +596,11 @@ struct bes2600_vif {
|
|
unsigned long rx_timestamp;
|
|
u32 cipherType;
|
|
|
|
+ /* Decrypt-storm fast-recover (Trigger B). See txrx.c. */
|
|
+ unsigned long decrypt_storm_window_start;
|
|
+ unsigned int decrypt_storm_count;
|
|
+ unsigned int decrypt_storm_recoveries;
|
|
+ struct work_struct decrypt_storm_recover_work;
|
|
|
|
/* AP powersave */
|
|
u32 link_id_map;
|
|
@@ -856,4 +861,8 @@ int bes2600_btusb_setup_pipes(struct sbus_priv *sbus_priv);
|
|
void bes2600_btusb_uninit(struct usb_interface *interface);
|
|
#endif
|
|
|
|
+/* Decrypt-storm fast-recover helpers — see txrx.c. */
|
|
+void bes2600_decrypt_storm_init(struct bes2600_vif *priv);
|
|
+void bes2600_decrypt_storm_account(struct bes2600_vif *priv);
|
|
+
|
|
#endif /* BES2600_H */
|
|
diff --git a/drivers/staging/bes2600/debug.c b/drivers/staging/bes2600/debug.c
|
|
index 5228b22..ca223dd 100644
|
|
--- a/drivers/staging/bes2600/debug.c
|
|
+++ b/drivers/staging/bes2600/debug.c
|
|
@@ -542,6 +542,8 @@ static int bes2600_status_show_priv(struct seq_file *seq, void *v)
|
|
priv->listening ? " (listening)" : "");
|
|
seq_printf(seq, "Assoc: %s\n",
|
|
bes2600_debug_join_status[priv->join_status]);
|
|
+ seq_printf(seq, "DecryptStormRecoveries: %u\n",
|
|
+ priv->decrypt_storm_recoveries);
|
|
if (priv->rx_filter.promiscuous)
|
|
seq_puts(seq, "Filter: promisc\n");
|
|
else if (priv->rx_filter.fcs)
|
|
diff --git a/drivers/staging/bes2600/sta.c b/drivers/staging/bes2600/sta.c
|
|
index 5f1a456..1b78051 100644
|
|
--- a/drivers/staging/bes2600/sta.c
|
|
+++ b/drivers/staging/bes2600/sta.c
|
|
@@ -448,6 +448,7 @@ void bes2600_remove_interface(struct ieee80211_hw *dev,
|
|
cancel_delayed_work_sync(&priv->join_timeout);
|
|
cancel_delayed_work_sync(&priv->set_cts_work);
|
|
cancel_delayed_work_sync(&priv->pending_offchanneltx_work);
|
|
+ cancel_work_sync(&priv->decrypt_storm_recover_work);
|
|
|
|
del_timer_sync(&priv->mcast_timeout);
|
|
/* TODO:COMBO: May be reset of these variables "delayed_link_loss and
|
|
@@ -2619,6 +2620,7 @@ int bes2600_vif_setup(struct bes2600_vif *priv)
|
|
|
|
/* Setup per vif workitems and locks */
|
|
spin_lock_init(&priv->vif_lock);
|
|
+ bes2600_decrypt_storm_init(priv);
|
|
INIT_WORK(&priv->join_work, bes2600_join_work);
|
|
INIT_DELAYED_WORK(&priv->join_timeout, bes2600_join_timeout);
|
|
INIT_WORK(&priv->unjoin_work, bes2600_unjoin_work);
|
|
diff --git a/drivers/staging/bes2600/txrx.c b/drivers/staging/bes2600/txrx.c
|
|
index dbd1b23..346312c 100644
|
|
--- a/drivers/staging/bes2600/txrx.c
|
|
+++ b/drivers/staging/bes2600/txrx.c
|
|
@@ -25,6 +25,78 @@
|
|
|
|
#define BES2600_INVALID_RATE_ID (0xFF)
|
|
|
|
+/*
|
|
+ * Decrypt-storm fast-recover (Trigger B).
|
|
+ *
|
|
+ * When the BES2600 firmware reports WSM_STATUS_DECRYPTFAILURE for a
|
|
+ * burst of received frames (typically because the host's PTK or GTK
|
|
+ * has fallen out of sync with the AP), the AP eventually concludes that
|
|
+ * the STA is not authenticated and emits an unprotected deauth-reason-6
|
|
+ * ("Class 2 frame received from non-authenticated station"). On the
|
|
+ * deployed pinetab2 + bes2600 stack this AP-initiated deauth has been
|
|
+ * observed to leave the link blackholed for up to 109 s before
|
|
+ * userspace finds a different SSID/channel to recover on. (Receipts at
|
|
+ * https://git.reauktion.de/marfrit/besser, notes/phase5-2026-05-06.md.)
|
|
+ *
|
|
+ * Recovery here pre-empts the AP: when we see THRESHOLD decrypt
|
|
+ * failures within WINDOW, we ask mac80211 for a clean reassoc via
|
|
+ * ieee80211_connection_loss(), which causes immediate disassociation
|
|
+ * and lets userspace auto-reconnect with fresh keys.
|
|
+ *
|
|
+ * mac80211 contract: ieee80211_connection_loss() may be called
|
|
+ * regardless of IEEE80211_HW_CONNECTION_MONITOR; it causes immediate
|
|
+ * disassociation without driver-side recovery attempts. See
|
|
+ * include/net/mac80211.h for the canonical doc-comment.
|
|
+ *
|
|
+ * The threshold is set well above the steady-state per-vif
|
|
+ * decrypt-fail rate observed in measurement (~1/min even under
|
|
+ * sustained 1 MB/s load), so a true storm is required to trip it.
|
|
+ */
|
|
+#define BES2600_DECRYPT_STORM_THRESHOLD 5
|
|
+#define BES2600_DECRYPT_STORM_WINDOW_MS 5000
|
|
+
|
|
+static void bes2600_decrypt_storm_recover_work(struct work_struct *work)
|
|
+{
|
|
+ struct bes2600_vif *priv = container_of(work, struct bes2600_vif,
|
|
+ decrypt_storm_recover_work);
|
|
+
|
|
+ if (!priv->vif)
|
|
+ return;
|
|
+
|
|
+ bes_warn("[bes2600] decrypt-storm fast-recover: forcing reassoc\n");
|
|
+ ieee80211_connection_loss(priv->vif);
|
|
+ priv->decrypt_storm_recoveries++;
|
|
+}
|
|
+
|
|
+void bes2600_decrypt_storm_init(struct bes2600_vif *priv)
|
|
+{
|
|
+ INIT_WORK(&priv->decrypt_storm_recover_work,
|
|
+ bes2600_decrypt_storm_recover_work);
|
|
+ priv->decrypt_storm_window_start = 0;
|
|
+ priv->decrypt_storm_count = 0;
|
|
+ priv->decrypt_storm_recoveries = 0;
|
|
+}
|
|
+
|
|
+void bes2600_decrypt_storm_account(struct bes2600_vif *priv)
|
|
+{
|
|
+ unsigned long now = jiffies;
|
|
+ unsigned long window = msecs_to_jiffies(BES2600_DECRYPT_STORM_WINDOW_MS);
|
|
+
|
|
+ if (priv->decrypt_storm_window_start == 0 ||
|
|
+ time_after(now, priv->decrypt_storm_window_start + window)) {
|
|
+ priv->decrypt_storm_window_start = now;
|
|
+ priv->decrypt_storm_count = 1;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (++priv->decrypt_storm_count >= BES2600_DECRYPT_STORM_THRESHOLD) {
|
|
+ priv->decrypt_storm_count = 0;
|
|
+ /* Skew the window so we don't re-fire on the same storm. */
|
|
+ priv->decrypt_storm_window_start = now + window;
|
|
+ schedule_work(&priv->decrypt_storm_recover_work);
|
|
+ }
|
|
+}
|
|
+
|
|
#ifdef CONFIG_BES2600_TESTMODE
|
|
#include "bes_nl80211_testmode_msg.h"
|
|
#endif /* CONFIG_BES2600_TESTMODE */
|
|
@@ -1672,6 +1744,8 @@ void bes2600_rx_cb(struct bes2600_vif *priv,
|
|
goto drop;
|
|
} else {
|
|
bes_warn("[RX] Receive failure: %d.\n", arg->status);
|
|
+ if (arg->status == WSM_STATUS_DECRYPTFAILURE)
|
|
+ bes2600_decrypt_storm_account(priv);
|
|
goto drop;
|
|
}
|
|
}
|
|
--
|
|
2.54.0
|
|
|