公司动态

DPDK数据面收包过程

📅 2026/8/16 9:49:26
DPDK数据面收包过程
分阶段明确两端角色1、收包 burst 阶段硬件 DMA 环生产者 NIC 网卡 DMA 硬件消费者rx_threadCPU2、rte_ring 传递阶段软件无锁环生产者rx_threadCPU消费者worker 线程CPU以下代码是第 1 阶段。/* 轮询网卡接收报文mbuf 送入无锁 rx_ring 完全不解析控制命令只处理业务数据帧 1、网口收到报文 - NIC DMA 硬件把报文写入 mbuf 物理内存更新硬件 RX 描述符 2、rte_eth_rx_burst() CPU 线程去 poll 硬件desc ring拿到已填好的 mbuf 3、软件做 vlan 过滤丢弃不匹配的报文 4、把合法的 mbuf 指针 push进 rte_ring软件无锁队列只存指针 5、worker 线程从 rte_ring 取出 mbuf 指针处理报文 6、worker 线程处理完调用 rte_pkt_mbuf_free 归还 mbuf 到 mempool */staticintdata_plane_rx_thread(void*arg){RTE_SET_USED(arg);printf([DataPlane] RX thread start\n);structrte_mbuf*bufs[32];while(1){// 从网卡硬件Rx队列批量收包uint16_tnb_rxrte_eth_rx_burst(g_port_id,0,bufs,32);if(nb_rx0){for(inti0;inb_rx;i){structrte_mbuf*mbufs[i];uint16_tvlanrte_vlan_get_vlan(m);if(vlan!g_dev_cfg.target_vlan){rte_pktmbuf_free(m);continue;}// 推入无锁ring交给worker处理rte_ring_enqueue(rx_ring,m);}}rte_pause();}return0;}DPDK 大页内存/* 1、struct rte_mbuf 报文描述头对象这个结构体本身的地址是用户态虚拟地址 2、mbuf 结构体 报文 buffer(payload) 是连续存在一个 mempool 对象里面都在大页内存 3、mempool 大页内存同时可供 DMA 硬件 用户进程 CPU 访问 */structrte_mbuf{void*buf_addr;// 虚拟地址VACPU访问报文数据用rte_iova_tbuf_iova;// IOVA物理地址DMA硬件使用// ...}/* 1、m 这个指针的值就是 struct rte_mbuf 实例的用户态虚拟地址 2、CPU通过这个虚拟地址访问 mbuf 里各个成员buf_addr、buf_iova、data_off 3、struct rte_mbuf元数据头只有 CPU 访问硬件不碰地址是用户虚拟地址。 4、payload 报文缓冲区CPU (VA)、网卡 DMA (IOVA) 两边都访问这块才是 DMA‑coherent 内存。 5、默认情况下mbuf 结构体和 payload 缓冲区在 mempool 里面物理连续的一大块大页 6、硬件只往 payload 部分 DMA 写数据 7、mbuf 结构体那一段硬件根本不去碰。 */structrte_mbuf*mrte_pkt_mbuf_alloc(pool)【rte_mempool】 ├─大页整块内存 │ ├─mbuf#0structrte_mbuf{buf_addr,buf_iova,...}紧随其后的报文buffer │ ├─mbuf#1structrte_mbuf{buf_addr,buf_iova,...}紧随其后的报文buffer │ └─mbuf#2structrte_mbuf{buf_addr,buf_iova,...}紧随其后的报文bufferRX 描述符环是网卡硬件自己维护的一块内存// 网卡硬件RX Descriptorstructrx_desc_hw{rte_iova_tbuf_iova;// DMA写入的IO物理地址CPU填入uint64_tstatus;// 硬件写收包完成、包长度、错误标记};整个 RX ring 就是一个数组头尾循环形成环rx_desc_hw desc_ring[DESC_NUM];// 环形数组比如512个描述符head(硬件指针)↓ ┌─────┬─────┬─────┬─────┬─────┬─────┐ │desc0│desc1│desc2│desc3│desc4│desc5│ └─────┴─────┴─────┴─────┴─────┴─────┘ ↑tail(CPU软件指针)head网卡硬件维护指针硬件下一个要用的描述符位置硬件顺着 head 填报文、更新 status。 tailCPU 软件维护指针CPU 下一个要填充新 buffer 的位置。1 个硬件 RX 描述符对应 1 个 struct rte_mbuf*对应 bufs[] 里面的一个元素 bufs[i]。