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: [email protected]
Signed-off-by: Robin Jarry <[email protected]>
---
 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

Reply via email to