Netdev List
 help / color / mirror / Atom feed
* [PATCH iwl-net] ice: keep the VLAN tag of priority-tagged frames with Rx stripping enabled
@ 2026-10-02 10:31 Petr Oros
  2026-10-03  9:48 ` Ivan Vecera
  0 siblings, 1 reply; 2+ messages in thread
From: Petr Oros @ 2026-10-02 10:31 UTC (permalink / raw)
  To: netdev
  Cc: Petr Oros, Tony Nguyen, Przemek Kitszel, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Stanislav Fomichev, Anirudh Venkataramanan,
	Maciej Fijalkowski, Larysa Zaremba, intel-wired-lan, linux-kernel,
	bpf

With Rx VLAN stripping enabled the hardware also strips tags with VID 0,
but ice_receive_skb() only puts the stripped tag back when the VID is
non-zero. Priority-tagged frames reach the stack as untagged and a vlan0
upper device never sees them, while the same traffic works with rxvlan
disabled.

Hit by our QE VLAN test on an E810-XXV, where ping over vlan0 fails and
tcpdump on the PF shows the peer's priority-tagged ARP requests arriving
untagged. Reproduced on the net tree with a PF and its VF as the peer in
both single and double VLAN mode. i40e had the same bug, fixed by commit
2a508c64ad27 ("i40e: fix VLAN.TCI == 0 RX HW offload").

Put the tag in ice_process_skb_fields() keyed on the L2TAG1P/L2TAG2P
status bits, let ice_get_vlan_tci() report whether a tag was stripped
(this also fixes the XDP VLAN hint for a zero TCI) and drop the now
trivial ice_receive_skb().

Fixes: 2b245cb29421 ("ice: Implement transmit and NAPI support")
Fixes: 714ed949c6f3 ("ice: Implement VLAN tag hint")
Signed-off-by: Petr Oros <poros@redhat.com>
---
 drivers/net/ethernet/intel/ice/ice_txrx.c     |  5 +---
 drivers/net/ethernet/intel/ice/ice_txrx_lib.c | 26 ++++--------------
 drivers/net/ethernet/intel/ice/ice_txrx_lib.h | 27 +++++++++++--------
 drivers/net/ethernet/intel/ice/ice_xsk.c      |  5 +---
 4 files changed, 23 insertions(+), 40 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c
index 31303ab5be175a..3935ac05a251b4 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.c
@@ -970,7 +970,6 @@ static int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
 		struct sk_buff *skb;
 		unsigned int size;
 		u16 stat_err_bits;
-		u16 vlan_tci;
 		bool rxe;
 
 		/* get the Rx desc from Rx ring based on 'next_to_clean' */
@@ -1051,8 +1050,6 @@ static int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
 			continue;
 		}
 
-		vlan_tci = ice_get_vlan_tci(rx_desc);
-
 		/* probably a little skewed due to removing CRC */
 		total_rx_bytes += skb->len;
 
@@ -1061,7 +1058,7 @@ static int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
 
 		ice_trace(clean_rx_irq_indicate, rx_ring, rx_desc, skb);
 		/* send completed skb up the stack */
-		ice_receive_skb(rx_ring, skb, vlan_tci);
+		napi_gro_receive(&rx_ring->q_vector->napi, skb);
 
 		/* update budget accounting */
 		total_rx_pkts++;
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
index e695a664e53d18..19307086c238f5 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c
@@ -218,6 +218,7 @@ ice_process_skb_fields(struct ice_rx_ring *rx_ring,
 		       struct sk_buff *skb)
 {
 	u16 ptype = ice_get_ptype(rx_desc);
+	u16 vlan_tci;
 
 	ice_rx_hash_to_skb(rx_ring, rx_desc, skb, ptype);
 
@@ -238,29 +239,13 @@ ice_process_skb_fields(struct ice_rx_ring *rx_ring,
 
 	ice_rx_csum(rx_ring, skb, rx_desc, ptype);
 
+	if (rx_ring->vlan_proto && ice_get_vlan_tci(rx_desc, &vlan_tci))
+		__vlan_hwaccel_put_tag(skb, rx_ring->vlan_proto, vlan_tci);
+
 	if (rx_ring->ptp_rx)
 		ice_ptp_rx_hwts_to_skb(rx_ring, rx_desc, skb);
 }
 
-/**
- * ice_receive_skb - Send a completed packet up the stack
- * @rx_ring: Rx ring in play
- * @skb: packet to send up
- * @vlan_tci: VLAN TCI for packet
- *
- * This function sends the completed packet (via. skb) up the stack using
- * gro receive functions (with/without VLAN tag)
- */
-void
-ice_receive_skb(struct ice_rx_ring *rx_ring, struct sk_buff *skb, u16 vlan_tci)
-{
-	if ((vlan_tci & VLAN_VID_MASK) && rx_ring->vlan_proto)
-		__vlan_hwaccel_put_tag(skb, rx_ring->vlan_proto,
-				       vlan_tci);
-
-	napi_gro_receive(&rx_ring->q_vector->napi, skb);
-}
-
 /**
  * ice_clean_xdp_tx_buf - Free and unmap XDP Tx buffer
  * @dev: device for DMA mapping
@@ -587,8 +572,7 @@ static int ice_xdp_rx_vlan_tag(const struct xdp_md *ctx, __be16 *vlan_proto,
 	if (!*vlan_proto)
 		return -ENODATA;
 
-	*vlan_tci = ice_get_vlan_tci(xdp_ext->desc);
-	if (!*vlan_tci)
+	if (!ice_get_vlan_tci(xdp_ext->desc, vlan_tci))
 		return -ENODATA;
 
 	return 0;
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.h b/drivers/net/ethernet/intel/ice/ice_txrx_lib.h
index f17990b68b621d..579ce56c0c3c0a 100644
--- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.h
+++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.h
@@ -70,25 +70,32 @@ ice_build_tstamp_desc(u16 tx_desc, u32 tstamp)
 /**
  * ice_get_vlan_tci - get VLAN TCI from Rx flex descriptor
  * @rx_desc: Rx 32b flex descriptor with RXDID=2
+ * @vlan_tci: VLAN TCI stripped by hardware
  *
  * The OS and current PF implementation only support stripping a single VLAN tag
- * at a time, so there should only ever be 0 or 1 tags in the l2tag* fields. If
- * one is found return the tag, else return 0 to mean no VLAN tag was found.
+ * at a time, so there should only ever be 0 or 1 tags in the l2tag* fields.
+ *
+ * Return: true if a VLAN tag was stripped and stored in @vlan_tci, false
+ * otherwise.
  */
-static inline u16
-ice_get_vlan_tci(const union ice_32b_rx_flex_desc *rx_desc)
+static inline bool
+ice_get_vlan_tci(const union ice_32b_rx_flex_desc *rx_desc, u16 *vlan_tci)
 {
 	u16 stat_err_bits;
 
 	stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_L2TAG1P_S);
-	if (ice_test_staterr(rx_desc->wb.status_error0, stat_err_bits))
-		return le16_to_cpu(rx_desc->wb.l2tag1);
+	if (ice_test_staterr(rx_desc->wb.status_error0, stat_err_bits)) {
+		*vlan_tci = le16_to_cpu(rx_desc->wb.l2tag1);
+		return true;
+	}
 
 	stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS1_L2TAG2P_S);
-	if (ice_test_staterr(rx_desc->wb.status_error1, stat_err_bits))
-		return le16_to_cpu(rx_desc->wb.l2tag2_2nd);
+	if (ice_test_staterr(rx_desc->wb.status_error1, stat_err_bits)) {
+		*vlan_tci = le16_to_cpu(rx_desc->wb.l2tag2_2nd);
+		return true;
+	}
 
-	return 0;
+	return false;
 }
 
 /**
@@ -132,7 +139,5 @@ void
 ice_process_skb_fields(struct ice_rx_ring *rx_ring,
 		       union ice_32b_rx_flex_desc *rx_desc,
 		       struct sk_buff *skb);
-void
-ice_receive_skb(struct ice_rx_ring *rx_ring, struct sk_buff *skb, u16 vlan_tci);
 
 #endif /* !_ICE_TXRX_LIB_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
index 0643017541c35a..fd2e628a8bc95c 100644
--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
+++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
@@ -591,7 +591,6 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring,
 		struct xdp_buff *xdp;
 		struct sk_buff *skb;
 		u16 stat_err_bits;
-		u16 vlan_tci;
 
 		rx_desc = ICE_RX_DESC(rx_ring, ntc);
 
@@ -667,10 +666,8 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring,
 		total_rx_bytes += skb->len;
 		total_rx_packets++;
 
-		vlan_tci = ice_get_vlan_tci(rx_desc);
-
 		ice_process_skb_fields(rx_ring, rx_desc, skb);
-		ice_receive_skb(rx_ring, skb, vlan_tci);
+		napi_gro_receive(&rx_ring->q_vector->napi, skb);
 	}
 
 	rx_ring->next_to_clean = ntc;
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-03  9:48 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-02 10:31 [PATCH iwl-net] ice: keep the VLAN tag of priority-tagged frames with Rx stripping enabled Petr Oros
2026-10-03  9:48 ` Ivan Vecera

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox