[PATCH] app/testpmd: fix inner UDP checksum offload fail

Chengwen Feng fengchengwen at huawei.com
Mon Nov 17 08:50:46 CET 2025


If the packet is ether+ipv6+vxlan+ether+ipv4+udp, the parse_l4_proto()
function will treat the inner IPv4 header as an IPv6 header. As a
result, it cannot identify the inner L4 protocol type, leading to the
failure of the inner UDP checksum offload.

This commit changes the handling of the inner layer to match that of
the outer layer, allowing for the reuse of subsequent processes. It
also fixes the issue where the L4 could not be identified in the case
of an ether+ipv4+vxlan+ether+ipv6+udp encapsulation.

Bugzilla ID: 1813
Fixes: 496159613ffc ("app/testpmd: fix L4 protocol retrieval from L3 header")
Fixes: 76730c7b9b5a ("app/testpmd: use packet type parsing API")
Cc: stable at dpdk.org

Signed-off-by: Chengwen Feng <fengchengwen at huawei.com>
---
 app/test-pmd/csumonly.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c
index a6e872e5a4..c841651756 100644
--- a/app/test-pmd/csumonly.c
+++ b/app/test-pmd/csumonly.c
@@ -526,11 +526,26 @@ get_tunnel_ol_flags_by_ptype(uint32_t ptype)
 }
 
 static uint8_t
-parse_l4_proto(const struct rte_mbuf *m, uint32_t off, uint32_t ptype, bool parse_inner)
+parse_l4_proto(const struct rte_mbuf *m, uint32_t off, uint32_t ptype, bool in_tunnel)
 {
+	uint32_t align_ptype = ptype;
 	int frag = 0, ret;
 
-	if (RTE_ETH_IS_IPV4_HDR(ptype)) {
+	if (in_tunnel) {
+		uint32_t mask_ptype = ptype & RTE_PTYPE_INNER_L3_MASK;
+		if (mask_ptype == RTE_PTYPE_INNER_L3_IPV4)
+			align_ptype = RTE_PTYPE_L3_IPV4;
+		else if (mask_ptype == RTE_PTYPE_INNER_L3_IPV4_EXT)
+			align_ptype = RTE_PTYPE_L3_IPV4_EXT;
+		else if (mask_ptype == RTE_PTYPE_INNER_L3_IPV6)
+			align_ptype = RTE_PTYPE_L3_IPV6;
+		else if (mask_ptype == RTE_PTYPE_INNER_L3_IPV6_EXT)
+			align_ptype = RTE_PTYPE_L3_IPV6_EXT;
+		else
+			align_ptype = 0;
+	}
+
+	if (RTE_ETH_IS_IPV4_HDR(align_ptype)) {
 		const struct rte_ipv4_hdr *ip4h;
 		struct rte_ipv4_hdr ip4h_copy;
 		ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
@@ -538,17 +553,14 @@ parse_l4_proto(const struct rte_mbuf *m, uint32_t off, uint32_t ptype, bool pars
 			return 0;
 
 		return ip4h->next_proto_id;
-	} else if (RTE_ETH_IS_IPV6_HDR(ptype)) {
+	} else if (RTE_ETH_IS_IPV6_HDR(align_ptype)) {
 		const struct rte_ipv6_hdr *ip6h;
 		struct rte_ipv6_hdr ip6h_copy;
 		ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
 		if (unlikely(ip6h == NULL))
 			return 0;
 
-		if (!parse_inner && (ptype & RTE_PTYPE_L3_MASK) != RTE_PTYPE_L3_IPV6_EXT)
-			return ip6h->proto;
-
-		if (parse_inner && (ptype & RTE_PTYPE_INNER_L3_MASK) != RTE_PTYPE_INNER_L3_IPV6_EXT)
+		if ((align_ptype & RTE_PTYPE_L3_MASK) != RTE_PTYPE_L3_IPV6_EXT)
 			return ip6h->proto;
 
 		off += sizeof(struct rte_ipv6_hdr);
-- 
2.17.1



More information about the dev mailing list