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:

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:

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:

If AP transmitted and client received roughly the same:

If AP transmitted far more than the client received:

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:

This does not mean 40 MHz is always better or 80 MHz is always worse:

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

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.

  1. 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.
  2. 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.
  3. 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.