You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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模式下无法接收数据包的根本原因:

  1. 核心对应的端口/队列参数未正确传递,portid变量未定义,导致收包操作指向错误的端口/队列。
  2. RX队列未与对应核心绑定,核心无权限从队列中接收数据包。
  3. 发送逻辑存在未定义变量,影响流程稳定性。

内容的提问来源于stack exchange,提问作者Das

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:25:56