1
votes

The offload flags used for checksum calculation at hardware level is not effective with newer version of DPDK 18.08.Checksum is not getting computed at hardware level after setting these flags.The checksum values remains the same as what is set by the application software.This results in bad IPV4 header checksum errors and UDP bad checksum errors and eventually packet drop at the router.These checksum offload flags were working with older version of DPDK and same flags and same piece of code is not working now.

The ol_flags in the rte_mbuf struct has been used to set the checksum offloading for IPV4 and UDP packets at the software level.Is there any known issue with DPDK 18.08 with respect to these checksum offload flags for IPV4 and UDP packets? The code used for checksum offload setting using ol_flags of rte_mbuf struct is shown below.

struct ipv4_hdr *ip = NULL;
struct udp_hdr* udphdr;
struct rte_mbuf *mbuf;

ip = (struct ipv4_hdr*)(rte_pktmbuf_mtod(m, unsigned char *) + l2_data_shift);
udphdr = (struct udp_hdr*)(rte_pktmbuf_mtod(m, unsigned char *) + l2_data_shift + sizeof(struct ipv4_hdr));


ip->hdr_checksum = 0;  
m->data_len = m->pkt_len = l2_data_shift +rte_be_to_cpu_16(ip->total_length);
mbuf->l3_len = sizeof(struct ipv4_hdr);
m->ol_flags |= PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM;
udphdr->dgram_cksum =ipv4sum(ip);



uint16_t ipv4sum(struct ipv4_hdr * ip_hdr)
{
    uint16_t proto;
    uint32_t sum;

    proto = ip_hdr->next_proto_id;
    proto = rte_cpu_to_be_16(proto);
    sum = proto;

    sum += rte_cpu_to_be_16((uint16_t)(rte_be_to_cpu_16(ip_hdr->total_length) - sizeof(struct ipv4_hdr)));
    if (sum > UINT16_MAX) sum -= UINT16_MAX;

    sum += ip_hdr->src_addr & 0xFFFF;
    if (sum > UINT16_MAX) sum -= UINT16_MAX;
    sum += (ip_hdr->src_addr >> 16);
    if (sum > UINT16_MAX) sum -= UINT16_MAX;

    sum += ip_hdr->dst_addr & 0xFFFF;
    if (sum > UINT16_MAX) sum -= UINT16_MAX;
    sum += (ip_hdr->dst_addr >> 16);
    if (sum > UINT16_MAX) sum -= UINT16_MAX;

    sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
    sum &= 0x0ffff;

    return (uint16_t)sum;

}

Can you please suggest a workaround solution to overcome these checksum errors and packet drop?

1
See the answer to a similar question for a working example.maxschlepzig

1 Answers

0
votes

There are two issues with the code:

  1. The l2_len must be correctly set (probably to the length of the Ethernet header?)
  2. Instead of a custom function ipv4sum(), we better use the DPDK's rte_ipv4_phdr_cksum().

So, to calculate the outer IP and UDP checksums:

mb->l2_len = len(out_eth)
mb->l3_len = len(out_ip)
mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM | PKT_TX_UDP_CKSUM
set out_ip checksum to 0 in the packet
set out_udp checksum to pseudo header using rte_ipv4_phdr_cksum()

Just in case, to calculate the outer IP and TCP checksums:

mb->l2_len = len(out_eth)
mb->l3_len = len(out_ip)
mb->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CSUM | PKT_TX_TCP_CKSUM
set out_ip checksum to 0 in the packet
set out_tcp checksum to pseudo header using rte_ipv4_phdr_cksum()

Source: DPDK Programmers Guide