4. pktgen 工具介绍:原理、加载、接口与核心参数

pktgen 是 Linux 内核内置的高性能数据包生成器,专为内核网络协议栈的极限压测设计。它运行在内核态,绕过用户态协议栈的开销,能够以接近线速的速率发送数据包,是评估网卡驱动、软中断处理、路由转发和 netfilter 等内核模块性能的首选工具。

适用场景: 网卡吞吐量极限测试、多队列 RSS 均衡性验证、XDP/DPDK 对比基准、内核协议栈转发性能(PPS)评估。

4.1 pktgen 工作原理

pktgen 作为内核线程运行,每个 CPU 可以绑定一个 kpktgend 线程。线程从预配置的设备列表读取发包参数,直接构造二层/三层帧头,通过 dev_queue_xmit() 将数据包注入驱动层,完全绕过 socket 层和 TCP/IP 协议栈的复杂处理路径。

pktgen 内核发包路径 用户态配置 /proc/net/pktgen/* kpktgend 线程 每 CPU 一个内核线程 pktgen 构造帧 L2/L3 头 + 载荷 dev_queue_xmit() 直接注入驱动层 网卡硬件 关键设计要点 • 完全绕过 socket 层和 TCP/IP 协议栈 • 内核线程直接构造数据帧,零用户态拷贝 • 支持多 CPU 并行发包,线性扩展 PPS • 可精确控制包大小、速率、MAC/IP 范围 性能优势 • 单核可达数百万 PPS(视 CPU 频率和网卡而定) • 多核线性扩展,适合 NUMA 亲和性测试 • 最小包(64B)压测最能暴露驱动/软中断瓶颈

4.2 内核模块加载

pktgen 以内核模块形式存在,默认不加载。使用前需要手动插入模块,或编译进内核(CONFIG_NET_PKTGEN=y)。

# 加载 pktgen 内核模块
modprobe pktgen

# 验证模块是否加载成功
lsmod | grep pktgen

# 查看内核线程是否启动(每个 CPU 一个)
ps aux | grep kpktgend

加载成功后,系统会出现 /proc/net/pktgen 目录,这是 pktgen 唯一的用户态控制接口。

注意事项: 在虚拟化环境(如 VMware、VirtualBox)中,pktgen 可能无法达到线速,因为虚拟网卡驱动和宿主机调度会引入额外开销。建议在物理机或具备 SR-IOV 直通的环境中进行性能测试。

4.3 用户态接口:/proc/net/pktgen

pktgen 通过 /proc/net/pktgen 下的虚拟文件与用户态交互,采用“写配置、读统计”的模型。核心文件包括:

文件路径 类型 作用
/proc/net/pktgen/pgctrl 控制 写入 start / stop / reset 控制整个测试流程
/proc/net/pktgen/kpktgend_X 线程 每个 CPU 对应一个,写入 add_device eth0 绑定发包设备
/proc/net/pktgen/eth0 设备 写入发包参数(包大小、速率、源/目的 IP 等),读取统计结果

典型配置流程:

  1. 重置所有配置: echo reset > /proc/net/pktgen/pgctrl
  2. 绑定设备到线程: echo add_device eth0 > /proc/net/pktgen/kpktgend_0
  3. 配置发包参数: 向 /proc/net/pktgen/eth0 写入参数
  4. 启动测试: echo start > /proc/net/pktgen/pgctrl
  5. 读取统计: cat /proc/net/pktgen/eth0
/proc/net/pktgen 接口交互流程 用户态脚本 pgctrl kpktgend_X eth0 (设备) pktgen 内核 kpktgend 线程 网卡驱动 配置流向:用户态 → proc 文件 → 内核模块 → 线程 → 驱动;统计信息反向读取

4.4 核心参数解析

设备文件(如 /proc/net/pktgen/eth0)支持数十个参数,以下是最常用的核心参数:

参数名 类型 示例值 说明
pkt_size 整数 64 数据包大小(字节),包含 MAC 头(14B)和 CRC(4B)
count 整数 1000000 发送包总数,0 表示无限发送
clone_skb 整数 1000 skb 克隆次数,减少内存分配开销,提升 PPS
dst_ip IP 192.168.1.2 目的 IP 地址,支持 @ 分隔的递增范围
src_ip IP 192.168.1.1 源 IP 地址,支持递增范围
dst_mac MAC 00:11:22:33:44:55 目的 MAC 地址,必须与下一跳网关或对端一致
udp_src_min 端口 1024 UDP 源端口最小值,配合 udp_src_max 实现端口范围
udp_dst_min 端口 9 UDP 目的端口最小值(默认 9 = discard 端口)
rate 字符串 100m 限速,支持 100m(Mbps)、10g(Gbps)
delay 整数 0 包间延迟(纳秒),用于精确控速

4.5 完整配置示例

以下是一个完整的 pktgen 配置脚本,演示如何对 eth0 进行 64 字节小包压测:

#!/bin/bash
# pktgen 配置示例:64B 小包压测

PGCTRL=/proc/net/pktgen/pgctrl
DEV=eth0

# 1. 重置
echo reset > $PGCTRL

# 2. 绑定设备到 CPU0
echo add_device $DEV > /proc/net/pktgen/kpktgend_0

# 3. 配置设备参数
echo pkt_size 64 > /proc/net/pktgen/$DEV
echo count 10000000 > /proc/net/pktgen/$DEV
echo clone_skb 1000 > /proc/net/pktgen/$DEV
echo dst_ip 192.168.1.2 > /proc/net/pktgen/$DEV
echo src_ip 192.168.1.1 > /proc/net/pktgen/$DEV
echo dst_mac 00:11:22:33:44:55 > /proc/net/pktgen/$DEV
echo udp_dst_min 9 > /proc/net/pktgen/$DEV

# 4. 启动
echo start > $PGCTRL

# 5. 等待完成
sleep 10

# 6. 查看统计
cat /proc/net/pktgen/$DEV | grep -E "pps|pkts"
性能调优提示: 使用 clone_skb 参数可以显著提升 PPS。当 clone_skb=0 时,每个包都分配新 skb,内存分配成为瓶颈;设置为 1000 以上时,skb 被复用,PPS 可提升 3-5 倍。但注意,clone 模式不支持修改包内容,适用于纯吞吐测试。

4.6 统计输出解读

测试完成后,读取设备文件可获取详细统计信息。关键字段如下:

统计字段 含义 示例值
pkts_sent 已发送包总数 10000000
pkts_dropped 驱动层丢弃的包数(通常为 0) 0
result 测试结果状态 OK: 10000000(c000000+d0)
pps 每秒发包数(关键性能指标) 1488095
mbps 吞吐量(Mbps) 761
pktgen 统计输出示例 cat /proc/net/pktgen/eth0 Params: count=10000000 pkt_size=64 clone_skb=1000 dst_ip=192.168.1.2 src_ip=192.168.1.1 dst_mac=00:11:22:33:44:55 Result: OK: 10000000(c10000000+d0) pps: 1488095 mbps: 761
关键指标解读: 64 字节小包下,1Gbps 网卡的理论极限约为 1.488 Mpps(百万包/秒)。如果实测 PPS 远低于此值,说明 CPU 软中断或驱动存在瓶颈。pktgen 的 pps 字段直接反映内核协议栈的包处理能力,是衡量网络性能的核心指标。