skip to Main Content

I am using DPDK19.11.10 on centos.

The application is working fine with HW offloading if I send only the IPV4 packet without the VLAN header.

If I add the VLAN header with IPV4, HW offloading is not working.
If capture the pcap on ubuntu gateway the IP header is corrupted with Fragmented IP packet even though we are not fragmenting IP packet.

We verified capabalities like this:

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

Below is my code:

.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));

Once I received the packet in the ubuntu gateway the IP packet is corrupted as a fragmented IP packet.
enter image description here

The same code works fine if I removed the VLAN header.
Does anything else need to add here?

2

Answers


  1. By the sound of it,

    1. You might misunderstand the way how HW Tx VLAN offload is supposed to work;
    2. Your code does not update m->l2_len when it inserts a VLAN header.

    First of all, your code enables support for HW Tx VLAN offload, but, oddly enough, it does not actually attempt to use it. If one wants to use hardware Tx VLAN offload, they should set PKT_TX_VLAN in m->ol_flags and fill out m->vlan_tci. The VLAN header will be added by the hardware.

    However, your code prepends the header itself, like if there was no intent to use a hardware offload in the first place. Your code does m->l2_len = L2_HDR_SIZE;, which, as I presume, only counts for Ethernet header. When your code prepends a VLAN header, this variable has to be updated accordingly:

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

    Login or Signup to reply.
  2. Most DPDK NIC PMD supports HW VLAN offload (RX direction). But a limited number of PMD support the DEV_TX_OFFLOAD_VLAN_INSERT feature namely

    1. Aquantia Atlantic
    2. Marvell OCTEON CN9K/CN10K SoC
    3. Cisco VIC adapter
    4. Pensando NIC
    5. OCTEON TX2
    6. Wangxun 10 Gigabit Ethernet NIC and
    7. Intel NIC – i40e, ice, iavf, ixgbe, igb

    To enable HW VLAN INSERT one needs to check

    1. if DEV_TX_OFFLOAD_VLAN_INSERT by checking get_dev_info
    2. configure tx offload for the port with DEV_TX_OFFLOAD_VLAN_INSERT
    3. enable MBUF descriptor with ol_flags = PKT_TX_VLAN and vlan_tci = [desired TCI in big-endian format]

    This will allow the driver code in xmit function to check mbuf descriptors ol_flags for PKT_TX_VLAN and enables VLAN Insert offload to Hardware by registering the appropriate command with the Packet Descriptor before DMA.

    From DPDK conditions are to be satisfied

    1. at a given instance there should only be 1 thread access and updating the mbuf.
    2. no modification for the mbuf is to be done on the original mbuf (with payload).

    If the intention is to perform VLAN insert via SW (especially if HW or virtual NIC PMD does not support), in dpdk one has to do the following

    • Ensure the refcnt is 1 to prevent multiple thread access and modification on the intended buffer.
    • There is enough headroom to shift the packet 4 bytes to accommodate the Ether type and VLAN values.
    • ensure pkt_len and data_len are in bound (greater than 60 bytes and less than 4 bytes of MTU)
    • MBUF offload descriptors is not enabled for PKT_TX_VLAN
    • update data_len on the modified MBUF by 4 Bytes.
    • Update total pkt_len by 4.
    • (optional for performance consideration) prefetch the 4 bytes prior to mtod of mbuf memory address

    Note: All the above things are easily achieved by using the DPDK function rte_vlan_insert. TO use the same follow the steps as

    • Do not configure the port with DEV_TX_OFFLOAD_VLAN_INSERT.

    • Update ol_flags with PKT_TX_VLAN and vlan_tci desired value.

    • Invoke rte_vlan_insert with the mbuf

    Sample code:

    /* 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]);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search