When a tag is discovered, the code does not remove 'RTE_PTYPE_L2_ETHER'
set on function entry. For single-tagged packets, 'RTE_PTYPE_L2_ETHER'
and 'RTE_PTYPE_L2_ETHER_VLAN' give 'RTE_PTYPE_L2_ETHER_QINQ' when
OR-ed together. Clear previously set L2 type when handling VLANs.

Also, since 'RTE_PTYPE_L2_ETHER_VLAN' requires that the EtherType field
in the Ethernet header be set to 0x8100 and 'RTE_PTYPE_L2_ETHER_QINQ'
requires that it be set to 0x88a8, it is the outermost (first) tag
that determines what the software L2 ptype should be. Clarify that.

Fixes: 1f250674085a ("net: fix packet type for stacked VLAN")
Cc: [email protected]

Signed-off-by: Ivan Malov <[email protected]>
---
 lib/net/rte_net.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c
index 0a91e92ba0..826d9f58b9 100644
--- a/lib/net/rte_net.c
+++ b/lib/net/rte_net.c
@@ -365,10 +365,18 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
 
                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;
+
+               /*
+                * It is the outermost tag that determines whether
+                * the packet will be classified as VLAN or QinQ.
+                */
+               if (vlan_depth == 1) {
+                       /* Override previously set 'RTE_PTYPE_L2_ETHER'. */
+                       pkt_type = (proto == 
rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) ?
+                                       RTE_PTYPE_L2_ETHER_VLAN :
+                                       RTE_PTYPE_L2_ETHER_QINQ);
+               }
+
                vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
                if (unlikely(vh == NULL))
                        return pkt_type;
-- 
2.47.3

Reply via email to