[PATCH dpdk v5 1/5] Revert "net: fix packet type for stacked VLAN"

Robin Jarry rjarry at redhat.com
Mon May 18 15:27:15 CEST 2026


This reverts commit 1f250674085aeb4ffd15ac2519a68efc04faf7ac.

rte_net_get_ptype() now uses |= to set the L2 ptype inside the VLAN
parsing loop. Since pkt_type is already initialized with
RTE_PTYPE_L2_ETHER (0x1), or-ing it with RTE_PTYPE_L2_ETHER_VLAN (0x6)
results in RTE_PTYPE_L2_ETHER_QINQ (0x7). This causes single VLAN frames
to be misidentified as QinQ.

This was detected while testing DPDK 25.11.1 in grout. The net/tap
driver calls rte_net_get_ptype() in tap_verify_csum() to determine the
L2 header length. With the wrong ptype, l2_len is set to 22 (ether
+ QinQ = 14 + 8) instead of 18 (ether + VLAN = 14 + 4), shifting the IP
header pointer by 4 bytes. The checksum is then computed on garbage
data, causing valid packets to be dropped.

Bugzilla ID: 1941
Fixes: 1f250674085a ("net: fix packet type for stacked VLAN")
Cc: stable at dpdk.org
Signed-off-by: Robin Jarry <rjarry at redhat.com>
---
 lib/net/rte_net.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c
index 458b4814a9c9..c70b57fdc0f8 100644
--- a/lib/net/rte_net.c
+++ b/lib/net/rte_net.c
@@ -320,9 +320,6 @@ rte_net_skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off,
 	return -1;
 }
 
-/* limit number of supported VLAN headers */
-#define RTE_NET_VLAN_MAX_DEPTH 8
-
 /* parse mbuf data to get packet type */
 RTE_EXPORT_SYMBOL(rte_net_get_ptype)
 uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
@@ -332,7 +329,7 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
 	const struct rte_ether_hdr *eh;
 	struct rte_ether_hdr eh_copy;
 	uint32_t pkt_type = RTE_PTYPE_L2_ETHER;
-	uint32_t off = 0, vlan_depth = 0;
+	uint32_t off = 0;
 	uint16_t proto;
 	int ret;
 
@@ -352,26 +349,30 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
 	if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4))
 		goto l3; /* fast path if packet is IPv4 */
 
-	while (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) ||
-	       proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
+	if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
 		const struct rte_vlan_hdr *vh;
 		struct rte_vlan_hdr vh_copy;
 
-		if (++vlan_depth > RTE_NET_VLAN_MAX_DEPTH)
-			return 0;
-		pkt_type |=
-			proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) ?
-				 RTE_PTYPE_L2_ETHER_VLAN :
-				 RTE_PTYPE_L2_ETHER_QINQ;
+		pkt_type = RTE_PTYPE_L2_ETHER_VLAN;
 		vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
 		if (unlikely(vh == NULL))
 			return pkt_type;
 		off += sizeof(*vh);
 		hdr_lens->l2_len += sizeof(*vh);
 		proto = vh->eth_proto;
-	}
+	} else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
+		const struct rte_vlan_hdr *vh;
+		struct rte_vlan_hdr vh_copy;
 
-	if ((proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) ||
+		pkt_type = RTE_PTYPE_L2_ETHER_QINQ;
+		vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh),
+			&vh_copy);
+		if (unlikely(vh == NULL))
+			return pkt_type;
+		off += 2 * sizeof(*vh);
+		hdr_lens->l2_len += 2 * sizeof(*vh);
+		proto = vh->eth_proto;
+	} else if ((proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) ||
 		(proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLSM))) {
 		unsigned int i;
 		const struct rte_mpls_hdr *mh;
-- 
2.54.0



More information about the stable mailing list