资讯中心

DPDK Testpmd实战:最小命令、性能压测与避坑指南

📅 2026/9/29 15:45:34
DPDK Testpmd实战:最小命令、性能压测与避坑指南
简介一份面向互联网与网络数据面开发者的应用指南围绕 DPDK 自带 testpmd 示例程序展开testpmd 既能用于包转发模式下的性能测试也能访问 Flow Director 等 NIC 硬件特性同时也是基于 DPDK SDK 构建更完整应用时的参考样板。压缩包内为单份 PDF 文档大小仅 137KB已有 599 人学习。文档先从编译流程讲起说明如何用 make、gcc 等工具并配合 -m64 等选项指定目标平台与架构随后介绍 EAL 与 testpmd 的命令行选项帮助读者指定 NIC 接口、包转发模式和 Flow Director 等运行参数并理解 DPDK 在数据包处理中的基本机制。运行时函数部分按功能模块梳理了帮助、控制、显示、配置、端口、链路绑定、寄存器与过滤器等常用操作基本覆盖日常性能测试、NIC 特性验证与调试场景内容预览还显示文档包含 Introduction、Overview、Compiling、Running、Runtime Functions 等章节结构清晰便于按需查阅。对希望掌握 DPDK 包转发流程、NIC 配置方法并快速上手 testpmd 的读者来说这份指南提供了从编译到运行的完整路径能帮助理解 EAL、Packet Framework 与 NIC Poll Mode Driver 的协作方式适合入门与进阶参考。1. DPDK Testpmd 应用先弄清它在真实开发里解决什么问题在 DPDK 的中文技术社区里Testpmd 可能是命令行被复制最多、解释最少的一个应用。捧着《DPDK Testpmd 应用》这类 PDF 从头翻到尾你会发现它更像一本参数字典一大堆命令行选项、转发模式、端口操作命令却没有告诉你第一步该敲哪条命令。它的真实角色其实是网卡驱动和转发路径的“试金石”验证 PMD 驱动能不能稳定收包压一压单核能跑多少 Mpps看看多队列 RSS 是否把流量均匀分发。适合做 DPDK 驱动开发、NFV 转发面、OVS-DPDK 调优的人也适合刚把环境编译好、想确认硬件没有白买的初学者。接下来这篇实战笔记会从跑通最小命令一路讲到性能压测和踩坑把 Testpmd 最有用的那部分落到键盘上。2. 用最小命令跑通 Testpmd先让它把包转起来2.1 一条能转发报文的启动命令第一次接触 Testpmd 的人最好先忘掉“背参数”这件事直接把下面这条命令粘到终端里。前提是你已经把网卡用dpdk-devbind.py绑到vfio-pci或igb_uio驱动并且分配了足够的大页内存。dpdk-testpmd -l 0-1 --huge-dir /dev/hugepages -n 2 \ -a 0000:01:00.0 \ -- -i --portmask0x1 --rxd1024 --txd1024 --burst64这条命令的意图是用 CPU 0 和 CPU 1 两个逻辑核跑 Testpmd从/dev/hugepages目录取大页内存假定主板有 2 个内存通道并只操作 PCI 地址为0000:01:00.0的那块网卡。--后面是 Testpmd 自己的参数-i表示进入交互模式这样你在启动后不会直接转发而是先停在控制台前输入start才真正开始收发包。参数这里拆开说一下。-l 0-1建议你选两个不超频、不被打扰的核必要时用-l指定核而不是让 DPDK 自己乱挑。-n 2是内存通道数一般可以从 BIOS 或dmidecode查填错了顶多性能差点不会报错。--rxd和--txd是收发描述符环的大小默认很多时候只有 256对 10G 网卡来说容易丢包设成 1024 或 2048 更稳。--burst64是每次从网卡取包的最大数量这个值决定了收包引擎分批次处理的粒度64 是一个对延迟和吞吐都相对平衡的默认值。2.2 端口、核和内存池的选型逻辑Testpmd 启动时会创建若干个内存池默认情况下一个收一个发。内存池的 block size 来自启动参数--mbuf-size默认是 2048 字节刚好覆盖一个标准 MTU 报文加头部和分片需要的空间。如果你们的报文带 VXLAN 或者更大的 metadata建议改大否则收包阶段就会因为 mbuf 不够放而丢包。关于核的用法-l指定的是 DPDK EAL 可以使用的逻辑核不是让你一个核给收、一个核给发。Testpmd 的线程模型是“一个转发核同时跑收和发”所以你通常会看到--nb-cores这个参数而不是让用户手动把一对端口塞给某个线程。最常见做法是dpdk-testpmd -l 0-15 --huge-dir /dev/hugepages -n 4 \ -a 0000:01:00.0 -a 0000:01:00.1 \ -- -i --nb-cores8 --rxq8 --txq8--nb-cores8决定 Testpmd 启用多少个转发线程每个线程挂在不同的核上。--rxq和--txq是端口队列数队列数和转发线程数不强制一致由 Testpmd 自动分配。这里我们分配 8 个线程、8 个队列如果 RSS 配置正确每个核各占一个队列不会出现多个核抢同一个队列的锁竞争。内存池数量也值得注意。Testpmd 内部经常出现allocation of mbuf pool失败的报错原因往往是--mbuf-size改得太大导致 sum of all requests 超过大页内存。我一般会保持默认--mbuf-cache32只在报文变大时调整--mbuf-size而不是去动 cache。cache 太小会让每个核频繁回写全局 list影响吞吐太大又会多占内存。2.3 为什么默认是 io forwardingmac forwarding 又差在哪默认转发模式是iofwd它只做一件事从某端口收原封不动从另一个端口或同一个端口发出去不改 MAC、不改 IP。这种模式非常适合测收发包引擎纯净吞吐。另一常见模式是macfwd它会改写目的 MAC 再转发模拟真实二层交换机的转发路径。两者在 Testpmd 命令行里几乎没有性能差但macfwd要对每个报文做一次头部修改开销略高一点点做性能对标时必须写清楚用的是哪个模式。如果你想模拟跨网段或者三层转发还可以用flow模板但生产环境里大家一般不会让 Testpmd 做复杂流表匹配测试那些都交给硬件卸载或更高层的转发应用。Testpmd 的价值在于把底层报文的走向看得清清楚楚set fwd mac start show port stats all上面这组命令把转发模式切成 mac 转发并启动接着打印所有端口的收发统计。统计里有rx-packets、tx-packets、rx-dropped和tx-dropped。测试互连时对端如果没收到包先看rx-packets是在涨还是停在 0这是最简单的一层定位。注意set fwd mac只改转发引擎类型不需要重启端口。2.4 打通环回的三种做法支持 loopback 的网卡可以加--port-topologyloopback让单个端口自发自收适合没有双端口设备的调试场景。命令如下dpdk-testpmd -l 0-1 -a 0000:01:00.0 \ -- -i --port-topologyloopback --forward-modeio链路如果没起来先执行set link up port 0再看show port info 0里的link status。另一种场景是端口不支持硬件 loopback那就必须用一根双口网卡把两个端口用光纤或网线环起来--port-topologychained对这种情况尤其好用它允许一个转发核连续处理多个端口。区别在于 chained 拓扑下每个核依次服务所有端口而 paired 是固定成对转发吞吐性能差异在高端多口网卡上能看出来。3. 用 Testpmd 做性能压测吞吐、时延与丢包的正确读法3.1 吞吐测试的典型步骤外部打流加 iofwdTestpmd 本身不是一个完整流量发生器所以测吞吐最可靠的做法是被测设备装 Testpmd测试仪从外部向端口打流Testpmd 转发测试仪读回数据。这样得到的是整条路径有没有丢包。启动参数建议按前面推荐来--rxd2048 --txd2048 --burst64 --nb-cores2 --rxq2 --txq2。dpdk-testpmd -l 4-5 --huge-dir /dev/hugepages -n 2 \ -a 0000:af:00.0 -a 0000:af:00.1 \ -- -i --rxd2048 --txd2048 --burst64 \ --rxq2 --txq2 --forward-modeio进入交互界面后按照测试计划先把端口状态拉起来再启动转发port stop all set link up port 0 set link up port 1 start show port stats all外部打流的速率建议从线速的 50% 开始逐步加到一个包长下刚好不丢的速率再用 Testpmd 的set burst 128之类调整 batch 大小看是否影响转发吞吐。官方文档里经常出现 Mpps 这个单位我更习惯直接看 Testpmd 输出的rx-packets与tx-packets两者之差就是被转丢的包数。丢包率不能拿测试仪一个端口的发包数去对最好以 Testpmd 收到的包数为基准这样能把入口丢包也算进去。3.2 txonly 和 rxonly用一块网卡也能做单方向压力没有测试仪时可以用 Testpmd 的txonly模式生成高速无意义 UDP 包直接把数据从端口发出去。配合对端用rxonly或者另一台机器的 Testpmd 收包就能测出单纯的发送能力。用法很简单set fwd txonly set txpkts 64 startset txpkts 64把生成的报文大小固定成 64 字节这是以太网最小帧长能把转发资源推到极限。测试完成后stop再用show port stats all看tx-packets。注意txonly模式下rx-packets通常仍是 0它不会处理入向流量所以不要拿 rx 统计去判断发送吞吐。反过来rxonly只负责从网卡收包并直接丢进 mbuf 池不转发。它可以和外部打流设备配合测出网卡驱动在纯接收模式下能收到多少包同时不会因为转发环上的 CPU 瓶颈掩盖接收瓶颈。两次测试一个收一个发也能定位性能瓶颈是出在收方向还是发方向。3.3 多队列和 RSS压测配置要和生产一致在正式性能验证里只开单队列跑 Testpmd 没有参考意义因为生产环境的 OVS-DPDK 或 VPP 都是多队列加 RSS。Testpmd 支持运行时配置 RSS我一般会这么操作port config rss all ipv4 show port rss all set fwd io start用port config rss all ipv4对所有端口开启 IPv4 哈希。测试前务必用show port rss all确认哈希类型真的写进去了否则流量可能因为哈希函数默认只看外层 MAC 而全部押到一个队列。很多人压测时遇到“流量全部在核 0 上空转其他核看着”十有八九是 RSS 没开或者哈希字段选错了。观察各队列计数可以用show port xstats all里面能看到rx_q0_packets、rx_q1_packets这样的登记项确认是否均匀。不均匀的原因很多测试流的五元组不够随机、哈希种子偏了、多队列下队列数量不是 2 的幂导致取模不均匀。这些都是踩过坑之后才会下意识去检查的项。3.4 结果记录参数要完整结论才有可比性Testpmd 的压测结果很难复现最常翻车的原因是记录参数太随意。一个可交付报告里至少要包含网卡型号和固件版本、驱动名称和 DPDK 版本、绑定模式vfio-pci/igb_uio、大页配置、CPU 型号和核绑定、内存通道数、端口数和拓扑、rxd/txd、burst、队列数、转发模式、报文长度、打流速率、持续时间、观察到的丢包率。用表格式记录会直观很多项目测试配置DPDK 版本22.11网卡Intel E810 / Mellanox ConnectX-6驱动绑定vfio-pci核 / 队列8 核 / 8 队列rxq / txq 描述符2048 / 2048转发模式iofwd报文长度64B / 1500B吞吐14.1 Mpps64B原始日志要保留不只看截图。Testpmd 退出时通常会在 stdout 打印一段简短的统计用重定向存成文件后续才能定位是哪个参数变了导致性能下降。4. Testpmd 控制台交互跑测试时这些命令能省一半时间4.1 最有价值的 show 命令Testpmd 的控制台比很多人想象的强得多。你不需要每改一个参数就重启进程大量动作都在运行中完成。先记住这组showshow port info all show port stats all show port xstats all show port rss allshow port info all看硬件状态和链路show port stats all看累计收发和丢包show port xstats all看每个队列单独的计数是排查 RSS 是否均匀的关键show port rss all看哈希配置。如果你在跑长时间稳定性测试想确认进程没有卡死连续执行两次show port stats all计数在增长就说明数据路径还活着。4.2 运行中调参的命令转发过程中可以调整的参数分成三类端口状态、转发引擎参数、队列配置。端口状态用port stop all/port start all控制链路状态用set link up/down port N。转发引擎参数像set fwd切模式set burst N调 batchset txpkts改发包长度。队列配置比较麻烦Testpmd 不允许运行中直接改已经启用的 rxq/txq 数量常见做法是先停掉端口再改队列数最后重新启动port stop all port config rxq all 8 port config txq all 8 port config rss all ipv4 port start all start这段操作的意义是验证多队列切换后 RSS 仍然生效。注意port config rxq之后队列数变了但转发核数量没有变Testpmd 会自动重新分配队列到核最好用show cfg看一眼分配结果避免某个核背了多条队列而另一个核闲着。4.3 用-f文件加大外层脚本组合成批处理如果测试经常重复手工敲命令就很浪费。Testpmd 支持用-f参数接一个命令文件文件里每一行就是一条交互命令启动后会顺序执行。先写一个只做配置和启动的文件tp_start.txtport stop all set fwd io set burst 64 port config rss all ipv4 port start all start再用 FIFO 配合 bash 控制时序mkfifo /tmp/tp_cmd dpdk-testpmd -l 0-1 --huge-dir /dev/hugepages -n 2 \ -a 0000:01:00.0 -- -i -f tp_start.txt /tmp/tp_cmd TP_PID$! exec 3/tmp/tp_cmd sleep 10 echo show port stats all 3 echo stop 3 echo quit 3 wait $TP_PID-f负责把配置和启动动作固化sleep 10控制实际转发时间后续命令通过 FIFO 发给 Testpmd 的 stdin。这种方式比“人盯着终端回车”可靠尤其适合放回 CI 里做冒烟测试。注意 FIFO 需要在写之前先打开读端否则进程会卡在 open 上这就是很多脚本“看起来没反应”的原因。5. Testpmd 实战避坑5 个反复出现的疑难问题5.1 启动报 EAL 内存分配失败现象不管怎么调--mbuf-size都出现EAL: No memory available或者hugepages not enough进程直接退出。原因大页内存根本没准备好。多数情况下是/dev/hugepages没有挂载或者vm.nr_hugepages设置得比网卡需要的还少。解决先看/proc/meminfo里的HugePages_Free如果是 0用sysctl vm.nr_hugepages1024并挂载 hugetlbfs。再启动 Testpmd指定--huge-dir /dev/hugepages。如果还不行检查双路台机上每个 socket 是否都分配了大页DPDK 默认优先在本 socket 用页需要--socket-mem显式指定两个节点的内存大小。5.2 绑定 vfio-pci 时提示操作不允许现象用dpdk-devbind.py绑定网卡到vfio-pci时出现cannot open /dev/vfio/vfio或者operation not permitted。原因用户空间进程没有访问 vfio 设备的权限或者是 IOMMU 被 BIOS 或内核参数关掉了。解决确认内核已经加载vfio_pci模块启动参数里有iommupt。把当前用户加入vfio组或者临时用chmod 666 /dev/vfio/vfio验证权限问题。绑定完后再用dpdk-devbind.py -s看驱动列确认已经从ixgbe/i40e换成vfio-pci再启动 Testpmd。5.3 Testpmd 收到了包转发出去却是 0现象show port stats all里rx-packets一直在涨tx-packets停在 0或者两个口数据对调。原因用的端口对和实际接线不一致或者forward-modeio时端口编号让 Testpmd 认为两个端口不成对常见于多端口网卡和 NUMA 节点不匹配。解决用show port info all确认链路状态再对照物理网口的 PCIe 接口编号把命令里的--portmask改成实际要用的前端口。转发前建议先用set fwd mac让 Testpmd 改写目的 MAC这样对端如果也在同一个广播域里能看到报文到底是从哪张卡出来的方便手工定位。5.4 多队列下流量全挤到一个核现象show port xstats all里rx_q0_packets是大头其他队列几乎为零转发吞吐一直上不去。原因RSS 没有打开或者哈希字段没有覆盖报文的五元组。还有一种可能是启动时没有设置--rxq8Testpmd 默认只有 1 个队列RSS 再开也只有 1 个队列可用。解决先看show port rss all执行port config rss all ipv4并确认哈希字段有值。再把队列数量改成核数port stop all、port config rxq all 8、port start all。如果还是不平均检查打流工具是不是只用了同一组源目 IP五元组不随机哈希当然均匀不了。5.5 交互终端被刷屏命令输不进去现象Testpmd 运行中每隔一秒打印一堆计数器你在控制台敲的命令被刷得几乎看不见。原因启动参数里带了--stats-period且设得很小或者 Testpmd 内部启用了set verbose 2之类的调试输出。解决不想看刷屏就去掉--stats-period或者临时用set verbose 0关掉详细打印。需要周期统计时把--stats-period设成 60 秒以上并把日志重定向到文件交互只保留一个干净的控制台。还有一点如果用-f脚本脚本里也别写太频繁的show port stats all否则一样会有刷屏效果。6. 把 Testpmd 用得更顺手脚本化、结果校验和一劳永逸的日志习惯做网卡驱动或转发面开发最怕的就是换了一版代码吞吐数字到底有没有变化说不清楚。我现在会把 Testpmd 装进一个带参数的封装脚本里一次性跑多种报文长度并把每次的原始输出留下来。#!/bin/bash for pkt in 64 256 1024 1500; do logresult_${pkt}.log cat tp_cfg.txt EOF set fwd txonly set txpkts ${pkt} start EOF timeout 10 dpdk-testpmd -l 0-1 --huge-dir /dev/hugepages -n 2 \ -a 0000:01:00.0 -- -i -f tp_cfg.txt $log 21 grep -E Tx-packets|Tx-pps|rx-packets $log | tail -3 result_summary.txt donecat生成配置文件timeout控制每个包长的运行时间这样每次跑 10 秒后自动退出统计输出全部落盘不会因为 CtrlC 丢掉最后一段结果。脚本里写的txonly适合验证发送路径如果要测完整转发只需要把配置文件里的set fwd txonly换成set fwd io再把打流器从外部送流量进来即可。结果校验我习惯用“对账”方式。比如两个端口直接光纤环回启动 Testpmd 后记录rx-packets和tx-packets如果两边数字在一个合理的偏差范围内说明驱动和队列配置没有吞包。真正的交叉验证是端到端一个端口抓外部流量另一个端口跑 Testpmd在外部抓包工具里过滤源 MAC看是否每条进来的数据都被原样发出。DPDK 进程绕过内核所以 tcpdump 在 Testpmd 接管网卡上是抓不到包的千万不要用在内核抓包的结果去推断 Testpmd 丢没丢。日志习惯是我最想提醒你的一件事。每次跑 Testpmd 前把命令行、DPDK 版本、网卡固件、大页配置先写进文件名或者日志第一行。不要只存一份结果截图否则两周后对比数据时你会连某个参数到底是谁改的都说不清。我吃过这个亏现在所有测试机上都保留一份testpmd_env.sh每次跑之前自动把环境信息拼进日志头。希望帮到你。本文还有配套的精品资源点击获取

看完文章,想为自己的企业也做一次专业网站诊断?

尧图顾问免费为您评估现有网站,并给出建站/改版建议与报价方案。

免费获取方案