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?
There are two issues with the code:
l2_len
must be correctly set (probably to the length of the Ethernet header?)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
1.)I forgot to mention that l2 len has been set as follows.
if (ETHER_TYPE_VLAN == eth_type)
{
mbuf->l2_len = sizeof(struct ether_hdr) + sizeof(struct vlan_hdr);
}
else {
mbuf->ol_flags = PKT_TX_VLAN_PKT;
mbuf->l2_len = sizeof(struct ether_hdr);
}
2.) I did try to use the second option as well after setting l2_len and l3_len but it didn't work.
ip->hdr_checksum = 0;
mbuf->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM;
udphdr->dgram_cksum = rte_ipv4_phdr_cksum(mbuf->l3_len, mbuf->ol_flags);
3.) As it was mentioned that its supported on hardware advertising DEV_TX_OFFLOAD_IPV4_CKSUM,DEV_TX_OFFLOAD_UDP_CKSUM and DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM.
So as another option I did try to set txmode offloads during port initialisation along with option 2.)
struct rte_eth_conf port_conf;
port_conf.txmode.offloads |= DEV_TX_OFFLOAD_UDP_CKSUM |DEV_TX_OFFLOAD_IPV4_CKSUM;
ret = rte_eth_dev_configure(port, nbqueue, nbqueue, &port_conf);
This also didn't work. Please suggest any other workarounds I can try.
User contributions licensed under CC BY-SA 3.0