早期做DPDK开发时,我曾遇到一个非常奇怪的问题:

程序运行正常:

  • 收包正常
  • 转发正常
  • ping 正常
  • 吞吐正常

但是:

tcpdump -i eth0 arp

始终抓不到任何 ARP 包。

更离谱的是:业务明明是通的。

说明:ARP 肯定发生过。

否则:MAC 地址根本解析不了。

那么问题来了:ARP 包到底去哪了?

第一次遇到时,我怀疑过很多东西:

  • tcpdump 有问题?
  • 网卡驱动异常?
  • 网卡 offload?
  • VLAN 配置错误?

但最终发现,问题根源其实是:PMD bypass

而这个问题,也让我真正理解了 DPDK 与 Linux 网络栈最本质的区别。

一、问题现场

环境:

服务器

双口 10G 网卡
Linux
DPDK 21.11

程序

简单 L2 转发:

port0 <-> port1

运行正常。

现象

业务互通:ping 正常

但:

tcpdump -i eth0 arp

没有任何输出。

即使:arping 也抓不到。

二、第一反应:是不是 tcpdump 权限问题

先检查:

tcpdump -D

接口存在。权限正常。

抓 ICMP:

tcpdump icmp

也没数据。

这里开始不对劲。

三、再看网卡状态

查看:

ip link

发现:

eth0 DOWN

这就很奇怪。

因为:业务流量明明在跑。

四、真正关键的一步:查看网卡绑定

执行:

dpdk-devbind.py --status

输出:

0000:18:00.0 drv=vfio-pci

这里问题终于浮现。

五、什么叫 vfio-pci

这意味着:网卡已经从 Linux 内核驱动解绑。

不再由:

  • ixgbe
  • i40e
  • mlx5_core

等内核驱动管理。

而是绑定到:vfio-pci 供 DPDK 用户态直接接管。

六、这就引出了 DPDK 最核心机制

即:Kernel Bypass

也称:PMD bypass

七、什么是 PMD

PMD 全称:Poll Mode Driver

即:轮询模式驱动。

在 DPDK 中:应用直接驱动网卡。

路径:

https://images.openai.com/static-rsc-4/7lpOSACShtWCjORVnNvfgFGMP2A7BdpgmE7SeRUe9AGkD-H8TZMZcMKYej3E5N9aN5uCXyMnJazafKIyS8roFyYPxAT-kUChrBUDrcTgH7JKVU8v8GQZ0AWZaRzz2qOWzj4rnqycK2Aks1IahKyWMq_R_vxJOKj4sb_HbqCKHqqIhD8DUvLGXE-V5kG-WT-l?purpose=fullsize

https://images.openai.com/static-rsc-4/7zVtyWlzHEqqNXhjDa9etj_9_AOWZFF9d4M6GnwFUjl2jr2kfqsjA5G1Tt5Gcfu9RaK5RrM5alBNBudN4_Jtc7o6gScSQGcEG2cIBVxJ_y5Q26L6tonPEmgYxPhlyuxoIse7NLh1WMuzqxR00pusXCLFoyqtQn-mDmOyZop1eE1JirmmhbYs1FPoleVS1wOS?purpose=fullsize

https://images.openai.com/static-rsc-4/Tv13P5y7crKIihXIDYbIIK9Ys_pzAl48lUGhfOCLBwEmUv9Jl1Ma3_SBwxkMNcnmKyKIYl5d64Y5ZohrldPs2JAV27kd9vh0_r7qMWpXuMXpvGskNeY-FLHyR0S7DN7Z0ytpdPb9xSi9aU4DUnf7miNLRAtzLMCACIHh0T1FrWChuUDWASqlSjMG7ipaDjik?purpose=fullsize


NIC
 ↓
DPDK PMD
 ↓
Userspace App

完全绕过:Linux kernel network stack。

八、传统 Linux 网络路径

普通 Linux:

NIC
 ↓
