Skip to content

xdp: on Intel i40e/X710, firmware LLDP's default DCB config silently halves RSS fanout — half the processing threads receive no packets #222

Description

@jason-sirius

Summary

When using xdp: (and likely any multi-queue format relying on NIC RSS) on Intel X710/XL710 NICs with the in-tree i40e driver, hardware RSS may only ever deliver packets to the lower half of the receive queues. Parallel libtrace applications sized to the NIC's reported queue count will have half their processing threads silently idle. Nothing errors and every software-visible setting looks correct, which makes this miserable to diagnose — we lost several days to it on our own AF_XDP stack and are sharing the findings (plus a small detection patch) in case they save someone else the trip.

Symptom

With N combined channels configured and traffic with plenty of flow entropy, ethtool -S <if> shows per-queue RX counters like:

rx-0.packets: 773,707      rx-8.packets:  0
rx-1.packets: 774,313      rx-9.packets:  0
...                        ...
rx-7.packets: 773,752      rx-15.packets: 0

Everything a user would normally check is consistent and correct the whole time:

  • ethtool -l reports 16 combined channels
  • ethtool -x shows a 512-entry indirection table evenly covering all 16 queues
  • /sys/class/net/<if>/queues/ shows rx-0..rx-15
  • 4-tuple Toeplitz hashing confirmed via ethtool -n <if> rx-flow-hash tcp4
  • (under AF_XDP) all 16 XSK buffer pools register in dmesg

Root cause

The i40e firmware LLDP agent applies a default FCoE-aware DCB configuration at startup: two traffic classes, splitting the queue pairs evenly. From the driver's debugfs VSI dump:

tc_config: numtc = 2, enabled_tc = 0x3
tc_config: tc = 0, qoffset = 0, qcount = 8, netdev_tc = 0
tc_config: tc = 1, qoffset = 8, qcount = 8, netdev_tc = 1

i40e hardware RSS distributes within a traffic class, not across TC boundaries. All normal traffic lands in TC0, so RSS only ever uses queues 0–7. The kernel's cached view (channels, indirection table, sysfs) does not reflect the hardware TC partition.

Observed on: Intel XL710 4-port 10GbE [8086:1572], firmware 9.30/9.130.73618, in-tree i40e on kernel 5.15.0-181-generic. The agent's state is visible via ethtool --show-priv-flags <if>disable-fw-lldp : off.

Fix / workaround

ethtool --set-priv-flags <if> disable-fw-lldp on

This is a persistent NVM write (survives reboots and driver reloads, but is per-device — replacement NICs regress). The driver collapses to a single TC immediately, no reload needed:

tc_config: numtc = 1, enabled_tc = 0x1
tc_config: tc = 0, qoffset = 0, qcount = 16, netdev_tc = 0

After the fix all 16 queues receive traffic within ~1.5% of each other.

Why this matters

linux_xdp_pstart_input() sizes perpkt_thread_count to the NIC's reported max queues and starts one stream per queue. On an affected NIC, threads 8–15 are fed by queues that hardware RSS never selects, so they run but process nothing — no error, no drop counter, just silently missing parallelism (and, for HASHER_BALANCE expectations, a skewed load distribution). The same applies to any RSS-dependent parallel format on this hardware.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions