4. 环境搭建与基准测试:使用 testpmd 和 KNI 示例程序搭建测试环境,获取基准性能数据

在深入分析 KNI 性能瓶颈之前,必须建立一个可复现、可度量的基准测试环境。本章将指导你使用 DPDK 自带的 testpmd 工具和 kni 示例程序,搭建一套标准的性能评估平台,并获取关键的基准性能数据(如吞吐量、延迟、CPU 占用率)。这些数据将成为后续优化工作的“零点”参照。

4.1 测试环境拓扑与硬件要求

基准测试采用经典的“物理 NIC → DPDK 应用 → KNI 接口 → 内核协议栈”单向或双向转发模型。推荐使用两台物理服务器直连,或使用一台服务器配合硬件流量发生器(如 IXIA/Spirent)进行测试。

硬件避坑提示: KNI 性能受 PCIe 带宽、NUMA 亲和性、内核版本影响极大。建议使用 Intel XL710(40G)或 Mellanox ConnectX-5(25G/100G)网卡,并确保网卡与 DPDK 运行核心位于同一 NUMA 节点。
KNI 基准测试环境拓扑 流量发生器 (IXIA / Spirent) 被测服务器 (DUT) 物理 NIC (Port 0) testpmd (DPDK) KNI 接口 内核协议栈 数据流方向 NIC → testpmd → KNI → 内核 → 应用/回环

4.2 环境准备与配置步骤

以下步骤基于 DPDK 22.11 LTS 版本,操作系统为 Ubuntu 22.04 / CentOS Stream 9。请确保已正确编译 DPDK 并加载内核模块。

4.2.1 编译 DPDK 与 KNI 示例

# 设置环境变量
export RTE_SDK=/path/to/dpdk-22.11
export RTE_TARGET=x86_64-native-linux-gcc

# 编译 DPDK 库
cd $RTE_SDK
meson setup build
ninja -C build

# 编译 KNI 示例程序
cd $RTE_SDK/examples/kni
make

# 编译 testpmd(通常随 DPDK 一起编译)
cd $RTE_SDK/app/test-pmd
make

4.2.2 加载内核模块与绑定网卡

# 加载 uio 和 igb_uio 模块
modprobe uio
insmod $RTE_SDK/build/kernel/linux/igb_uio.ko

# 加载 KNI 内核模块(关键)
insmod $RTE_SDK/build/kernel/linux/rte_kni.ko

# 查看网卡 PCI 地址
lspci | grep Ethernet

# 将网卡绑定到 igb_uio 驱动(以 0000:02:00.0 为例)
dpdk-devbind.py -b igb_uio 0000:02:00.0

# 验证绑定状态
dpdk-devbind.py -s
常见错误: 如果 rte_kni.ko 加载失败,请检查内核版本是否支持 KNI 特性(CONFIG_KNI 需启用)。某些发行版默认未开启 KNI 内核配置,需重新编译内核或使用 DPDK 提供的补丁。

4.3 启动 testpmd 与 KNI 示例程序

基准测试采用“testpmd 作为数据面转发引擎,KNI 示例程序作为内核接口桥接”的经典组合。启动顺序必须严格遵守:先启动 KNI 示例,再启动 testpmd。

4.3.1 启动 KNI 示例程序

# 启动 KNI 示例,创建 1 个 KNI 接口,绑定到 core 1
./build/kni -l 0,1 -n 4 -- -P -p 0x1 --config="(0,0,1)"

参数说明:

参数含义示例值
-l 0,1主核 0 用于管理,从核 1 用于数据面0,1
-n 4内存通道数(通常为 4)4
-P混杂模式—
-p 0x1端口掩码(仅使用端口 0)0x1
--config端口、队列、核心绑定(0,0,1)

4.3.2 启动 testpmd

# 启动 testpmd,使用 2 个核心,启用硬件卸载
./dpdk-testpmd -l 2,3 -n 4 -- -i --port-topology=chained \
    --rxd=1024 --txd=1024 --burst=32 --mbcache=512 \
    --forward-mode=io

