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

DPDK 19.11下i40e网卡无法发送rte_gso_segment分片的TCP包

DPDK 19.11 GSO分片后i40e网卡无法发送问题

问题场景

在DPDK 19.11中实现GSO(通用分段卸载)功能,参考testpmd完成初始化与分片逻辑,相同代码在hinic网卡上可正常发送,但在i40e网卡上,经rte_gso_segment分片后的报文传递到i40e_xmit_pkts函数后无法发出。

相关代码实现

GSO上下文初始化代码

struct rte_gso_ctx gso_ctx;
static int gso_ctx_setup(struct rte_gso_ctx *gso_ctx, int port_id)
{
    uint32_t gso_types;
    char pool_name[64];

    struct rte_mempool *mp;      /* Mempool for GSO packets */

    /* initialize GSO context */
    gso_types = DEV_TX_OFFLOAD_TCP_TSO;
    snprintf(pool_name, sizeof(pool_name), "gso_%d", port_id);
    mp = rte_mempool_lookup((const char *)pool_name);
    if (!mp) {
        mp = rte_pktmbuf_pool_create(pool_name, 128 * 10,
            4, 0,
            RTE_PKTMBUF_HEADROOM + 128,
            SOCKET_ID_ANY);
        if (!mp) {
            printf("failed to create mbuf pool for device %d\n",port_id);
            return -1;
        }
    }

    gso_ctx->direct_pool = mp;
    gso_ctx->indirect_pool = mp;
    gso_ctx->gso_types = gso_types;
    gso_ctx->gso_size = 1514;
    gso_ctx->flag = 0;
    return 0;
}

分片与发送函数

#define GSO_MAX_PKT_BURST 128
uint32_t tx_xmit(struct rte_mbuf *pkt)
{
    uint32_t sent_pkts = 0;
    struct rte_mbuf *gso_segments[GSO_MAX_PKT_BURST];
    uint16_t nb_segments = 0;
    int ret;

    ret = rte_gso_segment(pkt, &gso_ctx, &gso_segments[nb_segments], GSO_MAX_PKT_BURST - nb_segments);
    if (ret > 0) {
        nb_segments += ret;
    } else {
        printf("unable to segment packet\n");
        rte_pktmbuf_free(pkts[0]); // 此处存在错误,应为rte_pktmbuf_free(pkt)
    }

    rte_eth_tx_burst(port_id, queue_id, &gso_segments[0], nb_segments);
}

输入MBUF设置代码

struct rte_mbuf *head = m;
for (int i = 0; i < head->nb_segs; i++) {
    m->ol_flags = PKT_TX_IPV4 | PKT_TX_TCP_CKSUM | PKT_TX_IP_CKSUM | PKT_TX_TCP_SEG | DEV_TX_OFFLOAD_TCP_TSO;
    // I'm sure the TCP header and data are correct.
    m->data_len = 1514;
    m->pkt_len = 1514 + 1460 + 1460 ....;
    m->l2_len = 14;
    m->l3_len = 20;
    m->l4_len = 20;
    m = m->next;
}

GDB调试的MBUF信息

Thread 4 "tcpip_thread_00" hit Breakpoint 1, i40e_xmit_pkts (tx_queue=0x1fff359c0,
    tx_pkts=0x7ffff5d1adc0, nb_pkts=3)
    at /root/rpmbuild/BUILD/dpdk-19.11/drivers/net/i40e/i40e_rxtx.c:994
