* [PATCH net v3 1/5] net: stmmac: Remove VLAN perfect matching dead code
2026-08-25 16:45 [PATCH net v3 0/5] net: stmmac: Fix double VLAN 802.1ad tag handling Ovidiu Panait
@ 2026-08-25 16:45 ` Ovidiu Panait
2026-08-25 16:45 ` [PATCH net v3 2/5] net: stmmac: Move double VLAN handling to a dedicated op Ovidiu Panait
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Ovidiu Panait @ 2026-08-25 16:45 UTC (permalink / raw)
To: maxime.chevallier, andrew+netdev, davem, edumazet, kuba, pabeni,
mcoquelin.stm32, alexandre.torgue, shuah, joabreu, jun.ann.lai,
yi.fang.gan
Cc: linux-kernel, netdev, linux-stm32, linux-arm-kernel,
linux-kselftest, Ovidiu Panait
stmmac_vlan_update() falls back to "perfect matching" when the VLAN hash
filter is unavailable (!priv->dma_cap.vlhash). This fallback has been
unreachable in normal operation since its introduction in
commit c7ab0b8088d7 ("net: stmmac: Fallback to VLAN Perfect filtering if
HASH is not available") because the NETIF_F_HW_VLAN_{CTAG,STAG}_FILTER
features are advertised only when priv->dma_cap.vlhash is true.
The fallback is also duplicating the code in vlan_add_hw_rx_fltr(), which
is always available since stmmac_get_num_vlan() returns at least 1.
Therefore, remove it.
Fixes: c7ab0b8088d7 ("net: stmmac: Fallback to VLAN Perfect filtering if HASH is not available")
Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
v3 changes:
- Added "Reviewed-by" tag from Maxime.
v2 changes: None.
drivers/net/ethernet/stmicro/stmmac/hwif.h | 2 +-
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 13 +-----
.../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 41 +------------------
3 files changed, 4 insertions(+), 52 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 04dafec021b4..6f26dbf95ce1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -633,7 +633,7 @@ struct stmmac_est_ops {
struct stmmac_vlan_ops {
/* VLAN */
void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash,
- u16 perfect_match, bool is_double);
+ bool is_double);
void (*enable_vlan)(struct mac_device_info *hw, u32 type);
void (*rx_hw_vlan)(struct mac_device_info *hw, struct dma_desc *rx_desc,
struct sk_buff *skb);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index b2b7d0242dd3..16fe56a1f617 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -6809,29 +6809,18 @@ static u32 stmmac_vid_crc32_le(__le16 vid_le)
static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
{
u32 crc, hash = 0;
- u16 pmatch = 0;
- int count = 0;
u16 vid = 0;
for_each_set_bit(vid, priv->active_vlans, VLAN_N_VID) {
__le16 vid_le = cpu_to_le16(vid);
crc = bitrev32(~stmmac_vid_crc32_le(vid_le)) >> 28;
hash |= (1 << crc);
- count++;
- }
-
- if (!priv->dma_cap.vlhash) {
- if (count > 2) /* VID = 0 always passes filter */
- return -EOPNOTSUPP;
-
- pmatch = vid;
- hash = 0;
}
if (!netif_running(priv->dev))
return 0;
- return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double);
+ return stmmac_update_vlan_hash(priv, priv->hw, hash, is_double);
}
/* FIXME: This may need RXC to be running, but it may be called with BH
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
index e24efe3bfedb..983a90cb9767 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
@@ -162,7 +162,7 @@ static void vlan_restore_hw_rx_fltr(struct net_device *dev,
}
static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
- u16 perfect_match, bool is_double)
+ bool is_double)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;
@@ -184,20 +184,6 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
}
writel(value, ioaddr + VLAN_TAG);
- } else if (perfect_match) {
- u32 value = VLAN_ETV;
-
- if (is_double) {
- value |= VLAN_EDVLP;
- value |= VLAN_ESVL;
- value |= VLAN_DOVLTC;
- } else {
- value &= ~VLAN_EDVLP;
- value &= ~VLAN_ESVL;
- value &= ~VLAN_DOVLTC;
- }
-
- writel(value | perfect_match, ioaddr + VLAN_TAG);
} else {
value &= ~(VLAN_VTHM | VLAN_ETV);
value &= ~(VLAN_EDVLP | VLAN_ESVL);
@@ -251,7 +237,7 @@ static void vlan_set_hw_mode(struct mac_device_info *hw)
}
static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
- u16 perfect_match, bool is_double)
+ bool is_double)
{
void __iomem *ioaddr = hw->pcsr;
@@ -279,29 +265,6 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
value &= ~VLAN_VID;
writel(value, ioaddr + VLAN_TAG);
- } else if (perfect_match) {
- u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
-
- value |= XGMAC_FILTER_VTFE;
-
- writel(value, ioaddr + XGMAC_PACKET_FILTER);
-
- value = readl(ioaddr + VLAN_TAG);
-
- value &= ~VLAN_VTHM;
- value |= VLAN_ETV;
- if (is_double) {
- value |= VLAN_EDVLP;
- value |= VLAN_ESVL;
- value |= VLAN_DOVLTC;
- } else {
- value &= ~VLAN_EDVLP;
- value &= ~VLAN_ESVL;
- value &= ~VLAN_DOVLTC;
- }
-
- value &= ~VLAN_VID;
- writel(value | perfect_match, ioaddr + VLAN_TAG);
} else {
u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net v3 2/5] net: stmmac: Move double VLAN handling to a dedicated op
2026-08-25 16:45 [PATCH net v3 0/5] net: stmmac: Fix double VLAN 802.1ad tag handling Ovidiu Panait
2026-08-25 16:45 ` [PATCH net v3 1/5] net: stmmac: Remove VLAN perfect matching dead code Ovidiu Panait
@ 2026-08-25 16:45 ` Ovidiu Panait
2026-08-28 4:07 ` Joseph Steel
2026-08-25 16:45 ` [PATCH net v3 3/5] net: stmmac: Disable double VLAN handling on dwmac4 Ovidiu Panait
` (3 subsequent siblings)
5 siblings, 1 reply; 9+ messages in thread
From: Ovidiu Panait @ 2026-08-25 16:45 UTC (permalink / raw)
To: maxime.chevallier, andrew+netdev, davem, edumazet, kuba, pabeni,
mcoquelin.stm32, alexandre.torgue, shuah, joabreu, jun.ann.lai,
yi.fang.gan
Cc: linux-kernel, netdev, linux-stm32, linux-arm-kernel,
linux-kselftest, Ovidiu Panait
The double VLAN bits (EDVLP, ESVL, DOVLTC) are currently handled inside
update_vlan_hash(). This ties the double VLAN state to the hash filter
update, even though the two features are independent: hash filtering is
controlled by dma_cap.vlhash and double vlan by dma_cap.dvlan.
In preparation for removing double vlan support from dwmac4, move the
double vlan logic into a separate update_dvlan_state() VLAN operation.
Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
v3 changes:
- Rebased after dropping the dma_cap.dvlan patch.
- Added "Reviewed-by" tag from Maxime.
v2 changes: None.
drivers/net/ethernet/stmicro/stmmac/hwif.h | 6 ++-
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 4 +-
.../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 45 ++++++++-----------
3 files changed, 25 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 6f26dbf95ce1..66837caafa84 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -632,8 +632,8 @@ struct stmmac_est_ops {
struct stmmac_vlan_ops {
/* VLAN */
- void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash,
- bool is_double);
+ void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash);
+ void (*update_dvlan_state)(struct mac_device_info *hw, bool enable);
void (*enable_vlan)(struct mac_device_info *hw, u32 type);
void (*rx_hw_vlan)(struct mac_device_info *hw, struct dma_desc *rx_desc,
struct sk_buff *skb);
@@ -650,6 +650,8 @@ struct stmmac_vlan_ops {
#define stmmac_update_vlan_hash(__priv, __args...) \
stmmac_do_void_callback(__priv, vlan, update_vlan_hash, __args)
+#define stmmac_update_dvlan_state(__priv, __args...) \
+ stmmac_do_void_callback(__priv, vlan, update_dvlan_state, __args)
#define stmmac_enable_vlan(__priv, __args...) \
stmmac_do_void_callback(__priv, vlan, enable_vlan, __args)
#define stmmac_rx_hw_vlan(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 16fe56a1f617..e79b37fc716c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -6820,7 +6820,9 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
if (!netif_running(priv->dev))
return 0;
- return stmmac_update_vlan_hash(priv, priv->hw, hash, is_double);
+ stmmac_update_dvlan_state(priv, priv->hw, is_double);
+
+ return stmmac_update_vlan_hash(priv, priv->hw, hash);
}
/* FIXME: This may need RXC to be running, but it may be called with BH
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
index 983a90cb9767..1e47ae62093e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
@@ -161,8 +161,20 @@ static void vlan_restore_hw_rx_fltr(struct net_device *dev,
vlan_write_filter(dev, hw, i, hw->vlan_filter[i]);
}
-static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
- bool is_double)
+static void vlan_update_dvlan_state(struct mac_device_info *hw, bool enable)
+{
+ void __iomem *ioaddr = hw->pcsr;
+ u32 value;
+
+ value = readl(ioaddr + VLAN_TAG);
+ if (enable)
+ value |= VLAN_EDVLP | VLAN_ESVL | VLAN_DOVLTC;
+ else
+ value &= ~(VLAN_EDVLP | VLAN_ESVL | VLAN_DOVLTC);
+ writel(value, ioaddr + VLAN_TAG);
+}
+
+static void vlan_update_hash(struct mac_device_info *hw, u32 hash)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;
@@ -173,21 +185,9 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
if (hash) {
value |= VLAN_VTHM | VLAN_ETV;
- if (is_double) {
- value |= VLAN_EDVLP;
- value |= VLAN_ESVL;
- value |= VLAN_DOVLTC;
- } else {
- value &= ~VLAN_EDVLP;
- value &= ~VLAN_ESVL;
- value &= ~VLAN_DOVLTC;
- }
-
writel(value, ioaddr + VLAN_TAG);
} else {
value &= ~(VLAN_VTHM | VLAN_ETV);
- value &= ~(VLAN_EDVLP | VLAN_ESVL);
- value &= ~VLAN_DOVLTC;
value &= ~VLAN_VID;
writel(value, ioaddr + VLAN_TAG);
@@ -236,8 +236,7 @@ static void vlan_set_hw_mode(struct mac_device_info *hw)
writel(value, ioaddr + VLAN_TAG);
}
-static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
- bool is_double)
+static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash)
{
void __iomem *ioaddr = hw->pcsr;
@@ -253,15 +252,6 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
value = readl(ioaddr + VLAN_TAG);
value |= VLAN_VTHM | VLAN_ETV;
- if (is_double) {
- value |= VLAN_EDVLP;
- value |= VLAN_ESVL;
- value |= VLAN_DOVLTC;
- } else {
- value &= ~VLAN_EDVLP;
- value &= ~VLAN_ESVL;
- value &= ~VLAN_DOVLTC;
- }
value &= ~VLAN_VID;
writel(value, ioaddr + VLAN_TAG);
@@ -275,8 +265,6 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
value = readl(ioaddr + VLAN_TAG);
value &= ~(VLAN_VTHM | VLAN_ETV);
- value &= ~(VLAN_EDVLP | VLAN_ESVL);
- value &= ~VLAN_DOVLTC;
value &= ~VLAN_VID;
writel(value, ioaddr + VLAN_TAG);
@@ -285,6 +273,7 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
const struct stmmac_vlan_ops dwmac_vlan_ops = {
.update_vlan_hash = vlan_update_hash,
+ .update_dvlan_state = vlan_update_dvlan_state,
.enable_vlan = vlan_enable,
.add_hw_vlan_rx_fltr = vlan_add_hw_rx_fltr,
.del_hw_vlan_rx_fltr = vlan_del_hw_rx_fltr,
@@ -295,11 +284,13 @@ const struct stmmac_vlan_ops dwmac_vlan_ops = {
const struct stmmac_vlan_ops dwxlgmac2_vlan_ops = {
.update_vlan_hash = dwxgmac2_update_vlan_hash,
+ .update_dvlan_state = vlan_update_dvlan_state,
.enable_vlan = vlan_enable,
};
const struct stmmac_vlan_ops dwxgmac210_vlan_ops = {
.update_vlan_hash = dwxgmac2_update_vlan_hash,
+ .update_dvlan_state = vlan_update_dvlan_state,
.enable_vlan = vlan_enable,
.add_hw_vlan_rx_fltr = vlan_add_hw_rx_fltr,
.del_hw_vlan_rx_fltr = vlan_del_hw_rx_fltr,
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH net v3 2/5] net: stmmac: Move double VLAN handling to a dedicated op
2026-08-25 16:45 ` [PATCH net v3 2/5] net: stmmac: Move double VLAN handling to a dedicated op Ovidiu Panait
@ 2026-08-28 4:07 ` Joseph Steel
0 siblings, 0 replies; 9+ messages in thread
From: Joseph Steel @ 2026-08-28 4:07 UTC (permalink / raw)
To: Ovidiu Panait
Cc: maxime.chevallier, andrew+netdev, davem, edumazet, kuba, pabeni,
mcoquelin.stm32, alexandre.torgue, shuah, joabreu, jun.ann.lai,
yi.fang.gan, linux-kernel, netdev, linux-stm32, linux-arm-kernel,
linux-kselftest
Hi Ovidiu
On Tue, Aug 25, 2026 at 04:45:19PM +0000, Ovidiu Panait wrote:
> The double VLAN bits (EDVLP, ESVL, DOVLTC) are currently handled inside
> update_vlan_hash(). This ties the double VLAN state to the hash filter
> update, even though the two features are independent: hash filtering is
> controlled by dma_cap.vlhash and double vlan by dma_cap.dvlan.
>
> In preparation for removing double vlan support from dwmac4, move the
> double vlan logic into a separate update_dvlan_state() VLAN operation.
The S-VLAN implementation in STMMAC is a complete mess. It seems like
the original code author didn't fully understand what he was doing.
Double VLAN feature of DW *MACs has nothing to do with S-Tag VLANs.
It merely provides a way to insert/extract/filter an additional level
of VLAN header - inner. That's it. Seeing the networking subsystem
provides only the outer VLAN header for HW-accelerations, having the
DW MACs somehow working with the inner one is not only redundant but
had been harmful up until a recent kernel. The Tx path has been fixed
there. What you see here is a leftover of the incomplete fix.
Anyway if you feel like cleaning up a mess here then the only correct
solution would be to almost completely drop any double vlan stuff from
the VLAN implementation of the driver. That is:
1. Drop EDVLP flag toggle. But preserve the flag being always set
otherwise COE won't work for packets with an inner VLAN header.
2. Rename "double" word to "svlan".
You must not touch the ESVL and DOVLTC flags, since they are responsible
for the S-VLAN tags handling, have nothing to do with the Double VLAN
feature, and must be set so VLAN hash-based filter would perceive
VLAN S-tagged packets.
If you need to make DW GMAC4 not stripping VLAN S-Tags on Rx packets,
then you have to find a way to prevent the networking core from
enabling HW-accelerated S-Tags handling.
-Joseph
>
> Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
> Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
> ---
> v3 changes:
> - Rebased after dropping the dma_cap.dvlan patch.
> - Added "Reviewed-by" tag from Maxime.
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH net v3 3/5] net: stmmac: Disable double VLAN handling on dwmac4
2026-08-25 16:45 [PATCH net v3 0/5] net: stmmac: Fix double VLAN 802.1ad tag handling Ovidiu Panait
2026-08-25 16:45 ` [PATCH net v3 1/5] net: stmmac: Remove VLAN perfect matching dead code Ovidiu Panait
2026-08-25 16:45 ` [PATCH net v3 2/5] net: stmmac: Move double VLAN handling to a dedicated op Ovidiu Panait
@ 2026-08-25 16:45 ` Ovidiu Panait
2026-08-25 16:45 ` [PATCH net v3 4/5] selftests: drv-net: Move _set_ethtool_feat() into lib Ovidiu Panait
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Ovidiu Panait @ 2026-08-25 16:45 UTC (permalink / raw)
To: maxime.chevallier, andrew+netdev, davem, edumazet, kuba, pabeni,
mcoquelin.stm32, alexandre.torgue, shuah, joabreu, jun.ann.lai,
yi.fang.gan
Cc: linux-kernel, netdev, linux-stm32, linux-arm-kernel,
linux-kselftest, Ovidiu Panait
Currently, hardware VLAN stripping is broken for 802.1ad tags. vlan_rx_hw()
hardcodes ETH_P_8021Q when putting the hardware tag into the skb, rather
than using the actual protocol from the packet. Because of this, packets
that contain a 802.1ad outer tag are incorrectly passed up the stack as
having an 802.1Q tag. This causes QinQ ping between two hosts to fail.
vlan_rx_hw() is shared by dwxgmac2 and dwmac4: on dwxgmac2 the tag type
is available in the RDES3 write-back descriptor (the ET_LT field), so the
outer tag type can be determined based on that info. However, dwmac4
doesn't seem to provide the tag type. The Length/Type field in RDES3 only
indicates whether the packet is single or double-tagged, not which tag
type was stripped.
Since dwmac4 cannot report the stripped tag type, it cannot support
hardware double VLAN stripping correctly. Disable it by dropping
update_dvlan_state from dwmac_vlan_ops. With this, 802.1ad tags are
left in place and handled by the software VLAN path.
Also, restrict the NETIF_F_HW_VLAN_STAG_RX and NETIF_F_HW_VLAN_STAG_FILTER
advertisement to dwxgmac2.
Fixes: 750011e239a5 ("net: stmmac: Add support for HW-accelerated VLAN stripping")
Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
---
v3 changes:
- Rebased after dropping the dma_cap.dvlan patch.
v2 changes:
- Advertised NETIF_F_HW_VLAN_STAG_RX and NETIF_F_HW_VLAN_STAG_FILTER only
for XGMAC (reported by Sashiko).
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 8 ++++++--
drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c | 1 -
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index e79b37fc716c..7b6a506ce4c1 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -7956,14 +7956,18 @@ static int __stmmac_dvr_probe(struct device *device,
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
#ifdef STMMAC_VLAN_TAG_USED
/* Both mac100 and gmac support receive VLAN tag detection */
- ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX;
+ ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+ if (priv->plat->core_type == DWMAC_CORE_XGMAC)
+ ndev->features |= NETIF_F_HW_VLAN_STAG_RX;
+
if (dwmac_is_xmac(priv->plat->core_type)) {
ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
priv->hw->hw_vlan_en = true;
}
if (priv->dma_cap.vlhash) {
ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
- ndev->features |= NETIF_F_HW_VLAN_STAG_FILTER;
+ if (priv->plat->core_type == DWMAC_CORE_XGMAC)
+ ndev->features |= NETIF_F_HW_VLAN_STAG_FILTER;
}
if (priv->dma_cap.vlins)
ndev->features |= NETIF_F_HW_VLAN_CTAG_TX;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
index 1e47ae62093e..9b5b3f11f699 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c
@@ -273,7 +273,6 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash)
const struct stmmac_vlan_ops dwmac_vlan_ops = {
.update_vlan_hash = vlan_update_hash,
- .update_dvlan_state = vlan_update_dvlan_state,
.enable_vlan = vlan_enable,
.add_hw_vlan_rx_fltr = vlan_add_hw_rx_fltr,
.del_hw_vlan_rx_fltr = vlan_del_hw_rx_fltr,
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net v3 4/5] selftests: drv-net: Move _set_ethtool_feat() into lib
2026-08-25 16:45 [PATCH net v3 0/5] net: stmmac: Fix double VLAN 802.1ad tag handling Ovidiu Panait
` (2 preceding siblings ...)
2026-08-25 16:45 ` [PATCH net v3 3/5] net: stmmac: Disable double VLAN handling on dwmac4 Ovidiu Panait
@ 2026-08-25 16:45 ` Ovidiu Panait
2026-08-25 16:45 ` [PATCH net v3 5/5] selftests: drv-net: Add VLAN test Ovidiu Panait
2026-08-31 23:43 ` [PATCH net v3 0/5] net: stmmac: Fix double VLAN 802.1ad tag handling Jakub Kicinski
5 siblings, 0 replies; 9+ messages in thread
From: Ovidiu Panait @ 2026-08-25 16:45 UTC (permalink / raw)
To: maxime.chevallier, andrew+netdev, davem, edumazet, kuba, pabeni,
mcoquelin.stm32, alexandre.torgue, shuah, joabreu, jun.ann.lai,
yi.fang.gan
Cc: linux-kernel, netdev, linux-stm32, linux-arm-kernel,
linux-kselftest, Ovidiu Panait
Move the _set_ethtool_feat() helper from gro.py into lib, so that it can
be reused by the VLAN test added in the next commit. Drop the leading
underscore, now that the helper is exported.
Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
---
v3 changes:
- Fixed "ruff check" and "pylint --disable=R" warnings reported for
tools/testing/selftests/drivers/net/lib/py/feat.py.
v2 changes:
- New patch.
tools/testing/selftests/drivers/net/gro.py | 65 ++++++-------------
.../drivers/net/hw/lib/py/__init__.py | 3 +-
.../selftests/drivers/net/lib/py/__init__.py | 3 +-
.../selftests/drivers/net/lib/py/feat.py | 35 ++++++++++
4 files changed, 59 insertions(+), 47 deletions(-)
create mode 100644 tools/testing/selftests/drivers/net/lib/py/feat.py
diff --git a/tools/testing/selftests/drivers/net/gro.py b/tools/testing/selftests/drivers/net/gro.py
index 6ab8c97880d1..051a3b2d0ead 100755
--- a/tools/testing/selftests/drivers/net/gro.py
+++ b/tools/testing/selftests/drivers/net/gro.py
@@ -42,7 +42,7 @@ import re
from lib.py import ksft_run, ksft_exit, ksft_pr
from lib.py import NetDrvEpEnv, KsftFailEx, KsftXfailEx
from lib.py import NetdevFamily, EthtoolFamily
-from lib.py import bkg, cmd, defer, ethtool, ip
+from lib.py import bkg, cmd, defer, ethtool, ip, set_ethtool_feat
from lib.py import ksft_variants, KsftNamedVariant
@@ -96,31 +96,6 @@ def _set_mtu_restore(dev, mtu, host):
defer(ip, f"link set dev {dev['ifname']} mtu {dev['mtu']}", host=host)
-def _set_ethtool_feat(dev, current, feats, host=None):
- s2n = {True: "on", False: "off"}
-
- new = ["-K", dev]
- old = ["-K", dev]
- no_change = True
- for name, state in feats.items():
- new += [name, s2n[state]]
- old += [name, s2n[current[name]["active"]]]
-
- if current[name]["active"] != state:
- no_change = False
- if current[name]["fixed"]:
- raise KsftXfailEx(f"Device does not support {name}")
- if no_change:
- return
-
- eth_cmd = ethtool(" ".join(new), host=host)
- defer(ethtool, " ".join(old), host=host)
-
- # If ethtool printed something kernel must have modified some features
- if eth_cmd.stdout:
- ksft_pr(eth_cmd)
-
-
def _get_queue_stats(cfg, queue_id):
"""Get stats for a specific Rx queue."""
cfg.wait_hw_stats_settle()
@@ -247,15 +222,15 @@ def _setup(cfg, mode, test_name):
_write_defer_restore(cfg, flush_path, "200000", defer_undo=True)
_write_defer_restore(cfg, irq_path, "10", defer_undo=True)
- _set_ethtool_feat(cfg.ifname, cfg.feat,
- {"generic-receive-offload": True,
- "rx-gro-hw": False,
- "large-receive-offload": False})
+ set_ethtool_feat(cfg.ifname, cfg.feat,
+ {"generic-receive-offload": True,
+ "rx-gro-hw": False,
+ "large-receive-offload": False})
elif mode == "hw":
- _set_ethtool_feat(cfg.ifname, cfg.feat,
- {"generic-receive-offload": False,
- "rx-gro-hw": True,
- "large-receive-offload": False})
+ set_ethtool_feat(cfg.ifname, cfg.feat,
+ {"generic-receive-offload": False,
+ "rx-gro-hw": True,
+ "large-receive-offload": False})
# Some NICs treat HW GRO as a GRO sub-feature so disabling GRO
# will also clear HW GRO. Use a hack of installing XDP generic
@@ -270,27 +245,27 @@ def _setup(cfg, mode, test_name):
# Attaching XDP may change features, fetch the latest state
feat = ethtool(f"-k {cfg.ifname}", json=True)[0]
- _set_ethtool_feat(cfg.ifname, feat,
- {"generic-receive-offload": True,
- "rx-gro-hw": True,
- "large-receive-offload": False})
+ set_ethtool_feat(cfg.ifname, feat,
+ {"generic-receive-offload": True,
+ "rx-gro-hw": True,
+ "large-receive-offload": False})
elif mode == "lro":
# netdevsim advertises LRO for feature inheritance testing with
# bonding/team tests but it doesn't actually perform the offload
cfg.require_nsim(nsim_test=False)
- _set_ethtool_feat(cfg.ifname, cfg.feat,
- {"generic-receive-offload": False,
- "rx-gro-hw": False,
- "large-receive-offload": True})
+ set_ethtool_feat(cfg.ifname, cfg.feat,
+ {"generic-receive-offload": False,
+ "rx-gro-hw": False,
+ "large-receive-offload": True})
try:
# Disable TSO for local tests
cfg.require_nsim() # will raise KsftXfailEx if not running on nsim
- _set_ethtool_feat(cfg.remote_ifname, cfg.remote_feat,
- {"tcp-segmentation-offload": False},
- host=cfg.remote)
+ set_ethtool_feat(cfg.remote_ifname, cfg.remote_feat,
+ {"tcp-segmentation-offload": False},
+ host=cfg.remote)
except KsftXfailEx:
pass
diff --git a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
index 8a58cb17cc06..eea45d01cf7b 100644
--- a/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/hw/lib/py/__init__.py
@@ -31,6 +31,7 @@ try:
ksft_setup, ksft_variants, KsftNamedVariant
from net.lib.py import ksft_eq, ksft_ge, ksft_in, ksft_is, ksft_lt, \
ksft_ne, ksft_not_in, ksft_raises, ksft_true, ksft_gt, ksft_not_none
+ from drivers.net.lib.py import set_ethtool_feat
from drivers.net.lib.py import GenerateTraffic, Remote, Iperf3Runner
from drivers.net.lib.py import NetDrvEnv, NetDrvEpEnv, NetDrvContEnv
@@ -49,7 +50,7 @@ try:
"ksft_ne", "ksft_not_in", "ksft_raises", "ksft_true", "ksft_gt",
"ksft_not_none", "ksft_not_none",
"NetDrvEnv", "NetDrvEpEnv", "NetDrvContEnv", "GenerateTraffic",
- "Remote", "Iperf3Runner"]
+ "Remote", "Iperf3Runner", "set_ethtool_feat"]
except ModuleNotFoundError as e:
print("Failed importing `net` library from kernel sources")
print(str(e))
diff --git a/tools/testing/selftests/drivers/net/lib/py/__init__.py b/tools/testing/selftests/drivers/net/lib/py/__init__.py
index ee903bcf3207..c261aac2b976 100644
--- a/tools/testing/selftests/drivers/net/lib/py/__init__.py
+++ b/tools/testing/selftests/drivers/net/lib/py/__init__.py
@@ -48,11 +48,12 @@ try:
"ksft_not_none", "ksft_not_none"]
from .env import NetDrvEnv, NetDrvEpEnv, NetDrvContEnv
+ from .feat import set_ethtool_feat
from .load import GenerateTraffic, Iperf3Runner
from .remote import Remote
__all__ += ["NetDrvEnv", "NetDrvEpEnv", "NetDrvContEnv", "GenerateTraffic",
- "Remote", "Iperf3Runner"]
+ "Remote", "Iperf3Runner", "set_ethtool_feat"]
except ModuleNotFoundError as e:
print("Failed importing `net` library from kernel sources")
print(str(e))
diff --git a/tools/testing/selftests/drivers/net/lib/py/feat.py b/tools/testing/selftests/drivers/net/lib/py/feat.py
new file mode 100644
index 000000000000..014971c82b4b
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/lib/py/feat.py
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: GPL-2.0
+
+"""
+Netdev feature helper utilities for kernel selftests.
+
+Provides common operations for changing device features via ethtool.
+"""
+
+from lib.py import KsftXfailEx, defer, ethtool, ksft_pr
+
+
+def set_ethtool_feat(dev, current, feats, host=None):
+ """Set ethtool features with defer to restore original state."""
+ s2n = {True: "on", False: "off"}
+
+ new = ["-K", dev]
+ old = ["-K", dev]
+ no_change = True
+ for name, state in feats.items():
+ new += [name, s2n[state]]
+ old += [name, s2n[current[name]["active"]]]
+
+ if current[name]["active"] != state:
+ no_change = False
+ if current[name]["fixed"]:
+ raise KsftXfailEx(f"Device does not support {name}")
+ if no_change:
+ return
+
+ eth_cmd = ethtool(" ".join(new), host=host)
+ defer(ethtool, " ".join(old), host=host)
+
+ # If ethtool printed something kernel must have modified some features
+ if eth_cmd.stdout:
+ ksft_pr(eth_cmd)
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net v3 5/5] selftests: drv-net: Add VLAN test
2026-08-25 16:45 [PATCH net v3 0/5] net: stmmac: Fix double VLAN 802.1ad tag handling Ovidiu Panait
` (3 preceding siblings ...)
2026-08-25 16:45 ` [PATCH net v3 4/5] selftests: drv-net: Move _set_ethtool_feat() into lib Ovidiu Panait
@ 2026-08-25 16:45 ` Ovidiu Panait
2026-08-31 23:49 ` Jakub Kicinski
2026-08-31 23:43 ` [PATCH net v3 0/5] net: stmmac: Fix double VLAN 802.1ad tag handling Jakub Kicinski
5 siblings, 1 reply; 9+ messages in thread
From: Ovidiu Panait @ 2026-08-25 16:45 UTC (permalink / raw)
To: maxime.chevallier, andrew+netdev, davem, edumazet, kuba, pabeni,
mcoquelin.stm32, alexandre.torgue, shuah, joabreu, jun.ann.lai,
yi.fang.gan
Cc: linux-kernel, netdev, linux-stm32, linux-arm-kernel,
linux-kselftest, Ovidiu Panait
Add a test that validates ping traffic over VLAN interfaces. It aims
to catch drivers which mishandle hardware VLAN tag stripping, in
particular QinQ.
Three VLAN configurations are covered, each with hardware VLAN stripping
enabled and disabled:
- a single 802.1q VLAN interface
- a single 802.1ad VLAN interface
- an 802.1q VLAN stacked on top of an 802.1ad interface
NETIF=end1 LOCAL_V4=172.16.0.2 REMOTE_V4=172.16.0.3 \
REMOTE_TYPE=ssh REMOTE_ARGS=root@172.16.0.3 \
run_kselftest.sh -t drivers/net/hw:vlan.py
TAP version 13
1..1
# timeout set to 0
# selftests: drivers/net/hw: vlan.py
# # Interface: end1, driver: st_gmac
# TAP version 13
# 1..6
# ok 1 vlan.test.8021q_hw
# ok 2 vlan.test.8021q_sw
# ok 3 vlan.test.8021ad_hw
# ok 4 vlan.test.8021ad_sw
# ok 5 vlan.test.qinq_hw
# ok 6 vlan.test.qinq_sw
# # Totals: pass:6 fail:0 xfail:0 xpass:0 skip:0 error:0
ok 1 selftests: drivers/net/hw: vlan.py
# Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0
Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com>
---
v3 changes:
- Moved the selftest to drivers/net/hw, as the _hw variants couldn't run
under netdevsim.
- Fixed "ruff check" and "pylint --disable=R" warnings.
- Added CONFIG_VLAN_8021Q=m to configs file.
v2 changes:
- New patch.
.../testing/selftests/drivers/net/hw/Makefile | 1 +
tools/testing/selftests/drivers/net/hw/config | 1 +
.../testing/selftests/drivers/net/hw/vlan.py | 109 ++++++++++++++++++
3 files changed, 111 insertions(+)
create mode 100755 tools/testing/selftests/drivers/net/hw/vlan.py
diff --git a/tools/testing/selftests/drivers/net/hw/Makefile b/tools/testing/selftests/drivers/net/hw/Makefile
index 78bb0169350b..886a4222c6cf 100644
--- a/tools/testing/selftests/drivers/net/hw/Makefile
+++ b/tools/testing/selftests/drivers/net/hw/Makefile
@@ -49,6 +49,7 @@ TEST_PROGS = \
tso.py \
userns_devmem.py \
uso.py \
+ vlan.py \
xdp_metadata.py \
xsk_reconfig.py \
#
diff --git a/tools/testing/selftests/drivers/net/hw/config b/tools/testing/selftests/drivers/net/hw/config
index d89a9ba17655..c6c2b64bb712 100644
--- a/tools/testing/selftests/drivers/net/hw/config
+++ b/tools/testing/selftests/drivers/net/hw/config
@@ -24,5 +24,6 @@ CONFIG_NET_SCH_INGRESS=y
CONFIG_SYNC_FILE=y
CONFIG_UDMABUF=y
CONFIG_USER_NS=y
+CONFIG_VLAN_8021Q=m
CONFIG_VXLAN=y
CONFIG_XFRM_USER=y
diff --git a/tools/testing/selftests/drivers/net/hw/vlan.py b/tools/testing/selftests/drivers/net/hw/vlan.py
new file mode 100755
index 000000000000..79eec655973b
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/hw/vlan.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+
+"""
+VLAN tests.
+
+Validates that ping traffic is sent and received correctly over 802.1q
+and 802.1ad VLAN interfaces, with hardware VLAN stripping enabled and
+disabled.
+
+Test cases:
+ - 8021q_hw: Traffic over a single 802.1q VLAN, HW stripping on
+ - 8021q_sw: Traffic over a single 802.1q VLAN, HW stripping off
+ - 8021ad_hw: Traffic over a single 802.1ad VLAN, HW stripping on
+ - 8021ad_sw: Traffic over a single 802.1ad VLAN, HW stripping off
+ - qinq_hw: Traffic over an 802.1q VLAN stacked on an 802.1ad VLAN,
+ HW stripping on
+ - qinq_sw: Traffic over an 802.1q VLAN stacked on an 802.1ad VLAN,
+ HW stripping off
+"""
+
+import os
+
+from lib.py import (
+ KsftNamedVariant,
+ NetDrvEpEnv,
+ cmd,
+ defer,
+ ethtool,
+ ip,
+ ksft_exit,
+ ksft_run,
+ ksft_variants,
+ set_ethtool_feat,
+)
+
+OUTER_DEV = f"vlout{os.getpid()}"
+INNER_DEV = f"vlin{os.getpid()}"
+
+OUTER_VID = 100
+INNER_VID = 200
+
+LOCAL_IP = "198.51.100.1"
+REMOTE_IP = "198.51.100.2"
+
+
+def _vlan_add(base, name, proto, vid, host=None):
+ """Create a VLAN device on top of base and bring it up."""
+
+ ip(f"link add link {base} name {name} type vlan proto {proto} id {vid}",
+ host=host)
+ defer(ip, f"link del {name}", host=host)
+ ip(f"link set {name} up", host=host)
+
+
+def _vlan_setup(base, addr, outer_proto, inner_proto, host=None):
+ """Create VLAN interfaces on base and set an IP on the innermost one."""
+
+ _vlan_add(base, OUTER_DEV, outer_proto, OUTER_VID, host=host)
+ if inner_proto:
+ _vlan_add(OUTER_DEV, INNER_DEV, inner_proto, INNER_VID, host=host)
+
+ dev = INNER_DEV if inner_proto else OUTER_DEV
+ ip(f"addr add {addr}/24 dev {dev}", host=host)
+
+
+def _setup(cfg, outer_proto, inner_proto, hw_strip):
+ """Configure VLAN stripping and create the VLAN interfaces."""
+
+ feat = ethtool(f"-k {cfg.ifname}", json=True)[0]
+ set_ethtool_feat(cfg.ifname, feat, {"rx-vlan-offload": hw_strip})
+
+ _vlan_setup(cfg.ifname, LOCAL_IP, outer_proto, inner_proto)
+ _vlan_setup(cfg.remote_ifname, REMOTE_IP, outer_proto, inner_proto,
+ host=cfg.remote)
+
+
+def _vlan_variants():
+ """Generator that yields the VLAN protocols and the stripping mode."""
+
+ yield KsftNamedVariant("8021q_hw", "802.1q", None, True)
+ yield KsftNamedVariant("8021q_sw", "802.1q", None, False)
+ yield KsftNamedVariant("8021ad_hw", "802.1ad", None, True)
+ yield KsftNamedVariant("8021ad_sw", "802.1ad", None, False)
+ yield KsftNamedVariant("qinq_hw", "802.1ad", "802.1q", True)
+ yield KsftNamedVariant("qinq_sw", "802.1ad", "802.1q", False)
+
+
+@ksft_variants(_vlan_variants())
+def test(cfg, outer_proto, inner_proto, hw_strip):
+ """Run a single VLAN test"""
+
+ cfg.require_ipver("4")
+
+ _setup(cfg, outer_proto, inner_proto, hw_strip)
+
+ cmd(f"ping -c 1 -W 5 {REMOTE_IP}")
+
+
+def main() -> None:
+ """ Ksft boiler plate main """
+
+ with NetDrvEpEnv(__file__) as cfg:
+ ksft_run(cases=[test], args=(cfg, ))
+ ksft_exit()
+
+
+if __name__ == "__main__":
+ main()
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH net v3 5/5] selftests: drv-net: Add VLAN test
2026-08-25 16:45 ` [PATCH net v3 5/5] selftests: drv-net: Add VLAN test Ovidiu Panait
@ 2026-08-31 23:49 ` Jakub Kicinski
0 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2026-08-31 23:49 UTC (permalink / raw)
To: Ovidiu Panait
Cc: maxime.chevallier, andrew+netdev, davem, edumazet, pabeni,
mcoquelin.stm32, alexandre.torgue, shuah, joabreu, jun.ann.lai,
yi.fang.gan, linux-kernel, netdev, linux-stm32, linux-arm-kernel,
linux-kselftest
On Tue, 25 Aug 2026 16:45:22 +0000 Ovidiu Panait wrote:
> Add a test that validates ping traffic over VLAN interfaces. It aims
> to catch drivers which mishandle hardware VLAN tag stripping, in
> particular QinQ.
I take it back, sorry, looks like AI found something to complain about:
> +def _setup(cfg, outer_proto, inner_proto, hw_strip):
> + """Configure VLAN stripping and create the VLAN interfaces."""
> +
> + feat = ethtool(f"-k {cfg.ifname}", json=True)[0]
> + set_ethtool_feat(cfg.ifname, feat, {"rx-vlan-offload": hw_strip})
Does toggling rx-vlan-offload here actually change anything for the
802.1ad and QinQ variants?
In net/ethtool/common.c, netdev_features_strings maps the two RX VLAN
parse features to distinct bits:
[NETIF_F_HW_VLAN_CTAG_RX_BIT] = "rx-vlan-hw-parse",
...
[NETIF_F_HW_VLAN_STAG_RX_BIT] = "rx-vlan-stag-hw-parse",
rx-vlan-offload is the alias for rx-vlan-hw-parse, i.e.
NETIF_F_HW_VLAN_CTAG_RX (TPID 0x8100). Stripping of an 802.1ad S-tag
(TPID 0x88a8) is controlled by NETIF_F_HW_VLAN_STAG_RX, which this test
never reads or sets.
For the st_gmac/stmmac driver used in the commit message log,
stmmac_rx_vlan() gates each TPID on its own feature bit:
if ((vlan_proto == htons(ETH_P_8021Q) &&
dev->features & NETIF_F_HW_VLAN_CTAG_RX) ||
(vlan_proto == htons(ETH_P_8021AD) &&
dev->features & NETIF_F_HW_VLAN_STAG_RX)) {
and STAG_RX is only advertised for DWMAC_CORE_XGMAC, so on other cores
the outer-tag stripping state is unaffected by the flag the test flips.
Also, set_ethtool_feat() in tools/testing/selftests/drivers/net/lib/py/feat.py
only programs the feature names the caller passes, and _setup() applies
them to cfg.ifname only, never to cfg.remote. The TX counterparts
(tx-vlan-hw-insert / tx-vlan-stag-hw-insert) are left untouched as well.
Would it make sense to include the corresponding STAG feature in the dict
passed to set_ethtool_feat() for the 802.1ad and QinQ variants (xfail or
skip when the bit is fixed), or otherwise document the limitation?
> +
> + _vlan_setup(cfg.ifname, LOCAL_IP, outer_proto, inner_proto)
> + _vlan_setup(cfg.remote_ifname, REMOTE_IP, outer_proto, inner_proto,
> + host=cfg.remote)
> +
> +
> +def _vlan_variants():
> + """Generator that yields the VLAN protocols and the stripping mode."""
> +
> + yield KsftNamedVariant("8021q_hw", "802.1q", None, True)
> + yield KsftNamedVariant("8021q_sw", "802.1q", None, False)
> + yield KsftNamedVariant("8021ad_hw", "802.1ad", None, True)
> + yield KsftNamedVariant("8021ad_sw", "802.1ad", None, False)
> + yield KsftNamedVariant("qinq_hw", "802.1ad", "802.1q", True)
> + yield KsftNamedVariant("qinq_sw", "802.1ad", "802.1q", False)
Following on from the above: do the 8021ad_hw/8021ad_sw and
qinq_hw/qinq_sw pairs end up running the same outer-tag configuration
twice on devices that implement S-tag stripping separately from C-tag
stripping?
If so, the commit message statement
"Three VLAN configurations are covered, each with hardware VLAN
stripping enabled and disabled"
and the module docstring entries for 8021ad_hw/8021ad_sw and
qinq_hw/qinq_sw would describe coverage the test does not establish, and
the QinQ mis-stripping case the test aims to catch would pass in both
variants.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net v3 0/5] net: stmmac: Fix double VLAN 802.1ad tag handling
2026-08-25 16:45 [PATCH net v3 0/5] net: stmmac: Fix double VLAN 802.1ad tag handling Ovidiu Panait
` (4 preceding siblings ...)
2026-08-25 16:45 ` [PATCH net v3 5/5] selftests: drv-net: Add VLAN test Ovidiu Panait
@ 2026-08-31 23:43 ` Jakub Kicinski
5 siblings, 0 replies; 9+ messages in thread
From: Jakub Kicinski @ 2026-08-31 23:43 UTC (permalink / raw)
To: Ovidiu Panait
Cc: maxime.chevallier, andrew+netdev, davem, edumazet, pabeni,
mcoquelin.stm32, alexandre.torgue, shuah, joabreu, jun.ann.lai,
yi.fang.gan, linux-kernel, netdev, linux-stm32, linux-arm-kernel,
linux-kselftest
On Tue, 25 Aug 2026 16:45:17 +0000 Ovidiu Panait wrote:
> Currently, hardware VLAN stripping is broken for 802.1ad tags. vlan_rx_hw()
> hardcodes ETH_P_8021Q when putting the hardware tag into the skb, rather
> than using the actual protocol from the packet. Because of this, packets
> that contain an 802.1ad outer tag are incorrectly passed up the stack as
> having an 802.1Q tag.
Test LGTM, let me apply just the test since it looks like the driver
part will need a respin.
^ permalink raw reply [flat|nested] 9+ messages in thread