DPDK 19.11.10中TX_TYPE模式下无法接收UDP包问题求助
问题分析与修复方案
核心问题1:未正确传递核心对应的端口/队列参数
你的rxtx_loop函数中直接使用portid变量,但该变量未被正确赋值,且调用rte_eal_remote_launch时传递的参数是NULL,这会引发未定义行为——RX_TYPE模式下可能碰巧portid值符合预期,但TX_TYPE模式下指向错误端口,自然无法接收数据包。
修复方式:
- 定义结构体存储每个核心的端口、队列及类型参数,传递给
rxtx_loop:
struct lcore_args { int portid; int queueid; int lid_type; }; // main函数中为每个核心初始化参数 struct lcore_args lcore_args[RTE_MAX_LCORE]; for (int i = 0; i < RTE_MAX_LCORE; i++ ) { if ( (i == rte_get_main_lcore()) || !rte_lcore_is_enabled(i) ) continue; int type = get_type(i); lcore_args[i].lid_type = type; // 匹配启动命令的核心-端口映射:核心2/3对应port0,核心4/5对应port1 if (i == 2 || i == 3) { lcore_args[i].portid = 0; lcore_args[i].queueid = i - 2; } else if (i == 4 || i == 5) { lcore_args[i].portid = 1; lcore_args[i].queueid = i - 4; } int ret = rte_eal_remote_launch(rxtx_loop, &lcore_args[i], i); } // 修改rxtx_loop函数 int rxtx_loop(void * arg) { struct lcore_args *args = arg; int portid = args->portid; int lid_type = args->lid_type; int queueid = args->queueid; if (lid_type == TX_TYPE || lid_type == RX_TYPE){ send_udp_pkt(portid, queueid); } return 0; } // 修改send_udp_pkt,接收queueid参数 void send_udp_pkt(int portid, int queueid) { struct rte_mbuf *pkts[DEFAULT_PKT_BURST+1] = { }; while(1){ /* 构建UDP数据包逻辑(需补充) */ uint16_t cnt = DEFAULT_PKT_BURST; // 此处需填充pkts数组,设置正确的cnt值 rte_eth_tx_burst(portid, queueid, pkts, cnt); /* 接收并处理数据包 */ uint16_t rx_cnt = rte_eth_rx_burst(portid, queueid, pkts, 32); // 释放接收后的mbuf,避免内存池耗尽 for(int j=0; j<rx_cnt; j++){ rte_pktmbuf_free(pkts[j]); } } }
核心问题2:RX队列与核心绑定配置缺失
在config_ports()函数中,必须确保每个端口的RX队列绑定到对应核心,否则即使调用rte_eth_rx_burst,核心也无法从不属于自己的队列中接收数据包。
示例配置代码:
void config_ports() { struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = RTE_ETHER_MAX_LEN }, }; uint16_t nb_rx_queues = 2; uint16_t nb_tx_queues = 2; // 配置端口0,绑定RX队列到核心2、3 int ret = rte_eth_dev_configure(0, nb_rx_queues, nb_tx_queues, &port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Failed to configure port 0"); struct rte_mempool *pool0 = rte_pktmbuf_pool_create("POOL_PORT0_QUEUE0", 8192, 0, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_lcore_to_socket_id(2)); struct rte_mempool *pool1 = rte_pktmbuf_pool_create("POOL_PORT0_QUEUE1", 8192, 0, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_lcore_to_socket_id(3)); ret = rte_eth_rx_queue_setup(0, 0, 1024, rte_lcore_to_socket_id(2), NULL, pool0); ret = rte_eth_rx_queue_setup(0, 1, 1024, rte_lcore_to_socket_id(3), NULL, pool1); // 配置端口1,绑定RX队列到核心4、5 ret = rte_eth_dev_configure(1, nb_rx_queues, nb_tx_queues, &port_conf); struct rte_mempool *pool2 = rte_pktmbuf_pool_create("POOL_PORT1_QUEUE0", 8192, 0, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_lcore_to_socket_id(4)); struct rte_mempool *pool3 = rte_pktmbuf_pool_create("POOL_PORT1_QUEUE1", 8192, 0, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_lcore_to_socket_id(5)); ret = rte_eth_rx_queue_setup(1, 0, 1024, rte_lcore_to_socket_id(4), NULL, pool2); ret = rte_eth_rx_queue_setup(1, 1, 1024, rte_lcore_to_socket_id(5), NULL, pool3); // 启动端口 rte_eth_dev_start(0); rte_eth_dev_start(1); }
核心问题3:发送逻辑的未定义变量问题
你的代码中rte_eth_tx_burst的cnt变量未定义,且pkts数组初始为空,会导致发送空包或错误数量的数据包。必须在调用发送接口前,正确构建UDP数据包并设置cnt为实际要发送的包数量。
示例构建UDP包的逻辑片段:
// 在send_udp_pkt的发送部分添加 uint16_t cnt = DEFAULT_PKT_BURST; struct rte_mempool *mbuf_pool = /* 对应端口的内存池,需提前传递或全局定义 */; for(int j=0; j<cnt; j++){ pkts[j] = rte_pktmbuf_alloc(mbuf_pool); if(pkts[j] == NULL) break; // 填充以太网、IP、UDP头部 struct rte_ether_hdr *eth_hdr = rte_pktmbuf_mtod(pkts[j], struct rte_ether_hdr *); // 补充目标MAC、源MAC等字段 struct rte_ipv4_hdr *ip_hdr = (struct rte_ipv4_hdr *)(eth_hdr + 1); // 补充IP版本、长度、源/目的IP等字段 struct rte_udp_hdr *udp_hdr = (struct rte_udp_hdr *)(ip_hdr + 1); // 补充UDP源/目的端口、长度等字段 pkts[j]->data_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_udp_hdr); pkts[j]->pkt_len = pkts[j]->data_len; } cnt = j; // 实际成功分配的包数量 rte_eth_tx_burst(portid, queueid, pkts, cnt);
总结
TX_TYPE模式下无法接收数据包的根本原因:
- 核心对应的端口/队列参数未正确传递,
portid变量未定义,导致收包操作指向错误的端口/队列。 - RX队列未与对应核心绑定,核心无权限从队列中接收数据包。
- 发送逻辑存在未定义变量,影响流程稳定性。
内容的提问来源于stack exchange,提问作者Das
相关产品推荐
相关产品推荐

