[PATCH 08/10] net/bnxt: fix for VLAN stripping being set incorrectly

Mohammad Shuab Siddique mohammad-shuab.siddique at broadcom.com
Thu Jun 4 05:18:49 CEST 2026


From: Keegan Freyhof <keegan.freyhof at broadcom.com>

Driver was setting the VLAN strip ol flag based on port
settings rather than per packet for V3. This caused
TruFlow's per packet flows to incorrectly not report
VLAN_STRIPPED, as the TruFlow might set a flow to strip
VLAN based on other markers in the packet rather than
always for the port. Changed the logic to set the flag
per packet.

Fixes: 15276ba987bd ("net/bnxt: fix getting burst mode for Arm")
Cc: stable at dpdk.org
Signed-off-by: Keegan Freyhof <keegan.freyhof at broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique at broadcom.com>
---
 drivers/net/bnxt/bnxt_rxr.c           |  6 +--
 drivers/net/bnxt/bnxt_rxr.h           | 12 +++---
 drivers/net/bnxt/bnxt_rxtx_vec_avx2.c | 54 +++++++++++++++++++++++----
 3 files changed, 56 insertions(+), 16 deletions(-)

diff --git a/drivers/net/bnxt/bnxt_rxr.c b/drivers/net/bnxt/bnxt_rxr.c
index ee49d85d43..0fab4ddf78 100644
--- a/drivers/net/bnxt/bnxt_rxr.c
+++ b/drivers/net/bnxt/bnxt_rxr.c
@@ -1127,7 +1127,6 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
 	uint16_t cmp_type;
 	uint32_t vfr_flag = 0, mark_id = 0;
 	struct bnxt *bp = rxq->bp;
-	struct bnxt_vnic_info *vnic = rxq->vnic;
 
 	rxcmp = (struct rx_pkt_cmpl *)
 	    &cpr->cp_desc_ring[cp_cons];
@@ -1236,8 +1235,7 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
 	if (cmp_type == CMPL_BASE_TYPE_RX_L2_V3) {
 		bnxt_parse_csum_v3(mbuf, rxcmp1);
 		bnxt_parse_pkt_type_v3(mbuf, rxcmp, rxcmp1);
-		bnxt_rx_vlan_v3(mbuf, rxcmp, rxcmp1, vnic->vlan_strip);
-
+		bnxt_rx_vlan_v3(mbuf, rxcmp, rxcmp1);
 		/* Packet cannot be a PTP ethertype if it is detected as L4 */
 		if (mbuf->ol_flags & RTE_MBUF_F_RX_L4_CKSUM_GOOD) {
 			mbuf->ol_flags &= ~RTE_MBUF_F_RX_IEEE1588_PTP;
@@ -1259,7 +1257,7 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
 	if (cmp_type == CMPL_BASE_TYPE_RX_L2_V2) {
 		bnxt_parse_csum_v2(mbuf, rxcmp1);
 		bnxt_parse_pkt_type_v2(mbuf, rxcmp, rxcmp1);
-		bnxt_rx_vlan_v2(mbuf, rxcmp, rxcmp1);
+		bnxt_rx_vlan_v2(mbuf, bp, rxcmp, rxcmp1);
 		/* TODO Add support for cfa_code parsing */
 		goto reuse_rx_mbuf;
 	}
diff --git a/drivers/net/bnxt/bnxt_rxr.h b/drivers/net/bnxt/bnxt_rxr.h
index 352d509210..c971233dc3 100644
--- a/drivers/net/bnxt/bnxt_rxr.h
+++ b/drivers/net/bnxt/bnxt_rxr.h
@@ -276,12 +276,15 @@ static inline void bnxt_set_vlan(struct rx_pkt_cmpl_hi *rxcmp1,
 	  RX_PKT_V2_CMPL_HI_METADATA0_PRI_MASK))
 
 static inline void bnxt_rx_vlan_v2(struct rte_mbuf *mbuf,
+				   const struct bnxt *bp,
 				   struct rx_pkt_cmpl *rxcmp,
 				   struct rx_pkt_cmpl_hi *rxcmp1)
 {
 	if (RX_CMP_VLAN_VALID(rxcmp)) {
 		mbuf->vlan_tci = RX_CMP_METADATA0_VID(rxcmp1);
-		mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN | RTE_MBUF_F_RX_VLAN_STRIPPED;
+		mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN;
+		if (BNXT_RX_VLAN_STRIP_EN(bp))
+			mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN_STRIPPED;
 	}
 }
 
@@ -483,14 +486,13 @@ bnxt_parse_pkt_type_v2(struct rte_mbuf *mbuf,
 	  RX_PKT_V3_CMPL_HI_METADATA0_PRI_MASK))
 
 static inline void bnxt_rx_vlan_v3(struct rte_mbuf *mbuf,
-	struct rx_pkt_cmpl *rxcmp,
-	struct rx_pkt_cmpl_hi *rxcmp1,
-	bool stripped)
+				   struct rx_pkt_cmpl *rxcmp,
+				   struct rx_pkt_cmpl_hi *rxcmp1)
 {
 	if (RX_CMP_V3_VLAN_VALID(rxcmp)) {
 		mbuf->vlan_tci = RX_CMP_V3_METADATA0_VID(rxcmp1);
 		mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN;
-		if (stripped)
+		if (rxcmp1->flags2 & RX_PKT_V3_CMPL_HI_FLAGS2_META_FORMAT_MASK)
 			mbuf->ol_flags |= RTE_MBUF_F_RX_VLAN_STRIPPED;
 	}
 }
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
index 5e22b4fc11..38aca98cb1 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
@@ -70,6 +70,17 @@ recv_burst_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		_mm256_set1_epi32(RX_PKT_CMPL_FLAGS2_IP_TYPE);
 	const __m256i rss_mask =
 		_mm256_set1_epi32(RX_PKT_CMPL_FLAGS_RSS_VALID);
