Packet Processing Engine (PPE) sitting idle? Put it back to work

So you don’t have Hardware Flow Offloading enabled for whatever reason (usually because you have QoS (Quality of Service) or BufferBloat mitigation enabled), which means you have that powerful MediaTek Filogic SoC (System On Chip) PPE (Packet Processing Engine) just sitting idle.

But you can still put it back to use, and reduce your CPU usage in the process. Rather than having it focus on outbound packets, have it focus on packets internal to your network. Specifically your 5 GHz WiFi and / or 6 GHz WiFi.

https://openwrt.org/docs/guide-user/network/wifi/wed

Caveats and Limitations

  • Version: requires OpenWrt 22.03 or later.
  • Scope: only accelerates wireless traffic on 5 GHz and 6 GHz radios.
  • Stability: considered stable, however flows are less traceable than software routing and it is a relatively new feature.
  • Coexistence: can be used alone or with flow_offloading for wired traffic.
  • Limitations: since flows are offloading to the PPEs it cannot be used with QoS AQL (Airtime Queue Limits).
  • Topology: if you configure your device as a dumb AP the additional package bridger is required.

And of course, it requires that your hardware has the MediaTek 7915 (or later) Filogic SoC PPE engine.

Issue:

vi /etc/modules.conf

… press i to enter editing mode.

Then enter:

options mt7915e wed_enable=Y

… press Esc to exit editing mode, then :wq to save and exit.

Then reboot the router. When it comes back up, issue:

cat /sys/module/mt7915e/parameters/wed_enable

… which should return Y.

Start a large download and upload data transfer.

Watch: https://192.168.1.1/cgi-bin/luci/admin/status/realtime

You’ll see your CPU idling even as you’re pushing your datarate to the limit.

If you want to see the stats for WED, you can issue:

while true; do printf "\033[2J\033[3J\033[H"; cat /sys/kernel/debug/wed0/txinfo; sleep 10; done

You’ll see something like:

======== WED TX:
WED_TX_MIB(0)                    0001479e
WED_RING_TX(0) BASE              490e0000
WED_RING_TX(0) CNT               00000800
WED_RING_TX(0) CIDX              0000079e
WED_RING_TX(0) DIDX              0000079e
WED_TX_MIB(1)                    000a6948
WED_RING_TX(1) BASE              4a450000
WED_RING_TX(1) CNT               00000800
WED_RING_TX(1) CIDX              00000148
WED_RING_TX(1) DIDX              00000148

======== WPDMA TX:
WED_WPDMA_TX_MIB(0)              0001479e
WED_WPDMA_RING_TX(0) BASE        490e8000
WED_WPDMA_RING_TX(0) CNT         00000800
WED_WPDMA_RING_TX(0) CIDX        079e079e
WED_WPDMA_RING_TX(0) DIDX        0000079e
WED_WPDMA_TX_COHERENT_MIB(0)     00000000
WED_WPDMA_TX_MIB(1)              000a6948
WED_WPDMA_RING_TX(1) BASE        4a458000
WED_WPDMA_RING_TX(1) CNT         00000800
WED_WPDMA_RING_TX(1) CIDX        01480148
WED_WPDMA_RING_TX(1) DIDX        00000148
WED_WPDMA_TX_COHERENT_MIB(1)     00000000

======== WPDMA TX:
WPDMA_TX0 BASE                   490e8000
WPDMA_TX0 CNT                    00000800
WPDMA_TX0 CIDX                   0000079e
WPDMA_TX0 DIDX                   0000079e
WPDMA_TX1 BASE                   4a458000
WPDMA_TX1 CNT                    00000800
WPDMA_TX1 CIDX                   00000148
WPDMA_TX1 DIDX                   00000148

======== WED WDMA RX:
WED_WDMA_RX_MIB(0)               00000000
WED_WDMA_RING_RX(0) BASE         4a448000
WED_WDMA_RING_RX(0) CNT          00000400
WED_WDMA_RING_RX(0) CIDX         000003ff
WED_WDMA_RING_RX(0) DIDX         00000000
WED_WDMA_RX_THRES(0)             00040020
WED_WDMA_RX_RECYCLE_MIB(0)       00000000
WED_WDMA_RX_PROCESSED_MIB(0)     00000000
WED_WDMA_RX_MIB(1)               00000000
WED_WDMA_RING_RX(1) BASE         4a480000
WED_WDMA_RING_RX(1) CNT          00000400
WED_WDMA_RING_RX(1) CIDX         000003ff
WED_WDMA_RING_RX(1) DIDX         00000000
WED_WDMA_RX_THRES(1)             00040020
WED_WDMA_RX_RECYCLE_MIB(1)       00000000
WED_WDMA_RX_PROCESSED_MIB(1)     00000000

======== WDMA RX:
WDMA_GLO_CFG                     58404e75
WDMA_RING_RX(0) BASE             4a448000
WDMA_RING_RX(0) CNT              00000400
WDMA_RING_RX(0) CIDX             000003ff
vWDMA_RING_RX(0) DIDX             00000000
WDMA_RING_RX(1) BASE             4a480000
WDMA_RING_RX(1) CNT              00000400
WDMA_RING_RX(1) CIDX             000003ff
WDMA_RING_RX(1) DIDX             00000000

======== WED TX FREE:
WED_RX_MIB(0)                    000719e4
WED_RING_RX(0) BASE              413ce000
WED_RING_RX(0) CNT               00000200
WED_RING_RX(0) CIDX              000001e2
WED_RING_RX(0) DIDX              000001e4
WED_WPDMA_RX_COHERENT_MIB(0)     00000000
WED_RX_MIB(1)                    00000000
WED_RING_RX(1) BASE              00000000
WED_RING_RX(1) CNT               00000000
WED_RING_RX(1) CIDX              00000000
WED_RING_RX(1) DIDX              00000000
WED_WPDMA_RX_COHERENT_MIB(1)     00000000

======== WED WPDMA TX FREE:
WED_WPDMA_RING_RX(0) BASE        413ce000
WED_WPDMA_RING_RX(0) CNT         00000200
WED_WPDMA_RING_RX(0) CIDX        01e401e2
WED_WPDMA_RING_RX(0) DIDX        000001e4
WED_WPDMA_RING_RX(1) BASE        00000000
WED_WPDMA_RING_RX(1) CNT         00000000
WED_WPDMA_RING_RX(1) CIDX        00000000
WED_WPDMA_RING_RX(1) DIDX        00000000

The MIB (Management Information Base) counters:

  • WED_TX_MIB(0) 0001479e (Hexadecimal for 83,870 packets)

  • WED_TX_MIB(1) 000a6948 (Hexadecimal for 682,312 packets)

  • WED_TX_MIB(0) is 5 GHz WiFi

  • WED_TX_MIB(1) is 6 GHz WiFi

(Remember that I have the external EDUP WiFi 6e AX3000M USB adapter connected to the router).

The CIDX (Current Index) and DIDX (Destination/Done Index) show where the hardware is reading and writing data inside the ring buffers:

  • WED_RING_TX(0) CIDX 0000079e
  • WED_RING_TX(0) DIDX 0000079e

CIDX matches DIDX, meaning the WED engine is processing the wireless packet tokens as soon as they hit the hardware rings. There is zero backlog or buffer congestion.