Kernel Driver
 ↓
skb
 ↓
TCP/IP Stack
 ↓
socket
 ↓
tcpdump

tcpdump 能抓包。因为它工作在:内核协议栈。

九、DPDK 完全不同

DPDK 中:

NIC
 ↓
DMA
 ↓
Hugepage
 ↓
Userspace

根本不经过:

  • skb
  • netfilter
  • socket
  • tcpdump hook

所以:tcpdump 看不到。

十、ARP 为什么仍然能工作

这是很多人最迷惑的地方。

既然:Linux 看不到包。为什么还能通信?

因为:ARP 并不是 Linux 处理的。

而是:DPDK 应用自己处理。

十一、很多 DPDK 程序都有自己的 ARP 模块

例如:

  • L3 forward
  • vRouter
  • vSwitch
  • UPF

都会自己实现:

  • ARP request
  • ARP reply
  • neighbor table

完全用户态。

十二、也就是说

ARP 包其实存在。

只是:

NIC -> DPDK app

没有进入 Linux。

因此:

tcpdump

抓不到。

十三、进一步理解:什么叫“绕过内核”

很多人以为:DPDK 只是:“用户态收包更快”。

其实远不止。

它本质上是:完全接管 NIC。

包括:

  • RX queue
  • TX queue
  • descriptor
  • DMA
  • interrupt

全部用户态化。

十四、为什么 DPDK 必须这样设计

因为 Linux 网络栈太重。

路径里包含:

  • softirq
  • skb alloc
  • netfilter
  • qdisc
  • socket buffer

高 PPS 下成本巨大。

十五、DPDK 为什么性能高

因为它直接:

DMA -> userspace

没有:

  • skb 分配
  • 系统调用
  • 内核上下文切换

因此:吞吐和时延大幅优化。

十六、那怎么抓 DPDK 的包?

这也是实战里非常重要的问题。

方法一:程序内部打印

最常见:

rte_hexdump()

方法二:DPDK pdump

DPDK 自带:

dpdk-pdump

可以镜像流量。

方法三:KNI / virtio-user

把部分流量送回 Linux。

供:tcpdump 抓取。

十七、为什么有时 tcpdump 又能抓到

因为:某些场景网卡并未真正解绑。

例如:

场景一

混合模式:

kernel + dpdk

场景二

SR-IOV:

PF 在 kernel。VF 给 DPDK。

场景三

使用 AF_PACKET PMD。

所以:

是否能抓包取决于:数据路径是否经过 Linux。

十八、一个非常重要的工程经验

很多新手排查 DPDK 问题时:

第一反应:

tcpdump

但实际上:

很多时候:它根本看不到真实流量。

因为:Linux 已经不在数据路径里。

十九、为什么这很容易误导

例如:

你看到:

tcpdump 没包

会误以为:网卡没收到。

其实:DPDK 程序可能已经收到了几千万 PPS。

二十、如何真正确认 DPDK 收包

应该查看:

1. rte_eth_stats_get

2. 应用内部计数器

3. PMD debug log

二十一、进一步理解 DPDK 与 Linux 的关系

很多人认为:DPDK 是 Linux 网络加速。

其实更准确地说:DPDK 是在 Linux 上运行的“用户态网络栈”。

它并不是:增强 Linux 协议栈。

而是:绕过它。

二十二、总结

为什么 DPDK 程序运行正常,但 tcpdump 抓不到 ARP?

根本原因不是:

  • tcpdump 出错
  • 网卡异常
  • ARP 丢失

而是:网卡已经被 DPDK PMD 接管。

数据路径:根本不经过 Linux。

通过这个问题,我们实际上理解了 DPDK 最核心的几个概念:

包括

  • PMD
  • Kernel bypass
  • vfio-pci
  • userspace driver
  • DMA
  • hugepage

很多时候,一个“抓不到包”的小问题,背后其实是:整个网络架构设计理念的不同。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