Skip to main content
Short version: on a 100G Mellanox link, Wireblast fills the pipe at every frame size, from 1518-byte frames down to the smallest tagged frame there is. All the numbers on this page are measured, not modelled. Every one is a real run you can reproduce.

The test rig

Two identical boxes back to back, one sending and one receiving.

Line rate at every frame size

Each row is an unlimited-rate run held for 12 seconds. L1 is link utilisation, so ~98 Gbit/s L1 is a full 100G link once you account for the preamble, start-frame delimiter and interframe gap that the wire carries but the frame doesn’t. The small-frame number is the one that matters, because small frames are the hardest thing a NIC does. 138 million packets a second of 68-byte frames is 97% of tagged line rate, from a single process.
68 bytes, not 64, because these frames are VLAN-tagged and a tagged frame can’t be smaller than 68. On an untagged link the smallest frame is 64 bytes and the packet rate is correspondingly a touch higher. See reading the numbers.

It doesn’t take many cores

Queue count is your parallelism budget, and it turns out you don’t need much of it. Same 1518-byte frames, unlimited rate, varying the queue count: A single queue already does 83 Gbit/s. Two queues nearly saturate 100G. This is what zero-copy native XDP buys you: the NIC reads the frames straight out of the UMEM, so there’s very little per-packet work left for the CPU to do.

The receive side is real too

Sending is only half a test. Running a receiver on the far end, 1518-byte frames at 8 Mpps:
Every packet accounted for. Lossless at 8 Mpps through a real switch fabric.
High-rate receive needs many flows. A single flow is one 5-tuple, which the NIC steers to one receive queue, which is one core. That core tops out around 7 Mpps here, so a single-flow 138 Mpps blast overruns it and most frames are dropped in hardware before Wireblast ever sees them.The fix is flows: --flows 1000 spreads the traffic across receive queues so the work parallelises. This is a property of how NICs steer traffic, not of Wireblast, and it’s the same reason real high-rate capture setups fan out across queues.

The attach is quick on Mellanox

The link bounce that native XDP causes depends entirely on the driver. On this mlx5 NIC it’s barely there:
For comparison, a 10G Intel ixgbe NIC takes 8 to 11 seconds for the same thing. Either way the run clock doesn’t start until the link is back, and reruns reuse the attachment. See how it works.

For reference: 10 Gigabit

Not everyone has a 100G rig. On a 10G Intel ixgbe link, Wireblast saturates the pipe at every size too, and the aggregate rate limiter holds steady regardless of queue count. Measured at --pps 1M: You can reproduce the shape of any of this on a veth pair with no NIC at all, at whatever rate your CPU manages. See the namespace lab.

Reproducing these numbers

Nothing here is special-cased. The frame-size sweep is just this, once per size:
The queue sweep adds --queues N. The receive side is a plain receiver. Runnable versions are in the examples directory.

Why it’s fast

None of this is Wireblast being clever. The speed comes from AF_XDP and the zero-copy path, which live in go-afxdp, the library Wireblast is built on. Wireblast’s job is to make that reachable without knowing any of it. If you want to build your own line-rate tool in Go, go-afxdp is the foundation.