[PATCH v10 19/23] net/sxe2: add mbuf validation in Tx debug mode

liujie5 at linkdatatechnology.com liujie5 at linkdatatechnology.com
Sat Jun 27 06:14:49 CEST 2026


From: Jie Liu <liujie5 at linkdatatechnology.com>

Introduce the 'sxe2_txrx_check_mbuf' helper function to validate
outgoing mbuf tunnel type flags when RTE_ETHDEV_DEBUG_TX is enabled.
The function checks that the RTE_MBUF_F_TX_TUNNEL_x flag in mbuf
ol_flags matches the actual tunnel protocol detected in the packet
(GTP, VXLAN, VXLAN-GPE, Geneve, GRE, or IPIP).

The validation uses only UDP port matching and L4 protocol detection;
it does NOT re-derive header lengths or checksum fields already
verified by rte_validate_tx_offload() and rte_net_intel_cksum_prepare().

All code is wrapped inside RTE_ETHDEV_DEBUG_TX conditional compilation
to ensure zero overhead in production builds.

Signed-off-by: Jie Liu <liujie5 at linkdatatechnology.com>
---
 drivers/net/sxe2/sxe2_txrx.c | 156 +++++++++++++++++++++++++++++++++++
 1 file changed, 156 insertions(+)

diff --git a/drivers/net/sxe2/sxe2_txrx.c b/drivers/net/sxe2/sxe2_txrx.c
index 82b2e4fb7c..79870866d1 100644
--- a/drivers/net/sxe2/sxe2_txrx.c
+++ b/drivers/net/sxe2/sxe2_txrx.c
@@ -8,6 +8,9 @@
 #include <rte_malloc.h>
 #include <rte_memzone.h>
 #include <ethdev_driver.h>
+#include <rte_geneve.h>
+#include <rte_gtp.h>
+#include <rte_vxlan.h>
 #include <unistd.h>
 #include "sxe2_txrx.h"
 #include "sxe2_txrx_common.h"
@@ -89,6 +92,152 @@ static inline int32_t sxe2_tx_mbuf_empty_check(struct rte_mbuf *mbuf)
 	return 0;
 }
 
