[Bug] Flint 2 (GL-MT6000): WireGuard client/server leaves RPS masks pinned after shutdown, limiting router-local throughput

Hi,

I found a reproducible RPS/CPU-affinity bug on the Flint 2 that affects traffic generated locally by the router after WireGuard has been enabled in either client or server mode. The reduced performance persists after WireGuard is disabled and is cleared only by restarting the PPPoE WAN interface or manually restoring the RPS masks. The detailed measurements below were captured using a WireGuard client, but I can reproduce the same persistent slowdown after enabling and disabling the WireGuard server.

Environment

  • Router: Flint 2 / GL-MT6000 (MediaTek MT7986)

  • Firmware affected: GL.iNet 4.8.3 and 4.9.0

  • The detailed diagnostic capture below was made on 4.9.0. The same behavior was previously observed on 4.8.3; older releases may also be affected, but I have not verified them.

  • Kernel: 5.4.238

  • WAN: PPPoE over VLAN

  • WireGuard modes affected: both client and server

  • Interface used for the detailed capture below: wgclient1

  • Speed test: Ookla CLI executed directly on the router

LAN clients are not affected and can still reach full WAN speed. The problem is visible when the speed test or other high-throughput traffic originates from the router itself.

Steps to reproduce

  1. Restart only the PPPoE WAN interface.

  2. Check the Ethernet RX RPS masks. Both are f, allowing processing on all four CPU cores:


cat /sys/class/net/eth0/queues/rx-0/rps_cpus

cat /sys/class/net/eth1/queues/rx-0/rps_cpus

# f

# f

  1. Run an Ookla speed test directly on the router: approximately 2.17 Gbit/s.

  2. Enable either the WireGuard client or server. The detailed capture in this report used the client.

  3. The masks become 8 and 4:


eth0: 8

eth1: 4

  1. Disable the WireGuard client or server again. Confirm that the WG link, VPN policy-routing rules and WG firewall rules have disappeared.

  2. The RPS masks incorrectly remain 8/4 instead of returning to f/f.

  3. A router-local speed test is now limited to approximately 1.0–1.3 Gbit/s. One CPU core is saturated at 100% by network softirq processing while the other cores are mostly idle.

Controlled results

The following tests used the same Ookla server (Fastweb Napoli, ID 71992):

  • After PPPoE restart — RPS f/f — Download: 2.172 Gbit/s — Upload: 933 Mbit/s

  • WireGuard enabled — RPS 8/4 — Download: 974 Mbit/s — Upload: 945 Mbit/s

  • WireGuard disabled, without reconnecting PPPoE — RPS 8/4 — Download: 1.264 Gbit/s — Upload: 958 Mbit/s

Temporary workaround and screenshot

Manually restoring f/f immediately restores approximately 2 Gbit/s without restarting PPPoE:


echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus

echo f > /sys/class/net/eth1/queues/rx-0/rps_cpus

The attached screenshot provides an additional visual demonstration of this temporary recovery: router-local throughput returns to approximately 2 Gbit/s immediately after restoring the two f masks, without restarting the WAN or PPPoE session. The screenshot tests were interrupted and selected different nearby servers, whereas the controlled results above used the same fixed server and completed tests. The commands confirm the RPS masks as the cause, but they are only a temporary workaround because a later WireGuard/network event can overwrite them again.

Apparent root cause

The CPU/RPS partitioning applied while WireGuard is active may be an intentional performance optimization intended to reserve processing capacity for the tunnel. The confirmed bug is that this WireGuard-specific tuning is not reverted after WireGuard is disabled.

The responsible file is:


/etc/hotplug.d/iface/99-wireguard-irq

It belongs to:


gl-sdk4-wg-client - git-2026.129.28783-5c3eb2e-1

The wireguard_irq() function immediately returns unless ACTION=ifup, and on ifup it writes the single-core masks:


[ $ACTION = "ifup" ] || return

[ -e /sys/class/net/eth1 ] && echo 4 > /sys/class/net/eth1/queues/rx-0/rps_cpus

[ -e /sys/class/net/eth0 ] && echo 8 > /sys/class/net/eth0/queues/rx-0/rps_cpus

There is no corresponding MT6000 ifdown path that restores f/f.

The same MT6000 ifup block also writes 3 to the br-lan RPS mask. After WireGuard was disabled, br-lan was still set to 3. I have not measured a direct performance impact from this additional residual value, but it further indicates that the WireGuard-specific RPS configuration is not fully reverted.

Restarting PPPoE triggers the generic /etc/hotplug.d/net/20-smp-packet-steering script, which restores the four-core mask. This explains why restarting WAN works around the problem even though PPPoE itself is not the cause.

Suggested permanent fix for GL.iNet

The MT6000 path in 99-wireguard-irq should handle the WireGuard ifdown event instead of returning immediately. When the last relevant WireGuard client or server interface is disabled, it should restore the complete normal RPS configuration for every interface modified by the WireGuard ifup path, preferably by invoking the common packet-steering routine rather than duplicating its logic. The implementation should account for configurations with multiple simultaneous WireGuard interfaces and restore the normal masks only when appropriate.

I can provide additional before/after diagnostic snapshots and the read-only collection script if required. No public IP addresses, credentials, WireGuard keys or peer configuration will be included.

Hi,

Thank you for your detailed investigation and for providing the reproduction steps.

We have tested this issue on our Flint 2 (GL-MT6000) and were able to reproduce the same behavior: after enabling WireGuard, the RPS settings are changed, but after disabling WireGuard, the settings are not restored automatically.
We have forwarded this finding and your suggestion to our development team for further investigation. We will check the WireGuard related RPS handling logic and evaluate a proper fix.

Thank you again for your detailed analysis and for helping us identify this issue.

Thank you very much for reproducing and escalating the issue.

One important scope observation: the same wireguard_irq() function and its ifup-only logic also reference several other models:

be9300, be6500, be10000, be14000, mt6000, mt3600be, mt5000 and be3600.

I have only reproduced the problem on the Flint 2, but the shared code suggests that the other models should also be audited for persistent RPS settings after the last WireGuard interface is stopped. The correct normal masks may differ between models, so restoring the previous/common packet-steering configuration would likely be safer than hard-coding Flint 2 values.

I also performed some optional performance tests:

  • Restoring f/f while WireGuard was still active reduced tunneled throughput to approximately 550–600 Mbit/s, suggesting that the WireGuard-specific RPS tuning is useful while the tunnel is active.
  • Mask b on wgclient1 repeatedly produced the best result in my setup, reaching approximately 800 Mbit/s.
  • On my PPPoE WAN with MTU 1492, changing wgclient1 MTU from 1350 to 1420 improved tunneled throughput from approximately 500–630 Mbit/s to around 750–800 Mbit/s.

The first and most important issue remains restoring the normal RPS configuration after WireGuard shutdown. The mask and MTU results are only additional empirical observations that may be useful for future optimization, not proposed universal defaults.

All tests used temporary runtime changes only; no firmware scripts were modified.

Thank you again for your help.

1 Like