From: Jie Liu <[email protected]> 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 <[email protected]> --- 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

