1

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 Answers1

0

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

Andriy Berestovskyy
  • 8,059
  • 3
  • 17
  • 33
  • I guess its PKT_TX_IP_CKSUM and not PKT_TX_IP_CSUM correct me if I am wrong as it gave me compilation error when I tried to use PKT_TX_IP_CSUM – user11221955 Mar 30 '19 at 11:10
  • Sorry, it’s a copy paste from the guide. – Andriy Berestovskyy Mar 30 '19 at 11:59
  • I think I pasted my code as an "answer Your Question" instead of "Add Comment" above.Sorry for that.Do you see any issue with the code ?I think I should try to compute the ip header checksum at the application level as its not getting computed at the hardware level. – user11221955 Mar 30 '19 at 13:05
  • I don't follow, why is the code snippet duplicated in your answer? And what about the reference to outer checksums? – maxschlepzig Sep 11 '21 at 08:29