majorwiki/05-troubleshooting/networking/wifi-160mhz-airtime-saturation-game-streaming.md
majorlinux cb90bb69a2 wiki: add Steam Deck Wi-Fi flapping runbook (IWD periodic scan + rtw88 power save)
Client-side fix for OG Steam Deck (RTL8822CE/rtw88) flapping ~once a minute on
SteamOS: disable IWD periodic scan + disable Wi-Fi power save via NM dispatcher.
Cross-linked with the 160MHz airtime article; registered in SUMMARY.md nav.
2026-06-19 11:36:06 -04:00

5.9 KiB
Raw Permalink Blame History

title domain category tags status created updated
Wi-Fi Game Streaming Stutter: 160 MHz Channel Width Saturating the 5 GHz Radio troubleshooting networking
wifi
5ghz
160mhz
channel-width
dfs
steam-deck
game-streaming
asuswrt
airtime
chanim
published 2026-06-13 2026-06-13

Wi-Fi Game Streaming Stutter: 160 MHz Channel Width Saturating the 5 GHz Radio

🛑 Problem

Streaming a game from a desktop (wired) to a Steam Deck over Wi-Fi was stuttering intermittently — fine for a while, then choppy, hard to reproduce on demand. Throughput tests "looked fine," which is exactly why it was hard to pin down: game streaming fails on jitter and microbursts of contention, not on average bandwidth.

The Wi-Fi was an Asus RT-AX82U (AsusWRT, stock firmware) with the 5 GHz radio set to Auto channel at 160 MHz width.

🔍 Diagnosis

The key insight: signal was excellent, but latency was not. That combination means the airwaves are busy, not weak.

Step 1 — Measure jitter to the gateway from a Wi-Fi client

ping -c 20 -i 0.2 192.168.50.1
# round-trip min/avg/max/stddev = 7.5/27.0/61.0/16.5 ms

27 ms average and 16 ms of jitter to your own router over Wi-Fi is pathological. A healthy 5 GHz link sits at 25 ms. Yet the client's signal was -43 dBm (excellent) with a clean -92 dBm noise floor. Strong signal + high jitter = airtime contention, not range or interference at the receiver.

Step 2 — Confirm channel utilization at the router

AsusWRT/Broadcom exposes per-channel airtime stats via wl chanim_stats. SSH into the router and run it against the 5 GHz interface:

# 5 GHz interface name varies (eth6/eth7); resolve it from nvram
IF=$(nvram get wl1_ifname)
wl -i "$IF" chanspec        # e.g. 36/160 (0xe832)  → channel 36, 160 MHz
wl -i "$IF" assoclist | wc -l   # number of associated 5 GHz clients
wl -i "$IF" chanim_stats

The smoking gun (chanim_stats, version 3):

chanspec  tx  inbss obss nocat nopkt doze txop goodtx badtx glitch ... idle
0xe832    92    2    1    2     1     0    4    8      81    2          14

Read it as percentages of airtime:

Field Value Meaning
tx 92 Channel busy transmitting 92% of the time
txop 4 Transmit-opportunities available only 4% — the channel is starved
idle 14 Channel idle only 14%
goodtx / badtx 8 / 81 Failed/retried transmits vastly outnumber good ones

Seventeen clients were associated to that one 5 GHz radio.

Step 3 — Understand why 160 MHz makes it worse

A 160 MHz channel on the lower 5 GHz band spans channels 3664, which overlaps DFS sub-blocks. To stay clean it needs 160 MHz of uncontended spectrum — but in a dense RF environment (≈25 neighbor APs here, several on 5 GHz channels 48/52/100/132/153 that overlap or border the block), any one busy neighbor degrades the entire wide channel. 160 MHz also makes the radio DFS-radar exposed: a single radar detection forces a channel-switch with a 1 s+ blackout — a stream-killer.

So 160 MHz buys a higher peak PHY rate that game streaming doesn't need, at the cost of the stability it absolutely does.

Fix

Drop the 5 GHz radio to 80 MHz and pin it to a non-DFS channel (UNII-1: 36/40/44/48 — no radar, no DFS blackouts).

GUI: Wireless → 5 GHz → Channel Bandwidth = 80 MHz, Control Channel = 36, turn off "Auto."

Or over SSH (nvram + restart_wireless):

nvram set wl1_bw_cap=7        # cap at 80 MHz (bitmask: 1=20, 3=40, 7=80, 15=160)
nvram set wl1_chanspec=36/80  # channel 36 @ 80 MHz
nvram set wl1_channel=36
nvram commit
service restart_wireless      # ~15-20s radio bounce, drops all clients briefly

[!warning] restart_wireless drops every Wi-Fi client for 1520 seconds. nvram commit runs before the restart, so the config persists even if your own SSH/Wi-Fi session drops.

📊 Result

Verified from both the router and a client after the radio came back:

Metric Before (36/160) After (36/80)
Channel tx-busy 92% 9%
Transmit-opportunity available 4% 79%
Channel idle 14% 87%
Failed tx (badtx vs goodtx) 81 vs 8 1 vs 3
Gateway ping (avg / floor) 27 ms / 7.5 ms 9 ms / 2.7 ms
PHY peak rate 1729 Mbps 1200 Mbps

The PHY peak dropped (narrower channel) but that is irrelevant — Steam Remote Play wants ~3050 Mbps with consistent airtime, which it now has. The stutter resolved.

🧠 Takeaways

  • Diagnose Wi-Fi streaming problems with jitter, not throughput. A speed test can pass while a stream stutters. Ping your gateway and watch the stddev.
  • Strong signal + high latency = airtime congestion. Don't chase signal strength when RSSI is already good; look at channel utilization (chanim_stats).
  • 160 MHz is a trap in a dense RF environment. Use 80 MHz for reliability; reserve 160 MHz for clean spectrum and short range.
  • Prefer non-DFS channels (3648) for anything latency-sensitive — DFS radar events cause silent multi-second dropouts.
  • Wire the source. The streaming PC should be on Ethernet so the video only crosses the air once (AP → handheld). The handheld has to be Wi-Fi; the desktop doesn't.
  • Isolate IoT on 2.4 GHz (separate SSID) so it never competes for 5 GHz airtime with latency-sensitive clients.