+	/*
+	 * ol_flags_table already sets RX_VLAN|RX_VLAN_STRIPPED when VLAN strip
+	 * is enabled.  For completeness, also OR in the flags here based on the
+	 * per-packet VLAN-metadata bit so that the two sources agree.  The
+	 * constant is broadcast once: non-zero only when strip offload is on.
+	 */
+	const __m256i vlan_ol_val =
+		BNXT_RX_VLAN_STRIP_EN(rxq->bp) ?
+		_mm256_set1_epi32((uint32_t)(RTE_MBUF_F_RX_VLAN |
+					     RTE_MBUF_F_RX_VLAN_STRIPPED)) :
+					     _mm256_setzero_si256();
 	__m256i t0, t1, flags_type, flags2, index, errors;
 	__m256i ptype_idx, ptypes, is_tunnel;
 	__m256i mbuf01, mbuf23, mbuf45, mbuf67;
@@ -286,6 +297,25 @@ recv_burst_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		rss_flags = _mm256_srli_epi32(rss_flags, 9);
 		ol_flags = _mm256_or_si256(ol_flags, errors);
 		ol_flags = _mm256_or_si256(ol_flags, rss_flags);
+		/*
+		 * Set RX_VLAN | RX_VLAN_STRIPPED for packets whose vlan_tci
+		 * is non-zero (i.e. hardware reported VLAN metadata, indicated
+		 * by RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN in index bit 4).
+		 * vlan_ol_val is the broadcast constant computed before the
+		 * loop: non-zero only when VLAN RX strip offload is enabled.
+		 * _mm256_cmpeq_epi32 produces 0xFFFFFFFF per lane when the
+		 * VLAN bit is set, masking the constant to those lanes only.
+		 */
+		{
+			const __m256i vlan_bit =
+				_mm256_set1_epi32(RX_PKT_CMPL_FLAGS2_META_FORMAT_VLAN);
+			__m256i vlan_mask =
+				_mm256_cmpeq_epi32(_mm256_and_si256(index, vlan_bit),
+						   vlan_bit);
+			ol_flags = _mm256_or_si256(ol_flags,
+					_mm256_and_si256(vlan_mask,
+							 vlan_ol_val));
+		}
 		ol_flags_hi = _mm256_permute2f128_si256(ol_flags,
 							ol_flags, 0x11);
 
