DPDK 教程(二):mbuf、mempool、ethdev 的数据路径
1 DPDK 教程二mbuf、mempool、ethdev的数据路径本文对应学习路径第二步把“包从网卡进来到被应用消费”的主链路读成一张图。读完你应能口述描述符环 → PMD RX → mbuf 与 mempool → 用户处理 → TX burst → 描述符回收并知道关键结构体字段的语义与常见误用。1.1 总览一条 RX 主链概念正确、细节随 PMD 变化以典型收包路径为例简化NIC DMA 写入 mbuf 数据区 → 硬件更新 RX ring descriptor → PMDrx_burst扫描/批量回收描述符 → 填充rte_mbuf元数据pkt_len、RSS hash、ol_flags 等→ 应用处理 →rte_eth_tx_burst填充 TX ring → NIC DMA 读 mbuf 数据区 → PMD 回收 mbuf 回 pool或延迟回收策略依实现TX 路径上还有offload 分段/校验和等分支本文先给主干。1.2 第一部分rte_mempool对象池1.2.1 解决什么问题热路径禁止频繁 malloc每包malloc/free会带来不可预测延迟与锁竞争。为无锁/低锁优化提供对象粒度 mbuf、小结构体、自定义对象都可用同一套池化框架。1.2.2 核心原理预分配创建 pool 时一次性分配固定大小对象的存储以及元数据。两层结构常见全局空闲结构ring/stack 等 ops 实现。per-lcore local cache热路径优先命中本核 cache批量与全局层交换降低争用。1.2.3 你必须掌握的配置语义正确性相关SP/SC vs MP/MC多生产者/多消费者标志必须与真实并发模型一致否则是未定义行为不是“慢一点”。elt_size / cache_size / private_data_sizeprivate_data_size常用于 mbuf 的dynamic mbuf field或应用私有扩展以版本 API 为准。1.2.4 典型 API阅读源码的入口名rte_mempool_create()/rte_mempool_create_empty()rte_mempool_populate_default()rte_mempool_get_bulk()/rte_mempool_put_bulk()1.2.5 源码阅读线索upstream 主干lib/mempool/rte_mempool.clib/mempool/rte_mempool_ring.c常见 ring 后端lib/eal/include/rte_mempool.h1.2.6 常见误区把 mempool 当成通用堆不规则大小对象请走rte_malloc或自建 allocatormempool 是固定大小高速池。池太小导致 RX 丢包RX burst 取不到 mbuf 时只能丢或统计rx_nombuf具体统计项以 PMD/版本为准。1.3 第二部分rte_mbuf报文元数据 数据指针1.3.1 解决什么问题把“DMA buffer 报文元数据 链式分片”统一成一个可批量传递的对象。为硬件 offload 与软件解析提供统一承载长度、各层偏移、offload 标志、hash、时间戳等。1.3.2 核心结构概念字段名字以头文件为准数据指针与长度data_off、data_len、pkt_len链式 mbuf 用next串联。IOVAbuf_iova或等价字段用于填描述符与IOVA 模式PA/VA/DC强相关见教程四。元数据port、ol_flags、packet_type版本演进、RSShash等。引用计数refcntrte_pktmbuf_clone/attach/free错误会导致泄漏或 double free。1.3.3 mbuf 与 mempool 的关系mbuf对象本体通常来自rte_pktmbuf_pool_create()创建的mempool of mbufs。mbuf 指向的数据 buffer 可能内嵌在 mbuf 对象布局中常见小 mbuf或独立 buffer 区取决于 pool 配置与实现以rte_mbuf.h与 mbuf pool 创建参数为准。1.3.4 典型 APIrte_pktmbuf_alloc()/rte_pktmbuf_free()rte_pktmbuf_adj()/rte_pktmbuf_trim()修改可写头部空间rte_pktmbuf_read()跨链读取1.3.5 源码阅读线索lib/mbuf/rte_mbuf.clib/eal/include/rte_mbuf_core.h/rte_mbuf.h随版本拆分1.3.6 常见工程问题排障语言headroom 不足封装 VLAN/MPLS 时需要预留RTE_PKTMBUF_HEADROOM相关配置。链过长大包分片导致处理成本上升考虑 TSO/GRO 或重组策略。1.4 第三部分rte_ethdev网卡抽象与队列1.4.1 解决什么问题屏蔽厂商 PMD 差异用统一 API 配置端口、队列、RSS、offload、统计。1.4.2 核心对象port_id逻辑端口号0…N-1。RX/TX queue每队列一对descriptor ringrx_burst/tx_burst批量处理。1.4.3 典型初始化序列应用侧心智图rte_eal_init()rte_eth_dev_configure()端口级配置队列数、RSS key、mtu 等rte_eth_rx_queue_setup()/rte_eth_tx_queue_setup()绑定mempool、ring 长度、burst 相关阈值rte_eth_dev_start()运行时rte_eth_rx_burst()/rte_eth_tx_burst()1.4.4rx_burst做了什么抽象层从硬件/描述符环取出已完成项批量产出 mbuf 指针数组给上层。返回值为本次实际收到的 mbuf 个数可能小于nb_pkts请求。1.4.5tx_burst做了什么抽象层尝试把 mbuf 链挂到 TX ring返回实际发送个数未发送成功的 mbuf 仍由调用者负责释放/重试常见新手泄漏点。1.4.6 源码阅读线索抽象层与 PMD 交界lib/ethdev/rte_ethdev.cEthdev 框架具体 NICdrivers/net/*/下对应 PMD 的*_rx.c/*_tx.cIntel/Mellanox 等1.4.7 与 mempool/mbuf 的耦合点rx_queue_setup必须传入mbuf poolPMD 在 RX 上填充 mbuf 并设置port、hash等字段。TX offload可能要求 mbuf 元数据满足特定ol_flags组合否则硬件行为未定义或静默错误。1.5 第四部分把三者串成“一张图”建议你画在白板ethdev RX从 NIC 到 mbuf 指针数组。mbuf指向可 DMA 的 buffer并携带长度与 offload 元数据。mempoolmbuf 的分配/回收速度与无锁特性来源。1.6 推荐阅读顺序源码rte_ethdev.h配置与 burst API。rte_mbuf.h字段语义。rte_mempool.hcache 与 ops。任选一个你使用的 PMDxxx_recv_pkts/xxx_xmit_pkts对照rx_burst/tx_burst。1.7 自测题能答上来即掌握第二步为什么 TX burst 返回小于请求时不能丢 mbufrx_nombuf或等价统计上升意味着什么chained mbuf 下pkt_len与data_len的关系是什么1.8 参考文档DPDK Programmer’s GuideMbuf Library、Mempool Library、Poll Mode Driver、Ethernet Device。不同 PMD 对 offload、RSS、descriptor 格式支持不同性能数字必须以你硬件与 DPDK 版本实测为准。