mt7915/mt7981: GET_MIB_INFO survey counters underflow; BSS Load freezes at a bogus value
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 888
- Forks
- 436
- PR merge metrics
- No merged PRs in 30d
Description
Diagnosed with help of an AI coding agent; measurements and code cites below were taken on a live AP.
Hardware: Zyxel NWA50AX Pro (zyxel,nwa50ax-pro), MT7981, mt798x-wmac / mt7915e
OpenWrt 25.12.5 r33051-f5dae5ece4, kernel 6.12.94, mediatek/filogic
kmod-mt7915e 6.12.94.2026.03.19~39c960c3
FW: WM ____000000 20240823161304 / WA DEV_000000 20240823161841 / HW 20240823161240a
Uptime ~2.93 d. Dual-band AP, default hostapd bss_load_update_period (60).
Bug
mt7915_mcu_get_chan_mib_info() accumulates firmware airtime MIBs with unsigned subtraction and no wrap/reset check:
state->cc_tx += cc_tx - state_ts->cc_tx; /* and same for rx / busy */
/* mt7915/mcu.c — V2 MIB path used by MT7981 (!is_mt7915) */
If a firmware counter goes backwards, the driver adds ~2^64 and survey dump is garbage forever after. Channel active time stays correct (ktime, not MIB).
Per-STA WTBL airtime already has this guard in mt7915_mac_sta_poll() (Henry Yen, "fix bogus Tx/Rx airtime duration values"). Channel survey never got it.
Live numbers (iw dev phyX-ap0 survey dump, in-use channel)
Use iw dev … survey dump, not iw phy.
active (ms) busy (ms) tx (ms)
2.4 ch11 253053261 14986490482870210 486388838753191
5 GHz ch36 253052450 9202221537544591 18446743827918618
2^64/1000 = 18446744073709552. 5 GHz TX = that minus 245790934 ms ≈ 245791 s (~uptime; a 32-bit µs wrap would leave ~4295 s, so this is not that).
~99 s later the deltas are still sane (2.4 busy +8299 ms, 5 GHz tx +5192 ms). Firmware is still producing reasonable increments; only the accumulated state is poisoned.
Off-channel rows are poisoned too (5 GHz 5200 MHz: active 133 ms, tx 7.09e15 ms). After the wrap, busy < tx on 5 GHz, which is also physically impossible.
hostapd (ubus call hostapd.<if> get_status, before setting bss_load_update_period=0):
phy0 (2.4): time=252416656 time_busy=14986490482818287 utilization=0
phy1 (5): time=252422802 time_busy=9202221537499923 utilization=221
hostapd only updates utilization when channel_time > last AND channel_time > channel_time_busy (src/ap/hw_features.c). After the wrap that second test is permanently false, so BSS Load freezes at the last accepted sample (0 vs 221). 221/255 ≈ 87% — a stale snapshot, not wrap arithmetic. We did not pcap the IE.
How to reproduce
- MT7981/MT7916 AP, leave radios up ~2–3 days (maybe less).
iw dev phy1-ap0 survey dump- If busy/tx >> active (and especially tx ≈ 2^64/1000), this is it.
ubus call hostapd.<if> get_status→airtime.utilizationstuck,time_busy>>time.
wifi reload does not reset chan_state. Reboot / wifi down+up / channel switch (mac_reset_counters) does.
Suggested fix
Same idea as mt7915_mac_sta_poll: if new < old, treat as reset (delta=0 or delta=new), do not add unsigned wrap. Optionally clamp delta to elapsed survey_time.
Workaround (does not fix survey dump)
option bss_load_update_period '0'
option chan_util_avg_period '0'
then wifi reload. Stops the BSS Load IE; iw survey / usteer airtime still see the wrap.
Not claiming
- That Apple (or any client) left 5 GHz because of 221. Same-SSID 2.4 was also ~10–14 dB stronger here.
- A 32-bit µs wrap.
- hostapd is wrong — it is correctly refusing busy > time.
Related, different
- https://github.com/openwrt/mt76/issues/916 — DAP-X1860 utilization missing after b4a9174
- https://github.com/freifunk-gluon/gluon/issues/3338
- Chad Monroe “exclude tx backoff” — accuracy, not wrap (MT7915-only path)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in mt7915/mcu.c at mt7915_mcu_get_chan_mib_info(), then compare its counter handling with the reset guard in mt7915_mac_sta_poll(). Reproduce with iw dev phy1-ap0 survey dump on an MT7981 or MT7916 AP and verify that busy and TX values remain bounded after a counter reset, with hostapd utilization no longer frozen by busy time exceeding active time.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, linux
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 70/100