+#ifdef RTE_ETHDEV_DEBUG_TX
+static int32_t
+sxe2_txrx_check_mbuf(struct rte_mbuf *m)
+{
+	struct rte_ether_hdr *eth_hdr;
+	struct rte_ipv4_hdr *ipv4_hdr;
+	struct rte_ipv6_hdr *ipv6_hdr;
+	struct rte_vlan_hdr *vlan_hdr;
+	void *l3_hdr;
+	uint64_t ol_flags = m->ol_flags;
+	uint64_t tunnel_type = ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK;
+	uint16_t l2_len;
+	uint16_t l3_len;
+	uint8_t l4_proto;
+	uint16_t ethertype;
+
+	eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
+
+	/* Parse Ethernet + VLAN headers */
+	l2_len = sizeof(struct rte_ether_hdr);
+	ethertype = eth_hdr->ether_type;
+	while (ethertype == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) ||
+	       ethertype == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
+		vlan_hdr = (struct rte_vlan_hdr *)((char *)eth_hdr + l2_len);
+		l2_len += sizeof(struct rte_vlan_hdr);
+		ethertype = vlan_hdr->eth_proto;
+	}
+
+	/* Parse L3 to get L3 length and L4 protocol */
+	if (ethertype == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) {
+		ipv4_hdr = (struct rte_ipv4_hdr *)((char *)eth_hdr + l2_len);
+		l3_len = rte_ipv4_hdr_len(ipv4_hdr);
+		l4_proto = ipv4_hdr->next_proto_id;
+	} else if (ethertype == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) {
+		ipv6_hdr = (struct rte_ipv6_hdr *)((char *)eth_hdr + l2_len);
+		l3_len = sizeof(struct rte_ipv6_hdr);
+		l4_proto = ipv6_hdr->proto;
+	} else {
+		return 0;
+	}
+
+	l3_hdr = (char *)eth_hdr + l2_len;
+
+	/* Detect tunnel type and validate flag consistency */
+	if (l4_proto == IPPROTO_UDP) {
+		struct rte_udp_hdr *udp_hdr;
+		uint16_t dst_port;
+
+		udp_hdr = (struct rte_udp_hdr *)((char *)l3_hdr + l3_len);
+		dst_port = udp_hdr->dst_port;
+
+		/* GTP */
+		if (dst_port == rte_cpu_to_be_16(RTE_GTPC_UDP_PORT) ||
+		    dst_port == rte_cpu_to_be_16(RTE_GTPU_UDP_PORT)) {
+			if (!tunnel_type) {
+				PMD_LOG_ERR(TX, "GTP tunnel packet missing "
+					"RTE_MBUF_F_TX_TUNNEL_GTP flag");
+				return -1;
+			}
+			if (tunnel_type != RTE_MBUF_F_TX_TUNNEL_GTP) {
+				PMD_LOG_ERR(TX, "GTP tunnel packet has wrong "
+					"tx offload flag %s, expected GTP",
+					rte_get_tx_ol_flag_name(tunnel_type));
+				return -1;
+			}
+			return 0;
+		}
+		/* VXLAN-GPE */
+		if (dst_port == rte_cpu_to_be_16(RTE_VXLAN_GPE_DEFAULT_PORT)) {
+			if (!tunnel_type) {
+				PMD_LOG_ERR(TX, "VXLAN-GPE tunnel packet missing "
+					"RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE flag");
+				return -1;
+			}
+			if (tunnel_type != RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE) {
+				PMD_LOG_ERR(TX, "VXLAN-GPE tunnel packet has wrong "
+					"tx offload flag %s, expected VXLAN-GPE",
+					rte_get_tx_ol_flag_name(tunnel_type));
+				return -1;
+			}
+			return 0;
+		}
+		/* VXLAN */
+		if (dst_port == rte_cpu_to_be_16(RTE_VXLAN_DEFAULT_PORT)) {
+			if (!tunnel_type) {
+				PMD_LOG_ERR(TX, "VXLAN tunnel packet missing "
+					"RTE_MBUF_F_TX_TUNNEL_VXLAN flag");
+				return -1;
+			}
+			if (tunnel_type != RTE_MBUF_F_TX_TUNNEL_VXLAN) {
+				PMD_LOG_ERR(TX, "VXLAN tunnel packet has wrong "
+					"tx offload flag %s, expected VXLAN",
+					rte_get_tx_ol_flag_name(tunnel_type));
+				return -1;
+			}
+			return 0;
+		}
+		/* Geneve */
+		if (dst_port == rte_cpu_to_be_16(RTE_GENEVE_DEFAULT_PORT)) {
+			if (!tunnel_type) {
+				PMD_LOG_ERR(TX, "Geneve tunnel packet missing "
+					"RTE_MBUF_F_TX_TUNNEL_GENEVE flag");
+				return -1;
+			}
+			if (tunnel_type != RTE_MBUF_F_TX_TUNNEL_GENEVE) {
+				PMD_LOG_ERR(TX, "Geneve tunnel packet has wrong "
+					"tx offload flag %s, expected Geneve",
+					rte_get_tx_ol_flag_name(tunnel_type));
+				return -1;
+			}
+			return 0;
+		}
+	} else if (l4_proto == IPPROTO_GRE) {
+		/* GRE */
+		if (!tunnel_type) {
+			PMD_LOG_ERR(TX, "GRE tunnel packet missing "
+				"RTE_MBUF_F_TX_TUNNEL_GRE flag");
+			return -1;
+		}
+		if (tunnel_type != RTE_MBUF_F_TX_TUNNEL_GRE) {
+			PMD_LOG_ERR(TX, "GRE tunnel packet has wrong "
+				"tx offload flag %s, expected GRE",
+				rte_get_tx_ol_flag_name(tunnel_type));
+			return -1;
+		}
+		return 0;
+	} else if (l4_proto == IPPROTO_IPIP) {
+		/* IP-in-IP */
+		if (!tunnel_type) {
+			PMD_LOG_ERR(TX, "IPIP tunnel packet missing "
+				"RTE_MBUF_F_TX_TUNNEL_IPIP flag");
+			return -1;
+		}
+		if (tunnel_type != RTE_MBUF_F_TX_TUNNEL_IPIP) {
+			PMD_LOG_ERR(TX, "IPIP tunnel packet has wrong "
+				"tx offload flag %s, expected IPIP",
+				rte_get_tx_ol_flag_name(tunnel_type));
+			return -1;
+		}
+		return 0;
+	}
+
+	return 0;
+}
+#endif
+
 uint16_t sxe2_tx_pkts_prepare(void *tx_queue,
 		struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 {
@@ -137,6 +286,13 @@ uint16_t sxe2_tx_pkts_prepare(void *tx_queue,
 			rte_errno = -ret;
 			goto l_end;
 		}
+#ifdef RTE_ETHDEV_DEBUG_TX
+		ret = sxe2_txrx_check_mbuf(mbuf);
+		if (ret != 0) {
+			rte_errno = -ret;
+			goto l_end;
+		}
+#endif
 	}
 l_end:
 	return i;
-- 
2.52.0



More information about the dev mailing list