为什么网卡停止收包?——Intel网卡RX Buffer Replenishment机制深度解析(上)

📅 2026/7/5 3:50:01 👁️ 阅读次数 📝 编程学习
为什么网卡停止收包?——Intel网卡RX Buffer Replenishment机制深度解析(上)

一、一次十分诡异的现网故障

某数据中心部署了一套基于DPDK开发的100GbE高性能交换机。

系统上线数月后。

现场反馈:

业务偶尔出现:20~50ms流量中断。

随后自动恢复。

整个过程中:

CPU始终100%。

Worker没有退出。

PMD持续运行。

监控如下:

指标状态
PMD CPU100%
RX Queue正常
TX Queue正常
Descriptor Error0
DD Bit正常
LinkUp

继续抓取:网卡统计。

发现:

CRC Error:0。

Missed Packet:0。

RX No Buffer:0。

一切似乎都没有问题。

但是:

交换机就是停止收包几十毫秒。

随后又恢复正常。


核心知识点一

对于DPDK来说:DD Bit正常,并不意味着RX能够持续运行。

真正决定:NIC是否还能继续DMA。

还有另外一个容易被忽略的条件。


二、第一轮排查:怀疑DD Bit

由于收包停止。

团队首先怀疑Descriptor。

于是:增加调试日志。

持续打印Descriptor Status。

例如:

status = rxdp->wb.upper.status_error;

观察发现:

DD始终能够正常置位。

并不存在Descriptor没有回写的问题。

因此排除:Write Back异常。


三、第二轮排查:怀疑RX Ring

继续查看RX Ring。

发现:RDH、RDT均处于合理范围。

Descriptor没有耗尽。

Ring也没有Overflow。

很多开发者此时都会认为:RX Ring没有问题。

事实上这里恰恰隐藏着真正的陷阱。


核心知识点二

RX Ring里面保存的不是Packet。

保存的是:Buffer描述信息。


四、很多人一直误解了RX Descriptor

第一次阅读Intel网卡手册。

很多人都会认为:RX Descriptor就是Packet。

实际上完全不是。

例如:

Intel 82599:Advanced RX Descriptor里面主要包含:

Packet Buffer Address Header Buffer Address Status Length RSS Hash VLAN Checksum

注意。

真正的数据并没有存放:Descriptor。

Descriptor只保存一个DMA目标地址。

真正Packet存放在mbuf对应的数据缓冲区。

也就是说:Descriptor更像一张"地址卡片"。

告诉NIC:

下一帧数据,请DMA到这里。


五、真正的数据流是什么?

收到一个Packet以后。

NIC真正执行的是:

Packet ↓ MAC ↓ RX FIFO ↓ DMA到mbuf Data Buffer ↓ 更新Descriptor Status ↓ DD = 1

CPU随后读取Descriptor获得Packet Length、RSS、Checksum。

然后取得对应mbuf。真正处理Packet。

注意。

这里CPU已经拿走了这个mbuf。

那么问题来了。

NIC下一次收到Packet。

还能继续DMA到同一个Buffer吗?

答案:不能。


核心知识点三

一个RX Buffer只能完成一次DMA。

Packet被CPU接管以后。

NIC必须重新获得一个新的Buffer。

才能继续收包。


六、真正容易被忽略的一半生命周期

很多开发者理解的RX流程:

只有前半段。

例如:

Packet ↓ DMA ↓ DD=1 ↓ CPU收到mbuf

于是认为整个RX流程结束。

实际上真正完整的生命周期应该是:

Packet ↓ DMA到mbuf ↓ DD=1 ↓ CPU处理Packet ↓ 释放旧Buffer ↓ 重新申请mbuf ↓ 重新填写RX Descriptor ↓ 通知NIC ↓ 下一次DMA

也就是说。

CPU处理完Packet以后。

真正重要的工作才刚刚开始。

如果没有新的Buffer。

NIC即使收到Packet。

也没有地方DMA。


七、问题终于开始浮现

继续阅读PMD源码。

发现rte_eth_rx_burst():并不是收到Packet就结束。

真正最后还有一段容易被忽略的代码。

它负责:

  • 分配新的mbuf;
  • 重新填写RX Descriptor;
  • 更新RX Tail。

看到这里。

真正的问题终于浮现。

现场DD正常、Descriptor正常、CPU正常。

但是NIC为什么还是停止收包?

真正值得怀疑的已经不是DD Bit。

而是:RX Buffer Replenishment(接收缓冲补充)机制。


(未完待续)