为什么DPDK轮询DD Bit不会把PCIe读爆?——RX Descriptor Cache深度解析(上)

一、一次"理论上应该发生",实际上却没有发生的故障

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

新加入的一位开发同事阅读PMD源码时提出了一个问题:

PMD线程一直在不停读取DD Bit。

代码几乎就是:

while (nb_rx < nb_pkts) {

    rxdp = &rx_ring[rx_id];

    if (!(rxdp->status & DD))
        break;

    ...
}

按照CPU主频计算。

假设每个Worker每秒轮询2亿次。

系统16个Worker意味着:每秒读取30多亿次RX Descriptor。

开发同事立即提出疑问:

Descriptor不是放在网卡里面吗?

如果:

每次CPU读取Descriptor都要PCIe Read。

那么:

PCIe应该瞬间被读满。

然而:

现实情况却完全不同。

系统长期稳定运行100Gbps。

PCIe监控Read Traffic几乎没有明显增长。

为什么?


核心知识点一

很多人潜意识里认为:RX Descriptor属于网卡。

实际上。

真正拥有Descriptor内存的并不是NIC。

而是Host Memory。


二、Descriptor到底存放在哪里?

继续分析:DPDK初始化流程。

网卡初始化时:PMD首先申请Descriptor Ring。

例如:

rte_eth_rx_queue_setup(...)

最终:申请的是一块DMA一致性内存。

其位置实际上位于HugePage。

例如:

HugePage

↓

RX Descriptor Ring

↓

Descriptor0

Descriptor1

Descriptor2

...

随后:

驱动将Descriptor Ring物理地址写入网卡寄存器。

例如:

Intel网卡会保存RX Ring Base Address。

从这一刻开始。

CPU和NIC共同访问同一块Host Memory。

而不是:

CPU访问网卡内部RAM。


核心知识点二

Descriptor Ring不是放在NIC里面。

而是放在服务器内存。

NIC只是通过DMA访问它。


三、CPU读取Descriptor,到底读的是哪里?

继续思考:

PMD每次执行:

status = rxdp->status;

CPU是不是通过PCIe去读取Descriptor?

答案:几乎不是。

CPU首先读取L1 Cache。

如果没有继续L2。

然后L3。

最后才可能访问内存。

整个过程中。

CPU根本不会主动通过PCIe去读取Descriptor。

因为:Descriptor本来就在Host Memory。

CPU访问Descriptor与访问普通数组没有本质区别。


四、真正通过PCIe访问Descriptor的是谁?

这里很多人第一次会产生认知反转。

真正通过PCIe访问Descriptor。

并不是CPU。

而是NIC。

例如:

收到Packet真正流程如下:

Packet
        │
        ▼
      MAC
        │
        ▼
   RX Packet Buffer
        │
        ▼
 DMA 写入 mbuf Data Buffer
        │
        ▼
 DMA 更新 RX Descriptor
        │
        ▼
 Write Back DD Bit

可以看到Descriptor真正发生PCIe事务是在NIC执行DMA。

CPU只是后来读取已经更新好的内存。


核心知识点三

PCIe总线主要承担的是:NIC → Memory 和 Memory → NIC 的数据搬运。

CPU访问Descriptor走的是CPU自己的Cache体系。

不是PCIe。


五、那CPU怎么知道DD已经变化了?

问题开始变得更加有趣。

既然CPU一直读取Cache。

那么NICDMA更新Descriptor以后。

CPU为什么能够马上看到DD变成1?

难道CPUCache自己知道NIC写了内存?

如果不知道:CPU岂不是永远看到旧数据?

真正的问题开始指向:CPU Cache Coherency(缓存一致性)。


六、很多人误解了DMA与Cache的关系

不少开发者认为:

DMA直接修改内存。

CPU Cache不会同步。

因此:

CPU应该不断读到旧Descriptor。

事实上:

现代Intel服务器平台并非如此简单。

支持DMA一致性的PCIe平台中:

NIC发起DMA Write后,会通过平台的一致性机制(具体实现依赖CPU、Chipset及PCIe特性)保证CPU后续能够观察到最新的数据,而不需要软件主动去刷新Cache。

也就是说:

CPU不会一直看到旧DD。

否则:

DPDK根本无法正常工作。

这里需要特别说明:

Cache一致性的具体实现方式,与CPU架构、PCIe Root Complex以及DMA一致性能力有关,并不是所有SoC平台都完全一致。本文讨论的是主流Intel Xeon服务器平台,也是DPDK部署最常见的平台。


核心知识点四

DD Bit不是CPU主动去网卡读取。

而是NIC主动DMA写回Host Memory。

CPU随后通过Cache一致性观察到Descriptor已经发生变化。


七、真正值得思考的问题来了

如果CPU一直读取Cache。

那么为什么DPDK仍然要不断PrefetchDescriptor?

例如:

PMD源码大量出现:

rte_prefetch0(rxdp + 4);

如果:Descriptor一直都在Cache。

Prefetch岂不是毫无意义?

事实上。

真正影响RX性能的已经不是PCIe。

而是:另一件更加重要的事情……

CPU Cache Line。


(未完待续)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr.HeBoYan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值