0

我在 centos 上使用 DPDK19.11.10。

如果我只IPV4发送没有VLAN标头的数据包,则应用程序可以很好地进行硬件卸载。

如果我VLAN使用 IPV4 添加标头,则硬件卸载不起作用。如果在 ubuntu 网关上捕获 pcap,Fragmented IP packet即使我们没有对 IP 数据包进行分段,IP 标头也会损坏。

我们验证了这样的能力:

if (!(dev->tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT)) {
          rte_panic(" VLAN offload not supported");
}

下面是我的代码:

.offloads = (DEV_TX_OFFLOAD_IPV4_CKSUM |
                              DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_VLAN_INSERT),
m->l2_len = L2_HDR_SIZE;
m->l3_len = L3_IPV4_HDR_SIZE;
ip_hdr->check       = 0;
m->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM;
ip_hdr = rte_pktmbuf_mtod(m, struct iphdr *);
vlan1_hdr = (struct vlan1_hdr *) rte_pktmbuf_prepend(m, sizeof(struct vlan1_hdr));
eth_hdr = (struct ethernet_hdr *) rte_pktmbuf_prepend(m, (uint16_t)sizeof(struct ethernet_hdr));

一旦我在 ubuntu 网关中收到数据包,IP 数据包就会被损坏为碎片 IP 数据包。 在此处输入图像描述

如果我删除了VLAN标题,相同的代码可以正常工作。这里还有什么需要补充的吗?

4

2 回答 2

1

听它的声音,

  1. 您可能会误解 HW Tx VLAN 卸载的工作方式;
  2. m->l2_len您的代码在插入 VLAN 标头时不会更新。

首先,您的代码支持 HW Tx VLAN 卸载,但奇怪的是,它实际上并没有尝试使用它。如果要使用硬件Tx VLAN 卸载,则应设置PKT_TX_VLANm->ol_flags填写m->vlan_tci。VLAN 标头将由硬件添加。

但是,您的代码会预先添加标头本身,就像一开始就没有使用硬件卸载的意图一样。您的代码确实m->l2_len = L2_HDR_SIZE;如此,据我推测,这仅适用于以太网标头。当您的代码预先添加 VLAN 标头时,必须相应地更新此变量:

m->l2_len += sizeof(struct rte_vlan_hdr);

于 2021-12-24T10:46:59.753 回答
1

大多数 DPDK NIC PMD 支持 HW VLAN 卸载(RX 方向)。但是有限数量的 PMD 支持 DEV_TX_OFFLOAD_VLAN_INSERT 功能,即

  1. Aquantia大西洋
  2. Marvell OCTEON CN9K/CN10K SoC
  3. 思科 VIC 适配器
  4. 彭桑多网卡
  5. 奥克森TX2
  6. 网讯10G以太网网卡和
  7. 英特尔 NIC - i40e、ice、iavf、ixgbe、igb

要启用 HW VLAN INSERT 需要检查

  1. 如果 DEV_TX_OFFLOAD_VLAN_INSERT 通过检查 get_dev_info
  2. 使用 DEV_TX_OFFLOAD_VLAN_INSERT 为端口配置 tx 卸载
  3. ol_flags = PKT_TX_VLAN使用和启用 MBUF 描述符vlan_tci = [desired TCI in big-endian format]

这将允许xmit函数中的驱动程序代码检查 PKT_TX_VLAN 的 mbuf 描述符ol_flags,并通过在 DMA 之前使用数据包描述符注册适当的命令来启用 VLAN 插入卸载到硬件。

DPDK条件要满足

  1. 在给定的实例中,应该只有 1 个线程访问和更新 mbuf。
  2. 不会对原始 mbuf 进行任何修改(带有有效负载)。

如果打算通过 SW 执行 VLAN 插入(特别是如果 HW 或虚拟 NIC PMD 不支持),则在 dpdk 中必须执行以下操作

  • 确保 refcnt 为 1 以防止多线程访问和修改预期缓冲区。
  • 有足够的余量将数据包移动 4 个字节以适应 Ether 类型和 VLAN 值。
  • 确保 pkt_len 和 data_len 绑定(大于 60 字节且小于 4 字节的 MTU)
  • 未为 PKT_TX_VLAN 启用 MBUF 卸载描述符
  • 将修改后的 MBUF 上的 data_len 更新 4 个字节。
  • 将总 pkt_len 更新 4。
  • (出于性能考虑可选)预取 mbuf 内存地址的 mtod 之前的 4 个字节

注意:以上所有事情都可以通过使用 DPDK 函数 rte_vlan_insert 轻松实现。要使用相同的步骤,请按照

  • 不要使用 DEV_TX_OFFLOAD_VLAN_INSERT 配置端口。

  • 使用 PKT_TX_VLAN 和 vlan_tci 所需值更新 ol_flags。

  • 使用 mbuf 调用 rte_vlan_insert

示例代码:

/* Get burst of RX packets, from first port of pair. */
struct rte_mbuf *bufs[BURST_SIZE];
const uint16_t nb_rx = rte_eth_rx_burst(port, 0, bufs, BURST_SIZE);

if (unlikely(nb_rx == 0))
        continue;

for (int i = 0; i < nb_rx; i++) {
        bufs[i]->ol_flags = PKT_TX_VLAN;
        bufs[i]->vlan_tci = 0x10;

        rte_vlan_insert(&bufs[i]);
}

/* Send burst of TX packets, to second port of pair. */
const uint16_t nb_tx = rte_eth_tx_burst(port, 0,
                bufs, nb_rx);

/* Free any unsent packets. */
if (unlikely(nb_tx < nb_rx)) {
        uint16_t buf;
        for (buf = nb_tx; buf < nb_rx; buf++)
                rte_pktmbuf_free(bufs[buf]);
}
于 2021-12-30T08:54:16.277 回答