接上文为什么网卡停止收包——Intel网卡RX Buffer Replenishment机制深度解析上-CSDN博客八、rte_eth_rx_burst()真正做了什么很多开发者认为rte_eth_rx_burst()只是从网卡取Packet。实际上对于Intel PMD来说RX Burst通常包含四个阶段检查DD Bit ↓ 取出mbuf ↓ 补充新的RX Buffer ↓ 更新RDT真正保证RX能够持续运行的。不是DD。而是后两步。如果没有新的Buffer。整个RX Ring最终都会被消费完。核心知识点四RX Descriptor是可以重复使用的。真正需要不断重新分配的是Descriptor关联的mbuf Buffer。Descriptor只是重新写入新的DMA地址。九、PMD为什么不停申请新的mbuf来看Intel PMD的大致流程。逻辑可以抽象为mbuf rte_pktmbuf_alloc(rxq-mb_pool); rxdp-pkt_addr rte_mbuf_data_iova(mbuf); rxdp-hdr_addr 0;这里并没有重新创建Descriptor。而是把新的mbuf地址重新写入Descriptor。于是NIC下一次收到Packet。便可以继续DMA。如果这里没有成功申请mbuf。意味着Descriptor没有新的DMA目标。NIC最终就会没有Buffer可以使用。十、为什么不会每处理一个Packet就更新RDT继续阅读PMD源码。会发现更新RDT通常不是每个Packet执行。而是满足一定条件。例如rx_free_thresh达到以后。一次补充一批Descriptor。最后统一更新RDT。为什么如果每处理一个Packet。就写一次RDT。意味着CPU需要不断访问NIC寄存器。对于PCIe设备来说。寄存器属于MMIO。一次MMIO远远比普通Cache访问昂贵。因此。Intel PMD采用批量更新。大幅减少Doorbell。提升吞吐。核心知识点五RDT更新属于MMIO操作。它的成本远高于普通内存写。因此PMD一定采用批量更新。十一、RDT到底是什么Intel网卡维护两个重要指针。RDH Receive Descriptor Head NIC维护 RDT Receive Descriptor Tail Driver维护可以理解为RDH ------------- Descriptor Ring ------------- RDT其中RDH表示NIC已经消费到哪里。RDT表示驱动已经准备好多少新的Buffer。NIC只能在RDH和RDT之间继续DMA。如果RDH追上RDT。说明已经没有新的Buffer。即使链路仍然收到Packet。NIC也只能停止接收。直到Driver再次推进RDT。核心知识点六真正决定NIC还能继续DMA。不是DD。而是RDT后面是否还有可用Buffer。十二、为什么现场会出现停止几十毫秒继续分析现场日志。最终发现。某版本为了减少mbuf申请次数。修改了补充策略。导致rx_free_thresh设置过大。结果CPU一直忙于业务处理。长时间没有进入补Buffer流程。NIC不断消耗Descriptor。最终RDH追上RDT。RX短暂停止。随后CPU终于完成一次批量补充。更新RDT。NIC立即恢复DMA。整个过程持续几十毫秒。与现场现象完全一致。十三、为什么DPDK一定使用Mempool有人会问既然不断申请mbuf。为什么不用malloc()原因就在于RX路径必须极快。Mempool能够提供固定大小对象。Lockless。Cache友好。NUMA感知。批量分配。如果改成系统malloc。不仅延迟增加。碎片也会越来越严重。最终RXBuffer补充速度下降。影响整个RX流水线。因此高速数据平面几乎都会使用对象池。而不会动态申请内存。核心知识点七RX Buffer Replenishment本质上不是内存管理问题。而是高速DMA流水线的一部分。十四、RX完整生命周期理解整个RX路径最好的方式就是记住下面这条完整生命周期。Packet │ ▼ NIC收到Packet │ ▼ DMA写入mbuf │ ▼ Descriptor DD1 │ ▼ CPU读取Descriptor │ ▼ CPU处理Packet │ ▼ 旧mbuf交付协议栈 │ ▼ 申请新的mbuf │ ▼ 重新填写Descriptor │ ▼ 更新RDT │ ▼ NIC继续DMA真正高性能RX路径实际上是一个不断循环补充Buffer的过程。十五、全文总结很多DPDK开发者把注意力集中在DD Bit因为DD代表一个Descriptor已经可以被CPU处理。然而对于网卡来说DD只是一次DMA完成的标志并不意味着RX生命周期结束。真正保证RX持续运行的是CPU及时回收Descriptor分配新的mbuf重写Descriptor中的DMA地址批量更新RDT让NIC获得新的可用Buffer。只有这一整套Buffer Replenishment机制持续运行RX流水线才能始终保持满速。因此从工程角度看DD Bit回答的是这个包好了没有而RDT回答的是下一个包还有没有地方可放。理解两者的区别比单独理解DD Bit更重要。全文核心知识点Descriptor保存的是DMA目标地址而不是Packet数据。每个RX Buffer通常只能完成一次Packet DMA需要不断补充新的mbuf。rte_eth_rx_burst()不仅负责收包还负责Buffer Replenishment。PMD采用批量补充Descriptor和批量更新RDT以减少MMIO开销。RDT决定NIC还能否继续接收新的Packet而DD仅表示当前Descriptor已经完成DMA。rx_free_thresh直接影响Buffer补充时机配置不合理可能导致RX停顿。Mempool不仅是内存池更是高速RX流水线的重要组成部分。理解Packet→DMA→DD→CPU→补Buffer→更新RDT→继续DMA这一完整生命周期是理解Intel网卡RX机制的关键。
为什么网卡停止收包?——Intel网卡RX Buffer Replenishment机制深度解析(下)
发布时间:2026/7/5 3:37:20
接上文为什么网卡停止收包——Intel网卡RX Buffer Replenishment机制深度解析上-CSDN博客八、rte_eth_rx_burst()真正做了什么很多开发者认为rte_eth_rx_burst()只是从网卡取Packet。实际上对于Intel PMD来说RX Burst通常包含四个阶段检查DD Bit ↓ 取出mbuf ↓ 补充新的RX Buffer ↓ 更新RDT真正保证RX能够持续运行的。不是DD。而是后两步。如果没有新的Buffer。整个RX Ring最终都会被消费完。核心知识点四RX Descriptor是可以重复使用的。真正需要不断重新分配的是Descriptor关联的mbuf Buffer。Descriptor只是重新写入新的DMA地址。九、PMD为什么不停申请新的mbuf来看Intel PMD的大致流程。逻辑可以抽象为mbuf rte_pktmbuf_alloc(rxq-mb_pool); rxdp-pkt_addr rte_mbuf_data_iova(mbuf); rxdp-hdr_addr 0;这里并没有重新创建Descriptor。而是把新的mbuf地址重新写入Descriptor。于是NIC下一次收到Packet。便可以继续DMA。如果这里没有成功申请mbuf。意味着Descriptor没有新的DMA目标。NIC最终就会没有Buffer可以使用。十、为什么不会每处理一个Packet就更新RDT继续阅读PMD源码。会发现更新RDT通常不是每个Packet执行。而是满足一定条件。例如rx_free_thresh达到以后。一次补充一批Descriptor。最后统一更新RDT。为什么如果每处理一个Packet。就写一次RDT。意味着CPU需要不断访问NIC寄存器。对于PCIe设备来说。寄存器属于MMIO。一次MMIO远远比普通Cache访问昂贵。因此。Intel PMD采用批量更新。大幅减少Doorbell。提升吞吐。核心知识点五RDT更新属于MMIO操作。它的成本远高于普通内存写。因此PMD一定采用批量更新。十一、RDT到底是什么Intel网卡维护两个重要指针。RDH Receive Descriptor Head NIC维护 RDT Receive Descriptor Tail Driver维护可以理解为RDH ------------- Descriptor Ring ------------- RDT其中RDH表示NIC已经消费到哪里。RDT表示驱动已经准备好多少新的Buffer。NIC只能在RDH和RDT之间继续DMA。如果RDH追上RDT。说明已经没有新的Buffer。即使链路仍然收到Packet。NIC也只能停止接收。直到Driver再次推进RDT。核心知识点六真正决定NIC还能继续DMA。不是DD。而是RDT后面是否还有可用Buffer。十二、为什么现场会出现停止几十毫秒继续分析现场日志。最终发现。某版本为了减少mbuf申请次数。修改了补充策略。导致rx_free_thresh设置过大。结果CPU一直忙于业务处理。长时间没有进入补Buffer流程。NIC不断消耗Descriptor。最终RDH追上RDT。RX短暂停止。随后CPU终于完成一次批量补充。更新RDT。NIC立即恢复DMA。整个过程持续几十毫秒。与现场现象完全一致。十三、为什么DPDK一定使用Mempool有人会问既然不断申请mbuf。为什么不用malloc()原因就在于RX路径必须极快。Mempool能够提供固定大小对象。Lockless。Cache友好。NUMA感知。批量分配。如果改成系统malloc。不仅延迟增加。碎片也会越来越严重。最终RXBuffer补充速度下降。影响整个RX流水线。因此高速数据平面几乎都会使用对象池。而不会动态申请内存。核心知识点七RX Buffer Replenishment本质上不是内存管理问题。而是高速DMA流水线的一部分。十四、RX完整生命周期理解整个RX路径最好的方式就是记住下面这条完整生命周期。Packet │ ▼ NIC收到Packet │ ▼ DMA写入mbuf │ ▼ Descriptor DD1 │ ▼ CPU读取Descriptor │ ▼ CPU处理Packet │ ▼ 旧mbuf交付协议栈 │ ▼ 申请新的mbuf │ ▼ 重新填写Descriptor │ ▼ 更新RDT │ ▼ NIC继续DMA真正高性能RX路径实际上是一个不断循环补充Buffer的过程。十五、全文总结很多DPDK开发者把注意力集中在DD Bit因为DD代表一个Descriptor已经可以被CPU处理。然而对于网卡来说DD只是一次DMA完成的标志并不意味着RX生命周期结束。真正保证RX持续运行的是CPU及时回收Descriptor分配新的mbuf重写Descriptor中的DMA地址批量更新RDT让NIC获得新的可用Buffer。只有这一整套Buffer Replenishment机制持续运行RX流水线才能始终保持满速。因此从工程角度看DD Bit回答的是这个包好了没有而RDT回答的是下一个包还有没有地方可放。理解两者的区别比单独理解DD Bit更重要。全文核心知识点Descriptor保存的是DMA目标地址而不是Packet数据。每个RX Buffer通常只能完成一次Packet DMA需要不断补充新的mbuf。rte_eth_rx_burst()不仅负责收包还负责Buffer Replenishment。PMD采用批量补充Descriptor和批量更新RDT以减少MMIO开销。RDT决定NIC还能否继续接收新的Packet而DD仅表示当前Descriptor已经完成DMA。rx_free_thresh直接影响Buffer补充时机配置不合理可能导致RX停顿。Mempool不仅是内存池更是高速RX流水线的重要组成部分。理解Packet→DMA→DD→CPU→补Buffer→更新RDT→继续DMA这一完整生命周期是理解Intel网卡RX机制的关键。