You attach an XDP drop program to a 25 GbE Linux server's interface. The filter works, but throughput and CPU use are no better than the iptables rule it replaced, and `ip link show` reports the attachment as xdpgeneric. What are XDP's three attach modes, and what has happened here?
answer
- three modes, one of them is a fallback
- the fallback runs too late to help
- ask explicitly or the kernel picks silently
- the driver decides, not the program
- ip link show reads back what you got
basics
~20 sXDP attaches in native mode inside the driver, generic mode in the shared kernel receive path after the sk_buff is allocated, or offloaded onto a capable NIC. Generic mode is a correctness fallback with none of the performance benefit — the driver did not support native XDP.
solid answer
~50 sXDP has three modes. Native (`xdpdrv`) runs in the driver's receive routine before the `sk_buff` exists — that is the fast one. Generic (`xdpgeneric`) runs in generic kernel code, after the skb has already been allocated, and exists so you can develop and test a program on hardware whose driver has no XDP support; it is semantically correct and performance-wise pointless, because the allocation you were trying to avoid has already happened. Offloaded (`xdpoffload`) pushes the program onto the NIC itself, which only a few SmartNICs support. Attaching with the plain `xdp` keyword lets the kernel choose, and it silently falls back to generic. The fix is to attach with `xdpdrv` so a driver without support fails loudly, then check the driver with `ethtool -i` and make sure you are attaching to the physical NIC rather than a bond, bridge or VLAN device on top of it.
code
bash · 11 lines# Which driver is behind this interface?
ethtool -i eth0
# Demand native mode: fail loudly rather than fall back
ip link set dev eth0 xdpdrv obj xdp_drop.o sec xdp
# Read back the mode that is actually in force
ip link show dev eth0
bpftool net show dev eth0
ip link set dev eth0 xdp offgo deeper
Know that XDP needs support from the network driver to be fast, and that it can attach in a slower compatibility mode if that support is missing.
Be able to name native, generic and offloaded, explain that generic runs after the sk_buff has already been allocated, and show how to read the mode back with ip link show.
Demonstrate the diagnosis: measure, read the attached mode rather than assume it, check the driver with ethtool -i, confirm you targeted the physical NIC, and pin production attachments to xdpdrv so failures are loud.
Treat driver XDP support as a hardware and kernel procurement constraint: if the datapath design depends on native mode, that requirement belongs in NIC selection and kernel baselines, with a fleet-wide assertion that no host is silently running the fallback.
## The three modes **Native (driver) mode** is what people mean by XDP. The driver implements the XDP entry point and calls your program from its NAPI poll loop, on the raw receive buffer, before allocating an `sk_buff`. Drivers with native support include mlx5, ixgbe, i40e, bnxt and virtio-net, among others; many drivers, particularly on consumer and older server hardware, have none. **Generic (SKB) mode** is a fallback implemented in shared kernel code rather than in any driver. The kernel allocates the `sk_buff` as usual and then runs your XDP program against it, presenting the same `xdp_md` context. Every verdict behaves the same way, so your program is functionally correct and you can develop against a laptop. But the entire performance argument for XDP is "decide before the skb exists", and in generic mode the skb already exists. You have added a BPF program's worth of work to the receive path and removed nothing. **Offloaded mode** hands the program to the NIC, which runs it on its own processors so packets are dropped or forwarded without ever crossing PCIe. This requires a NIC with a programmable datapath and driver support for offload; it is rare, and offloaded programs face extra restrictions on which helpers and map types they can use. ## Why you ended up in generic mode iproute2 lets you ask for a mode explicitly, or leave it to the kernel: ```bash ip link set dev eth0 xdp obj prog.o sec xdp # kernel chooses; falls back ip link set dev eth0 xdpdrv obj prog.o sec xdp # native only, or fail ip link set dev eth0 xdpgeneric obj prog.o sec xdp # force the fallback ip link set dev eth0 xdpoffload obj prog.o sec xdp # onto the NIC ip link set dev eth0 xdp off ``` The plain `xdp` keyword is the trap. It tries native, and if the driver does not implement it, quietly attaches in generic mode instead. Nothing fails; a load-time error would have told you immediately, but a successful attach tells you nothing about which mode you got. That is why the diagnosis is `ip link show` (or `bpftool net show dev eth0`) reading back the actual mode — the flag in the output is the answer. The usual causes, in order of likelihood: 1. **The driver has no native XDP support.** Confirm the driver with `ethtool -i eth0` and check whether that driver implements XDP in your kernel version. 2. **You attached to a virtual device, not the NIC.** A bond, bridge, VLAN or similar stacked device is not the same attach target as the underlying physical interface, and support differs. Attach to the device that actually receives from the wire. 3. **The kernel is too old for that driver's support**, which landed at different releases per driver. The operational lesson is to always attach with `xdpdrv` in production. If native mode is not available you want the attach to fail during deployment, not to succeed and silently deliver none of the benefit you sized the machine around. ## What native mode costs you Getting native mode is not free. Attaching an XDP program typically causes the driver to reconfigure and briefly reset the interface, so it is not a no-impact operation on a live box. `XDP_TX` and `XDP_REDIRECT` need transmit resources, so drivers commonly allocate additional TX queues when a program attaches — on a machine with a very high core count, that allocation can fail. Historically, native XDP also required the packet to fit in a single buffer, which put a ceiling on MTU and interacted badly with receive offloads; multi-buffer XDP, added in kernel 5.18, relaxes that, but only for drivers and programs that opt into it. So the correct reading of this incident is not "XDP is overhyped". It is that XDP's speed comes from *where* it runs, the mode determines where it runs, and the mode is a property of the driver, not of your program.
- If generic mode gives no performance benefit, why does the kernel implement it at all?For development and portability. It lets you write, load and functionally test an XDP program on any interface — a laptop NIC, a veth pair in CI — without hardware whose driver supports XDP. The verdicts behave identically, so the program's logic is exercised correctly; only the placement, and therefore the performance, differs.
- Why can attaching an XDP program briefly interrupt traffic on a live interface?Native attachment changes the driver's receive configuration, so most drivers tear down and re-establish their rings — effectively a link reset — and may also allocate extra TX queues to serve XDP_TX and XDP_REDIRECT. Treat attaching as a change to the interface, not as a transparent hot-patch, and schedule it accordingly.
- How would you verify, without a load generator, that a deployed program is actually in native mode across a fleet?Read the mode back per host rather than trusting the deploy command: `ip link show dev <iface>` reports the mode flag with the program id, and `bpftool net show` reports the same. Assert on that string in configuration management or a health check, since a fallback attach exits successfully and leaves no error behind.
saying these in an interview costs you the question
- Believing generic mode is just slightly slower
- Thinking the mode depends on the BPF program
- Trusting a successful attach to mean native mode
- Assuming every NIC driver supports XDP
- Expecting offloaded mode on an ordinary NIC