994     {
(gdb) p *tx_pkts[0]
$1 = {cacheline0 = 0x1da918f00, buf_addr = 0x1da918f80, {buf_iova = 13330648960,
    buf_physaddr = 13330648960}, rearm_data = 0x1da918f10, data_off = 128, {
    refcnt_atomic = {cnt = 1}, refcnt = 1}, nb_segs = 2, port = 65535,
  ol_flags = 58546795155816448, rx_descriptor_fields1 = 0x1da918f20, {packet_type = 0, {
      l2_type = 0, l3_type = 0, l4_type = 0, tun_type = 0, {
        inner_esp_next_proto = 0 '\000', {inner_l2_type = 0 '\000',
          inner_l3_type = 0 '\000'}}, inner_l4_type = 0}}, pkt_len = 1514,
  data_len = 54, vlan_tci = 0, {hash = {rss = 0, fdir = {{{hash = 0, id = 0}, lo = 0},
        hi = 0}, sched = {queue_id = 0, traffic_class = 0 '\000', color = 0 '\000',
        reserved = 0}, txadapter = {reserved1 = 0, reserved2 = 0, txq = 0}, usr = 0}},
  vlan_tci_outer = 0, buf_len = 256, timestamp = 0, cacheline1 = 0x1da918f40, {
    userdata = 0x0, udata64 = 0}, pool = 0x1da9a8c00, next = 0x1da918d40, {
    tx_offload = 1313294, {l2_len = 14, l3_len = 20, l4_len = 20, tso_segsz = 0,
      outer_l3_len = 0, outer_l2_len = 0}}, priv_size = 0, timesync = 0, seqn = 0,
  shinfo = 0x0, dynfield1 = {0, 0}}
(gdb) p *tx_pkts[0]->next
$2 = {cacheline0 = 0x1da918d40, buf_addr = 0x1e0d33ac8, {buf_iova = 13435615944,
    buf_physaddr = 13435615944}, rearm_data = 0x1da918d50, data_off = 182, {
    refcnt_atomic = {cnt = 1}, refcnt = 1}, nb_segs = 1, port = 65535,
  ol_flags = 4670232813583204352, rx_descriptor_fields1 = 0x1da918d60, {
    packet_type = 0, {l2_type = 0, l3_type = 0, l4_type = 0, tun_type = 0, {
        inner_esp_next_proto = 0 '\000', {inner_l2_type = 0 '\000',
          inner_l3_type = 0 '\000'}}, inner_l4_type = 0}}, pkt_len = 1514,
  data_len = 1460, vlan_tci = 0, {hash = {rss = 0, fdir = {{{hash = 0, id = 0},
          lo = 0}, hi = 0}, sched = {queue_id = 0, traffic_class = 0 '\000',
        color = 0 '\000', reserved = 0}, txadapter = {reserved1 = 0, reserved2 = 0,
        txq = 0}, usr = 0}},
  vlan_tci_outer = 0, buf_len = 2176, timestamp = 0,
  cacheline1 = 0x1da918d80, {userdata = 0x0, udata64 = 0}, pool = 0x1da9a8c00,
  next = 0x0, {tx_offload = 1313294, {l2_len = 14, l3_len = 20, l4_len = 20,
      tso_segsz = 0, outer_l3_len = 0, outer_l2_len = 0}}, priv_size = 72,
  timesync = 0, seqn = 0, shinfo = 0x0, dynfield1 = {0, 0}}

问题分析与修复方案

核心问题点

  1. MBUF的port字段无效:调试信息显示port字段为65535(RTE_MAX_ETHPORTS),i40e驱动依赖该字段做端口合法性校验,无效值会导致报文被丢弃。
  2. ol_flags值异常:输出的ol_flags为超大无意义数值,是循环设置每个seg时的位操作错误(重复赋值或类型溢出);同时保留了DEV_TX_OFFLOAD_TCP_TSO标志——软件GSO已完成分片,无需硬件再执行TSO,该标志会与i40e驱动逻辑冲突。
  3. MBUF字段设置错误:
    • 循环给每个seg设置data_len=1514不符合实际,数据段的data_len应为1460(MTU减去L2/L3/L4头长度)。
    • 仅需在head mbuf上设置l2_len/l3_len/l4_len,无需给每个seg重复设置。
  4. tx_xmit函数的错误处理:分片失败时错误释放pkts[0],实际应释放输入的pkt。

修复步骤

  1. 修正MBUF设置逻辑:
    struct rte_mbuf *head = m;
    // 仅在head上设置ol_flags,移除硬件TSO标志
    head->ol_flags = PKT_TX_IPV4 | PKT_TX_TCP_CKSUM | PKT_TX_IP_CKSUM | PKT_TX_TCP_SEG;
    head->pkt_len = 1514 + 1460 + 1460; // 总报文长度
    head->data_len = 54; // 第一个seg的有效数据长度(L2+L3+L4头)
    head->l2_len = 14;
    head->l3_len = 20;
    head->l4_len = 20;
    head->port = port_id; // 设置正确的端口ID
    
    struct rte_mbuf *seg = head->next;
    while (seg) {
        seg->data_len = 1460; // 数据段长度
        seg->pkt_len = head->pkt_len; // 每个seg的pkt_len为总长度
        seg->l2_len = 0;
        seg->l3_len = 0;
        seg->l4_len = 0;
        seg->port = port_id; // 设置端口ID
        seg->ol_flags = 0; // 数据段无需设置ol_flags
        seg = seg->next;
    }
    
  2. 修正tx_xmit的错误处理:
    if (ret > 0) {
        nb_segments += ret;
    } else {
        printf("unable to segment packet\n");
        rte_pktmbuf_free(pkt); // 释放输入的原始报文
    }
    
  3. 验证GSO上下文配置:确认gso_size=1514符合当前端口MTU配置(需包含L2头),若端口MTU为1500,需保持gso_size=1500+14=1514一致。

内容的提问来源于stack exchange,提问作者J.Heng

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 05:01:06