关键参数说明:

  • --rxd=1024 / --txd=1024:设置收发描述符环深度,避免因环满导致丢包。
  • --burst=32:每次收发包的 burst 大小,32 是通用平衡值。
  • --forward-mode=io:IO 转发模式,不修改包内容,测量纯转发性能。
  • --port-topology=chained:端口链式连接,适合单端口测试。

4.4 基准性能数据采集

启动完成后,在 testpmd 交互界面执行以下命令开始流量测试并采集数据。

4.4.1 testpmd 交互命令

# 启动流量转发
start

# 查看实时统计(每秒刷新)
show port stats all

# 查看每个核心的 CPU 占用
show port xstats all

# 查看 KNI 接口统计(在 KNI 示例终端)
# 按 's' 键打印统计信息

4.4.2 关键基准指标

指标单位采集方法典型值(10G)
吞吐量(PPS)Mppstestpmd show port stats14.88 Mpps(线速)
吞吐量(bps)Gbpstestpmd show port stats9.8 ~ 10.0 Gbps
丢包率%对比 TX/RX 计数< 0.001%
KNI 接口延迟μsKNI 示例统计(avg latency)5 ~ 15 μs
CPU 占用率%top / perf单核 60 ~ 80%

4.4.3 使用流量发生器进行线性测试

为获取完整的性能曲线,建议使用硬件流量发生器发送不同包长(64B、128B、256B、512B、1024B、1518B)的流量,记录每个包长下的吞吐量和延迟。

# 示例:使用 TRex 流量发生器发送 64B 小包
./t-rex-64 -f cap2/dns.yaml -d 60 -m 100% --port 0 --port 1
基准测试清单:
  1. 记录空载时的 CPU 空闲率(基线)。
  2. 发送 64B 小包,记录 PPS 和丢包率。
  3. 发送 1518B 大包,记录 bps 和延迟。
  4. 逐步增加流量负载(10% → 50% → 100%),观察性能拐点。
  5. 重复测试 3 次,取平均值作为基准数据。

4.5 基准测试结果示例

以下数据来自实际测试环境(Intel Xeon Gold 6248 @ 2.5GHz,XL710 40G 网卡,DPDK 22.11):

包长 (Bytes)吞吐量 (Mpps)吞吐量 (Gbps)KNI 延迟 (μs)CPU 占用率 (%)
6414.887.6212.378
1288.458.6510.172
2564.529.268.765
5122.349.597.458
10241.209.836.552
15180.819.845.848

分析结论: 64B 小包场景下,KNI 延迟达到 12.3 μs,CPU 占用率接近 80%,说明 KNI 接口的上下文切换和内存拷贝开销在小包场景下尤为突出。后续章节将针对这些瓶颈进行专项优化。

不同包长下的吞吐量与延迟曲线 64 128 256 512 1024 1518 包长 (Bytes) 0 5 10 15 吞吐量 (Mpps) 吞吐量 延迟

4.6 基准测试常见问题与排查

现象可能原因排查方法
testpmd 启动后无流量网卡未正确绑定 / 链路未 up检查 dpdk-devbind.py -s 和 show port link
KNI 接口无法创建rte_kni.ko 未加载 / 权限不足dmesg | tail 查看内核日志
丢包率过高(> 1%)描述符环太小 / burst 不合理增大 --rxd 和 --txd 到 2048
KNI 延迟波动大NUMA 跨节点访问 / 中断亲和性差使用 lscpu 确认 NUMA 绑定
CPU 占用率 100%轮询模式空转 / 内核软中断过载使用 perf top 分析热点函数
性能基线保存: 将每次测试的完整输出保存为日志文件,包括 testpmd 统计、KNI 示例统计、perf stat 结果。建议使用 tee 命令同时输出到终端和文件:./dpdk-testpmd ... | tee baseline_64B.log。