目录
- DPDK 基础使用:从 EAL 初始化到 RX/TX 队列收发数据
- 1. 初始化顺序不能乱
- 2. 配置端口与队列
- 3. 从队列取包并解析
- 4. 组包与发送
- 5. 验证结果
- 小结
DPDK 基础使用:从 EAL 初始化到 RX/TX 队列收发数据
标签:DPDKrte_mbufrte_mempool收发队列
课程的receive.c、send.c与echo.c建立了最小收发闭环:初始化 EAL,创建 mbuf 内存池,配置端口队列,轮询接收,解析以太网帧并组包发送。
1. 初始化顺序不能乱
rte_eal_init -> rte_pktmbuf_pool_create -> rte_eth_dev_configure -> rte_eth_rx_queue_setup / rte_eth_tx_queue_setup -> rte_eth_dev_start -> rte_eth_rx_burst <-> rte_eth_tx_burstEAL 负责解析 DPDK 参数、初始化大页内存和逻辑核环境。端口启动前,RX/TX 描述符环必须就绪。
if(rte_eal_init(argc,argv)<0)rte_exit(EXIT_FAILURE,"EAL init failed\n");structrte_mempool*pool=rte_pktmbuf_pool_create("MBUF_POOL",NUM_MBUFS,MBUF_CACHE_SIZE,0,RTE_MBUF_DEFAULT_BUF_SIZE,rte_socket_id());if(pool==NULL)rte_exit(EXIT_FAILURE,"mempool create failed\n");NUM_MBUFS在课程中常取2^n - 1。rte_ring 的容量管理与 2 的幂相关,具体值仍应由队列数、突发大小和内存预算确定。
2. 配置端口与队列
structrte_eth_confport_conf={0};rte_eth_dev_configure(port_id,1,1,&port_conf);rte_eth_rx_queue_setup(port_id,0,1024,rte_eth_dev_socket_id(port_id),NULL,pool);rte_eth_tx_queue_setup(port_id,0,1024,rte_eth_dev_socket_id(port_id),NULL);rte_eth_dev_start(port_id);一个队列对应一组描述符。多队列网卡可将队列、中断(若使用)和 lcore 进行 CPU 亲和性规划;本课程先以单队列把数据路径跑通。
3. 从队列取包并解析
rte_eth_rx_burst一次取一批rte_mbuf,没有数据时返回 0。这也是 DPDK 轮询模型的核心。
structrte_mbuf*mbufs[BURST_SIZE];uint16_tn=rte_eth_rx_burst(port_id,0,mbufs,BURST_SIZE);for(uint16_ti=0;i<n;i++){structrte_ether_hdr*eth=rte_pktmbuf_mtod(mbufs[i],structrte_ether_hdr*);if(eth->ether_type==rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)){structrte_ipv4_hdr*ip=rte_pktmbuf_mtod_offset(mbufs[i],structrte_ipv4_hdr*,sizeof(*eth));/* 按 ip->next_proto_id 继续分发 */}rte_pktmbuf_free(mbufs[i]);}rte_pktmbuf_mtod取得数据首地址;rte_pktmbuf_mtod_offset在同一 mbuf 上按字节偏移解释下一个协议头。任何分支处理结束后都要明确释放或转交 mbuf 所有权。
4. 组包与发送
发送方向相反:从内存池申请 mbuf,追加实际数据空间,填充协议头,最后批量入 TX 队列。
structrte_mbuf*tx=rte_pktmbuf_alloc(pool);char*buf=rte_pktmbuf_append(tx,pkt_len);if(buf==NULL){rte_pktmbuf_free(tx);return-ENOMEM;}/* 填充 Ethernet/IP/UDP 或 ICMP 数据 */uint16_tsent=rte_eth_tx_burst(port_id,0,&tx,1);if(sent<1)rte_pktmbuf_free(tx);注意:data_len是当前分段长度,pkt_len是完整报文长度;多段 mbuf 时二者并不相等。IP/UDP/TCP 校验和必须在字段填完、校验和字段清零后计算。
5. 验证结果
课程用 echo 回包建立了收发验证闭环:
小结
掌握这六个 API 就掌握了 DPDK 的骨架:rte_eal_init、rte_pktmbuf_pool_create、rte_eth_dev_configure、队列 setup、rte_eth_rx_burst、rte_eth_tx_burst。后续 ARP、ICMP、UDP 与 TCP 的区别,主要发生在 mbuf 数据区如何解析和重组。
学习链接: https://github.com/0voice