In csum forwarding mode, software UDP/TCP csum calculation only takes the first segment into account while using the whole packet length so the calculation will read invalid memory region with multi-segments packets and will get wrong value. This patch fixes this issue.
Fixes: af75078fece3 ("first public release") Cc: sta...@dpdk.org Signed-off-by: Xiaoyun Li <xiaoyun...@intel.com> --- v2: * Use static stack memory instead of dynamic allocating in datapath. --- app/test-pmd/csumonly.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c index 090797318a..9f78ac74e1 100644 --- a/app/test-pmd/csumonly.c +++ b/app/test-pmd/csumonly.c @@ -56,6 +56,11 @@ #define GRE_SUPPORTED_FIELDS (GRE_CHECKSUM_PRESENT | GRE_KEY_PRESENT |\ GRE_SEQUENCE_PRESENT) +/* When UDP or TCP or outer UDP csum offload is off, sw l4 csum is needed */ +#define UDP_TCP_CSUM (DEV_TX_OFFLOAD_UDP_CKSUM |\ + DEV_TX_OFFLOAD_TCP_CKSUM |\ + DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) + /* We cannot use rte_cpu_to_be_16() on a constant in a switch/case */ #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN #define _htons(x) ((uint16_t)((((x) & 0x00ffU) << 8) | (((x) & 0xff00U) >> 8))) @@ -602,12 +607,8 @@ process_outer_cksums(void *outer_l3_hdr, struct testpmd_offload_info *info, /* do not recalculate udp cksum if it was 0 */ if (udp_hdr->dgram_cksum != 0) { udp_hdr->dgram_cksum = 0; - if (info->outer_ethertype == _htons(RTE_ETHER_TYPE_IPV4)) - udp_hdr->dgram_cksum = - rte_ipv4_udptcp_cksum(ipv4_hdr, udp_hdr); - else - udp_hdr->dgram_cksum = - rte_ipv6_udptcp_cksum(ipv6_hdr, udp_hdr); + udp_hdr->dgram_cksum = get_udptcp_checksum(outer_l3_hdr, + udp_hdr, info->outer_ethertype); } return ol_flags; @@ -877,7 +878,17 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) rte_ether_addr_copy(&ports[fs->tx_port].eth_addr, ð_hdr->src_addr); parse_ethernet(eth_hdr, &info); - l3_hdr = (char *)eth_hdr + info.l2_len; + /* When sw csum is needed, multi-segs needs a buf to contain + * the whole packet for later UDP/TCP csum calculation. + */ + if (m->nb_segs > 1 && !(tx_ol_flags & PKT_TX_TCP_SEG) && + !(tx_offloads & UDP_TCP_CSUM)) { + char l3_buf[RTE_IPV4_MAX_PKT_LEN + 1]; + rte_pktmbuf_read(m, info.l2_len, + info.pkt_len - info.l2_len, l3_buf); + l3_hdr = l3_buf; + } else + l3_hdr = (char *)eth_hdr + info.l2_len; /* check if it's a supported tunnel */ if (txp->parse_tunnel) { -- 2.25.1