When benchmarking high-bandwidth 10GbE, 25GbE, or 100GbE network interfaces, traditional user-space traffic generators (such as iperf3 or netperf) often bottleneck on CPU interrupt handling, user-to-kernel context switches, and socket buffer copies long before saturating physical wire capacity. To evaluate raw network interface card (NIC) throughput, packet-per-second (PPS) limits, and kernel packet scheduler performance, the Linux kernel includes a built-in packet generator module: pktgen. Operating directly within kernel thread space, pktgen can saturate multi-gigabit links with millions of packets per second.
Understanding the In-Kernel pktgen Architecture
The pktgen framework runs as an in-kernel module (net/core/pktgen.c). Rather than relying on traditional Berkeley sockets, it communicates directly with kernel device drivers (such as ixgbe, i40e, or mlx5_core):
- Zero Context Switching: Packets are generated and submitted to device transmission ring buffers directly inside kernel space.
- Multi-Threaded Scaling: Kernel threads (
kpktgend_X) can be pinned to individual CPU cores, allowing linear throughput scaling across modern multi-core processors. - Control via procfs: All runtime configuration (packet size, target MAC/IP, rate throttling, and packet counts) is managed through standard shell interaction with the
/proc/net/pktgen/virtual directory.
Loading the pktgen Kernel Module
Before configuring traffic streams, load the module into the active kernel:
sudo modprobe pktgen
Verify that the procfs control interface is mounted:
ls -l /proc/net/pktgen/
You will observe:
kpktgend_X: One thread control entry for each available logical CPU core (e.g.,kpktgend_0,kpktgend_1).pgctrl: The master control interface used to start, pause, and stop packet generation.
Configuring an In-Kernel Packet Generation Thread
To configure a packet generation run on interface eth0 pinned to CPU core 0:
First, associate the physical device with the kernel thread:
echo "rem_device_all" | sudo tee /proc/net/pktgen/kpktgend_0
echo "add_device eth0" | sudo tee /proc/net/pktgen/kpktgend_0
This creates a dedicated device control handle at /proc/net/pktgen/eth0.
Next, configure the packet parameters (destination IP, destination MAC, packet size, and packet count):
# Set packet count (0 indicates continuous transmission until manually stopped)
echo "count 10000000" | sudo tee /proc/net/pktgen/eth0
# Set packet payload size (64 bytes for maximum packet-per-second stress testing)
echo "pkt_size 64" | sudo tee /proc/net/pktgen/eth0
# Configure destination IP and MAC addresses
echo "dst 192.168.10.50" | sudo tee /proc/net/pktgen/eth0
echo "dst_mac 00:1B:21:BA:81:42" | sudo tee /proc/net/pktgen/eth0
# Set source IP and delay
echo "src_min 192.168.10.10" | sudo tee /proc/net/pktgen/eth0
echo "delay 0" | sudo tee /proc/net/pktgen/eth0
Starting and Monitoring the Packet Stream
Once parameters are defined, trigger packet generation by sending start to the master controller:
echo "start" | sudo tee /proc/net/pktgen/pgctrl
While the test is executing, inspect live transmission telemetry and wire statistics by reading the interface status file:
cat /proc/net/pktgen/eth0
The output reports granular kernel statistics:
Params: count 10000000 min_pkt_size: 64 max_pkt_size: 64
frags: 0 delay: 0 clone_skb: 0 ifname: eth0
flows: 0 flowlen: 0
dst_min: 192.168.10.50 dst_max:
src_min: 192.168.10.10 src_max:
dst_mac: 00:1B:21:BA:81:42
Result: OK: 10000000(c9999820+d180) usec, 10000000 (64byte,0frags)
14285714pps 7314Mb/sec (7314285568bps) errors: 0
The summary provides:
- PPS (Packets Per Second): Here, 14.28 million packets per second.
- Mb/sec: Instantaneous wire throughput achieved without dropping packets.
- Errors: Driver ring buffer drops or transmit queue overruns.
Stopping the Benchmark and Unloading the Driver
To halt an active packet generation test:
echo "stop" | sudo tee /proc/net/pktgen/pgctrl
To remove the interface binding and reset the kernel threads:
echo "rem_device_all" | sudo tee /proc/net/pktgen/kpktgend_0
When testing is concluded, unload the kernel module to restore standard system state:
sudo modprobe -r pktgen