Networking / Under the Hood

RSS vs RPS vs RFS vs XPS

Separate hardware queue selection, software CPU steering, application locality, and transmit queue selection before deciding what to tune.

Palash Vij / Published / 4 min read
Source-backed explainer RSS RPS RFS XPS NUMA Performance

Four mechanisms, four different decisions

A receive workload is unevenly distributed across CPUs. Should you add hardware queues, enable RPS, configure RFS, or change XPS?

These are not four names for the same setting. They make decisions at different places, and XPS concerns transmit queue selection, not receive balancing. Begin by naming the saturated resource and the direction of traffic.

Separate queue selection from CPU selection

  1. 01 RSS: receive queue
  2. 02 IRQ / NAPI context
  3. 03 RPS / RFS: protocol CPU
  4. 04 Application thread
  5. 05 XPS: transmit queue
A map of decisions, not a requirement to enable every mechanism. The final XPS step belongs to a transmit path, such as a response.
MechanismPrincipal decisionImportant qualification
RSSHardware receive queue, commonly using a flow hash and indirection tableQueue-to-CPU behavior also depends on IRQ and driver configuration
RPSCPU for later receive protocol processingSoftware handoffs can add backlog and inter-processor interrupt work
RFSReceive processing locality informed by the consuming applicationBuilds on RPS mechanisms and flow-tracking state
XPSTransmit queue using CPU or receive-queue mappingsDoes not set the application’s CPU affinity

These are choices about distribution and locality, not throughput guarantees.

How steering affects the receive and transmit paths

Queue selection and CPU selection are different

RSS-capable hardware commonly hashes selected header fields into an indirection table. That spreads flows across queues, not necessarily every packet of one flow across every core. Queue count alone tells you neither workload balance nor the complete CPU mapping.

RPS operates later in software and can enqueue work onto another CPU’s backlog. It can help when hardware queues are limited, but can be redundant when RSS already distributes work appropriately. An extra handoff has a cost.

Locality has its own state

RFS uses information about where a flow’s consuming application has run, alongside per-queue state, to improve locality without casually reordering work during CPU migration. Both the global flow-table capacity and per-queue flow counts matter to its configuration.

Accelerated RFS is a separate capability requiring support from the kernel, driver, and NIC. Do not infer it from the existence of ordinary RSS.

XPS maps CPUs or receive queues to transmit queues. Reducing contention or keeping completion work local may help a workload, but a device with only one transmit queue has no queue choice to optimize.

Inventory the current mapping first

Start with read-only inventory on an authorized Linux lab host. This is not a prescription to write CPU masks or change a production interface:

ethtool -l eth0
ethtool -x eth0
cat /proc/interrupts
cat /sys/class/net/eth0/queues/rx-0/rps_cpus
cat /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
sysctl net.core.rps_sock_flow_entries
cat /sys/class/net/eth0/queues/tx-0/xps_cpus
cat /sys/class/net/eth0/queues/tx-0/xps_rxqs

Replace the interface and queue identifiers. Missing files or unsupported ethtool operations are meaningful compatibility information, not something to silently ignore. IRQ labels may use driver-specific queue names rather than the interface name.

Record the mapping you actually have. For a controlled follow-up experiment, preserve the baseline configuration and a rollback procedure, change one mechanism, replay the same workload, and compare repeated runs. The exact change should follow a measured hypothesis, not a universal hexadecimal mask copied from an article.

What a useful steering comparison records

A useful steering comparison records:

  • Hardware, driver, kernel, physical cores/SMT, and NUMA topology.
  • Connection count, flow distribution, payload sizes, offered load, and run duration.
  • Per-CPU utilization and queue-level statistics where the driver exposes them.
  • Useful throughput, latency distributions, drops, retransmissions, and error rates.
  • Baseline and modified settings, repetitions, warmup, and raw observations.

Capture counter deltas over equal intervals and note resets. A larger cumulative drop counter is not by itself evidence that the latest configuration caused more loss.

Extra steering is not free

Software steering can improve balance while worsening locality. More queues can increase interrupt work. Moving work onto a NIC-local node can still overload that node or compete with the application.

irqbalance may change affinities, and containers or virtual NICs may expose only part of the underlying topology. Busy polling and threaded NAPI further complicate a simple “one IRQ equals one CPU” story.

The right question is not “which setting is fastest?” It is “which measured bottleneck does this change address, and what did it cost elsewhere?” Keep the NUMA teaching model separate from measurements of real hardware.

Further reading

Primary references behind this explanation. Consult documentation for the version and environment you actually run.

  1. Linux kernel: scaling in the networking stack
  2. Linux kernel: SMP IRQ affinity
  3. Linux kernel: NAPI and queue mapping
Follow the thread

Related reading

Search the notebook

Search articles, projects, and experiments. Everything stays on your device.

palash / notebook

A small doorway into the site. No shell, no remote execution.

Welcome. Type help to find your way around.

lab →experience →contact →Ctrl / Cmd + K