OpenWrt Wi-Fi slow after idle: a 10-minute diagnostic and reversible tests
By Wu Jun · Updated 2026-10-29 · 5 min read
Symptom: after an idle period, one device's downlink drops to around 10 Mbps and may remain slow, while other
devices are fine. On a GL-MT6000 running OpenWrt mt76, we reproduced two independent conditions: vow_atf
preventing rate recovery, and a 40 MHz-only client operating inside an 80 MHz BSS.
This page gives a reversible diagnostic order. It does not recommend blindly copying "optimisation commands". The CSI capture is public [1], the diagnostic/tuning scripts ship in the toolkit [2], and the driver is upstream mt76 [3].
0. Back up before measuring
Record:
uname -a
cat /etc/openwrt_release
iwinfo <ap> info
iw dev <ap> station dump
ubus call system board
Save /etc/config/wireless and the installed firmware. Do not run an unknown script on a production router.
1. Locate the layer that is slow
| Symptom | Most likely layer | First check |
|---|---|---|
| wired is also slow | WAN/ONT/ISP/CPU | link negotiation and a router-local download |
| only Wi-Fi downlink is slow | AP-to-client rate/width state | tx/rx bitrate and BSS width |
| all Wi-Fi clients slow together | congestion, DFS, interference, AP resource | scan neighbours and airtime |
| one client slow, others fine | client power save, MCS, width or driver | direction test and A/B |
| Speedtest slow but LAN fast | ISP, server, DNS | do not use the public Internet as the only baseline |
Separate broadband from Wi-Fi first. One Speedtest screenshot cannot prove which layer is responsible.
2. Check whether WAN/LAN is really 100 Mbps
for i in /sys/class/net/*; do
name=$(basename "$i")
[ -r "$i/speed" ] && echo "$name $(cat "$i/speed") Mb/s"
done
Then inspect the WAN and suspect LAN ports:
ethtool <wan-iface>
ethtool <lan-iface>
Look for:
Speed100 versus 1000/2500;- local and link-partner advertised modes;
rx_errors,tx_errors,rx_crc_errors;- cable, wall port and computer NIC limitations.
In our case the WAN link was 1000 Mbps full duplex all along. The actual 100 Mbps link was another machine's advertised NIC mode. Calling that LAN result "the router turned gigabit into 100 Mbps" was a diagnostic error: check link-partner advertisement before touching Wi-Fi.
3. Sample the station rate repeatedly
for i in $(seq 1 20); do
date +%H:%M:%S
iw dev <ap> station dump | grep -E "Station|tx bitrate|rx bitrate|signal:"
sleep 2
done
Interpretation:
tx bitrateis AP-to-client and often explains slow download;- a drop to
VHT-MCS 0 1SSafter idle, with occasional recovery under traffic, points to rate adaptation/recovery; - high rx and low tx shows the client can transmit but AP transmit is impaired;
- if every client is low, investigate channel/DFS/interference first.
One tx bitrate value is the last sample, not an average. Observe it over time.
4. Byte accounting: low rate or retransmission?
During a LAN transfer record:
- bytes transmitted by the AP radio;
- bytes actually received by the client;
- PHY rate, duration and retry counters.
If AP transmitted and client received roughly the same:
- data is not being lost en masse;
- the radio may be staying at a low rate and leaving airtime idle;
- rate selection is a strong suspect.
If AP transmitted far more than the client received:
- suspect retransmission, interference, weak signal or a receiver issue;
- inspect RSSI/SNR, channel and hardware before changing
vow_atf.
5. A/B test one: vow_atf and recovery
On this MT7986 + mt76 setup, vow_atf=1 allowed the client to fall to MCS0 after idle and remain there under
continuous traffic. Setting it to 0 allowed recovery within roughly 15-20 seconds.
Read first:
for f in /sys/kernel/debug/ieee80211/phy*/mt76/vow_atf; do
echo "$f: $(cat "$f")"
done
Temporary A/B on a research device only:
echo 0 > /sys/kernel/debug/ieee80211/phy*/mt76/vow_atf
# idle 60 s, then run six 6-second LAN downloads
# record tx bitrate, achieved throughput, AP TX bytes and client RX bytes
Restore the original value:
echo 1 > /sys/kernel/debug/ieee80211/phy*/mt76/vow_atf
The toolkit's mt76-wifi-tune and watchdog can persist the zero value, but this is not a universal patch.
Different firmware, chips and clients may not reproduce it. Keep a rollback path:
tar.gz /
SHA-256.
6. A/B test two: client width versus BSS width
Inspect the radio and stations:
iw dev <ap> info
iw dev <ap> station dump | grep -E "Station|bitrate|signal"
iwinfo <ap> info
In this case:
- an older client could negotiate only 40 MHz and repeatedly fell to MCS0 inside HE80;
- an 80 MHz phone and another 80 MHz device were stable;
- switching the 5 GHz radio to HE40 produced 328-419 Mbps in 6/6 runs for the older client.
This does not mean 40 MHz is always better or 80 MHz is always worse:
- 80 MHz provides more CSI subcarriers and finer range resolution;
- a narrow-band client in a wide BSS needs explicit compatibility testing;
- if the router also serves the home, isolate the sensing radio/AP from ordinary clients where possible.
Before switching, save the configuration. After switching, confirm interface names, CSI daemon bandwidth metadata and client association.
7. Ten-minute decision flow
slow
|- wired also slow?
| |- check WAN/LAN speed, link partner, errors and ISP
| \\- Wi-Fi is not the first suspect
|- only Wi-Fi downlink slow?
| |- tx bitrate at MCS0?
| | |- idle-triggered and stuck -> test vow_atf A/B
| | \\- 40 MHz client in an 80 MHz BSS -> test width A/B
| |- AP TX versus client RX differs a lot -> retries/signal/interference
| \\- every client slow -> channel/DFS/airtime
\\- Speedtest slow but LAN normal -> ISP/server/DNS
8. Record results
Save for every A/B:
| Field | Example |
|---|---|
| router/firmware | GL-MT6000 / OpenWrt commit / mt76 version |
| client | chip, NSS, negotiated width, power-save state |
| radio | channel, width, country, TX power |
| time | UTC, idle duration, burst duration |
| PHY | repeated tx/rx bitrate samples |
| throughput | six achieved Mbps values, not only the maximum |
| bytes | AP TX, client RX, retries |
| conclusion | correlation and unverified mechanism separately |
9. Do not do this
- use a public Speedtest as the only A/B;
- trust one
iw station dump; - permanently modify debugfs/wireless without backup;
- call
vow_atfthe only firmware root cause based on correlation; - keep every legacy client unusable just to obtain 80 MHz CSI.
Verify first, persist second. Publish failed sessions before publishing an "optimisation script".
Related: the full slow-Wi-Fi investigation · mt76 rate-control analysis · 80 versus 40 MHz
References and data sources
Every external claim carries a source and an evidence grade (grading scheme). Grade E marks first-party, reproducible measurements from this project.
- Grade E · first-party measurement
This project's 10-minute raw capture (57,293 records / 600.0 s, SHA-256 00373f83…95e2)
Router CSI Lab · 2026
okwujun.pw/en/datasets/ · verified: Reassembled chunks verified byte-identical (2026-10-11) · The local raw master has SHA-256 00373f83…95e2; the public de-identified derivative has SHA-256 527466ce…a440. They must not be confused. - Grade E · first-party measurement
Router CSI Toolkit — capture/analysis/watchdog scripts (MIT, public repository)
Router CSI Lab · 2026
github.com/jjjwu/router-csi-toolkit · verified: GitHub API verified the public repository, capture-quality preflight, successful CI and the v0.1.3 release on 2026-11-02; the archive SHA-256 is 59f144c0…adea7 · The public repository includes a dependency-free capture preflight; the browser checker uses the same container definition and evidence boundaries. - Grade C · official docs
openwrt/mt76 — mac80211 driver for MediaTek Wi-Fi chipsets
OpenWrt project / MediaTek
github.com/openwrt/mt76 · verified: GitHub API 2026-10-11 (stars 890, last push 2026-10-08) · Upstream of the open-source mt76 driver used here; the CSI patch is applied on top of this codebase.