ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

DPDK环境搭建与qnsm抓包工具部署完全指南

DPDK环境搭建与qnsm抓包工具部署完全指南 简介面向网络安全监控与流量分析场景的QNSMDPDK安装文档适合需要部署旁路全流量监控引擎的运维、安全工程师及二次开发人员。文档基于CentOS 7.2/7.6/7.7环境首先阐明为什么选择QNSM——针对Suricata在RSS多队列下易导致数据包乱序与丢包的问题QNSM依托DPDK对称哈希模式可有效规避并深入解析QNSM的DDOS检测、IDPS模块、流水线架构等核心机制。随后逐步讲解依赖包安装、系统配置以及安装过程中的常见踩坑与解决方案如虚拟网卡不支持RSS key update/RETA update时报PANIC的处理以及内核版本需保持3.10.0等注意事项。资源共1个doc文件约14.74MB内容层级清晰从背景原理到实操排错均有覆盖便于按文档顺序完成部署。已有238人学习适合作为QNSMDPDK从入门到实际部署的参考手册。1. qnsm 是什么为什么它比 tcpdump 更依赖 DPDKqnsm 是一个基于 DPDK 的轻量级流量采集工具仓库路径是 iqi/qnsm。看到这个标题你大概和我当初一样先冒出一个问题抓包有 tcpdump为什么还要再装一套 DPDK答案在量级上。普通服务器用 tcpdump 抓 10G 网卡单核跑到 1~2Gbps 就开始大面积丢包因为路径要经过内核协议栈、libpcap、socket中间全是拷贝和调度而 qnsm 这类 DPDK 应用直接接管网卡收包只走 DMA 到内存、用户态处理两步线速收包才成为可能。这篇笔记解决的就是把 dpdk 安装、网卡切换到用户态、qnsm 编译和首次抓包整条链路跑通的问题。2. 环境摸底网卡、内核与编译依赖先就位跳过环境检查直接编译是这类安装任务里最常见的失败路径。DPDK 对硬件有一套自己的脾气网卡型号不在支持列表、内核版本太老、IOMMU 没开、HugePages 没预留任何一个不满足后面编译再顺利也起不来。所以第一步不是敲 make而是把机器的家底盘清楚。2.1 用 lspci 和 ethtool 确认网卡能被 DPDK 接管先跑三条命令lspci | grep -i ethernet uname -r ethtool -i eth0lspci列出的是 PCI 设备网卡会显示厂商和型号比如 Intel I350、Intel X710、Mellanox ConnectX-5。输出里的0000:02:00.0就是网卡 PCI 地址后面dpdk-devbind.py绑卡要用的就是它。uname -r看内核版本DPDK 20.11 LTS 在 4.9 以上内核基本没有兼容性问题老内核则需要反过来迁就 DPDK 版本。ethtool -i eth0显示当前驱动比如 ixgbe、i40e、ice这个信息在回滚绑定操作时会用到先记下来。第一关的核心是确认网卡在 DPDK 支持列表里。Intel 和 Mellanox 的网卡是日常部署里最省心的Realtek 这种家用卡DPDK 的 pmd 覆盖很弱装上大概率起不来不值得浪费时间。虚拟机的 virtio-net 能跑 DPDK但性能和真实网卡差得远只适合验证流程不适合拿来做性能结论。顺带说一句多队列能力和型号强相关后面调 RSS 时发现网卡只有两个队列不要惊讶那是硬件限制。2.2 HugePages 预分配grub 参数或运行时写入怎么选DPDK 和普通程序最大的不同是它依赖大页内存。默认 4KB 页在高速收包时 TLB 会频繁失效性能断崖式下跌所以 DPDK 的 mbuf 池、描述符队列都要放在 HugePages 里。qnsm 启动时 EAL 会直接去申请大页内存机器上没预留程序会报错退出没有任何协商空间。预留 HugePages 有两条路。生产环境我推荐改 grub 内核参数一劳永逸hugepagesz1G hugepages8把这段加进/etc/default/grub的GRUB_CMDLINE_LINUX然后update-grub重启。系统启动时预留 8 个 1GB 大页干净利落没有碎片问题。调试环境可以用运行时写入echo 8 /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages这行命令往 1GB 大页池里申请 8 个大页立即生效不用重启。缺点也很实际系统跑久后内存碎片化可能申请不到连续的 1GB 页而且重启后配置消失。还有一种折中的 2MB 页方式写入 /etc/sysctl.confvm.nr_hugepages20482MB 页申请难度低但页表项多性能比 1GB 页略差。qnsm 抓包场景对内存带宽敏感我更倾向于 1GB 页。分配完用grep -i huge /proc/meminfo看实际生效数量Total 和 Free 都要关注Free 为零说明大页被其他进程占了EAL 照样可能分配失败测试环境可以先echo 3 /proc/sys/vm/drop_caches释放缓存再试。2.3 DPDK 编译依赖的最小集合少装一个 libpcap-dev 都会翻车Debian/Ubuntu 系的依赖安装sudo apt install -y build-essential meson ninja-build python3-pip \ numactl libnuma-dev pkg-config libpcap-devmeson和ninja负责 DPDK 的构建系统DPDK 从 19.11 起离开 make 体系这两个装不上连配置都跑不起来。libnuma-dev提供 NUMA 内存分配接口qnsm 在多 Socket 机器上管理队列内存绕不开它缺了会报 numa.h 找不到。libpcap-dev是一个经典的黑匣子坑——DPDK 本身不是非要它不可但 qnsm 导出 pcap 文件、DPDK 的 pcap pmd 做回放测试时都要 pcap.h。我在 CentOS 上遇到过fatal error: pcap.h: No such file or directory排查半天发现就是依赖没装齐。RHEL/CentOS 系对应包是gcc gcc-c meson ninja-build numactl-devel libpcap-devel pkgconfig用 yum 装。CentOS 7 这类老系统的 meson 版本太旧可以pip3 install meson装新版但要先which meson确认用的是哪个两个版本混着容易出现构建目录不兼容的诡异报错。另外强烈建议把linux-headers-$(uname -r)CentOS 上叫 kernel-devel也装上编译 DPDK 的 igb_uio 模块时需要它。虽然主流已经用 vfio-pci但老项目或者没有 IOMMU 的机器上igb_uio 是唯一后路先配好就是给自己买后悔药。环境摸底做完按下面这张表核对一遍再进下一步检查项命令期望结果网卡型号lspciIntel / Mellanox 常见型号内核版本uname -r4.9 及以上当前驱动ethtool -i eth0ixgbe / i40e / ice大页内存grep -i huge /proc/meminfoHugePages_Total 不为 03. DPDK 编译与网卡绑定从源码到用户态收包DPDK 的安装可以拆成版本选择、构建系统、网卡切换三个环节。每一环都有参数可调但 qnsm 这类应用的目标是稳定跑起来而不是追求极限所以默认参数贴近 LTS 即可。3.1 版本选型LTS 优先内核版本和 qnsm 的依赖都要看DPDK 的版本线分 LTS 和 mainline。LTS 两年一个20.11、21.11、22.11 是常见选择mainline 每季度发布新功能多但 ABI 不稳定。qnsm 是有一定历史的项目代码写的是旧 API编译时遇到rte_eth_dev_info这类函数签名对不上是常事。我的建议是项目没明确要求就选 20.11 LTS这个版本在社区里兼容性口碑最好大量教程和补丁都以它为基础。不同 LTS 对内核有最低版本要求选型时对一下DPDK 版本建议内核适用场景20.11 LTS4.9qnsm 等老项目、稳定部署21.11 LTS4.14功能略新兼容主流发行版22.11 LTS4.18新网卡支持好老 API 少拿到 qnsm 源码但不确定它依赖哪个 DPDK 时先看 README 的依赖说明或者搜源码里的版本宏grep -rn RTE_VER_YEAR能定位到它编出来的 DPDK 大版本。版本差距大时优先考虑降 DPDK 而不是改 qnsm 代码改 API 得不偿失。安装方式上Ubuntu 的apt install libdpdk-dev省去编译路径和 pkg-config 都现成第一次部署用它跑通流程最稳源码编译自由度最高还能加-Dplatformnative做 CPU 指令集优化代价是路径管理要自己来。3.2 meson ninja 构建为什么不用 make 编译老教程让你用make config Tx86_64-native-linuxapp-gcc那是 DPDK 17.x 时代的事。现在官方构建工具是 meson三步完成编译安装tar xf dpdk-20.11.tar.xz cd dpdk-20.11 meson setup build ninja -C build sudo ninja -C build install sudo ldconfigmeson setup build里的build是构建目录名所有编译中间文件都隔离在里面源码目录保持干净。ninja -C build实际执行编译-C指定目录。sudo ninja -C build install把库和头文件装到系统路径默认为 /usr/localldconfig让动态链接器找到新装的 libdpdk.so。装完验证一下pkg-config --modversion libdpdk能输出版本号就说明 DPDK 环境正常。编译时想带测试程序在meson setup里加-Dexamplesl2fwd这样 build/examples 下会多出 l2fwd它是后面验证网卡收发的标准工具。-Dplatformnative按需加它让编译器针对当前 CPU 指令集优化测试机上无所谓二进制要拷到别的机器就得谨慎。meson 版本建议 0.53 以上低于这个版本对 DPDK 20.11 的构建描述支持不完整。3.3 绑定网卡到 vfio-pci一段命令和两个前置条件构建完成不代表 DPDK 能用网卡还差临门一脚把网卡从内核驱动切换到用户态驱动。现代 DPDK 首选 vfio-pci它比老牌的 igb_uio 更安全也更好调试前提是内核支持 IOMMUmodprobe vfio-pci dpdk-devbind.py --bindvfio-pci 0000:02:00.0 dpdk-devbind.py --status第一行加载 vfio-pci 模块第三行的--status会列出所有网卡及其驱动归属绑定后能看到0000:02:00.0的 active driver 变成 vfio-pci。dpdk-devbind.py位于/usr/local/share/dpdk/usertools/没加 PATH 就用完整路径执行。两个前置条件缺一不可一是 BIOS 打开 VT-dAMD 平台叫 IOMMU二是内核启动参数带intel_iommuon iommupt。这里的iommupt表示透传模式只做 DMA 隔离不做地址转换性能和直通差不多。没开 IOMMU 就绑 vfio会报 no iommu_group 一类错误只能退回 igb_uio。绑定后的状态变化要心里有数网卡从内核消失ip addr里看不到业务 IP 也断了所以生产网卡绑定前必须确认业务可中断。回滚命令对称dpdk-devbind.py --bindi40e 0000:02:00.0把 vfio-pci 换回原来的驱动名 i40e / ixgbe / ice。这个操作我首次绑定时反复做了三四次血泪经验是先改 grub 把 IOMMU 确认好再碰绑卡。4. 避坑qnsmDPDK 安装里最常见的 5 类翻车这一章按频率列出我在装 DPDK 和 qnsm 时遇到的五类问题每一条按现象、原因、解决的顺序写。你在复现时优先对照这个清单能省下大半天搜索时间。4.1 EAL 启动报内存错误把 DPDK 英文报错翻译成中文就是没内存现象运行 qnsm 或 l2fwd 时EAL 打印一段英文报错然后进程退出常见是EAL: Not enough memory available to allocate DMA memory或者EAL: Detected memory layout changed。不熟悉 DPDK 的人会觉得像天书翻译成中文其实就是你要的大页内存没准备好。原因机器没有预分配 HugePages或分配数量小于 mbuf 池的需求。还有一种隐蔽情况是物理内存够但 1GB 大页全部被其他进程占用EAL 申请不到连续区域。这类问题在 DPDK 里最常见也最好查。解决先看现状再决定补法。grep -i huge /proc/meminfoHugePages_Total 为 0 就直接按运行时写入申请echo 8 /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages生产环境建议回头改 grub 参数临时 echo 重启就失效只配在测试机用。改完启动 qnsm 时留 1~2 个大页余量给 EAL 做 DMA 映射别卡得刚刚好。4.2 vfio-pci 绑定报 no iommu_group不是命令错是 BIOS 没开现象执行dpdk-devbind.py --bindvfio-pci 0000:02:00.0后输出Error: cannot bind to driver vfio-pci附带no iommu_group的字样。原因vfio-pci 依赖 IOMMU 把网卡放进独立的 iommu_group 才能做 DMA 隔离。BIOS 里 VT-d 没开或者内核启动参数没带intel_iommuon iommupt设备就没有这个 group内核拒绝接管。解决重启进 BIOS 开 VT-d同时在 grub 的GRUB_CMDLINE_LINUX里补参数update-grub 重启后再绑定。如果服务器老旧根本不支持 IOMMU切换 igb_uio 方案modprobe igb_uio dpdk-devbind.py --bindigb_uio 0000:02:00.0igb_uio 需要 DPDK 源码额外编译内核模块前面装 kernel-devel 的用场就在这里。抓包场景 igb_uio 完全够用这不是性能问题是平台能力问题。4.3 编译 qnsm 报 rte_eal.h 找不到RTE_SDK 和 PKG_CONFIG_PATH 的锅现象进入 qnsm 源码目录执行 make编译中断报fatal error: rte_eal.h: No such file or directory后面跟着一串头文件引用失败。有时报 pcap.h 找不到。原因qnsm 的 Makefile 是典型的 DPDK 老式工程靠环境变量RTE_SDK定位 DPDK 安装目录再拼出 include 路径。只装了 DPDK 库但没设置变量编译器自然找不到头文件。报 pcap.h 的则是第 2 章提过的 libpcap-dev 遗漏。解决编译前导出环境变量export RTE_SDK/usr/local/share/dpdk export RTE_TARGETbuild export PKG_CONFIG_PATH/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH makeRTE_SDK 指向 DPDK 安装根目录RTE_TARGET 是构建目录名新版是 build老版是x86_64-native-linuxapp-gcc。用了系统包 libdpdk-dev 的路径可能不同先跑pkg-config --cflags libdpdk看返回再对准。这几个 export 每个终端都要执行写进 ~/.bashrc 里省得每次手敲。4.4 启动后收不到包qnsm 计数永远为 0 的三个排查点现象qnsm 正常启动EAL 没报错但抓包计数一直是 0平行地用 tcpdump 抓同一个网口流量明明在跑。原因最常见的是网卡绑定错了 PCI 地址qnsm 在抓一个没有流量的端口或者端口掩码只开了一个端口流量从另一个端口进来还有一个隐蔽点是交换机没配端口镜像物理网卡根本看不到业务流量。解决用dpdk-devbind.py --status确认绑定状态下网口和 PCI 地址的对应关系再把端口掩码对齐。两块网卡都绑定时只抓第一块掩码是 0x1抓两块是 0x3。排查顺序是先确认绑定端口有链路再 ping 网关注入数据包最后看计数是否增长。如果还不行回到 tcpdump 确认流量确实从这个物理口经过。4.5 收包时单核 CPU 打满吞吐上不去RSS 多队列没生效现象qnsm 跑起来了但一有流量某一个 CPU 核立刻 100%吞吐量停在 2~3Gbps完全没发挥 10G 网卡能力。原因网卡的 RSSReceive Side Scaling多队列没开启所有到达的包都哈希进同一个接收队列qnsm 分配了 8 个核也没用一个队列只能由一个核 poll。另一个常见原因是线程没有绑核被调度器在不同核之间迁移缓存命中率掉得厉害。解决在把网卡绑进 vfio-pci 之前先用 ethtool 打开 RSSethtool -L eth0 combined 4这行命令把 eth0 的接收队列设为 4 个网卡硬件按五元组哈希分散到各队列。然后再做 DPDK 绑定启动 qnsm 时队列参数和核数对齐用-l 0-3分配 4 个核。双路服务器还要注意 NUMA 拓扑qnsm 在哪个 socket 上跑网卡就接在哪个 socket 上跨 NUMA 访问远端内存会让性能再打个七折。验证方法最后一章细讲。5. 编译 qnsm 并首抓包RTE_SDK、EAL 参数与第一个 pcap 文件环境就绪、DPDK 装好、网卡切到用户态这一步是把 qnsm 本身编译出来并跑一次完整流程。第一次跑通后后面调参数就有基准了。5.1 编译前设置 RTE_SDK 与 PKG_CONFIG_PATH一次配置终身后悔药qnsm 这类 DPDK 应用通常自带 Makefile编译时通过RTE_SDK环境变量定位 DPDK。用源码编译的 DPDK 时export 指向安装前缀目录即可export RTE_SDK/usr/local/share/dpdk export RTE_TARGETbuild export PKG_CONFIG_PATH/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH make -j$(nproc)三个变量各司其职。RTE_SDK告诉 Makefile 去哪找 DPDK 头文件和库函数RTE_TARGET指定 DPDK 构建目录名新版是 build老版本是x86_64-native-linuxapp-gcc。PKG_CONFIG_PATH是给用 pkg-config 的新式 Makefile 用的DPDK 装好后的 libdpdk.pc 文件就在这个目录里。make -j$(nproc)并行编译第一次会刷出大量 cc 命令最后生成 qnsm 可执行文件就算成功。make 报 rte_eal.h 找不到就回头看 4.3这类问题不是玄学是环境变量没生效。export 追加到 ~/.bashrc 后记得source ~/.bashrc否则每个新终端窗口都要重设一遍。5.2 启动参数EAL 部分和应用参数的分界在 --编译出来的可执行文件启动时参数分两段--左边是 DPDK EAL 参数右边是 qnsm 应用自己的参数。这个规律在所有 DPDK 程序里通用搞混了 EAL 会把应用参数当自己的参数解析然后报一个莫名其妙的配置错误。我把这个顺序看成一条铁律从来没变过。./build/qnsm -l 0-1 -n 2 -- -p 0x1 --queue 4-l 0-1表示让 DPDK 使用逻辑核 0 和 1-n 2是内存通道数。内存通道数和硬件相关一般主板双通道写 2、四通道写 4写大了 EAL 报无效参数写小了性能受影响。-p 0x1是端口掩码0x1 表示只处理第一个 DPDK 端口--queue 4表示对每个端口开 4 个接收队列队列参数的具体名字以你下载的 qnsm 版本为准。队列和核的对应关系是一个队列占用一个核的 poll 循环核少了队列利用率低反过来核多了也是浪费。启动前再确认一次大页内存grep -i huge /proc/meminfo看到 HugePages_Total 不为 0 再执行。启动后窗口会打印 EAL 初始化和各端口链路状态看到Link up就是网卡已识别。5.3 用 ping 和 tcpdump 验证 qnsm 真的在收包工具跑起来收尾工作是验证它在正确工作。我一般用最小注入法不依赖复杂流量环境# 终端 A启动 qnsm 并输出 pcap 文件 ./build/qnsm -l 0-1 -n 2 -- -p 0x1 --queue 2 --write dump.pcap # 终端 B对网关发起 ping 注入双向流量 ping -c 100 192.168.1.1几秒后回到终端 Aqnsm 的统计输出里计数应该和 ping 的包数量接近如果输出 pcap 文件用 ls 观察文件在增长再用 tcpdump 读回确认内容tcpdump -r dump.pcap -c 10能读到 ICMP 请求和应答整条链路就是通的。判断标准有两条一是计数 pps 不断增长二是 CPU 占用不超过一个核。计数不涨按 4.4 的顺序查端口掩码和绑定状态tcpdump 能读但 qnsm 没写文件优先查 pcap 导出模块的编译依赖是不是把 libpcap-dev 漏了。第一次跑通之后把启动命令和端口对照表写进笔记后续所有参数调整都从这一版出发。也可以把--write指向独立磁盘路径抓大流量时避免 pcap 文件和系统盘抢 IO。6. 进阶多队列 RSS 与 CPU 绑核验证性能是否到位装好只是开始qnsm 这类工具的价值在高吞吐下体现而这取决于 RSS 多队列和 CPU 绑核是否配合到位。验证方法不复杂但能省掉后期性能排障的时间。先确认网卡 RSS 能力。打开多队列要在绑定 DPDK 之前完成ethtool -L eth0 combined 4把接收队列设为 4然后ethtool -S eth0看每个 rx_queue_N 的独立计数流量打进来时四个队列计数涨得差不多硬件哈希才算正常工作。绑定 vfio-pci 之后 ethtool 就对这块网卡失效了所以这个确认必须前置没有后悔药。再看应用侧。qnsm 启动参数里队列数和 EAL 核列表对齐比如-l 0-3 -n 2 -- -p 0x1 --queue 4四个核分别 poll 四个队列。验证靠观察满流量时用top加1键看每个核的占用理想状态是四个核各 25% 左右而不是一个核 100%。某个核打满而其他核空闲说明包都哈希进了一个队列——检查 RSS 是否真的开启或者流量五元组是否过于单一。单条 TCP 大流只能进一个队列这是硬件哈希的物理限制不是配置能解决的。绑核方面确认线程没有漂移可以用ps -o psr -p pid看线程当前运行在哪个核上配合taskset -c 0-3 ./build/qnsm ...把进程锁在核组。双路服务器上网卡所在 NUMA node 的核要优先分配跨 socket 收包会有额外的内存延迟。这些做完线速抓包的底子就打好了。最后说一句我自己的习惯每次部署这类工具我都会把从lspci到ethtool的每一步输出存成一份文本出问题时对照排错比翻命令历史快得多。希望这套从环境摸底到性能验证的流程能帮你在 qnsm 和 DPDK 的部署上少走几步弯路。本文还有配套的精品资源点击获取
返回列表