* [PATCH] net: support VLAN stacking packet type parsing
@ 2025-07-03 9:30 Dengdui Huang
2025-07-04 10:18 ` Morten Brørup
0 siblings, 1 reply; 6+ messages in thread
From: Dengdui Huang @ 2025-07-03 9:30 UTC (permalink / raw)
To: dev
Cc: stephen, jasvinder.singh, thomas, aman.deep.singh, lihuisong,
fengchengwen, liuyonglong
The current rte_net_get_ptype() only supports parsing packets with
one 0x8100 VLAN tag or two 0x88a8 VLAN tags. This patch extends it
to support parsing packets with two 0x8100 VLAN tags.
Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
---
lib/net/rte_net.c | 34 ++++++++++++++++++++++------------
lib/net/rte_net.h | 2 ++
2 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c
index 44fb6c0f51..fa8d023ca7 100644
--- a/lib/net/rte_net.c
+++ b/lib/net/rte_net.c
@@ -352,14 +352,19 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
const struct rte_vlan_hdr *vh;
struct rte_vlan_hdr vh_copy;
+ uint8_t vlan_num = 1;
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;
+ while (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) &&
+ vlan_num <= MAX_VLAN_STACKING_TAGS) {
+ 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;
+ vlan_num++;
+ }
} else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
const struct rte_vlan_hdr *vh;
struct rte_vlan_hdr vh_copy;
@@ -504,15 +509,20 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
const struct rte_vlan_hdr *vh;
struct rte_vlan_hdr vh_copy;
+ uint8_t vlan_num = 1;
pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
pkt_type |= RTE_PTYPE_INNER_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->inner_l2_len += sizeof(*vh);
- proto = vh->eth_proto;
+ while (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) &&
+ vlan_num <= MAX_VLAN_STACKING_TAGS) {
+ vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
+ if (unlikely(vh == NULL))
+ return pkt_type;
+ off += sizeof(*vh);
+ hdr_lens->inner_l2_len += sizeof(*vh);
+ proto = vh->eth_proto;
+ vlan_num++;
+ }
} else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
const struct rte_vlan_hdr *vh;
struct rte_vlan_hdr vh_copy;
diff --git a/lib/net/rte_net.h b/lib/net/rte_net.h
index 65d724b84b..fdd55d57c8 100644
--- a/lib/net/rte_net.h
+++ b/lib/net/rte_net.h
@@ -13,6 +13,8 @@
extern "C" {
#endif
+#define MAX_VLAN_STACKING_TAGS 2
+
/**
* Structure containing header lengths associated to a packet, filled
* by rte_net_get_ptype().
--
2.33.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH] net: support VLAN stacking packet type parsing
2025-07-03 9:30 [PATCH] net: support VLAN stacking packet type parsing Dengdui Huang
@ 2025-07-04 10:18 ` Morten Brørup
2025-07-04 11:32 ` Bruce Richardson
0 siblings, 1 reply; 6+ messages in thread
From: Morten Brørup @ 2025-07-04 10:18 UTC (permalink / raw)
To: Dengdui Huang, dev
Cc: stephen, jasvinder.singh, thomas, aman.deep.singh, lihuisong,
fengchengwen, liuyonglong
> From: Dengdui Huang [mailto:huangdengdui@huawei.com]
> Sent: Thursday, 3 July 2025 11.30
>
> The current rte_net_get_ptype() only supports parsing packets with
> one 0x8100 VLAN tag or two 0x88a8 VLAN tags. This patch extends it
> to support parsing packets with two 0x8100 VLAN tags.
>
> Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
> ---
> lib/net/rte_net.c | 34 ++++++++++++++++++++++------------
> lib/net/rte_net.h | 2 ++
> 2 files changed, 24 insertions(+), 12 deletions(-)
>
> diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c
> index 44fb6c0f51..fa8d023ca7 100644
> --- a/lib/net/rte_net.c
> +++ b/lib/net/rte_net.c
> @@ -352,14 +352,19 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf
> *m,
> if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
> const struct rte_vlan_hdr *vh;
> struct rte_vlan_hdr vh_copy;
> + uint8_t vlan_num = 1;
>
> 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;
> + while (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) &&
> + vlan_num <= MAX_VLAN_STACKING_TAGS) {
> + 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;
> + vlan_num++;
> + }
It's not that simple.
VLAN tags are not like MPLS labels.
With the MPLS packet type, we expect a stack of labels.
But with VLAN tagged packets, we expect exactly one VLAN tag at each outer/inner layer of headers. (Or no VLAN tag at the inner layer.)
This function already supports packets with 2 VLAN tags:
A stack of 2 VLAN tags is currently detected as 1 outer VLAN tag, adjusting hdr_lens->l2_len accordingly, and 1 inner VLAN tag, adjusting hdr_lens->inner_l2_len accordingly.
This behavior should not be changed.
I don't have a firm idea about how to better represent packets with a stack of 3+ VLAN tags than what we do today, so suggestions are welcome.
Which use case is this patch addressing?
Maybe information about the use case could guide us in some direction.
> } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
> const struct rte_vlan_hdr *vh;
> struct rte_vlan_hdr vh_copy;
> @@ -504,15 +509,20 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf
> *m,
> if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
> const struct rte_vlan_hdr *vh;
> struct rte_vlan_hdr vh_copy;
> + uint8_t vlan_num = 1;
>
> pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
> pkt_type |= RTE_PTYPE_INNER_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->inner_l2_len += sizeof(*vh);
> - proto = vh->eth_proto;
> + while (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) &&
> + vlan_num <= MAX_VLAN_STACKING_TAGS) {
> + vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
> + if (unlikely(vh == NULL))
> + return pkt_type;
> + off += sizeof(*vh);
> + hdr_lens->inner_l2_len += sizeof(*vh);
> + proto = vh->eth_proto;
> + vlan_num++;
> + }
> } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_QINQ)) {
> const struct rte_vlan_hdr *vh;
> struct rte_vlan_hdr vh_copy;
> diff --git a/lib/net/rte_net.h b/lib/net/rte_net.h
> index 65d724b84b..fdd55d57c8 100644
> --- a/lib/net/rte_net.h
> +++ b/lib/net/rte_net.h
> @@ -13,6 +13,8 @@
> extern "C" {
> #endif
>
> +#define MAX_VLAN_STACKING_TAGS 2
> +
> /**
> * Structure containing header lengths associated to a packet, filled
> * by rte_net_get_ptype().
> --
> 2.33.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] net: support VLAN stacking packet type parsing
2025-07-04 10:18 ` Morten Brørup
@ 2025-07-04 11:32 ` Bruce Richardson
2025-07-07 18:08 ` Morten Brørup
0 siblings, 1 reply; 6+ messages in thread
From: Bruce Richardson @ 2025-07-04 11:32 UTC (permalink / raw)
To: Morten Brørup
Cc: Dengdui Huang, dev, stephen, jasvinder.singh, thomas,
aman.deep.singh, lihuisong, fengchengwen, liuyonglong
On Fri, Jul 04, 2025 at 12:18:45PM +0200, Morten Brørup wrote:
> > From: Dengdui Huang [mailto:huangdengdui@huawei.com]
> > Sent: Thursday, 3 July 2025 11.30
> >
> > The current rte_net_get_ptype() only supports parsing packets with
> > one 0x8100 VLAN tag or two 0x88a8 VLAN tags. This patch extends it
> > to support parsing packets with two 0x8100 VLAN tags.
> >
> > Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
> > ---
> > lib/net/rte_net.c | 34 ++++++++++++++++++++++------------
> > lib/net/rte_net.h | 2 ++
> > 2 files changed, 24 insertions(+), 12 deletions(-)
> >
> > diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c
> > index 44fb6c0f51..fa8d023ca7 100644
> > --- a/lib/net/rte_net.c
> > +++ b/lib/net/rte_net.c
> > @@ -352,14 +352,19 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf
> > *m,
> > if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) {
> > const struct rte_vlan_hdr *vh;
> > struct rte_vlan_hdr vh_copy;
> > + uint8_t vlan_num = 1;
> >
> > 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;
> > + while (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN) &&
> > + vlan_num <= MAX_VLAN_STACKING_TAGS) {
> > + 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;
> > + vlan_num++;
> > + }
>
> It's not that simple.
>
> VLAN tags are not like MPLS labels.
> With the MPLS packet type, we expect a stack of labels.
> But with VLAN tagged packets, we expect exactly one VLAN tag at each outer/inner layer of headers. (Or no VLAN tag at the inner layer.)
>
> This function already supports packets with 2 VLAN tags:
> A stack of 2 VLAN tags is currently detected as 1 outer VLAN tag, adjusting hdr_lens->l2_len accordingly, and 1 inner VLAN tag, adjusting hdr_lens->inner_l2_len accordingly.
> This behavior should not be changed.
>
> I don't have a firm idea about how to better represent packets with a stack of 3+ VLAN tags than what we do today, so suggestions are welcome.
>
> Which use case is this patch addressing?
> Maybe information about the use case could guide us in some direction.
>
Hi all,
this email discussion comes at a bit of a fortunate time for me, as I'm
currently looking at our vlan tag/qinq stripping behaviour in our Intel NIC
drivers, and there is some discussion internally as to what our driver
behaviour should be compared to what it has historically been. :-)
The documentation - both in the NIC guide [1] and the testpmd guide [2] -
is rather short on detail as to what exactly the behaviour should be when
vlan strip or qinq strip is implemented. Therefore, I'd hope that those
more familiar with networking than me would be able to help clarify things
so we can document the correct behaviour precisely - and hopefully test our
drivers against it in future!
The simple cases are obvious (looking only at stripping behaviour here):
* no vlan stripping - nothing done to packet
* no vlan tag in pkg - nothing to do, irrespective of offload
* Vlan strip enabled and single vlan tag present - HW should strip the tag and
place it in descriptor for placing in mbuf.
Now the questions I have:
* To handle questions with 2 vlan tags, the QinQ case - do we need to
enable both vlan-strip and QinQ strip, or does QinQ strip imply stripping
both?
- one suggested interpretation here, was that QinQ implies stripping the
tag with id EtherType 0x88a8, and vlan stripping implies taking off the
tag with 0x8100
- another interpretation is vlan strip means just to take off one tag (if
present), and qinq strip means to take off both tags (if present).
The question above leads to other consequences:
* if we enable qinq strip, but get a single-vlan tagged frame, what is the
behaviour?
* if we get a qinq packet, but regular vlan strip is enabled, which tag, if
any, is stripped?
* should it be an error to enable both qinq strip and vlan strip at the
same time? Should it be an error to enable qinq strip without vlan strip?
* in the mbuf, we have a "vlan_tci" field, and an "vlan_tci_outer" field.
For single vlan strip, presumably only the vlan_tci field should be used,
and for qinq traffic stripped, it's obvious which field goes where.
However, what if we have QinQ strip and we only receive a single vlan
tag, where should that be put? Should it go in inner or outer?
Feedback welcome, and suggested doc updates welcome too.
Thanks,
/Bruce
[1] https://doc.dpdk.org/guides/nics/features.html#vlan-offload
[2] https://doc.dpdk.org/guides/testpmd_app_ug/run_app.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH] net: support VLAN stacking packet type parsing
2025-07-04 11:32 ` Bruce Richardson
@ 2025-07-07 18:08 ` Morten Brørup
2025-07-07 20:10 ` Vladimir Medvedkin
0 siblings, 1 reply; 6+ messages in thread
From: Morten Brørup @ 2025-07-07 18:08 UTC (permalink / raw)
To: Bruce Richardson
Cc: Dengdui Huang, dev, stephen, jasvinder.singh, thomas,
aman.deep.singh, lihuisong, fengchengwen, liuyonglong
> From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> Sent: Friday, 4 July 2025 13.32
> Hi all,
>
> this email discussion comes at a bit of a fortunate time for me, as I'm
> currently looking at our vlan tag/qinq stripping behaviour in our Intel
> NIC
> drivers, and there is some discussion internally as to what our driver
> behaviour should be compared to what it has historically been. :-)
>
> The documentation - both in the NIC guide [1] and the testpmd guide [2]
> -
> is rather short on detail as to what exactly the behaviour should be
> when
> vlan strip or qinq strip is implemented. Therefore, I'd hope that those
> more familiar with networking than me would be able to help clarify
> things
> so we can document the correct behaviour precisely - and hopefully test
> our
> drivers against it in future!
>
> The simple cases are obvious (looking only at stripping behaviour here):
> * no vlan stripping - nothing done to packet
> * no vlan tag in pkg - nothing to do, irrespective of offload
> * Vlan strip enabled and single vlan tag present - HW should strip the
> tag and
> place it in descriptor for placing in mbuf.
>
> Now the questions I have:
> * To handle questions with 2 vlan tags, the QinQ case - do we need to
> enable both vlan-strip and QinQ strip, or does QinQ strip imply
> stripping
> both?
> - one suggested interpretation here, was that QinQ implies stripping
> the
> tag with id EtherType 0x88a8, and vlan stripping implies taking off
> the
> tag with 0x8100
> - another interpretation is vlan strip means just to take off one tag
> (if
> present), and qinq strip means to take off both tags (if present).
>
First off, consider VLAN stripping...
It strips the VLAN tag if present, but also allows (and parses) untagged packets.
A link with a mix of tagged and untagged packets is called a "hybrid link", so this scenario is perfectly valid and common.
Referring to this behavior, I would expect something similar for QinQ stripping, i.e. with QinQ stripping enabled, two, one or zero tags are allowed (and parsed).
This makes the VLAN strip flag superfluous when the QinQ strip flag is set.
You could have a QinQ trunk carrying only QinQ tagged packets and untagged Layer 2 Control Protocol packets (LACP etc.).
In this case you might want the ability to drop VLAN tagged packets, which should not occur on the link.
However, since we don't have such a feature for VLAN trunks, I wouldn't expect it for QinQ trunks either.
Another important detail...
Formally, QinQ is EtherType 0x88a8 with two VLAN tags.
However, I think double-tagging with EtherType 0x8100 is still broadly in use (in old networks, where it is difficult to upgrade to the official QinQ EtherType), so I would also treat packets with two VLAN tags (of EtherType 0x8100) as QinQ.
There was also an intermediate unofficial EtherType 0x9100 for QinQ tagging, before EtherType 0x88a8 was standardized... but I think we can ignore that.
> The question above leads to other consequences:
> * if we enable qinq strip, but get a single-vlan tagged frame, what is
> the
> behaviour?
> * if we get a qinq packet, but regular vlan strip is enabled, which tag,
> if
> any, is stripped?
> * should it be an error to enable both qinq strip and vlan strip at the
> same time? Should it be an error to enable qinq strip without vlan
> strip?
> * in the mbuf, we have a "vlan_tci" field, and an "vlan_tci_outer"
> field.
> For single vlan strip, presumably only the vlan_tci field should be
> used,
> and for qinq traffic stripped, it's obvious which field goes where.
> However, what if we have QinQ strip and we only receive a single vlan
> tag, where should that be put? Should it go in inner or outer?
From a protocol parsing perspective, a single VLAN tagged packet has no "outer" tag.
Also: Consider the link being configured as a "super-hybrid link" (probably not an official name for such a link, but expanding on the common term "hybrid link"), carrying a mix of untagged, VLAN tagged and QinQ tagged packets. In this case, a single VLAN tagged packet is just a normal VLAN tagged packet, with the VLAN ID obviously going to the ordinary vlan_tci field.
>
> Feedback welcome, and suggested doc updates welcome too.
>
> Thanks,
> /Bruce
>
>
> [1] https://doc.dpdk.org/guides/nics/features.html#vlan-offload
> [2] https://doc.dpdk.org/guides/testpmd_app_ug/run_app.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] net: support VLAN stacking packet type parsing
2025-07-07 18:08 ` Morten Brørup
@ 2025-07-07 20:10 ` Vladimir Medvedkin
2025-07-07 22:00 ` Morten Brørup
0 siblings, 1 reply; 6+ messages in thread
From: Vladimir Medvedkin @ 2025-07-07 20:10 UTC (permalink / raw)
To: Morten Brørup
Cc: Bruce Richardson, Dengdui Huang, dev, stephen, jasvinder.singh,
thomas, aman.deep.singh, lihuisong, fengchengwen, liuyonglong
[-- Attachment #1: Type: text/plain, Size: 5691 bytes --]
Hi Morten, all,
пн, 7 июл. 2025 г. в 19:09, Morten Brørup <mb@smartsharesystems.com>:
> > From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> > Sent: Friday, 4 July 2025 13.32
>
> > Hi all,
> >
> > this email discussion comes at a bit of a fortunate time for me, as I'm
> > currently looking at our vlan tag/qinq stripping behaviour in our Intel
> > NIC
> > drivers, and there is some discussion internally as to what our driver
> > behaviour should be compared to what it has historically been. :-)
> >
> > The documentation - both in the NIC guide [1] and the testpmd guide [2]
> > -
> > is rather short on detail as to what exactly the behaviour should be
> > when
> > vlan strip or qinq strip is implemented. Therefore, I'd hope that those
> > more familiar with networking than me would be able to help clarify
> > things
> > so we can document the correct behaviour precisely - and hopefully test
> > our
> > drivers against it in future!
> >
> > The simple cases are obvious (looking only at stripping behaviour here):
> > * no vlan stripping - nothing done to packet
> > * no vlan tag in pkg - nothing to do, irrespective of offload
> > * Vlan strip enabled and single vlan tag present - HW should strip the
> > tag and
> > place it in descriptor for placing in mbuf.
> >
> > Now the questions I have:
> > * To handle questions with 2 vlan tags, the QinQ case - do we need to
> > enable both vlan-strip and QinQ strip, or does QinQ strip imply
> > stripping
> > both?
> > - one suggested interpretation here, was that QinQ implies stripping
> > the
> > tag with id EtherType 0x88a8, and vlan stripping implies taking off
> > the
> > tag with 0x8100
> > - another interpretation is vlan strip means just to take off one tag
> > (if
> > present), and qinq strip means to take off both tags (if present).
> >
>
> First off, consider VLAN stripping...
> It strips the VLAN tag if present, but also allows (and parses) untagged
> packets.
> A link with a mix of tagged and untagged packets is called a "hybrid
> link", so this scenario is perfectly valid and common.
> Referring to this behavior, I would expect something similar for QinQ
> stripping, i.e. with QinQ stripping enabled, two, one or zero tags are
> allowed (and parsed).
> This makes the VLAN strip flag superfluous when the QinQ strip flag is set.
>
> You could have a QinQ trunk carrying only QinQ tagged packets and untagged
> Layer 2 Control Protocol packets (LACP etc.).
> In this case you might want the ability to drop VLAN tagged packets, which
> should not occur on the link.
>
That's not quite correct.
There are 2 valid usecases, that may bring some ambiguity:
1. Some vendors may support mixing dual/single tagged packets on a
physical port, (for example refer to the JunOS flexible-vlan-tagging)
2. Service provider(SP) provides L2 connectivity to a customer, and
customer is able to send non tagged frames via SP infrastructure.
Thus, upon receive single tagged packet at the SP exit node (the switch
customer is connected to) how does it distinguish (w/o reading local
configuration, i.e. VLAN A - QinQ outer tag, vlans B and C - regular VLANs)
whether the packet is non tagged encapsulated into SP's QinQ, or a regular
VLAN packet belonging to the internal SP infrastructure?
In each case, NIC has to place the VLAN tag in different places of the
descriptor/mbuf.
However, since we don't have such a feature for VLAN trunks, I wouldn't
> expect it for QinQ trunks either.
>
> Another important detail...
> Formally, QinQ is EtherType 0x88a8 with two VLAN tags.
> However, I think double-tagging with EtherType 0x8100 is still broadly in
> use (in old networks, where it is difficult to upgrade to the official QinQ
> EtherType), so I would also treat packets with two VLAN tags (of EtherType
> 0x8100) as QinQ.
> There was also an intermediate unofficial EtherType 0x9100 for QinQ
> tagging, before EtherType 0x88a8 was standardized... but I think we can
> ignore that.
>
> > The question above leads to other consequences:
> > * if we enable qinq strip, but get a single-vlan tagged frame, what is
> > the
> > behaviour?
> > * if we get a qinq packet, but regular vlan strip is enabled, which tag,
> > if
> > any, is stripped?
> > * should it be an error to enable both qinq strip and vlan strip at the
> > same time? Should it be an error to enable qinq strip without vlan
> > strip?
> > * in the mbuf, we have a "vlan_tci" field, and an "vlan_tci_outer"
> > field.
> > For single vlan strip, presumably only the vlan_tci field should be
> > used,
> > and for qinq traffic stripped, it's obvious which field goes where.
> > However, what if we have QinQ strip and we only receive a single vlan
> > tag, where should that be put? Should it go in inner or outer?
>
> From a protocol parsing perspective, a single VLAN tagged packet has no
> "outer" tag.
>
> Also: Consider the link being configured as a "super-hybrid link"
> (probably not an official name for such a link, but expanding on the common
> term "hybrid link"), carrying a mix of untagged, VLAN tagged and QinQ
> tagged packets. In this case, a single VLAN tagged packet is just a normal
> VLAN tagged packet, with the VLAN ID obviously going to the ordinary
> vlan_tci field.
>
> >
> > Feedback welcome, and suggested doc updates welcome too.
> >
> > Thanks,
> > /Bruce
> >
> >
> > [1] https://doc.dpdk.org/guides/nics/features.html#vlan-offload
> > [2] https://doc.dpdk.org/guides/testpmd_app_ug/run_app.html
>
--
Regards,
Vladimir
[-- Attachment #2: Type: text/html, Size: 8738 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: [PATCH] net: support VLAN stacking packet type parsing
2025-07-07 20:10 ` Vladimir Medvedkin
@ 2025-07-07 22:00 ` Morten Brørup
0 siblings, 0 replies; 6+ messages in thread
From: Morten Brørup @ 2025-07-07 22:00 UTC (permalink / raw)
To: Vladimir Medvedkin
Cc: Bruce Richardson, Dengdui Huang, dev, stephen, jasvinder.singh,
thomas, aman.deep.singh, lihuisong, fengchengwen, liuyonglong
[-- Attachment #1: Type: text/plain, Size: 7480 bytes --]
From: Vladimir Medvedkin [mailto:medvedkinv@gmail.com]
Sent: Monday, 7 July 2025 22.10
Hi Morten, all,
пн, 7 июл. 2025 г. в 19:09, Morten Brørup <mb@smartsharesystems.com>:
> From: Bruce Richardson [mailto:bruce.richardson@intel.com]
> Sent: Friday, 4 July 2025 13.32
> Hi all,
>
> this email discussion comes at a bit of a fortunate time for me, as I'm
> currently looking at our vlan tag/qinq stripping behaviour in our Intel
> NIC
> drivers, and there is some discussion internally as to what our driver
> behaviour should be compared to what it has historically been. :-)
>
> The documentation - both in the NIC guide [1] and the testpmd guide [2]
> -
> is rather short on detail as to what exactly the behaviour should be
> when
> vlan strip or qinq strip is implemented. Therefore, I'd hope that those
> more familiar with networking than me would be able to help clarify
> things
> so we can document the correct behaviour precisely - and hopefully test
> our
> drivers against it in future!
>
> The simple cases are obvious (looking only at stripping behaviour here):
> * no vlan stripping - nothing done to packet
> * no vlan tag in pkg - nothing to do, irrespective of offload
> * Vlan strip enabled and single vlan tag present - HW should strip the
> tag and
> place it in descriptor for placing in mbuf.
>
> Now the questions I have:
> * To handle questions with 2 vlan tags, the QinQ case - do we need to
> enable both vlan-strip and QinQ strip, or does QinQ strip imply
> stripping
> both?
> - one suggested interpretation here, was that QinQ implies stripping
> the
> tag with id EtherType 0x88a8, and vlan stripping implies taking off
> the
> tag with 0x8100
> - another interpretation is vlan strip means just to take off one tag
> (if
> present), and qinq strip means to take off both tags (if present).
>
First off, consider VLAN stripping...
It strips the VLAN tag if present, but also allows (and parses) untagged packets.
A link with a mix of tagged and untagged packets is called a "hybrid link", so this scenario is perfectly valid and common.
Referring to this behavior, I would expect something similar for QinQ stripping, i.e. with QinQ stripping enabled, two, one or zero tags are allowed (and parsed).
This makes the VLAN strip flag superfluous when the QinQ strip flag is set.
You could have a QinQ trunk carrying only QinQ tagged packets and untagged Layer 2 Control Protocol packets (LACP etc.).
In this case you might want the ability to drop VLAN tagged packets, which should not occur on the link.
That's not quite correct.
There are 2 valid usecases, that may bring some ambiguity:
1. Some vendors may support mixing dual/single tagged packets on a physical port, (for example refer to the JunOS flexible-vlan-tagging)
2. Service provider(SP) provides L2 connectivity to a customer, and customer is able to send non tagged frames via SP infrastructure.
Thus, upon receive single tagged packet at the SP exit node (the switch customer is connected to) how does it distinguish (w/o reading local configuration, i.e. VLAN A - QinQ outer tag, vlans B and C - regular VLANs) whether the packet is non tagged encapsulated into SP's QinQ, or a regular VLAN packet belonging to the internal SP infrastructure?
In each case, NIC has to place the VLAN tag in different places of the descriptor/mbuf.
I was trying to make the point that QinQ stripping only needs to support 2, 1, or 0 tags, it doesn’t need an option to support only 2 or 0 tags (and disallow 1 tag).
I’m not sure I understand your example.
Are you talking about packets ingressing on a backbone port (i.e. not a customer-facing port) on a DPDK-based SP exit node?
And the backbone is using one individual VLAN ID per customer?
So customers’ untagged traffic is VLAN tagged packets in the backbone, and customers VLAN tagged traffic is double tagged packets in the backbone?
In such a case, the VLAN ID used internally for infrastructure/management purposes by the SP will be reserved, and not assigned to any customer.
And you suggest putting the VLAN ID of the single tagged packets in the vlan_tci_outer and set RTE_MBUF_F_RX_QINQ but not RTE_MBUF_F_RX_VLAN, instead of treating them as normal VLAN tagged packets?
OK, then the “superfluous” VLAN stripping flag could be used for indicating which mbuf field vlan_tci/vlan_tci_outer the VLAN ID of single VLAN tagged packets should go into, when QinQ stripping is enabled.
But: If QinQ/VLAN stripping is not enabled, the VLAN ID of such a single VLAN tagged packet will still go into the mbuf->vlan_tci field with RTE_MBUF_F_RX_VLAN (but not RTE_MBUF_F_RX_VLAN_STRIPPED) set.
So I don’t think such flexibility about where to put the VLAN ID of single VLAN tagged packets is a good idea, if such optional behavior is only available when stripping the VLAN/QinQ tags, but not when simply parsing the VLAN/QinQ tagged packets.
If you are talking about a backbone using QinQ with individual {outer, inner} ID pair per customer, VLAN tagged customer traffic will be triple tagged packets in such a backbone.
However, since we don't have such a feature for VLAN trunks, I wouldn't expect it for QinQ trunks either.
Another important detail...
Formally, QinQ is EtherType 0x88a8 with two VLAN tags.
However, I think double-tagging with EtherType 0x8100 is still broadly in use (in old networks, where it is difficult to upgrade to the official QinQ EtherType), so I would also treat packets with two VLAN tags (of EtherType 0x8100) as QinQ.
There was also an intermediate unofficial EtherType 0x9100 for QinQ tagging, before EtherType 0x88a8 was standardized... but I think we can ignore that.
> The question above leads to other consequences:
> * if we enable qinq strip, but get a single-vlan tagged frame, what is
> the
> behaviour?
> * if we get a qinq packet, but regular vlan strip is enabled, which tag,
> if
> any, is stripped?
> * should it be an error to enable both qinq strip and vlan strip at the
> same time? Should it be an error to enable qinq strip without vlan
> strip?
> * in the mbuf, we have a "vlan_tci" field, and an "vlan_tci_outer"
> field.
> For single vlan strip, presumably only the vlan_tci field should be
> used,
> and for qinq traffic stripped, it's obvious which field goes where.
> However, what if we have QinQ strip and we only receive a single vlan
> tag, where should that be put? Should it go in inner or outer?
From a protocol parsing perspective, a single VLAN tagged packet has no "outer" tag.
Also: Consider the link being configured as a "super-hybrid link" (probably not an official name for such a link, but expanding on the common term "hybrid link"), carrying a mix of untagged, VLAN tagged and QinQ tagged packets. In this case, a single VLAN tagged packet is just a normal VLAN tagged packet, with the VLAN ID obviously going to the ordinary vlan_tci field.
>
> Feedback welcome, and suggested doc updates welcome too.
>
> Thanks,
> /Bruce
>
>
> [1] https://doc.dpdk.org/guides/nics/features.html#vlan-offload
> [2] https://doc.dpdk.org/guides/testpmd_app_ug/run_app.html
--
Regards,
Vladimir
[-- Attachment #2: Type: text/html, Size: 14283 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-07-07 22:00 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-07-03 9:30 [PATCH] net: support VLAN stacking packet type parsing Dengdui Huang
2025-07-04 10:18 ` Morten Brørup
2025-07-04 11:32 ` Bruce Richardson
2025-07-07 18:08 ` Morten Brørup
2025-07-07 20:10 ` Vladimir Medvedkin
2025-07-07 22:00 ` Morten Brørup
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).