If you’ve followed my blog for a while, you know I love tinkering with packets and making them go fast in software. Today I'm releasing a new tool called wireblast, a blazingly fast network packet generator.
A few weeks ago, I wrote about go-afxdp, a small Go library I've been working on for sending and receiving Ethernet frames at line rate using AF_XDP, without DPDK and without leaving Go.
I was pretty happy with how it turned out. But a library is just a library; the real value is in how you use it. So the next question is, what can we build with it?
I have a few things cooking, all about fast packet forwarding on Linux. But to know whether a fast forwarding path is actually fast, you need to throw traffic at it. A lot of traffic! And you need to trust the numbers. So I built a packet generator. It’s called Wireblast.
The gap iperf leaves
For network performance testing, most of us reach for iperf3. I do too.
It’s easy, it’s everywhere, and if you want a quick answer to “How many gigabits per second can these two hosts push?”, it’s exactly the right tool.
But network performance isn’t only about bits per second. Packets per second matter just as much, especially when you’re testing routers, firewalls, load balancers, or anything else that has to do work for every packet.
That is where iperf starts to hit a wall.
Its traffic still travels through the Linux socket and networking stacks. A Linux host might process somewhere around a million packets per second per core, depending on the hardware and workload.
That sounds like a lot until you compare it with 10G line rate for 64-byte Ethernet frames: 14.88 million packets per second. And yeah, for 100G that's 148M pps. The kernel won’t even get close to that; you’re lucky if you reach 10% of it on a beefy box.
iperf3 is not going to get us anywhere near line rate. The kernel becomes the bottleneck long before the wire does.
So, if you want to quickly test whether two hosts can move a few gigabits per second, use iperf3. But if you want to know what the network path can really do with small packets, high packet rates, and lots of different flows, you need a different kind of tool.
Historically, that meant jumping to something like T-Rex, DPDK Pktgen, or a hardware tester such as Ixia. These are powerful tools and will happily saturate 100G, but now you’re dealing with DPDK, hugepages, special drivers, dedicated interfaces, lots of setup, and sometimes a purchase order.
There’s a pretty big gap between those worlds:
| Tool | Best for | Ceiling |
|---|---|---|
iperf3 | Quick host-to-host bandwidth tests | Limited by the kernel |
wireblast | Packet-rate, flow, and line-rate testing | Line rate |
| T-Rex, Pktgen, or Ixia | Advanced traffic generation and test suites | Line rate and beyond |
That middle row is the whole idea: something nearly as easy to use as iperf, but able to tell you what the network can actually do when packets per second, not just bits per second, become the limiting factor.
Meet Wireblast
Wireblast is a single, static, 14 MB Go binary. There’s no DPDK and no complicated setup. You download it, run it, and start sending (or receiving) packets.
Run it without arguments and you get a small interactive wizard. Or provide everything as command-line flags, which makes it easy to use from scripts and automated tests.
The code is available on GitHub, and the documentation is at wireblast.mintlify.site.
Under the hood, Wireblast uses AF_XDP to bypass most of the normal kernel networking path when transmitting packets. That makes it possible to reach very high packet rates: 14M pps on 10G hardware and 148M packets per second on 100G NICs.
Let’s send some packets
Grab the latest binary:
curl -sSL https://github.com/atoonk/wireblast/releases/latest/download/wireblast_linux_amd64.tar.gz \
| tar xz
sudo install -m 0755 wireblast /usr/local/bin/
wireblast --version
There’s an arm64 build too, or you can install it using Go:
go install github.com/atoonk/wireblast/cmd/wireblast@latest
Now let’s start with the hardest thing you can ask a NIC to do: tiny packets.
Small frames are the classic stress test because you’re bottlenecked on packets per second rather than bits per second.
sudo wireblast --start --yes -i eno2 --vlan 2043 \
--src-ip 192.168.43.1 \
--dst-ip 192.168.43.2 \
--dst-mac 7c:c2:55:be:f4:1b \
--packet-size 80 \
--flows 100 \
--pps unlimited -d 30sUDP is the default, so that’s the whole command. Of course you only need the vlan flag when running on tagged vlans.
On a 10G capable nic, that's 14.88 million packets per second: line rate for 10G, from a Go program using only a few CPU cores. I still think that’s kind of amazing.
IMIX and PCAP replay
Fixed-size packets are great for finding the ceiling, but real traffic contains a mix of packet sizes.
Wireblast includes the classic IMIX profile: a 7:4:1 ratio of 64-, 594-, and 1518-byte frames.
sudo wireblast -i eth1 \
--dst-ip 192.0.2.10 \
--mode imix \
--flows 64 \
--pps 200k \
--start
The 64 flows vary the source ports, which is useful when testing anything involving RSS, ECMP, link aggregation, load balancers, or connection tables.
You can also replay PCAP and PCAPNG files:
sudo wireblast -i eth1 \
--pcap capture.pcap \
--pps 100k \
--start
By default, Wireblast loops the capture at your requested rate. It can also reproduce the original packet timing:
sudo wireblast -i eth1 \
--pcap capture.pcap \
--pcap-timing original \
--pcap-loop=false
For automation, --no-tui skips the wizard and dashboard and prints plain-text statistics once per second:
sudo wireblast --no-tui \
-i eth1 \
--dst-ip 192.0.2.10 \
--pps unlimited \
-d 30s \
-y
[0:05] tx 74.4 M pkts 14.88 Mpps L1 10 Gbit/s L2 7.62 Gbit/s avg 64B
Everything is scriptable, and there isn’t much to learn.
Going big: 100G
10G is fun, but I had to know how far this thing would go.
So I put Wireblast on a pair of machines with 100G Mellanox ConnectX NICs using the mlx5 driver and let it rip. (By the way, I’ve been spending waaay too much money on Latitude.sh for this project, but I highly recommend them for renting bare-metal machines with a second NIC for network testing.)
Below is a test with 80 bytes packets. 98Gb/s at 122Mpps! nice!
That’s 99% of tagged line rate for minimum-size frames on a 100G link, from one Go binary. And it wasn’t limited to tiny packets:
| Frame size | Packets per second | L1 throughput |
|---|---|---|
| 68 B | 138.2 Mpps | 97.3 Gbit/s |
| 512 B | 23.0 Mpps | 98.0 Gbit/s |
| 1518 B | 8.0 Mpps | 98.5 Gbit/s |
| IMIX, approximately 362 B | 32.0 Mpps | 98.3 Gbit/s |
The queue-scaling results surprised me even more. With large frames, one queue already pushed 83 Gbit/s. Two queues nearly saturated the link.
You don’t need a monster machine. You need a decent NIC and a couple of CPU cores, which is a wild thing to be able to say about a software packet generator.
Where Wireblast fits
Wireblast is meant to cover the easy 80%. It is not trying to replace an Ixia.
It counts packets and bytes, but it does not measure latency or jitter, and it does not support hardware timestamping. Its TCP mode generates stateless SYN packets rather than complete TCP sessions.
That makes it useful for testing:
- Packet-forwarding performance
- Firewalls and ACLs
- Connection tables
- RSS and queue distribution
- ECMP Link aggregation
- Load balancers
- Packet-processing software
When I want to know, “Can this path do line rate, and does the far end see the packets?”, Wireblast answers that question in about 30 seconds.
Wrap-up
Building Wireblast was fun. More importantly, building it on top of go-afxdp was easy.
Claude Code also made building the TUI surprisingly quick. That’s a nice thing to be able to say about both the library and the current state of software development.
For years, software traffic generation meant choosing between an easy tool limited by the normal kernel path and a powerful tool that pulled you into DPDK, out dated howto's and specialized test setups.
Wireblast is the middle ground I wanted: download one binary, point it at an interface, and start sending packets at line rate.
No hugepages. No NIC surgery. No DPDK expertise required. And let’s be real: what’s more fun than sending packets at line rate?
Fourteen million packets per second on a normal 10G box. More than 100 million packets per second on a 100G NIC. All from one command, with almost no setup required. Pretty amazing!
Next up, now that I have a reliable traffic generator, I want to get back to the project that started all of this: a completely Go-based dataplane that bypasses the kernel for routing, switching, and firewalling.
Now I finally have a good way to measure it. Stay tuned!
The code is on GitHub, the documentation is at wireblast.mintlify.site, and it’s all built on go-afxdp.
That’s it :) you made it to the end. Thanks for reading!
Cheers,
Andree