@@ -908,7 +938,6 @@ static uint16_t
 recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 {
 	struct bnxt_rx_queue *rxq = rx_queue;
-	struct bnxt_vnic_info *vnic = rxq->vnic;
 	const __m256i mbuf_init =
 		_mm256_set_epi64x(0, 0, 0, rxq->mbuf_initializer);
 	struct bnxt_cp_ring_info *cpr = rxq->cp_ring;
@@ -1001,8 +1030,8 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 				  mbcons += BNXT_RX_DESCS_PER_LOOP_VEC256) {
 		__m256i desc0, desc1, desc2, desc3, desc4, desc5, desc6, desc7;
 		__m256i rxcmp0_1, rxcmp2_3, rxcmp4_5, rxcmp6_7, info3_v;
+		__m256i errors_v2, cs_calc, cs_valid, meta_format;
 		__m256i md1_0123, lo2_3, md1_4567, lo6_7;
-		__m256i errors_v2, cs_calc, cs_valid;
 		uint32_t num_valid;
 
 		t0 = _mm256_loadu_si256((void *)&rxr->rx_buf_ring[mbcons]);
@@ -1070,7 +1099,9 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 		flags2 = _mm256_unpackhi_epi64(t0, t1);
 		/* fs mask used for RX_PKT_CMPL_CALC */
 		cs_calc = _mm256_and_si256(flags2, mask_fs);
-		cs_valid = _mm256_cmpeq_epi32(cs_calc, _mm256_setzero_si256());
+		/* Add the meta_format to cs_calc */
+		cs_calc = _mm256_or_si256(cs_calc, _mm256_and_si256(flags2,
+							_mm256_slli_epi32(mask_fs, 4)));
 
 		/* Extract metadata0 and errors from high completion */
 		t0 = _mm256_unpackhi_epi32(rxcmp0_1, rxcmp2_3);
@@ -1082,6 +1113,11 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 		 */
 		errors_csum_idx = _mm256_srli_epi32(_mm256_and_si256(errors_v2,
 						    _mm256_slli_epi32(mask_fs, 4)), 4);
+		meta_format = _mm256_cmpeq_epi32(_mm256_and_si256(cs_calc,
+							_mm256_slli_epi32(mask_fs, 4)),
+							_mm256_setzero_si256());
+		cs_valid = _mm256_cmpeq_epi32(_mm256_and_si256(cs_calc, mask_fs),
+							_mm256_setzero_si256());
 		errors_csum_idx = _mm256_andnot_si256(cs_valid, errors_csum_idx);
 
 		/*
@@ -1104,10 +1140,14 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 		vlan_flags = _mm256_and_si256(metadata1, _mm256_slli_epi32(mask_1s, 15));
 		vlan_flags = _mm256_min_epu32(vlan_flags, mask_1s);
 
-		if (vnic->vlan_strip) {
-			vlan_flags = _mm256_or_si256(vlan_flags,
-					_mm256_slli_epi32(vlan_flags, 6));
-		}
+		/*
+		 * VLAN present in mbuf when metadata valid (vlan_flags) and
+		 * meta_format is non-zero in flags2. andnot(cmpeq(tci,0), vlan_flags) is
+		 * (~zero_mask) & vlan_flags.
+		 */
+		t0 = _mm256_andnot_si256(meta_format, vlan_flags);
+		/* RTE_MBUF_F_RX_VLAN + STRIPPED when hardware reports valid VLAN. */
+		vlan_flags = _mm256_or_si256(vlan_flags, _mm256_slli_epi32(t0, 6));
 
 		/* Extract flags_type from low completion for eight packets */
 		t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
-- 
2.47.3



More information about the dev mailing list