DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/10] net/bnxt: vector mode implementation for V3 packets
From: Mohammad Shuab Siddique @ 2026-06-04  3:18 UTC (permalink / raw)
  To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
	Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>

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

Added support for AVX2 vector mode reporting of the
VLAN TCI for Thor 2.

Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
 drivers/net/bnxt/bnxt_ethdev.c          |   7 +-
 drivers/net/bnxt/bnxt_rxr.h             |   2 +
 drivers/net/bnxt/bnxt_rxtx_vec_avx2.c   | 402 ++++++++++++++++++++++++
 drivers/net/bnxt/bnxt_rxtx_vec_common.h |  36 +++
 4 files changed, 446 insertions(+), 1 deletion(-)

diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index c45afdb20a..5bd51de3cd 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1493,7 +1493,12 @@ bnxt_receive_function(struct rte_eth_dev *eth_dev)
 		bp->flags |= BNXT_FLAG_RX_VECTOR_PKT_MODE;
 		if (bnxt_compressed_rx_cqe_mode_enabled(bp))
 			return bnxt_crx_pkts_vec_avx2;
-		return bnxt_recv_pkts_vec_avx2;
+		if (BNXT_TRUFLOW_EN(bp) && bnxt_ulp_explicit_mark_enabled(bp))
+			goto use_scalar_rx;
+		if (BNXT_CHIP_P7(bp))
+			return bnxt_recv_pkts_vec_avx2_v3;
+		else
+			return bnxt_recv_pkts_vec_avx2;
 	}
 #endif
 	if (rte_vect_get_max_simd_bitwidth() >= RTE_VECT_SIMD_128) {
diff --git a/drivers/net/bnxt/bnxt_rxr.h b/drivers/net/bnxt/bnxt_rxr.h
index 2a28fa2073..352d509210 100644
--- a/drivers/net/bnxt/bnxt_rxr.h
+++ b/drivers/net/bnxt/bnxt_rxr.h
@@ -165,6 +165,8 @@ int bnxt_rxq_vec_setup(struct bnxt_rx_queue *rxq);
 #if defined(RTE_ARCH_X86)
 uint16_t bnxt_recv_pkts_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts,
 				 uint16_t nb_pkts);
+uint16_t bnxt_recv_pkts_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts,
+				    uint16_t nb_pkts);
 uint16_t bnxt_crx_pkts_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts,
 				uint16_t nb_pkts);
 #endif
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
index 35550534de..46b51b20e4 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
@@ -903,3 +903,405 @@ bnxt_xmit_pkts_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 	return nb_sent;
 }
+
+
+/*
+ * V3 (Thor2) RX burst processing - AVX2 vectorized implementation
+ *
+ * V3 completions have a different layout for checksum and VLAN handling
+ * compared to the standard and compressed completion formats.
+ */
+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;
+	struct bnxt_rx_ring_info *rxr = rxq->rx_ring;
+	uint16_t cp_ring_size = cpr->cp_ring_struct->ring_size;
+	uint16_t rx_ring_size = rxr->rx_ring_struct->ring_size;
+	struct cmpl_base *cp_desc_ring = cpr->cp_desc_ring;
+	uint64_t valid, desc_valid_mask = ~0ULL;
+	const __m256i info3_v_mask = _mm256_set1_epi32(CMPL_BASE_V);
+	uint32_t raw_cons = cpr->cp_raw_cons;
+	uint32_t cons, mbcons;
+	int nb_rx_pkts = 0;
+	int i;
+	const __m256i valid_target =
+		_mm256_set1_epi32(!!(raw_cons & cp_ring_size));
+
+	/*
+	 * Shuffle mask for V3 descriptors to rearrange fields into mbuf layout.
+	 */
+	const __m256i shuf_msk =
+		_mm256_set_epi8(15, 14, 13, 12,          /* rss */
+				0xFF, 0xFF,              /* vlan_tci (filled separately) */
+				3, 2,                    /* data_len */
+				0xFF, 0xFF, 3, 2,        /* pkt_len */
+				0xFF, 0xFF, 0xFF, 0xFF,  /* pkt_type (zeroes) */
+				15, 14, 13, 12,          /* rss */
+				0xFF, 0xFF,              /* vlan_tci (filled separately) */
+				3, 2,                    /* data_len */
+				0xFF, 0xFF, 3, 2,        /* pkt_len */
+				0xFF, 0xFF, 0xFF, 0xFF); /* pkt_type (zeroes) */
+
+	/* Shuffle mask for high completion to extract metadata0 and errors */
+	const __m256i dsc_shuf_msk =
+		_mm256_set_epi8(0xff, 0xff, 0xff, 0xff,  /* Zeroes */
+				11, 10,                  /* metadata0 (vlan_tci) */
+				9, 8,                    /* errors_v2 */
+				5, 4,                    /* metadata1 (payload_offset) */
+				1, 0,                    /* flags2 low */
+				0xff, 0xff, 0xff, 0xff,  /* Zeroes */
+				0xff, 0xff, 0xff, 0xff,  /* Zeroes */
+				11, 10,                  /* metadata0 (vlan_tci) */
+				9, 8,                    /* errors_v2 */
+				5, 4,                    /* metadata1 (payload_offset) */
+				1, 0,                    /* flags2 low */
+				0xff, 0xff, 0xff, 0xff); /* Zeroes */
+
+	const __m256i flags_type_mask =
+		_mm256_set1_epi32(RX_PKT_V3_CMPL_FLAGS_ITYPE_MASK);
+	const __m256i flags2_ip_type_mask =
+		_mm256_set1_epi32(RX_PKT_V3_CMPL_HI_FLAGS2_IP_TYPE);
+	const __m256i rss_mask =
+		_mm256_set1_epi32(RX_PKT_V3_CMPL_FLAGS_RSS_VALID);
+	const __m256i metadata1_valid_mask =
+		_mm256_set1_epi32(RX_PKT_V3_CMPL_METADATA1_VALID);
+	const __m256i vlan_tci_mask =
+		_mm256_set1_epi32(RX_PKT_V3_CMPL_HI_METADATA0_VID_MASK |
+				  RX_PKT_V3_CMPL_HI_METADATA0_DE |
+				  RX_PKT_V3_CMPL_HI_METADATA0_PRI_MASK);
+	const __m256i cs_err_mask =
+		_mm256_set1_epi32(RX_PKT_CMPL_ERRORS_T_L4_CS_ERROR |
+				  RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR |
+				  RX_PKT_CMPL_ERRORS_L4_CS_ERROR |
+				  RX_PKT_CMPL_ERRORS_IP_CS_ERROR);
+	const __m256i cs_calc_mask =
+		_mm256_set1_epi32(RX_PKT_CMPL_CALC);
+
+	__m256i t0, t1, flags_type, flags2, errors, metadata1;
+	__m256i ptype_idx, ptypes, vlan_tci, vlan_flags;
+	__m256i mbuf01, mbuf23, mbuf45, mbuf67;
+	__m256i rearm0, rearm1, rearm2, rearm3, rearm4, rearm5, rearm6, rearm7;
+	__m256i ol_flags, ol_flags_hi;
+	__m256i rss_flags;
+
+	/* Validate ptype table indexing at build time. */
+	bnxt_check_ptype_constants();
+
+	if (unlikely(!rxq->rx_started))
+		return 0;
+
+	if (rxq->rxrearm_nb >= rxq->rx_free_thresh)
+		bnxt_rxq_rearm(rxq, rxr);
+
+	nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, BNXT_RX_DESCS_PER_LOOP_VEC256);
+
+	cons = raw_cons & (cp_ring_size - 1);
+	mbcons = (raw_cons / 2) & (rx_ring_size - 1);
+
+	if (!bnxt_cpr_cmp_valid(&cp_desc_ring[cons], raw_cons, cp_ring_size))
+		return 0;
+
+	nb_pkts = RTE_MIN(nb_pkts, RTE_MIN(rx_ring_size - mbcons,
+					   (cp_ring_size - cons) / 2));
+	/*
+	 * If we are at the end of the ring, ensure that descriptors after the
+	 * last valid entry are not treated as valid.
+	 */
+	if (nb_pkts < BNXT_RX_DESCS_PER_LOOP_VEC256) {
+		desc_valid_mask >>=
+			CHAR_BIT * (BNXT_RX_DESCS_PER_LOOP_VEC256 - nb_pkts);
+	} else {
+		nb_pkts =
+			RTE_ALIGN_FLOOR(nb_pkts, BNXT_RX_DESCS_PER_LOOP_VEC256);
+	}
+
+	for (i = 0; i < nb_pkts; i += BNXT_RX_DESCS_PER_LOOP_VEC256,
+				  cons += BNXT_RX_DESCS_PER_LOOP_VEC256 * 2,
+				  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, meta0_err, cs_calc, cs_valid;
+		uint32_t num_valid;
+
+		t0 = _mm256_loadu_si256((void *)&rxr->rx_buf_ring[mbcons]);
+		_mm256_storeu_si256((void *)&rx_pkts[i], t0);
+#ifdef RTE_ARCH_X86_64
+		t0 = _mm256_loadu_si256((void *)&rxr->rx_buf_ring[mbcons + 4]);
+		_mm256_storeu_si256((void *)&rx_pkts[i + 4], t0);
+#endif
+
+		/*
+		 * Load eight receive completion descriptors into 256-bit
+		 * registers. Loads are issued in reverse order for consistent state.
+		 */
+		desc7 = _mm256_load_si256((void *)&cp_desc_ring[cons + 14]);
+		rte_compiler_barrier();
+		desc6 = _mm256_load_si256((void *)&cp_desc_ring[cons + 12]);
+		rte_compiler_barrier();
+		desc5 = _mm256_load_si256((void *)&cp_desc_ring[cons + 10]);
+		rte_compiler_barrier();
+		desc4 = _mm256_load_si256((void *)&cp_desc_ring[cons + 8]);
+		rte_compiler_barrier();
+		desc3 = _mm256_load_si256((void *)&cp_desc_ring[cons + 6]);
+		rte_compiler_barrier();
+		desc2 = _mm256_load_si256((void *)&cp_desc_ring[cons + 4]);
+		rte_compiler_barrier();
+		desc1 = _mm256_load_si256((void *)&cp_desc_ring[cons + 2]);
+		rte_compiler_barrier();
+		desc0 = _mm256_load_si256((void *)&cp_desc_ring[cons + 0]);
+
+		/*
+		 * Pack needed fields from each descriptor pair.
+		 * For V3: extract rxcmp (low) for flags_type, len, rss
+		 * and rxcmp1 (hi) for flags2, metadata0, metadata1, errors_v2
+		 */
+		t0 = _mm256_permute2f128_si256(desc6, desc7, 0x20);
+		t1 = _mm256_permute2f128_si256(desc6, desc7, 0x31);
+		t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
+		rxcmp6_7 = _mm256_blend_epi32(t0, t1, 0x66);
+
+		t0 = _mm256_permute2f128_si256(desc4, desc5, 0x20);
+		t1 = _mm256_permute2f128_si256(desc4, desc5, 0x31);
+		t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
+		rxcmp4_5 = _mm256_blend_epi32(t0, t1, 0x66);
+
+		t0 = _mm256_permute2f128_si256(desc2, desc3, 0x20);
+		t1 = _mm256_permute2f128_si256(desc2, desc3, 0x31);
+		t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
+		rxcmp2_3 = _mm256_blend_epi32(t0, t1, 0x66);
+
+		t0 = _mm256_permute2f128_si256(desc0, desc1, 0x20);
+		t1 = _mm256_permute2f128_si256(desc0, desc1, 0x31);
+		t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
+		rxcmp0_1 = _mm256_blend_epi32(t0, t1, 0x66);
+
+		/* Extract flags_type from low completion for eight packets */
+		t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
+		t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
+		flags_type = _mm256_unpacklo_epi64(t0, t1);
+
+		/* Compute ptype_idx from flags_type itype field */
+		ptype_idx = _mm256_and_si256(flags_type, flags_type_mask);
+		ptype_idx = _mm256_srli_epi32(ptype_idx,
+					      RX_PKT_V3_CMPL_FLAGS_ITYPE_SFT -
+					      BNXT_PTYPE_TBL_TYPE_SFT);
+
+		/* Extract flags2 from high completion */
+		t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
+		t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
+		flags2 = _mm256_unpackhi_epi64(t0, t1);
+
+		t0 = _mm256_srli_epi32(_mm256_and_si256(flags2, flags2_ip_type_mask),
+				       RX_PKT_V3_CMPL_FLAGS2_IP_TYPE_SFT -
+				       BNXT_PTYPE_TBL_IP_VER_SFT);
+		ptype_idx = _mm256_or_si256(ptype_idx, t0);
+
+		/*
+		 * Extract metadata1 (contains VLAN valid bit) from LOW completion.
+		 * metadata1_payload_offset is at word 2 of rxcmp (low 128 bits of desc).
+		 */
+		{
+			__m128i m01, m23, hi;
+			hi =
+		_mm_unpacklo_epi64(_mm_unpackhi_epi32(_mm256_castsi256_si128(desc4),
+						    _mm256_castsi256_si128(desc5)),
+				 _mm_unpackhi_epi32(_mm256_castsi256_si128(desc6),
+						    _mm256_castsi256_si128(desc7)));
+			m01 = _mm_unpackhi_epi32(_mm256_castsi256_si128(desc0),
+						 _mm256_castsi256_si128(desc1));
+			m23 = _mm_unpackhi_epi32(_mm256_castsi256_si128(desc2),
+						 _mm256_castsi256_si128(desc3));
+			metadata1 =
+			_mm256_inserti128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(m01,
+								       m23)), hi, 1);
+		}
+		metadata1 = _mm256_srli_epi32(metadata1, 16);
+
+		t0 = _mm256_srli_epi32(_mm256_and_si256(metadata1, metadata1_valid_mask),
+				       RX_PKT_V3_CMPL_METADATA1_VALID_SFT -
+				       BNXT_PTYPE_TBL_VLAN_SFT);
+		ptype_idx = _mm256_or_si256(ptype_idx, t0);
+
+		/*
+		 * Load ptypes for eight packets using gather.
+		 */
+		ptypes = _mm256_i32gather_epi32((int *)bnxt_ptype_table,
+						ptype_idx, sizeof(uint32_t));
+
+		/* Extract RSS valid flags for eight packets */
+		rss_flags = _mm256_and_si256(flags_type, rss_mask);
+		rss_flags = _mm256_srli_epi32(rss_flags, 9);
+
+		/* Extract metadata0 (contains vlan_tci) and errors from high completion */
+		t0 = _mm256_unpackhi_epi32(rxcmp0_1, rxcmp2_3);
+		t1 = _mm256_unpackhi_epi32(rxcmp4_5, rxcmp6_7);
+		meta0_err = _mm256_unpacklo_epi64(t0, t1);
+
+		/* Extract vlan_tci from high 16 bits of meta0_err (metadata0) */
+		vlan_tci = _mm256_and_si256(_mm256_srli_epi32(meta0_err, 16), vlan_tci_mask);
+
+		vlan_flags = _mm256_and_si256(metadata1, metadata1_valid_mask);
+		vlan_flags = _mm256_min_epu32(vlan_flags, _mm256_set1_epi32(1));
+
+		if (vnic->vlan_strip) {
+			vlan_flags = _mm256_or_si256(vlan_flags,
+				_mm256_slli_epi32(vlan_flags, 6));
+		}
+
+		errors_v2 = meta0_err;
+
+		errors = _mm256_srli_epi32(_mm256_and_si256(meta0_err, cs_err_mask), 4);
+
+		cs_calc = _mm256_and_si256(flags2, cs_calc_mask);
+		cs_valid = _mm256_cmpeq_epi32(cs_calc, _mm256_setzero_si256());
+		errors = _mm256_andnot_si256(cs_valid, errors);
+		ol_flags = _mm256_i32gather_epi32((const int *)errors_to_olflags_v3,
+						  errors, sizeof(uint32_t));
+		__m256i unknown_flags = _mm256_and_si256(cs_valid,
+				_mm256_set1_epi32(RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN));
+		ol_flags = _mm256_or_si256(ol_flags, unknown_flags);
+
+		const __m256i perm_msk =
+				_mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
+		info3_v = _mm256_permutevar8x32_epi32(errors_v2, perm_msk);
+		info3_v = _mm256_and_si256(errors_v2, info3_v_mask);
+		info3_v = _mm256_xor_si256(info3_v, valid_target);
+
+		info3_v = _mm256_packs_epi32(info3_v, _mm256_setzero_si256());
+		valid = _mm_cvtsi128_si64(_mm256_extracti128_si256(info3_v, 1));
+		valid = (valid << CHAR_BIT) |
+			_mm_cvtsi128_si64(_mm256_castsi256_si128(info3_v));
+		num_valid = rte_popcount64(valid & desc_valid_mask);
+
+		if (num_valid == 0)
+			break;
+
+		mbuf01 = _mm256_shuffle_epi8(rxcmp0_1, shuf_msk);
+		mbuf23 = _mm256_shuffle_epi8(rxcmp2_3, shuf_msk);
+		mbuf45 = _mm256_shuffle_epi8(rxcmp4_5, shuf_msk);
+		mbuf67 = _mm256_shuffle_epi8(rxcmp6_7, shuf_msk);
+
+		mbuf01 = _mm256_blend_epi32(mbuf01, ptypes, 0x11);
+		mbuf23 = _mm256_blend_epi32(mbuf23,
+					_mm256_srli_si256(ptypes, 4), 0x11);
+		mbuf45 = _mm256_blend_epi32(mbuf45,
+					_mm256_srli_si256(ptypes, 8), 0x11);
+		mbuf67 = _mm256_blend_epi32(mbuf67,
+					_mm256_srli_si256(ptypes, 12), 0x11);
+
+		const __m256i tci_perm_01 = _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0);
+		const __m256i tci_perm_23 = _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2);
+		const __m256i tci_perm_45 = _mm256_set_epi32(5, 5, 5, 5, 4, 4, 4, 4);
+		const __m256i tci_perm_67 = _mm256_set_epi32(7, 7, 7, 7, 6, 6, 6, 6);
+
+		mbuf01 = _mm256_blend_epi16(mbuf01,
+			_mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
+						tci_perm_01), 10), 0x20);
+		mbuf23 = _mm256_blend_epi16(mbuf23,
+			_mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
+						tci_perm_23), 10), 0x20);
+		mbuf45 = _mm256_blend_epi16(mbuf45,
+			_mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
+						tci_perm_45), 10), 0x20);
+		mbuf67 = _mm256_blend_epi16(mbuf67,
+			_mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
+						tci_perm_67), 10), 0x20);
+
+		rearm0 = _mm256_permute2f128_si256(mbuf_init, mbuf01, 0x20);
+		rearm1 = _mm256_blend_epi32(mbuf_init, mbuf01, 0xF0);
+		rearm2 = _mm256_permute2f128_si256(mbuf_init, mbuf23, 0x20);
+		rearm3 = _mm256_blend_epi32(mbuf_init, mbuf23, 0xF0);
+
+		ol_flags = _mm256_or_si256(ol_flags, rss_flags);
+		ol_flags = _mm256_or_si256(ol_flags, vlan_flags);
+		ol_flags_hi = _mm256_permute2f128_si256(ol_flags,
+							ol_flags, 0x11);
+
+		rearm0 = _mm256_blend_epi32(rearm0,
+					    _mm256_slli_si256(ol_flags, 8),
+					    0x04);
+		rearm1 = _mm256_blend_epi32(rearm1,
+					    _mm256_slli_si256(ol_flags_hi, 8),
+					    0x04);
+		rearm2 = _mm256_blend_epi32(rearm2,
+					    _mm256_slli_si256(ol_flags, 4),
+					    0x04);
+		rearm3 = _mm256_blend_epi32(rearm3,
+					    _mm256_slli_si256(ol_flags_hi, 4),
+					    0x04);
+
+		_mm256_storeu_si256((void *)&rx_pkts[i + 0]->rearm_data,
+				    rearm0);
+		_mm256_storeu_si256((void *)&rx_pkts[i + 1]->rearm_data,
+				    rearm1);
+		_mm256_storeu_si256((void *)&rx_pkts[i + 2]->rearm_data,
+				    rearm2);
+		_mm256_storeu_si256((void *)&rx_pkts[i + 3]->rearm_data,
+				    rearm3);
+
+		rearm4 = _mm256_permute2f128_si256(mbuf_init, mbuf45, 0x20);
+		rearm5 = _mm256_blend_epi32(mbuf_init, mbuf45, 0xF0);
+		rearm6 = _mm256_permute2f128_si256(mbuf_init, mbuf67, 0x20);
+		rearm7 = _mm256_blend_epi32(mbuf_init, mbuf67, 0xF0);
+
+		rearm4 = _mm256_blend_epi32(rearm4, ol_flags, 0x04);
+		rearm5 = _mm256_blend_epi32(rearm5, ol_flags_hi, 0x04);
+		rearm6 = _mm256_blend_epi32(rearm6,
+					    _mm256_srli_si256(ol_flags, 4),
+					    0x04);
+		rearm7 = _mm256_blend_epi32(rearm7,
+					    _mm256_srli_si256(ol_flags_hi, 4),
+					    0x04);
+
+		_mm256_storeu_si256((void *)&rx_pkts[i + 4]->rearm_data,
+				    rearm4);
+		_mm256_storeu_si256((void *)&rx_pkts[i + 5]->rearm_data,
+				    rearm5);
+		_mm256_storeu_si256((void *)&rx_pkts[i + 6]->rearm_data,
+				    rearm6);
+		_mm256_storeu_si256((void *)&rx_pkts[i + 7]->rearm_data,
+				    rearm7);
+
+		nb_rx_pkts += num_valid;
+		if (num_valid < BNXT_RX_DESCS_PER_LOOP_VEC256)
+			break;
+	}
+
+	if (nb_rx_pkts) {
+		rxr->rx_raw_prod = RING_ADV(rxr->rx_raw_prod, nb_rx_pkts);
+
+		rxq->rxrearm_nb += nb_rx_pkts;
+		cpr->cp_raw_cons += 2 * nb_rx_pkts;
+		bnxt_db_cq(cpr);
+	}
+
+	return nb_rx_pkts;
+}
+
+uint16_t
+bnxt_recv_pkts_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts,
+			   uint16_t nb_pkts)
+{
+	struct bnxt_rx_queue *rxq = rx_queue;
+	uint32_t expected_burst = rxq->rx_free_thresh;
+	uint16_t cnt = 0;
+
+	while (nb_pkts > expected_burst) {
+		uint16_t burst;
+
+		burst = recv_burst_vec_avx2_v3(rx_queue, rx_pkts + cnt, expected_burst);
+
+		cnt += burst;
+		nb_pkts -= burst;
+
+		if (burst < expected_burst)
+			return cnt;
+	}
+	return cnt + recv_burst_vec_avx2_v3(rx_queue, rx_pkts + cnt, nb_pkts);
+}
+
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_common.h b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
index e185005293..e8da010dc3 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_common.h
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
@@ -177,4 +177,40 @@ bnxt_tx_cmp_vec(struct bnxt_tx_queue *txq, uint32_t nr_pkts)
 	}
 	txr->tx_raw_cons = raw_cons;
 }
+
+static const uint64_t errors_to_olflags_v3[16] = {
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+	RTE_MBUF_F_RX_IP_CKSUM_GOOD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+	RTE_MBUF_F_RX_IP_CKSUM_BAD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+	RTE_MBUF_F_RX_IP_CKSUM_GOOD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+	RTE_MBUF_F_RX_IP_CKSUM_BAD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+	RTE_MBUF_F_RX_L4_CKSUM_GOOD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+	RTE_MBUF_F_RX_L4_CKSUM_GOOD | RTE_MBUF_F_RX_IP_CKSUM_BAD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+	RTE_MBUF_F_RX_L4_CKSUM_BAD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+	RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_BAD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+	RTE_MBUF_F_RX_IP_CKSUM_GOOD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
+	RTE_MBUF_F_RX_IP_CKSUM_BAD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+	RTE_MBUF_F_RX_IP_CKSUM_GOOD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_BAD |
+	RTE_MBUF_F_RX_IP_CKSUM_BAD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+	RTE_MBUF_F_RX_L4_CKSUM_GOOD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+	RTE_MBUF_F_RX_L4_CKSUM_GOOD | RTE_MBUF_F_RX_IP_CKSUM_BAD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+	RTE_MBUF_F_RX_L4_CKSUM_BAD,
+	RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD |
+	RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_BAD
+};
+
 #endif /* _BNXT_RXTX_VEC_COMMON_H_ */
-- 
2.47.3


^ permalink raw reply related

* [PATCH 02/10] net/bnxt: stale values in nr_bds are cleared
From: Mohammad Shuab Siddique @ 2026-06-04  3:18 UTC (permalink / raw)
  To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
	Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>

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

Fixed an issue where the stale value held in txr->nr_bds[0]
would get read when the ring loops back around and cause
the tx producer to get behind the tx consumer position.
This then causes the driver to think that there were no
available buffers.

Fixes: 925cd0705836 ("net/bnxt: update PTP support on Thor")
Cc: stable@dpdk.org
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
 drivers/net/bnxt/bnxt_txr.c | 136 ++++++++++++++++++++++++++++++++++--
 1 file changed, 130 insertions(+), 6 deletions(-)

diff --git a/drivers/net/bnxt/bnxt_txr.c b/drivers/net/bnxt/bnxt_txr.c
index d37a38735c..45d1a93fdc 100644
--- a/drivers/net/bnxt/bnxt_txr.c
+++ b/drivers/net/bnxt/bnxt_txr.c
@@ -511,11 +511,48 @@ static int bnxt_start_xmit(struct rte_mbuf *tx_pkt,
 	return rc;
 }
 
+static void bnxt_tx_coal_cmp_fast(struct bnxt_tx_queue *txq, int nr_cons)
+{
+	struct bnxt_tx_ring_info *txr = txq->tx_ring;
+	struct bnxt_ring *ring = txr->tx_ring_struct;
+	struct rte_mbuf **free = txq->free;
+	uint16_t raw_cons = txr->tx_raw_cons;
+	unsigned int blk = 0;
+	int cons, bds;
+
+	for (cons = 0; cons < nr_cons; cons++) {
+		struct rte_mbuf **tx_buf;
+		unsigned short nr_bds;
+
+		tx_buf = &txr->tx_buf_ring[RING_IDX(ring, raw_cons)];
+		nr_bds = (*tx_buf)->nb_segs +
+			 bnxt_xmit_need_long_bd(*tx_buf, txq);
+		for (bds = 0; bds < nr_bds; bds++) {
+			if (*tx_buf) {
+				free[blk++] = *tx_buf;
+				/*
+				 * Each BD also tracks a consumer index.
+				 * Update cons, otherwise it will fall behind.
+				 */
+				cons++;
+				*tx_buf = NULL;
+			}
+			raw_cons = RING_NEXT(raw_cons);
+			tx_buf = &txr->tx_buf_ring[RING_IDX(ring, raw_cons)];
+		}
+	}
+	if (blk)
+		rte_mempool_put_bulk(free[0]->pool, (void *)free, blk);
+
+	txr->tx_raw_cons = raw_cons;
+}
+
 /*
  * Transmit completion function for use when RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
  * is enabled.
  */
-static void bnxt_tx_cmp_fast(struct bnxt_tx_queue *txq, int nr_pkts)
+static void bnxt_tx_cmp_fast(struct bnxt_tx_queue *txq, int nb_tx,
+			      bool tx_coal_cmp)
 {
 	struct bnxt_tx_ring_info *txr = txq->tx_ring;
 	struct bnxt_ring *ring = txr->tx_ring_struct;
@@ -524,7 +561,10 @@ static void bnxt_tx_cmp_fast(struct bnxt_tx_queue *txq, int nr_pkts)
 	unsigned int blk = 0;
 	int i, j;
 
-	for (i = 0; i < nr_pkts; i++) {
+	if (tx_coal_cmp)
+		return bnxt_tx_coal_cmp_fast(txq, nb_tx);
+
+	for (i = 0; i < nb_tx; i++) {
 		struct rte_mbuf **tx_buf;
 		unsigned short nr_bds;
 
@@ -547,7 +587,72 @@ static void bnxt_tx_cmp_fast(struct bnxt_tx_queue *txq, int nr_pkts)
 	txr->tx_raw_cons = raw_cons;
 }
 
-static void bnxt_tx_cmp(struct bnxt_tx_queue *txq, int nr_pkts)
+static void bnxt_tx_coal_cmp(struct bnxt_tx_queue *txq, int nr_cons)
+{
+	struct bnxt_tx_ring_info *txr = txq->tx_ring;
+	struct bnxt_ring *ring = txr->tx_ring_struct;
+	struct rte_mempool *pool = NULL;
+	struct rte_mbuf **free = txq->free;
+	uint16_t raw_cons = txr->tx_raw_cons;
+	unsigned int blk = 0;
+	int cons, bds;
+
+	for (cons = 0; cons < nr_cons; cons++) {
+		struct rte_mbuf *mbuf;
+		struct rte_mbuf **tx_buf;
+		unsigned short nr_bds;
+
+		tx_buf = &txr->tx_buf_ring[RING_IDX(ring, raw_cons)];
+		nr_bds = txr->nr_bds[RING_IDX(ring, raw_cons)];
+		/* Clear the now stale number of buffer descriptors */
+		txr->nr_bds[RING_IDX(ring, raw_cons)] = 0;
+
+		for (bds = 0; bds < nr_bds; bds++) {
+			mbuf = *tx_buf;
+			*tx_buf = NULL;
+			raw_cons = RING_NEXT(raw_cons);
+			/*
+			 * Each BD also tracks a consumer index. So update the cons.
+			 * Otherwise the cons will fall behind.
+			 */
+			cons++;
+			tx_buf = &txr->tx_buf_ring[RING_IDX(ring, raw_cons)];
+			if (!mbuf)	/* long_bd's tx_buf ? */
+				continue;
+
+			mbuf = rte_pktmbuf_prefree_seg(mbuf);
+			if (unlikely(!mbuf))
+				continue;
+
+			/* EW - no need to unmap DMA memory? */
+
+			if (likely(mbuf->pool == pool)) {
+				/* Add mbuf to the bulk free array */
+				free[blk++] = mbuf;
+			} else {
+				/* Found an mbuf from a different pool. Free
+				 * mbufs accumulated so far to the previous
+				 * pool
+				 */
+				if (likely(pool != NULL))
+					rte_mempool_put_bulk(pool,
+							     (void *)free,
+							     blk);
+
+				/* Start accumulating mbufs in a new pool */
+				free[0] = mbuf;
+				pool = mbuf->pool;
+				blk = 1;
+			}
+		}
+	}
+	if (blk)
+		rte_mempool_put_bulk(pool, (void *)free, blk);
+
+	txr->tx_raw_cons = raw_cons;
+}
+
+static void bnxt_tx_cmp(struct bnxt_tx_queue *txq, int nb_tx, bool tx_coal_cmp)
 {
 	struct bnxt_tx_ring_info *txr = txq->tx_ring;
 	struct bnxt_ring *ring = txr->tx_ring_struct;
@@ -557,13 +662,19 @@ static void bnxt_tx_cmp(struct bnxt_tx_queue *txq, int nr_pkts)
 	unsigned int blk = 0;
 	int i, j;
 
-	for (i = 0; i < nr_pkts; i++) {
+	if (tx_coal_cmp)
+		return bnxt_tx_coal_cmp(txq, nb_tx);
+
+	for (i = 0; i < nb_tx; i++) {
 		struct rte_mbuf *mbuf;
 		struct rte_mbuf **tx_buf;
 		unsigned short nr_bds;
 
 		tx_buf = &txr->tx_buf_ring[RING_IDX(ring, raw_cons)];
 		nr_bds = txr->nr_bds[RING_IDX(ring, raw_cons)];
+		/* Clear the now stale number of buffer descriptors */
+		txr->nr_bds[RING_IDX(ring, raw_cons)] = 0;
+
 		for (j = 0; j < nr_bds; j++) {
 			mbuf = *tx_buf;
 			*tx_buf = NULL;
@@ -631,6 +742,8 @@ static int bnxt_handle_tx_cp(struct bnxt_tx_queue *txq)
 	struct bnxt_cp_ring_info *cpr = txq->cp_ring;
 	uint32_t raw_cons = cpr->cp_raw_cons;
 	struct bnxt_ring *cp_ring_struct;
+	uint32_t tx_ring_mask;
+	bool tx_coal_cmp = false;
 	struct tx_cmpl *txcmp;
 
 	if (bnxt_tx_bds_in_hw(txq) < txq->tx_free_thresh)
@@ -638,6 +751,7 @@ static int bnxt_handle_tx_cp(struct bnxt_tx_queue *txq)
 
 	cp_ring_struct = cpr->cp_ring_struct;
 	ring_mask = cp_ring_struct->ring_mask;
+	tx_ring_mask = txq->tx_ring->tx_ring_struct->ring_mask;
 
 	do {
 		cons = RING_CMPL(ring_mask, raw_cons);
@@ -646,6 +760,16 @@ static int bnxt_handle_tx_cp(struct bnxt_tx_queue *txq)
 		if (!bnxt_cpr_cmp_valid(txcmp, raw_cons, ring_mask + 1))
 			break;
 
+		if (CMP_TYPE(txcmp) == CMPL_BASE_TYPE_TX_L2_COAL) {
+			struct tx_cmpl_coal *txcmp_c = (struct tx_cmpl_coal *)txcmp;
+
+			nb_tx_pkts = (rte_le_to_cpu_32(txcmp_c->sq_cons_idx) -
+				      (txq->tx_ring->tx_raw_cons & tx_ring_mask)) & tx_ring_mask;
+			raw_cons = NEXT_RAW_CMP(raw_cons);
+			tx_coal_cmp = true;
+			break;
+		}
+
 		opaque = rte_le_to_cpu_32(txcmp->opaque);
 
 		if (bnxt_is_tx_cmpl_type(CMP_TYPE(txcmp)))
@@ -661,9 +785,9 @@ static int bnxt_handle_tx_cp(struct bnxt_tx_queue *txq)
 
 	if (nb_tx_pkts) {
 		if (txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
-			bnxt_tx_cmp_fast(txq, nb_tx_pkts);
+			bnxt_tx_cmp_fast(txq, nb_tx_pkts, tx_coal_cmp);
 		else
-			bnxt_tx_cmp(txq, nb_tx_pkts);
+			bnxt_tx_cmp(txq, nb_tx_pkts, tx_coal_cmp);
 		cpr->cp_raw_cons = raw_cons;
 		bnxt_db_cq(cpr);
 	}
-- 
2.47.3


^ permalink raw reply related

* [PATCH 03/10] net/bnxt: fix advertising RX LRO offload capability
From: Mohammad Shuab Siddique @ 2026-06-04  3:18 UTC (permalink / raw)
  To: dev
  Cc: kishore.padmanabha, stable, Damodharam Ammepalli,
	Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>

From: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>

Do not set the RX LRO offload capability bit mask if the
hardware did not advertise the function, and let
the driver take non-tpa path in configuring the vnic
in such cases.

Fixes: b150a7e7ee66 ("net/bnxt: support LRO on Thor adapters")
Cc: stable@dpdk.org
Signed-off-by: Damodharam Ammepalli <damodharam.ammepalli@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
 drivers/net/bnxt/bnxt.h      |  1 +
 drivers/net/bnxt/bnxt_hwrm.c | 29 +++++++++++++++++++++++++++--
 drivers/net/bnxt/bnxt_rxq.c  |  3 ++-
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index f21753e40c..5ae4e620a4 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -1273,6 +1273,7 @@ extern int bnxt_logtype_driver;
 #define BNXT_LINK_SPEEDS_V2(bp) (((bp)->link_info) && (((bp)->link_info->support_speeds_v2) || \
 						       BNXT_LINK_SPEEDS_V2_VF((bp))))
 #define BNXT_MAX_SPEED_LANES 8
+#define BNXT_SUPPORTS_TPA(bp)  (!BNXT_CHIP_P5_P7(bp) || (bp)->max_tpa_v2)
 extern const struct rte_flow_ops bnxt_ulp_rte_flow_ops;
 int32_t bnxt_ulp_port_init(struct bnxt *bp);
 void bnxt_ulp_port_deinit(struct bnxt *bp);
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index 02a5d00738..590543ad6a 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -3120,10 +3120,10 @@ int bnxt_hwrm_vnic_tpa_cfg(struct bnxt *bp,
 		return -ENOTSUP;
 	}
 
-	if ((BNXT_CHIP_P5(bp) || BNXT_CHIP_P7(bp)) && !bp->max_tpa_v2) {
+	if (!BNXT_SUPPORTS_TPA(bp)) {
 		if (enable)
 			PMD_DRV_LOG_LINE(ERR, "No HW support for LRO");
-		return -ENOTSUP;
+		return 0;
 	}
 
 	if (vnic->fw_vnic_id == INVALID_HW_RING_ID) {
@@ -4946,6 +4946,31 @@ int bnxt_hwrm_pf_evb_mode(struct bnxt *bp)
 	return rc;
 }
 
+static int bnxt_hwrm_set_tpa(struct bnxt *bp)
+{
+	struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
+	uint64_t rx_offloads = dev_conf->rxmode.offloads;
+	bool tpa_flags = 0;
+	int rc, i;
+
+	if (!BNXT_SUPPORTS_TPA(bp))
+		return 0;
+
+	tpa_flags = (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) ?  true : false;
+	for (i = 0; i < bp->max_vnics; i++) {
+		struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
+
+		if (vnic->fw_vnic_id == INVALID_HW_RING_ID)
+			continue;
+
+		rc = bnxt_hwrm_vnic_tpa_cfg(bp, vnic, tpa_flags);
+		if (rc)
+			return rc;
+	}
+	return 0;
+}
+
+
 int bnxt_hwrm_tunnel_dst_port_alloc(struct bnxt *bp, uint16_t port,
 				uint8_t tunnel_type)
 {
diff --git a/drivers/net/bnxt/bnxt_rxq.c b/drivers/net/bnxt/bnxt_rxq.c
index b93f5043de..023cb0e174 100644
--- a/drivers/net/bnxt/bnxt_rxq.c
+++ b/drivers/net/bnxt/bnxt_rxq.c
@@ -38,7 +38,8 @@ uint64_t bnxt_get_rx_port_offloads(struct bnxt *bp)
 				    RTE_ETH_RX_OFFLOAD_VLAN_EXTEND);
 
 
-	if (!bnxt_compressed_rx_cqe_mode_enabled(bp))
+	if (!bnxt_compressed_rx_cqe_mode_enabled(bp) &&
+	    BNXT_SUPPORTS_TPA(bp))
 		rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
 	if (bp->flags & BNXT_FLAG_PTP_SUPPORTED)
 		rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
-- 
2.47.3


^ permalink raw reply related

* [PATCH 04/10] net/bnxt: scalar rx path disregarded rxcmp flags for setting ptp mbuf flag setting ptp mbuf flag
From: Mohammad Shuab Siddique @ 2026-06-04  3:18 UTC (permalink / raw)
  To: dev; +Cc: kishore.padmanabha, stable, Mohammad Shuab Siddique,
	Keegan Freyhof
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>

From: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>

Added a check so that if bp->ptp_all_rx_tstamp is true
- it is always set to true when set fwd ieee1588 is called via
bnxt_timesync_enable - the hardware must also report that the packet
is ptp. Also changed the code so that the path properly reports if
the packet has a timestamp.

Fixes: 925cd0705836 ("net/bnxt: update PTP support on Thor")
Cc: stable@dpdk.org
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
 drivers/net/bnxt/bnxt_ethdev.c |  2 --
 drivers/net/bnxt/bnxt_hwrm.c   | 28 +++-------------------------
 drivers/net/bnxt/bnxt_rxr.c    | 13 ++++++++-----
 drivers/net/bnxt/bnxt_stats.c  |  3 +++
 drivers/net/bnxt/bnxt_txr.c    | 34 ++++++++++++++++++++++++++++++----
 4 files changed, 14 insertions(+), 32 deletions(-)

diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 5bd51de3cd..791a89f040 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -1493,8 +1493,6 @@ bnxt_receive_function(struct rte_eth_dev *eth_dev)
 		bp->flags |= BNXT_FLAG_RX_VECTOR_PKT_MODE;
 		if (bnxt_compressed_rx_cqe_mode_enabled(bp))
 			return bnxt_crx_pkts_vec_avx2;
-		if (BNXT_TRUFLOW_EN(bp) && bnxt_ulp_explicit_mark_enabled(bp))
-			goto use_scalar_rx;
 		if (BNXT_CHIP_P7(bp))
 			return bnxt_recv_pkts_vec_avx2_v3;
 		else
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index 590543ad6a..4a5b83d29c 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -4347,6 +4347,9 @@ static int bnxt_hwrm_set_tpa(struct bnxt *bp)
 	bool tpa_flags = 0;
 	int rc, i;
 
+	if (!BNXT_SUPPORTS_TPA(bp))
+		return 0;
+
 	tpa_flags = (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) ?  true : false;
 	for (i = 0; i < bp->max_vnics; i++) {
 		struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
@@ -4946,31 +4949,6 @@ int bnxt_hwrm_pf_evb_mode(struct bnxt *bp)
 	return rc;
 }
 
-static int bnxt_hwrm_set_tpa(struct bnxt *bp)
-{
-	struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
-	uint64_t rx_offloads = dev_conf->rxmode.offloads;
-	bool tpa_flags = 0;
-	int rc, i;
-
-	if (!BNXT_SUPPORTS_TPA(bp))
-		return 0;
-
-	tpa_flags = (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) ?  true : false;
-	for (i = 0; i < bp->max_vnics; i++) {
-		struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
-
-		if (vnic->fw_vnic_id == INVALID_HW_RING_ID)
-			continue;
-
-		rc = bnxt_hwrm_vnic_tpa_cfg(bp, vnic, tpa_flags);
-		if (rc)
-			return rc;
-	}
-	return 0;
-}
-
-
 int bnxt_hwrm_tunnel_dst_port_alloc(struct bnxt *bp, uint16_t port,
 				uint8_t tunnel_type)
 {
diff --git a/drivers/net/bnxt/bnxt_rxr.c b/drivers/net/bnxt/bnxt_rxr.c
index ab2175d21a..046276f931 100644
--- a/drivers/net/bnxt/bnxt_rxr.c
+++ b/drivers/net/bnxt/bnxt_rxr.c
@@ -1203,11 +1203,14 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
 	mbuf->data_len = mbuf->pkt_len;
 	mbuf->port = rxq->port_id;
 
-	if (unlikely(((rte_le_to_cpu_16(rxcmp->flags_type) &
-		      RX_PKT_CMPL_FLAGS_MASK) ==
-		      RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP) ||
-		      bp->ptp_all_rx_tstamp) && bp->ieee_1588 &&
-		      bp->ptp_cfg) {
+	if (unlikely((((rte_le_to_cpu_16(rxcmp->flags_type) &
+			RX_PKT_CMPL_FLAGS_MASK) ==
+			RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP) ||
+			((rte_le_to_cpu_16(rxcmp->flags_type) &
+			RX_PKT_CMPL_FLAGS_MASK) ==
+			RX_PKT_CMPL_FLAGS_ITYPE_PTP_WO_TIMESTAMP)) &&
+			bp->ptp_all_rx_tstamp) && bp->ieee_1588 &&
+			bp->ptp_cfg) {
 		mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP |
 				  RTE_MBUF_F_RX_IEEE1588_TMST;
 		if (BNXT_CHIP_P5_P7(bp))
diff --git a/drivers/net/bnxt/bnxt_stats.c b/drivers/net/bnxt/bnxt_stats.c
index 49367588e4..ba858710a5 100644
--- a/drivers/net/bnxt/bnxt_stats.c
+++ b/drivers/net/bnxt/bnxt_stats.c
@@ -695,6 +695,9 @@ static int bnxt_stats_get_ext(struct rte_eth_dev *eth_dev,
 		struct bnxt_cp_ring_info *cpr = txq->cp_ring;
 		struct bnxt_ring_stats_ext ring_stats = {0};
 
+		bnxt_stats->oerrors += rte_atomic_load_explicit(&txq->tx_mbuf_drop,
+							     rte_memory_order_relaxed);
+
 		if (!txq->tx_started)
 			continue;
 

^ permalink raw reply related

* [PATCH 05/10] net/bnxt: fix RX timestamping for non-PTP packets
From: Mohammad Shuab Siddique @ 2026-06-04  3:18 UTC (permalink / raw)
  To: dev; +Cc: kishore.padmanabha, stable, Chenna Arnoori,
	Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>

From: Chenna Arnoori <chenna.arnoori@broadcom.com>

When the adapter is configured to timestamp all incoming packets,
timestamps were silently missing for non-PTP traffic (such as IPv6
packets). A previous update incorrectly restricted the timestamp
processing to only recognised PTP packets by changing an OR condition
to an AND condition. This is corrected so that timestamps are properly
extracted for all received packets when promiscuous timestamping is
enabled.

A comment is added to clarify the two conditions under which the
hardware timestamp is extracted from the completion record:
1. The packet is explicitly classified as a PTP packet (with or
   without timestamp).
2. Promiscuous timestamping is enabled (ptp_all_rx_tstamp), which
   instructs the hardware to timestamp all packets, including
   non-PTP traffic (e.g., IPv6).

Cc: stable@dpdk.org
Fixes: 925cd0705836 ("net/bnxt: update PTP support on Thor")

Signed-off-by: Chenna Arnoori <chenna.arnoori@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
 drivers/net/bnxt/bnxt_rxr.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/bnxt/bnxt_rxr.c b/drivers/net/bnxt/bnxt_rxr.c
index 046276f931..ee49d85d43 100644
--- a/drivers/net/bnxt/bnxt_rxr.c
+++ b/drivers/net/bnxt/bnxt_rxr.c
@@ -1203,13 +1203,21 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
 	mbuf->data_len = mbuf->pkt_len;
 	mbuf->port = rxq->port_id;
 
-	if (unlikely((((rte_le_to_cpu_16(rxcmp->flags_type) &
+	/* Extract the hardware timestamp from the completion record if:
+	 * 1. The packet is explicitly classified as a PTP packet (with or
+	 *    without timestamp), OR
+	 * 2. Promiscuous timestamping is enabled (ptp_all_rx_tstamp), which
+	 *    instructs the hardware to timestamp all packets, including
+	 *    non-PTP traffic (e.g., IPv6).
+	 */
+	if (unlikely(((rte_le_to_cpu_16(rxcmp->flags_type) &
 			RX_PKT_CMPL_FLAGS_MASK) ==
 			RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP) ||
 			((rte_le_to_cpu_16(rxcmp->flags_type) &
 			RX_PKT_CMPL_FLAGS_MASK) ==
-			RX_PKT_CMPL_FLAGS_ITYPE_PTP_WO_TIMESTAMP)) &&
-			bp->ptp_all_rx_tstamp) && bp->ieee_1588 &&
+			RX_PKT_CMPL_FLAGS_ITYPE_PTP_WO_TIMESTAMP) ||
+			bp->ptp_all_rx_tstamp) &&
+			bp->ieee_1588 &&
 			bp->ptp_cfg) {
 		mbuf->ol_flags |= RTE_MBUF_F_RX_IEEE1588_PTP |
 				  RTE_MBUF_F_RX_IEEE1588_TMST;
-- 
2.47.3


^ permalink raw reply related

* [PATCH 06/10] net/bnxt: fix packet burst truncation after invalid Tx descriptor descriptor
From: Mohammad Shuab Siddique @ 2026-06-04  3:18 UTC (permalink / raw)
  To: dev; +Cc: kishore.padmanabha, stable, Zoe Cheimets, Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>

From: Zoe Cheimets <zoe.cheimets@broadcom.com>

When bnxt_start_xmit() returned -EINVAL for a bad packet, the burst
loop broke immediately, dropping all subsequent valid packets. The
Tx ring was also left in a corrupt state because tx_raw_prod was not
rolled back after a partial descriptor write. Additionally, the
tx_mbuf_drop oerrors accumulation was gated behind a tx_started
check, silently omitting drops from the statistics.

Fix by rolling back tx_raw_prod and any partially-written ring slots
on the drop path, replacing the break with continue so the burst
loop keeps processing remaining packets, and moving the tx_mbuf_drop
read to before the tx_started guard in both stats paths. Return
value is corrected to RTE_MIN(nb_tx_pkts + dropped, nb_pkts) to
accurately report consumed packet count.

Fixes: 220de9869bc3 ("net/bnxt: optimize Tx batching")
Cc: stable@dpdk.org
Signed-off-by: Zoe Cheimets <zoe.cheimets@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
 drivers/net/bnxt/bnxt_txr.c | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/net/bnxt/bnxt_txr.c b/drivers/net/bnxt/bnxt_txr.c
index a6b062637c..bb9917d705 100644
--- a/drivers/net/bnxt/bnxt_txr.c
+++ b/drivers/net/bnxt/bnxt_txr.c
@@ -239,15 +239,17 @@ static int bnxt_start_xmit(struct rte_mbuf *tx_pkt,
 				uint16_t *coal_pkts,
 				struct tx_bd_long **last_txbd)
 {
+	struct tx_bd_long *last_txbd_save = *last_txbd;
 	struct bnxt_tx_ring_info *txr = txq->tx_ring;
 	struct bnxt_ring *ring = txr->tx_ring_struct;
+	uint16_t tx_raw_prod_save = txr->tx_raw_prod;
 	uint32_t outer_tpid_bd = 0;
 	struct tx_bd_long *txbd;
 	struct tx_bd_long_hi *txbd1 = NULL;
 	uint32_t vlan_tag_flags;
 	bool long_bd = false;
 	unsigned short nr_bds;
-	uint16_t prod;
+	uint16_t prod, idx;
 	bool pkt_needs_ts = 0;
 	struct rte_mbuf *m_seg;
 	struct rte_mbuf **tx_buf;
@@ -507,6 +509,24 @@ static int bnxt_start_xmit(struct rte_mbuf *tx_pkt,
 
 	return 0;
 drop:
+	/* Roll back any descriptors and tx_buf_ring slots that were written
+	 * for this packet before the failure was detected.  Walking from the
+	 * saved producer index up to (but not including) the current one is
+	 * safe because we hold the Tx lock and the HW has not been notified
+	 * (the doorbell is only rung after bnxt_start_xmit() returns
+	 * successfully).
+	 */
+	idx = tx_raw_prod_save;
+
+	while (idx != txr->tx_raw_prod) {
+		uint16_t slot = RING_IDX(ring, idx);
+
+		txr->tx_buf_ring[slot] = NULL;
+		txr->tx_desc_ring[slot].address = 0;
+		idx = RING_NEXT(idx);
+	}
+	txr->tx_raw_prod = tx_raw_prod_save;
+	*last_txbd = last_txbd_save;
 	rte_pktmbuf_free(tx_pkt);
 ret:
 	return rc;
@@ -836,22 +856,28 @@ uint16_t _bnxt_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 		if (unlikely(rc)) {
 			if (rc == -EINVAL) {
+				coal_pkts--;
 				rte_atomic_fetch_add_explicit(&txq->tx_mbuf_drop, 1,
 							      rte_memory_order_relaxed);
 				dropped++;
+				continue;
 			}
 			break;
 		}
 	}
 
-	if (likely(nb_tx_pkts)) {
+	/* last_txbd is used to check for if any packets have been sent in
+	 * the burst as bnxt_start_xmit will update it to the most recent
+	 * non-dropped buffer descriptor in the burst.
+	 */
+	if (likely(last_txbd != NULL)) {
 		/* Request a completion on the last packet */
 		last_txbd->flags_type &= ~TX_BD_LONG_FLAGS_NO_CMPL;
 		bnxt_db_write(&txq->tx_ring->tx_db, txq->tx_ring->tx_raw_prod);
 	}
 
-	nb_tx_pkts += dropped;
-	return nb_tx_pkts;
+	return RTE_MIN((uint16_t)(nb_tx_pkts + dropped), nb_pkts);
+
 }
 
 int bnxt_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
-- 
2.47.3


^ permalink raw reply related

* [PATCH 07/10] net/bnxt: optimization of the AVX2 RX paths
From: Mohammad Shuab Siddique @ 2026-06-04  3:18 UTC (permalink / raw)
  To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
	Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>

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

Fixed some dead code and some variable names to make them more
descriptive. Also optimized the V3 path to stay under 16
registers.

Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
 drivers/net/bnxt/bnxt_rxtx_vec_avx2.c   | 240 +++++++++++-------------
 drivers/net/bnxt/bnxt_rxtx_vec_common.h |   2 +-
 2 files changed, 114 insertions(+), 128 deletions(-)

diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
index 46b51b20e4..5e22b4fc11 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
@@ -187,15 +187,12 @@ recv_burst_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
 		t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
 		flags_type = _mm256_unpacklo_epi64(t0, t1);
+		flags2 = _mm256_unpackhi_epi64(t0, t1);
 		ptype_idx = _mm256_and_si256(flags_type, flags_type_mask);
 		ptype_idx = _mm256_srli_epi32(ptype_idx,
 					      RX_PKT_CMPL_FLAGS_ITYPE_SFT -
 					      BNXT_PTYPE_TBL_TYPE_SFT);
 
-		t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
-		t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
-		flags2 = _mm256_unpackhi_epi64(t0, t1);
-
 		t0 = _mm256_srli_epi32(_mm256_and_si256(flags2, flags2_mask1),
 				       RX_PKT_CMPL_FLAGS2_META_FORMAT_SFT -
 				       BNXT_PTYPE_TBL_VLAN_SFT);
@@ -251,9 +248,6 @@ recv_burst_vec_avx2(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		 * bits and count the number of set bits in order to determine
 		 * the number of valid descriptors.
 		 */
-		const __m256i perm_msk =
-				_mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
-		info3_v = _mm256_permutevar8x32_epi32(errors_v2, perm_msk);
 		info3_v = _mm256_and_si256(errors_v2, info3_v_mask);
 		info3_v = _mm256_xor_si256(info3_v, valid_target);
 
@@ -904,7 +898,6 @@ bnxt_xmit_pkts_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return nb_sent;
 }
 
-
 /*
  * V3 (Thor2) RX burst processing - AVX2 vectorized implementation
  *
@@ -924,7 +917,6 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 	uint16_t rx_ring_size = rxr->rx_ring_struct->ring_size;
 	struct cmpl_base *cp_desc_ring = cpr->cp_desc_ring;
 	uint64_t valid, desc_valid_mask = ~0ULL;
-	const __m256i info3_v_mask = _mm256_set1_epi32(CMPL_BASE_V);
 	uint32_t raw_cons = cpr->cp_raw_cons;
 	uint32_t cons, mbcons;
 	int nb_rx_pkts = 0;
@@ -937,12 +929,12 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 	 */
 	const __m256i shuf_msk =
 		_mm256_set_epi8(15, 14, 13, 12,          /* rss */
-				0xFF, 0xFF,              /* vlan_tci (filled separately) */
+				11, 10,                  /* vlan_tci */
 				3, 2,                    /* data_len */
 				0xFF, 0xFF, 3, 2,        /* pkt_len */
 				0xFF, 0xFF, 0xFF, 0xFF,  /* pkt_type (zeroes) */
 				15, 14, 13, 12,          /* rss */
-				0xFF, 0xFF,              /* vlan_tci (filled separately) */
+				11, 10,                  /* vlan_tci */
 				3, 2,                    /* data_len */
 				0xFF, 0xFF, 3, 2,        /* pkt_len */
 				0xFF, 0xFF, 0xFF, 0xFF); /* pkt_type (zeroes) */
@@ -952,40 +944,24 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 		_mm256_set_epi8(0xff, 0xff, 0xff, 0xff,  /* Zeroes */
 				11, 10,                  /* metadata0 (vlan_tci) */
 				9, 8,                    /* errors_v2 */
-				5, 4,                    /* metadata1 (payload_offset) */
+				5, 4,                    /* metadata2 */
 				1, 0,                    /* flags2 low */
 				0xff, 0xff, 0xff, 0xff,  /* Zeroes */
 				0xff, 0xff, 0xff, 0xff,  /* Zeroes */
 				11, 10,                  /* metadata0 (vlan_tci) */
 				9, 8,                    /* errors_v2 */
-				5, 4,                    /* metadata1 (payload_offset) */
+				5, 4,                    /* metadata2 */
 				1, 0,                    /* flags2 low */
 				0xff, 0xff, 0xff, 0xff); /* Zeroes */
+	const __m256i mask_1s =
+		_mm256_set1_epi32(0x1);
+	const __m256i mask_fs =
+		_mm256_set1_epi32(0xf);
 
-	const __m256i flags_type_mask =
-		_mm256_set1_epi32(RX_PKT_V3_CMPL_FLAGS_ITYPE_MASK);
-	const __m256i flags2_ip_type_mask =
-		_mm256_set1_epi32(RX_PKT_V3_CMPL_HI_FLAGS2_IP_TYPE);
-	const __m256i rss_mask =
-		_mm256_set1_epi32(RX_PKT_V3_CMPL_FLAGS_RSS_VALID);
-	const __m256i metadata1_valid_mask =
-		_mm256_set1_epi32(RX_PKT_V3_CMPL_METADATA1_VALID);
-	const __m256i vlan_tci_mask =
-		_mm256_set1_epi32(RX_PKT_V3_CMPL_HI_METADATA0_VID_MASK |
-				  RX_PKT_V3_CMPL_HI_METADATA0_DE |
-				  RX_PKT_V3_CMPL_HI_METADATA0_PRI_MASK);
-	const __m256i cs_err_mask =
-		_mm256_set1_epi32(RX_PKT_CMPL_ERRORS_T_L4_CS_ERROR |
-				  RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR |
-				  RX_PKT_CMPL_ERRORS_L4_CS_ERROR |
-				  RX_PKT_CMPL_ERRORS_IP_CS_ERROR);
-	const __m256i cs_calc_mask =
-		_mm256_set1_epi32(RX_PKT_CMPL_CALC);
-
-	__m256i t0, t1, flags_type, flags2, errors, metadata1;
-	__m256i ptype_idx, ptypes, vlan_tci, vlan_flags;
-	__m256i mbuf01, mbuf23, mbuf45, mbuf67;
 	__m256i rearm0, rearm1, rearm2, rearm3, rearm4, rearm5, rearm6, rearm7;
+	__m256i t0, t1, flags_type, flags2, errors_csum_idx, metadata1;
+	__m256i mbuf01, mbuf23, mbuf45, mbuf67;
+	__m256i ptype_idx, ptypes, vlan_flags;
 	__m256i ol_flags, ol_flags_hi;
 	__m256i rss_flags;
 
@@ -1025,7 +1001,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, meta0_err, cs_calc, cs_valid;
+		__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]);
@@ -1057,119 +1034,134 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 
 		/*
 		 * Pack needed fields from each descriptor pair.
-		 * For V3: extract rxcmp (low) for flags_type, len, rss
+		 * extract rxcmp (low) for flags_type, len, rss
 		 * and rxcmp1 (hi) for flags2, metadata0, metadata1, errors_v2
+		 * metadata1 is incrementally extracted to save on
+		 * register pressure
 		 */
 		t0 = _mm256_permute2f128_si256(desc6, desc7, 0x20);
 		t1 = _mm256_permute2f128_si256(desc6, desc7, 0x31);
 		t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
 		rxcmp6_7 = _mm256_blend_epi32(t0, t1, 0x66);
+		lo6_7 = t0;
 
 		t0 = _mm256_permute2f128_si256(desc4, desc5, 0x20);
 		t1 = _mm256_permute2f128_si256(desc4, desc5, 0x31);
 		t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
 		rxcmp4_5 = _mm256_blend_epi32(t0, t1, 0x66);
+		md1_4567 = _mm256_unpackhi_epi32(t0, lo6_7);
 
 		t0 = _mm256_permute2f128_si256(desc2, desc3, 0x20);
 		t1 = _mm256_permute2f128_si256(desc2, desc3, 0x31);
 		t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
 		rxcmp2_3 = _mm256_blend_epi32(t0, t1, 0x66);
+		lo2_3 = t0;
 
 		t0 = _mm256_permute2f128_si256(desc0, desc1, 0x20);
 		t1 = _mm256_permute2f128_si256(desc0, desc1, 0x31);
 		t1 = _mm256_shuffle_epi8(t1, dsc_shuf_msk);
 		rxcmp0_1 = _mm256_blend_epi32(t0, t1, 0x66);
+		md1_0123 = _mm256_unpackhi_epi32(t0, lo2_3);
+		metadata1 = _mm256_unpacklo_epi64(md1_0123, md1_4567);
 
-		/* Extract flags_type from low completion for eight packets */
-		t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
-		t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
-		flags_type = _mm256_unpacklo_epi64(t0, t1);
-
-		/* Compute ptype_idx from flags_type itype field */
-		ptype_idx = _mm256_and_si256(flags_type, flags_type_mask);
-		ptype_idx = _mm256_srli_epi32(ptype_idx,
-					      RX_PKT_V3_CMPL_FLAGS_ITYPE_SFT -
-					      BNXT_PTYPE_TBL_TYPE_SFT);
-
-		/* Extract flags2 from high completion */
+		/* Extract flags2 from high completion for eight packets */
 		t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
 		t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
 		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());
 
-		t0 = _mm256_srli_epi32(_mm256_and_si256(flags2, flags2_ip_type_mask),
-				       RX_PKT_V3_CMPL_FLAGS2_IP_TYPE_SFT -
-				       BNXT_PTYPE_TBL_IP_VER_SFT);
-		ptype_idx = _mm256_or_si256(ptype_idx, t0);
-
-		/*
-		 * Extract metadata1 (contains VLAN valid bit) from LOW completion.
-		 * metadata1_payload_offset is at word 2 of rxcmp (low 128 bits of desc).
+		/* Extract metadata0 and errors from high completion */
+		t0 = _mm256_unpackhi_epi32(rxcmp0_1, rxcmp2_3);
+		t1 = _mm256_unpackhi_epi32(rxcmp4_5, rxcmp6_7);
+		errors_v2 = _mm256_unpacklo_epi64(t0, t1);
+		/* mask_fs used in place of RX_PKT_CMPL_ERRORS_T_L4_CS_ERROR |
+		 * RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR | RX_PKT_CMPL_ERRORS_L4_CS_ERROR |
+		 * RX_PKT_CMPL_ERRORS_IP_CS_ERROR
 		 */
-		{
-			__m128i m01, m23, hi;
-			hi =
-		_mm_unpacklo_epi64(_mm_unpackhi_epi32(_mm256_castsi256_si128(desc4),
-						    _mm256_castsi256_si128(desc5)),
-				 _mm_unpackhi_epi32(_mm256_castsi256_si128(desc6),
-						    _mm256_castsi256_si128(desc7)));
-			m01 = _mm_unpackhi_epi32(_mm256_castsi256_si128(desc0),
-						 _mm256_castsi256_si128(desc1));
-			m23 = _mm_unpackhi_epi32(_mm256_castsi256_si128(desc2),
-						 _mm256_castsi256_si128(desc3));
-			metadata1 =
-			_mm256_inserti128_si256(_mm256_castsi128_si256(_mm_unpacklo_epi64(m01,
-								       m23)), hi, 1);
-		}
-		metadata1 = _mm256_srli_epi32(metadata1, 16);
-
-		t0 = _mm256_srli_epi32(_mm256_and_si256(metadata1, metadata1_valid_mask),
-				       RX_PKT_V3_CMPL_METADATA1_VALID_SFT -
-				       BNXT_PTYPE_TBL_VLAN_SFT);
-		ptype_idx = _mm256_or_si256(ptype_idx, t0);
+		errors_csum_idx = _mm256_srli_epi32(_mm256_and_si256(errors_v2,
+						    _mm256_slli_epi32(mask_fs, 4)), 4);
+		errors_csum_idx = _mm256_andnot_si256(cs_valid, errors_csum_idx);
 
 		/*
-		 * Load ptypes for eight packets using gather.
+		 * Load ol_flags for eight packets using gather. Gather
+		 * operations have extremely high latency (~19 cycles),
+		 * execution and use of result should be separated as much
+		 * as possible.
 		 */
-		ptypes = _mm256_i32gather_epi32((int *)bnxt_ptype_table,
-						ptype_idx, sizeof(uint32_t));
-
-		/* Extract RSS valid flags for eight packets */
-		rss_flags = _mm256_and_si256(flags_type, rss_mask);
-		rss_flags = _mm256_srli_epi32(rss_flags, 9);
-
-		/* Extract metadata0 (contains vlan_tci) and errors from high completion */
-		t0 = _mm256_unpackhi_epi32(rxcmp0_1, rxcmp2_3);
-		t1 = _mm256_unpackhi_epi32(rxcmp4_5, rxcmp6_7);
-		meta0_err = _mm256_unpacklo_epi64(t0, t1);
+		ol_flags = _mm256_i32gather_epi32((const int *)errors_to_olflags_v3,
+						  errors_csum_idx, sizeof(uint32_t));
 
-		/* Extract vlan_tci from high 16 bits of meta0_err (metadata0) */
-		vlan_tci = _mm256_and_si256(_mm256_srli_epi32(meta0_err, 16), vlan_tci_mask);
+		/* Exctract if the packet is VLAN and the VLAN tci */
+		metadata1 = _mm256_srli_epi32(metadata1, 16);
+		/* mask_1s used in place of RX_PKT_V3_CMPL_METADATA1_VALID */
+		ptype_idx = _mm256_srli_epi32(_mm256_and_si256(metadata1,
+					      _mm256_slli_epi32(mask_1s, 15)),
+					      RX_PKT_V3_CMPL_METADATA1_VALID_SFT -
+					      BNXT_PTYPE_TBL_VLAN_SFT);
 
-		vlan_flags = _mm256_and_si256(metadata1, metadata1_valid_mask);
-		vlan_flags = _mm256_min_epu32(vlan_flags, _mm256_set1_epi32(1));
+		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));
+					_mm256_slli_epi32(vlan_flags, 6));
 		}
 
-		errors_v2 = meta0_err;
+		/* Extract flags_type from low completion for eight packets */
+		t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
+		t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
+		flags_type = _mm256_unpacklo_epi64(t0, t1);
 
-		errors = _mm256_srli_epi32(_mm256_and_si256(meta0_err, cs_err_mask), 4);
+		/* Compute ptype_idx from flags_type itype field
+		 * mask_fs is used in place of
+		 * RX_PKT_V3_CMPL_FLAGS_ITYPE_MASK
+		 */
+		t0 = _mm256_and_si256(flags_type,
+				      _mm256_slli_epi32(mask_fs, 12));
+		t0 = _mm256_srli_epi32(t0, RX_PKT_V3_CMPL_FLAGS_ITYPE_SFT -
+				       BNXT_PTYPE_TBL_TYPE_SFT);
+		ptype_idx = _mm256_or_si256(ptype_idx, t0);
 
-		cs_calc = _mm256_and_si256(flags2, cs_calc_mask);
+		/* Extract flags2 from low completion for eight packets
+		 * flags2 is re-extracted to save on registers
+		 */
+		t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
+		t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
+		flags2 = _mm256_unpackhi_epi64(t0, t1);
+
+		/* mask_fs is being used in place of
+		 * RX_PKT_CMPL_CALC
+		 */
+		cs_calc = _mm256_and_si256(flags2, mask_fs);
 		cs_valid = _mm256_cmpeq_epi32(cs_calc, _mm256_setzero_si256());
-		errors = _mm256_andnot_si256(cs_valid, errors);
-		ol_flags = _mm256_i32gather_epi32((const int *)errors_to_olflags_v3,
-						  errors, sizeof(uint32_t));
-		__m256i unknown_flags = _mm256_and_si256(cs_valid,
-				_mm256_set1_epi32(RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN));
-		ol_flags = _mm256_or_si256(ol_flags, unknown_flags);
+		ol_flags = _mm256_andnot_si256(cs_valid, ol_flags);
 
-		const __m256i perm_msk =
-				_mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);
-		info3_v = _mm256_permutevar8x32_epi32(errors_v2, perm_msk);
-		info3_v = _mm256_and_si256(errors_v2, info3_v_mask);
+		/* mask_1s is being used in place of
+		 * RX_PKT_V3_CMPL_HI_FLAGS2_IP_TYPE
+		 */
+		t0 = _mm256_srli_epi32(_mm256_and_si256(flags2,
+				       _mm256_slli_epi32(mask_1s, 8)),
+				       RX_PKT_V3_CMPL_FLAGS2_IP_TYPE_SFT -
+				       BNXT_PTYPE_TBL_IP_VER_SFT);
+		ptype_idx = _mm256_or_si256(ptype_idx, t0);
+
+		/*
+		 * Load ptypes for eight packets using gather. Gather operations
+		 * have extremely high latency (~19 cycles), execution and use
+		 * of result should be separated as much as possible.
+		 */
+		ptypes = _mm256_i32gather_epi32((int *)bnxt_ptype_table,
+						ptype_idx, sizeof(uint32_t));
+
+		/*
+		 * Pack the 128-bit array of valid descriptor flags into 64
+		 * bits and count the number of set bits in order to determine
+		 * the number of valid descriptors.
+		 * mask_1s is used in place of CMPL_BASE_V
+		 */
+		info3_v = _mm256_and_si256(errors_v2, mask_1s);
 		info3_v = _mm256_xor_si256(info3_v, valid_target);
 
 		info3_v = _mm256_packs_epi32(info3_v, _mm256_setzero_si256());
@@ -1181,6 +1173,11 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 		if (num_valid == 0)
 			break;
 
+		/* Extract flags_type from low completion for eight packets*/
+		t0 = _mm256_unpacklo_epi32(rxcmp0_1, rxcmp2_3);
+		t1 = _mm256_unpacklo_epi32(rxcmp4_5, rxcmp6_7);
+		flags_type = _mm256_unpacklo_epi64(t0, t1);
+
 		mbuf01 = _mm256_shuffle_epi8(rxcmp0_1, shuf_msk);
 		mbuf23 = _mm256_shuffle_epi8(rxcmp2_3, shuf_msk);
 		mbuf45 = _mm256_shuffle_epi8(rxcmp4_5, shuf_msk);
@@ -1194,29 +1191,18 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 		mbuf67 = _mm256_blend_epi32(mbuf67,
 					_mm256_srli_si256(ptypes, 12), 0x11);
 
-		const __m256i tci_perm_01 = _mm256_set_epi32(1, 1, 1, 1, 0, 0, 0, 0);
-		const __m256i tci_perm_23 = _mm256_set_epi32(3, 3, 3, 3, 2, 2, 2, 2);
-		const __m256i tci_perm_45 = _mm256_set_epi32(5, 5, 5, 5, 4, 4, 4, 4);
-		const __m256i tci_perm_67 = _mm256_set_epi32(7, 7, 7, 7, 6, 6, 6, 6);
-
-		mbuf01 = _mm256_blend_epi16(mbuf01,
-			_mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
-						tci_perm_01), 10), 0x20);
-		mbuf23 = _mm256_blend_epi16(mbuf23,
-			_mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
-						tci_perm_23), 10), 0x20);
-		mbuf45 = _mm256_blend_epi16(mbuf45,
-			_mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
-						tci_perm_45), 10), 0x20);
-		mbuf67 = _mm256_blend_epi16(mbuf67,
-			_mm256_slli_si256(_mm256_permutevar8x32_epi32(vlan_tci,
-						tci_perm_67), 10), 0x20);
-
 		rearm0 = _mm256_permute2f128_si256(mbuf_init, mbuf01, 0x20);
 		rearm1 = _mm256_blend_epi32(mbuf_init, mbuf01, 0xF0);
 		rearm2 = _mm256_permute2f128_si256(mbuf_init, mbuf23, 0x20);
 		rearm3 = _mm256_blend_epi32(mbuf_init, mbuf23, 0xF0);
 
+		/* Extract RSS valid flags for eight packets
+		 * mask_1s is being used in place of
+		 * RX_PKT_V3_CMPL_FLAGS_RSS_VALID
+		 */
+		rss_flags = _mm256_and_si256(flags_type,
+					     _mm256_slli_epi32(mask_1s, 10));
+		rss_flags = _mm256_srli_epi32(rss_flags, 9);
 		ol_flags = _mm256_or_si256(ol_flags, rss_flags);
 		ol_flags = _mm256_or_si256(ol_flags, vlan_flags);
 		ol_flags_hi = _mm256_permute2f128_si256(ol_flags,
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_common.h b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
index e8da010dc3..d8659d1001 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_common.h
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
@@ -178,7 +178,7 @@ bnxt_tx_cmp_vec(struct bnxt_tx_queue *txq, uint32_t nr_pkts)
 	txr->tx_raw_cons = raw_cons;
 }
 
-static const uint64_t errors_to_olflags_v3[16] = {
+static const uint32_t errors_to_olflags_v3[16] = {
 	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
 	RTE_MBUF_F_RX_IP_CKSUM_GOOD,
 	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
-- 
2.47.3


^ permalink raw reply related

* [PATCH 08/10] net/bnxt: fix for VLAN stripping being set incorrectly
From: Mohammad Shuab Siddique @ 2026-06-04  3:18 UTC (permalink / raw)
  To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
	Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>

From: Keegan Freyhof <keegan.freyhof@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@dpdk.org
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@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


^ permalink raw reply related

* [PATCH 09/10] net/bnxt: add vector AVX2 burst mode indicator for v3
From: Mohammad Shuab Siddique @ 2026-06-04  3:18 UTC (permalink / raw)
  To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
	Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>

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

When querying the burst mode while the AVX2 RX vector
mode was in use, bnxt_rx_burst_mode_get added nothing
to the mode->info as the bnxt_rx_burst_info was not
populated with an entry for the v3. Added an entry
for v3 in bnxt_rx_burst_info.

Fixes: 15276ba987bd ("net/bnxt: fix getting burst mode for Arm")
Cc: stable@dpdk.org
Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
 drivers/net/bnxt/bnxt_ethdev.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 791a89f040..63f9f6fb48 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -3326,6 +3326,7 @@ static const struct {
 	{bnxt_recv_pkts_vec,		"Vector SSE"},
 	{bnxt_crx_pkts_vec_avx2,	"Vector AVX2"},
 	{bnxt_recv_pkts_vec_avx2,	"Vector AVX2"},
+	{bnxt_recv_pkts_vec_avx2_v3,	"Vector AVX2"},
 #endif
 #if defined(RTE_ARCH_ARM64)
 	{bnxt_recv_pkts_vec,		"Vector Neon"},
-- 
2.47.3


^ permalink raw reply related

* [PATCH 10/10] net/bnxt: fix v3 vector mode not selecting cksum unknown unknown
From: Mohammad Shuab Siddique @ 2026-06-04  3:18 UTC (permalink / raw)
  To: dev; +Cc: kishore.padmanabha, stable, Keegan Freyhof,
	Mohammad Shuab Siddique
In-Reply-To: <20260604031851.2267548-1-Mohammad-Shuab.Siddique@broadcom.com>

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

The v3 vector mode would default to all cksums being good rather
than cksum unknown in the case that flags2 cscalc section was 0.
Added an entry in the lookup table for this case and corrected
the logic.

Signed-off-by: Keegan Freyhof <keegan.freyhof@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
 drivers/net/bnxt/bnxt_rxtx_vec_avx2.c   | 14 ++++++++------
 drivers/net/bnxt/bnxt_rxtx_vec_common.h |  3 ++-
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
index 38aca98cb1..b5fb9d35c4 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_avx2.c
@@ -1111,14 +1111,16 @@ recv_burst_vec_avx2_v3(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pk
 		 * RX_PKT_CMPL_ERRORS_T_IP_CS_ERROR | RX_PKT_CMPL_ERRORS_L4_CS_ERROR |
 		 * RX_PKT_CMPL_ERRORS_IP_CS_ERROR
 		 */
-		errors_csum_idx = _mm256_srli_epi32(_mm256_and_si256(errors_v2,
-						    _mm256_slli_epi32(mask_fs, 4)), 4);
+		errors_csum_idx = _mm256_and_si256(_mm256_srli_epi32(errors_v2, 4),
+						   mask_fs);
 		meta_format = _mm256_cmpeq_epi32(_mm256_and_si256(cs_calc,
-							_mm256_slli_epi32(mask_fs, 4)),
-							_mm256_setzero_si256());
+						 _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);
+					      _mm256_setzero_si256());
+		errors_csum_idx = _mm256_add_epi32(_mm256_andnot_si256(cs_valid, mask_1s),
+						   _mm256_andnot_si256(cs_valid,
+								       errors_csum_idx));
 
 		/*
 		 * Load ol_flags for eight packets using gather. Gather
diff --git a/drivers/net/bnxt/bnxt_rxtx_vec_common.h b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
index d8659d1001..c75a8bd09f 100644
--- a/drivers/net/bnxt/bnxt_rxtx_vec_common.h
+++ b/drivers/net/bnxt/bnxt_rxtx_vec_common.h
@@ -178,7 +178,8 @@ bnxt_tx_cmp_vec(struct bnxt_tx_queue *txq, uint32_t nr_pkts)
 	txr->tx_raw_cons = raw_cons;
 }
 
-static const uint32_t errors_to_olflags_v3[16] = {
+static const uint32_t errors_to_olflags_v3[17] = {
+	RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN,
 	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
 	RTE_MBUF_F_RX_IP_CKSUM_GOOD,
 	RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD | RTE_MBUF_F_RX_L4_CKSUM_GOOD |
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2] net/ark: use standard IPv4 address parser
From: Denis Sergeev @ 2026-06-04  3:48 UTC (permalink / raw)
  To: dev; +Cc: shepard.siegel, ed.czeck, john.miller, stephen, Denis Sergeev,
	stable
In-Reply-To: <20260603054742.120101-1-denserg.edu@gmail.com>

The IPv4 parsing helper used by pktgen and pktchkr read each octet with
"%u", which accepts values above 255 from the configuration file and
encodes them into unintended device register values.

Replace the hand-rolled parser in both modules with inet_pton(), which
validates the dotted-quad format and the octet range, and matches the
IPv4 parsing already used by other DPDK drivers. For valid input the
returned value is byte-order identical to the previous helper, so the
register contents are unchanged.

Fixes: 9c7188a68d7b ("net/ark: provide API for hardware modules pktchkr and pktgen")
Cc: stable@dpdk.org

Signed-off-by: Denis Sergeev <denserg.edu@gmail.com>
---
v2:
 - Replace the hand-rolled parser with inet_pton() in both modules
   instead of adding explicit octet range checks.

 drivers/net/ark/ark_pktchkr.c | 9 +++++----
 drivers/net/ark/ark_pktgen.c  | 9 +++++----
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ark/ark_pktchkr.c b/drivers/net/ark/ark_pktchkr.c
index e1f336c73c..67405ac18a 100644
--- a/drivers/net/ark/ark_pktchkr.c
+++ b/drivers/net/ark/ark_pktchkr.c
@@ -4,9 +4,11 @@
 
 #include <stdlib.h>
 #include <unistd.h>
+#include <arpa/inet.h>
 
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
+#include <rte_byteorder.h>
 
 #include "ark_pktchkr.h"
 #include "ark_logs.h"
@@ -374,12 +376,11 @@ static int32_t parse_ipv4_string(char const *ip_address);
 static int32_t
 parse_ipv4_string(char const *ip_address)
 {
-	unsigned int ip[4];
+	struct in_addr addr;
 
-	if (sscanf(ip_address, "%u.%u.%u.%u",
-		   &ip[0], &ip[1], &ip[2], &ip[3]) != 4)
+	if (inet_pton(AF_INET, ip_address, &addr) != 1)
 		return 0;
-	return ip[3] + ip[2] * 0x100 + ip[1] * 0x10000ul + ip[0] * 0x1000000ul;
+	return rte_be_to_cpu_32(addr.s_addr);
 }
 
 void
diff --git a/drivers/net/ark/ark_pktgen.c b/drivers/net/ark/ark_pktgen.c
index 69ff7072b2..05d5773d44 100644
--- a/drivers/net/ark/ark_pktgen.c
+++ b/drivers/net/ark/ark_pktgen.c
@@ -4,9 +4,11 @@
 
 #include <stdlib.h>
 #include <unistd.h>
+#include <arpa/inet.h>
 
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
+#include <rte_byteorder.h>
 #include <rte_thread.h>
 
 #include "ark_pktgen.h"
@@ -355,12 +357,11 @@ static int32_t parse_ipv4_string(char const *ip_address);
 static int32_t
 parse_ipv4_string(char const *ip_address)
 {
-	unsigned int ip[4];
+	struct in_addr addr;
 
-	if (sscanf(ip_address, "%u.%u.%u.%u",
-		   &ip[0], &ip[1], &ip[2], &ip[3]) != 4)
+	if (inet_pton(AF_INET, ip_address, &addr) != 1)
 		return 0;
-	return ip[3] + ip[2] * 0x100 + ip[1] * 0x10000ul + ip[0] * 0x1000000ul;
+	return rte_be_to_cpu_32(addr.s_addr);
 }
 
 static void
-- 
2.50.1


^ permalink raw reply related

* [PATCH] net/mlx5: fix the eCPRI match on HWS root table
From: Bing Zhao @ 2026-06-04  3:52 UTC (permalink / raw)
  To: viacheslavo, dev, rasland; +Cc: orika, dsosnowski, suanmingm, matan, thomas

When inserting a rule on the root table in HWS mode, the DV
interfaces are still being used for the matcher and value
translation.

For item eCPRI in HWS mode, the DWs of message header and body may be
0 for a valid rule. So we need to use some flags on root table to
decide if the sample ID and matching value should be set for the
rule. Since the table and rule may be created in turn for
asynchronous flow API, the flags should be per table to avoid
over-written. In SWS mode, nothing would be done separately for the
matcher itself.

On the non-root table in HWS, the callbacks to fill the WQE will
handle such case automatically.

Fixes: 93c7d4c22628 ("net/mlx5: support eCPRI with HWS")

Signed-off-by: Bing Zhao <bingz@nvidia.com>
Acked-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
---
 drivers/net/mlx5/hws/mlx5dr_matcher.c |  1 +
 drivers/net/mlx5/hws/mlx5dr_matcher.h |  1 +
 drivers/net/mlx5/hws/mlx5dr_rule.c    |  1 +
 drivers/net/mlx5/mlx5_flow.h          |  7 +++
 drivers/net/mlx5/mlx5_flow_dv.c       | 77 +++++++++++++++++++++------
 5 files changed, 70 insertions(+), 17 deletions(-)

diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.c b/drivers/net/mlx5/hws/mlx5dr_matcher.c
index 8c07ea8882..511f394448 100644
--- a/drivers/net/mlx5/hws/mlx5dr_matcher.c
+++ b/drivers/net/mlx5/hws/mlx5dr_matcher.c
@@ -1381,6 +1381,7 @@ static int mlx5dr_matcher_init_root(struct mlx5dr_matcher *matcher)
 	LIST_INSERT_HEAD(&matcher->tbl->head, matcher, next);
 	pthread_spin_unlock(&ctx->ctrl_lock);
 
+	matcher->hws_root_match_flags = flow_attr.hws_root_match_flags;
 	return 0;
 
 free_mask:
diff --git a/drivers/net/mlx5/hws/mlx5dr_matcher.h b/drivers/net/mlx5/hws/mlx5dr_matcher.h
index ef42b7de6b..fbcf9fe09e 100644
--- a/drivers/net/mlx5/hws/mlx5dr_matcher.h
+++ b/drivers/net/mlx5/hws/mlx5dr_matcher.h
@@ -82,6 +82,7 @@ struct mlx5dr_matcher {
 	uint8_t num_of_at;
 	/* enum mlx5dr_matcher_flags */
 	uint8_t flags;
+	uint32_t hws_root_match_flags;
 	struct mlx5dr_devx_obj *end_ft;
 	struct mlx5dr_matcher *col_matcher;
 	struct mlx5dr_matcher *resize_dst;
diff --git a/drivers/net/mlx5/hws/mlx5dr_rule.c b/drivers/net/mlx5/hws/mlx5dr_rule.c
index 0fda0a2d71..fe69721c92 100644
--- a/drivers/net/mlx5/hws/mlx5dr_rule.c
+++ b/drivers/net/mlx5/hws/mlx5dr_rule.c
@@ -741,6 +741,7 @@ int mlx5dr_rule_create_root_no_comp(struct mlx5dr_rule *rule,
 	}
 
 	flow_attr.tbl_type = rule->matcher->tbl->type;
+	flow_attr.hws_root_match_flags = rule->matcher->hws_root_match_flags;
 
 	ret = mlx5_flow_dv_translate_items_hws(items, &flow_attr, value->match_buf,
 					       MLX5_SET_MATCHER_HS_V, NULL,
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index c9e72a33d6..39c85eb9a4 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -117,6 +117,9 @@ enum mlx5_indirect_type {
 	((struct rte_flow_action_handle *)(uintptr_t) \
 	 ((MLX5_INDIRECT_ACTION_TYPE_CT << MLX5_INDIRECT_ACTION_TYPE_OFFSET) | (index)))
 
+#define MLX5_EMPTY_ECPRI_TYPE_MASK RTE_BIT32(0)
+#define MLX5_EMPTY_ECPRI_BODY_MASK RTE_BIT32(1)
+
 enum mlx5_indirect_list_type {
 	MLX5_INDIRECT_ACTION_LIST_TYPE_ERR = 0,
 	MLX5_INDIRECT_ACTION_LIST_TYPE_LEGACY = 1,
@@ -1264,6 +1267,7 @@ struct mlx5_flow_attr {
 	/* Action flags, used by priority adjustment. */
 	uint32_t act_flags;
 	uint32_t tbl_type; /* Flow table type. */
+	uint32_t hws_root_match_flags;
 };
 
 /* Flow structure. */
@@ -1985,6 +1989,8 @@ struct mlx5_flow_workspace {
 	uint32_t skip_matcher_reg:1;
 	/* Indicates if need to skip matcher register in translate. */
 	uint32_t mark:1; /* Indicates if flow contains mark action. */
+	uint32_t empty_ecpri_type_mask:1; /* Indicates if eCPRI type was not masked. */
+	uint32_t empty_ecpri_body_mask:1; /* Indicates if 1st DW of eCPRI payload was not masked. */
 	uint32_t vport_meta_tag; /* Used for vport index match. */
 };
 
@@ -2018,6 +2024,7 @@ struct mlx5_dv_matcher_workspace {
 	const struct rte_flow_item *tunnel_item; /* Flow tunnel item. */
 	const struct rte_flow_item *gre_item; /* Flow GRE item. */
 	const struct rte_flow_item *integrity_items[2];
+	uint32_t *p_root_flags;
 };
 
 struct mlx5_flow_split_info {
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index c2a2874913..307354c886 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -7798,7 +7798,7 @@ mlx5_flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 				.u32 =
 				RTE_BE32(((const struct rte_ecpri_common_hdr) {
 					.type = 0xFF,
-					}).u32),
+				}).u32),
 			},
 			.dummy[0] = 0xffffffff,
 		},
@@ -11401,6 +11401,20 @@ flow_dv_translate_item_gtp_psc(void *key, const struct rte_flow_item *item,
 	return 0;
 }
 
+
+static inline void
+flow_dv_set_ecpri_sample1(void *misc4_v,
+			  const struct rte_flow_item_ecpri *ecpri_m,
+			  const struct rte_flow_item_ecpri *ecpri_v,
+			  uint32_t sample1)
+{
+	void *dw_v;
+	dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v, prog_sample_field_value_1);
+	*(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] & ecpri_m->hdr.dummy[0];
+	/* Sample#1, to match message body, offset 4. */
+	MLX5_SET(fte_match_set_misc4, misc4_v, prog_sample_field_id_1, sample1);
+}
+
 /**
  * Add eCPRI item to matcher and to the value.
  *
@@ -11418,6 +11432,7 @@ flow_dv_translate_item_gtp_psc(void *key, const struct rte_flow_item *item,
 static void
 flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
 			     const struct rte_flow_item *item,
+			     struct mlx5_dv_matcher_workspace *wks,
 			     uint64_t last_item, uint32_t key_type)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
@@ -11446,18 +11461,32 @@ flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
 					RTE_BE16(RTE_ETHER_TYPE_ECPRI);
 		}
 	}
+	/* HWS matcher does need a non-empty mask. */
 	if (MLX5_ITEM_VALID(item, key_type))
 		return;
-	MLX5_ITEM_UPDATE(item, key_type, ecpri_v, ecpri_m,
-		&rte_flow_item_ecpri_mask);
+	MLX5_ITEM_UPDATE(item, key_type, ecpri_v, ecpri_m, &rte_flow_item_ecpri_mask);
 	/*
 	 * Maximal four DW samples are supported in a single matching now.
 	 * Two are used now for a eCPRI matching:
 	 * 1. Type: one byte, mask should be 0x00ff0000 in network order
 	 * 2. ID of a message: one or two bytes, mask 0xffff0000 or 0xff000000
 	 *    if any.
+	 * Translation also handles the following cases.
+	 * 1. HWS mode may face a case with NULL mask and value all zeros.
+	 * 2. Matching all eCPRI packets will be done in ETH / VLAN item.
+	 * 3. If type is not masked, then message body will not be masked either, forcefully.
 	 */
-	if (!ecpri_m->hdr.common.u32)
+	if (key_type == MLX5_SET_MATCHER_HS_M) {
+		if (!ecpri_m->hdr.common.u32) {
+			*wks->p_root_flags |= MLX5_EMPTY_ECPRI_TYPE_MASK;
+			return;
+		}
+		/* Initialized with 0, this should not hit. */
+		*wks->p_root_flags &= ~MLX5_EMPTY_ECPRI_TYPE_MASK;
+	}
+	if (key_type == MLX5_SET_MATCHER_HS_V && (*wks->p_root_flags & MLX5_EMPTY_ECPRI_TYPE_MASK))
+		return;
+	if ((key_type & MLX5_SET_MATCHER_SW) && !ecpri_m->hdr.common.u32)
 		return;
 	samples = priv->sh->ecpri_parser.ids;
 	/* Need to take the whole DW as the mask to fill the entry. */
@@ -11473,27 +11502,40 @@ flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *key,
 	 * Checking if message body part needs to be matched.
 	 * Some wildcard rules only matching type field should be supported.
 	 */
-	if (ecpri_m->hdr.dummy[0]) {
-		if (key_type == MLX5_SET_MATCHER_SW_M)
-			common.u32 = rte_be_to_cpu_32(ecpri_vv->hdr.common.u32);
-		else
-			common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32);
+	if (key_type == MLX5_SET_MATCHER_HS_M) {
+		if (!ecpri_m->hdr.dummy[0]) {
+			*wks->p_root_flags |= MLX5_EMPTY_ECPRI_BODY_MASK;
+			return;
+		}
+		*wks->p_root_flags &= ~MLX5_EMPTY_ECPRI_BODY_MASK;
+	}
+	if (key_type == MLX5_SET_MATCHER_HS_V && (*wks->p_root_flags & MLX5_EMPTY_ECPRI_BODY_MASK))
+		return;
+	if (key_type & MLX5_SET_MATCHER_SW) {
+		if (!ecpri_m->hdr.dummy[0])
+			return;
+		common.u32 = rte_be_to_cpu_32(ecpri_vv->hdr.common.u32);
+	} else if (key_type == MLX5_SET_MATCHER_HS_V) {
+		common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32);
+	}
+	if (key_type != MLX5_SET_MATCHER_HS_M) {
 		switch (common.type) {
 		case RTE_ECPRI_MSG_TYPE_IQ_DATA:
 		case RTE_ECPRI_MSG_TYPE_RTC_CTRL:
 		case RTE_ECPRI_MSG_TYPE_DLY_MSR:
-			dw_v = MLX5_ADDR_OF(fte_match_set_misc4, misc4_v,
-					    prog_sample_field_value_1);
-			*(uint32_t *)dw_v = ecpri_v->hdr.dummy[0] &
-					    ecpri_m->hdr.dummy[0];
-			/* Sample#1, to match message body, offset 4. */
-			MLX5_SET(fte_match_set_misc4, misc4_v,
-				 prog_sample_field_id_1, samples[1]);
+			flow_dv_set_ecpri_sample1(misc4_v, ecpri_v, ecpri_m, samples[1]);
 			break;
 		default:
 			/* Others, do not match any sample ID. */
 			break;
 		}
+	} else {
+		/* When MLX5_SET_MATCHER_HS_M on root table (default value),
+		 * the sample ID and mask should be set, or else prog_sample_field_id_1 will
+		 * be zero and a mismatch with the HWS rule.
+		 * Empty body mask for a matcher returns directly in the previous lines.
+		 */
+		flow_dv_set_ecpri_sample1(misc4_v, ecpri_v, ecpri_m, samples[1]);
 	}
 }
 
@@ -14501,7 +14543,7 @@ flow_dv_translate_items(struct rte_eth_dev *dev,
 					"cannot create eCPRI parser");
 		}
 		flow_dv_translate_item_ecpri
-				(dev, key, items, last_item, key_type);
+				(dev, key, items, wks, last_item, key_type);
 		/* No other protocol should follow eCPRI layer. */
 		last_item = MLX5_FLOW_LAYER_ECPRI;
 		break;
@@ -14698,6 +14740,7 @@ mlx5_flow_dv_translate_items_hws_impl(const struct rte_flow_item *items,
 		.attr = &rattr,
 		.rss_desc = &rss_desc,
 		.group = attr->group,
+		.p_root_flags = &attr->hws_root_match_flags,
 	};
 	int ret = 0;
 
-- 
2.21.0


^ permalink raw reply related

* [DPDK/core Bug 1952] hash: build fails with LTO
From: bugzilla @ 2026-06-04  7:46 UTC (permalink / raw)
  To: dev

http://bugs.dpdk.org/show_bug.cgi?id=1952

            Bug ID: 1952
           Summary: hash: build fails with LTO
           Product: DPDK
           Version: unspecified
          Hardware: All
                OS: All
            Status: UNCONFIRMED
          Severity: normal
          Priority: Normal
         Component: core
          Assignee: bruce.richardson@intel.com
          Reporter: david.marchand@redhat.com
                CC: dev@dpdk.org, konstantin.v.ananyev@yandex.ru,
                    ktraynor@redhat.com, vladimir.medvedkin@intel.com
  Target Milestone: ---

It is similar to a previous report, that resulting in silencing associated
warnings in dea4c5415506 ("ring: silence GCC 12 warnings").

For now, I associate the issue to the hash library, though the problem may be
on the ring library side.


Minimal reproducer:

# rm -rf build; meson setup build -Db_lto=true -Dcpu_instruction_set=generic
-Doptimization=0 -Ddisable_libs=* -Denable_apps=test-pmd
-Denable_drivers=net/null -Ddeveloper_mode=disabled && ninja -C build
...
The Meson build system
Version: 1.7.2
...
Project version: 26.07.0-rc0
C compiler for the host machine: ccache cc (gcc 15.2.1 "cc (GCC) 15.2.1
20260123 (Red Hat 15.2.1-7)")
C linker for the host machine: cc ld.bfd 2.44-12
...
Found pkg-config: YES (/usr/bin/pkg-config) 2.3.0
...
Compiler for C supports arguments -ffat-lto-objects: YES 
...
Found ninja-1.12.1 at /usr/bin/ninja
ninja: Entering directory `build'                                               
[280/284] Linking target lib/librte_hash.so.26.2
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘rte_hash_create’ at ../lib/hash/rte_cuckoo_hash.c:375:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_create’:
../lib/hash/rte_cuckoo_hash.c:184:18: note: source object ‘i’ of size 4
  184 |         uint32_t i;
      |                  ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘rte_hash_create’ at ../lib/hash/rte_cuckoo_hash.c:524:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_create’:
../lib/hash/rte_cuckoo_hash.c:184:18: note: source object ‘i’ of size 4
  184 |         uint32_t i;
      |                  ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘rte_hash_reset’ at ../lib/hash/rte_cuckoo_hash.c:730:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_reset’:
../lib/hash/rte_cuckoo_hash.c:693:32: note: source object ‘i’ of size 4
  693 |         uint32_t tot_ring_cnt, i;
      |                                ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘rte_hash_reset’ at ../lib/hash/rte_cuckoo_hash.c:735:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_reset’:
../lib/hash/rte_cuckoo_hash.c:693:32: note: source object ‘i’ of size 4
  693 |         uint32_t tot_ring_cnt, i;
      |                                ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘enqueue_slot_back’ at ../lib/hash/rte_cuckoo_hash.c:761:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘enqueue_slot_back’:
../lib/hash/rte_cuckoo_hash.c:755:26: note: source object ‘slot_id’ of size 4
  755 |                 uint32_t slot_id)
      |                          ^
In function ‘__rte_ring_dequeue_elems_128’,
    inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
    inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
    inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
    inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
    inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
    inlined from ‘alloc_slot’ at ../lib/hash/rte_cuckoo_hash.c:1098:7:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
  250 |                         memcpy((obj + i), (const void *)(ring + idx),
32);
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘alloc_slot’:
../lib/hash/rte_cuckoo_hash.c:1078:18: note: destination object ‘slot_id’ of
size 4
 1078 |         uint32_t slot_id;
      |                  ^
In function ‘__rte_ring_dequeue_elems_128’,
    inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
    inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
    inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
    inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
    inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
    inlined from ‘__rte_hash_add_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1260:6:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
  250 |                         memcpy((obj + i), (const void *)(ring + idx),
32);
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_add_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1114:18: note: destination object ‘ext_bkt_id’ of
size 4
 1114 |         uint32_t ext_bkt_id = 0;
      |                  ^
In function ‘__rte_ring_dequeue_elems_128’,
    inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
    inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
    inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
    inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
    inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
    inlined from ‘__rte_hash_add_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1267:5:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
  250 |                         memcpy((obj + i), (const void *)(ring + idx),
32);
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_add_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1114:18: note: destination object ‘ext_bkt_id’ of
size 4
 1114 |         uint32_t ext_bkt_id = 0;
      |                  ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘__hash_rcu_qsbr_free_resource’ at
../lib/hash/rte_cuckoo_hash.c:1616:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 12 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__hash_rcu_qsbr_free_resource’:
../lib/hash/rte_cuckoo_hash.c:1592:40: note: at offset [4, 16] into source
object ‘rcu_dq_entry’ of size 16
 1592 |         struct __rte_hash_rcu_dq_entry rcu_dq_entry =
      |                                        ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘__rte_hash_del_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1899:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_del_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1831:18: note: source object ‘index’ of size 4
 1831 |         uint32_t index = EMPTY_SLOT;
      |                  ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘rte_hash_free_key_with_position’ at
../lib/hash/rte_cuckoo_hash.c:1981:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_free_key_with_position’:
../lib/hash/rte_cuckoo_hash.c:1978:26: note: source object ‘index’ of size 4
 1978 |                 uint32_t index = h->ext_bkt_to_free[position];
      |                          ^
[284/284] Linking target app/dpdk-testpmd
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘rte_hash_create’ at ../lib/hash/rte_cuckoo_hash.c:375:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_create’:
../lib/hash/rte_cuckoo_hash.c:184:18: note: source object ‘i’ of size 4
  184 |         uint32_t i;
      |                  ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘rte_hash_create’ at ../lib/hash/rte_cuckoo_hash.c:524:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_create’:
../lib/hash/rte_cuckoo_hash.c:184:18: note: source object ‘i’ of size 4
  184 |         uint32_t i;
      |                  ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘rte_hash_reset’ at ../lib/hash/rte_cuckoo_hash.c:730:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_reset’:
../lib/hash/rte_cuckoo_hash.c:693:32: note: source object ‘i’ of size 4
  693 |         uint32_t tot_ring_cnt, i;
      |                                ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘rte_hash_reset’ at ../lib/hash/rte_cuckoo_hash.c:735:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_reset’:
../lib/hash/rte_cuckoo_hash.c:693:32: note: source object ‘i’ of size 4
  693 |         uint32_t tot_ring_cnt, i;
      |                                ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘enqueue_slot_back’ at ../lib/hash/rte_cuckoo_hash.c:761:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘enqueue_slot_back’:
../lib/hash/rte_cuckoo_hash.c:755:26: note: source object ‘slot_id’ of size 4
  755 |                 uint32_t slot_id)
      |                          ^
In function ‘__rte_ring_dequeue_elems_128’,
    inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
    inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
    inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
    inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
    inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
    inlined from ‘alloc_slot’ at ../lib/hash/rte_cuckoo_hash.c:1098:7:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
  250 |                         memcpy((obj + i), (const void *)(ring + idx),
32);
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘alloc_slot’:
../lib/hash/rte_cuckoo_hash.c:1078:18: note: destination object ‘slot_id’ of
size 4
 1078 |         uint32_t slot_id;
      |                  ^
In function ‘__rte_ring_dequeue_elems_128’,
    inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
    inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
    inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
    inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
    inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
    inlined from ‘__rte_hash_add_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1260:6:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
  250 |                         memcpy((obj + i), (const void *)(ring + idx),
32);
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_add_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1114:18: note: destination object ‘ext_bkt_id’ of
size 4
 1114 |         uint32_t ext_bkt_id = 0;
      |                  ^
In function ‘__rte_ring_dequeue_elems_128’,
    inlined from ‘__rte_ring_do_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:279:3,
    inlined from ‘__rte_ring_dequeue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:298:2,
    inlined from ‘__rte_ring_do_dequeue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:466:2,
    inlined from ‘rte_ring_sc_dequeue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:344:9,
    inlined from ‘rte_ring_sc_dequeue_elem’ at
../lib/ring/rte_ring_elem.h:444:9,
    inlined from ‘__rte_hash_add_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1267:5:
../lib/ring/rte_ring_elem_pvt.h:250:25: warning: ‘memcpy’ writing 32 bytes into
a region of size 4 overflows the destination [-Wstringop-overflow=]
  250 |                         memcpy((obj + i), (const void *)(ring + idx),
32);
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_add_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1114:18: note: destination object ‘ext_bkt_id’ of
size 4
 1114 |         uint32_t ext_bkt_id = 0;
      |                  ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘__hash_rcu_qsbr_free_resource’ at
../lib/hash/rte_cuckoo_hash.c:1616:3:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 12 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__hash_rcu_qsbr_free_resource’:
../lib/hash/rte_cuckoo_hash.c:1592:40: note: at offset [4, 16] into source
object ‘rcu_dq_entry’ of size 16
 1592 |         struct __rte_hash_rcu_dq_entry rcu_dq_entry =
      |                                        ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘__rte_hash_del_key_with_hash’ at
../lib/hash/rte_cuckoo_hash.c:1899:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘__rte_hash_del_key_with_hash’:
../lib/hash/rte_cuckoo_hash.c:1831:18: note: source object ‘index’ of size 4
 1831 |         uint32_t index = EMPTY_SLOT;
      |                  ^
In function ‘__rte_ring_enqueue_elems_128’,
    inlined from ‘__rte_ring_do_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:141:3,
    inlined from ‘__rte_ring_enqueue_elems’ at
../lib/ring/rte_ring_elem_pvt.h:160:2,
    inlined from ‘__rte_ring_do_enqueue_elem’ at
../lib/ring/rte_ring_elem_pvt.h:419:2,
    inlined from ‘rte_ring_sp_enqueue_bulk_elem’ at
../lib/ring/rte_ring_elem.h:159:9,
    inlined from ‘rte_ring_sp_enqueue_elem’ at
../lib/ring/rte_ring_elem.h:260:9,
    inlined from ‘rte_hash_free_key_with_position’ at
../lib/hash/rte_cuckoo_hash.c:1981:4:
../lib/ring/rte_ring_elem_pvt.h:108:25: warning: ‘memcpy’ reading 32 bytes from
a region of size 4 [-Wstringop-overread]
  108 |                         memcpy((void *)(ring + idx),
      |                         ^
../lib/hash/rte_cuckoo_hash.c: In function ‘rte_hash_free_key_with_position’:
../lib/hash/rte_cuckoo_hash.c:1978:26: note: source object ‘index’ of size 4
 1978 |                 uint32_t index = h->ext_bkt_to_free[position];
      |                          ^

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply

* Re: [PATCH] eal: fix function versioning with LTO
From: David Marchand @ 2026-06-04  7:50 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev, stable, Thomas Monjalon
In-Reply-To: <20260603085359.739ab626@phoenix.local>

On Wed, 3 Jun 2026 at 17:56, Stephen Hemminger
<stephen@networkplumber.org> wrote:
>
> On Wed, 3 Jun 2026 12:01:48 +0200
> David Marchand <david.marchand@redhat.com> wrote:
>
> > Hello,
> >
> > On Wed, 3 Jun 2026 at 00:57, Stephen Hemminger
> > <stephen@networkplumber.org> wrote:
> > >
> > > When using function versioning and building with Link Time Optimization,
> > > the compiler does not see the __asm__ annotation of symbols and
> > > therefore thinks there are two versions of the same symbol.
> > >
> > > The fix is to use compiler symver attribute on the function which
> > > was added in GCC 10. Keep the older method for backward compatibility
> > > with older compilers.
> > >
> > > Bugzilla ID: 1949
> > > Fixes: e30e194c4d06 ("eal: rework function versioning macros")
> >
> > We never used the symver stuff, so it seems unlikely the issue was
> > introduced with this rework.
> >
> > The fact that clang does not support this attribute is a concern.
>
> Clang doesn't have this problem. It works as is.

The Fixes: tag is wrong regardless.
The issue is probably present since introduction of the versioning
macros, or introduction of LTO in DPDK (not sure which came first).


> > > Cc: stable@dpdk.org
> >
> > Why do we need to backport?
>
> Well LTO has worked for a long time, it is not experimental just
> not commonly done since it takes so long to build.
>
> We were doing it years ago at MSFT.

Well, sorry, but every time I enable LTO, I end up with some warnings somewhere.
I don't think I am doing stuff really exotic though.

Looking at bugzilla, we had various fixes for LTO over the years.
We still have one open bz btw: https://bugs.dpdk.org/show_bug.cgi?id=1709

Hence my feeling this feature is not something used by many people around.
And without a CI, we will keep on having to fix bugs/issues.


> > LTO is kind of experimental, so it seems good enough to reply "not
> > expected to work in older LTS" if someone reported an issue.
> >
> > And in practice, no LTS release call the versioning macros, since a
> > LTS drops all compatibility.

Just to be clear, we don't need fixing the macros in LTS: every time
we prepare a LTS rc0, we drop any kind of symbol compat.


> >
> > > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> >
> > I would like to reproduce, but I can't build main with LTO.
> > What patches did you apply locally to avoid warnings on the hash library?
> I use Debian testing and GCC 15 but shows up on older versions as well
> I get no warnings building main

Building from scratch, I do avoid the warnings I hit yesterday.

The fix looks correct, my problem is with the form.
Fixes: tags accuracy is important.
And I prefer we stick to "It is not broken, don't fix it".


Thanks.


>
>  $ git am ~/Downloads/v2-ethdev-add-buffer-size-parameter-to-rte_eth_dev_get_name_by_port.patch
>  $ meson setup build-lto -Db_lto=true
>  $ ninja -C build-lto
> ninja: Entering directory `build-lto'
> [620/3781] Linking target lib/librte_ethdev.so.26.2
> FAILED: [code=1] lib/librte_ethdev.so.26.2
> cc  -o lib/librte_ethdev.so.26.2 lib/librte_ethdev.so.26.2.p/ethdev_ethdev_driver.c.o lib/librte_ethdev.so.26.2.p/ethdev_ethdev_private.c.o lib/librte_ethdev.so.26.2.p/ethdev_ethdev_profile.c.o lib/librte_ethdev.so.26.2.p/ethdev_ethdev_trace_points.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_class_eth.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_ethdev.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_ethdev_cman.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_ethdev_telemetry.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_flow.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_mtr.c.o lib/librte_ethdev.so.26.2.p/ethdev_rte_tm.c.o lib/librte_ethdev.so.26.2.p/ethdev_sff_telemetry.c.o lib/librte_ethdev.so.26.2.p/ethdev_sff_common.c.o lib/librte_ethdev.so.26.2.p/ethdev_sff_8079.c.o lib/librte_ethdev.so.26.2.p/ethdev_sff_8472.c.o lib/librte_ethdev.so.26.2.p/ethdev_sff_8636.c.o lib/librte_ethdev.so.26.2.p/ethdev_ethdev_linux_ethtool.c.o -flto=auto -Wl,--as-needed -Wl,--no-undefined -Wl,-O1 -shared -fPIC -Wl,-soname,librte_ethdev.so.26 -Wl,--no-as-needed -Wl,--undefined-version -pthread -Wl,--start-group -lm -ldl -lnuma -lfdt '-Wl,-rpath,$ORIGIN/' lib/librte_eal.so.26.2 lib/librte_kvargs.so.26.2 lib/librte_log.so.26.2 lib/librte_telemetry.so.26.2 lib/librte_argparse.so.26.2 lib/librte_net.so.26.2 lib/librte_mbuf.so.26.2 lib/librte_mempool.so.26.2 lib/librte_ring.so.26.2 lib/librte_meter.so.26.2 -Wl,--version-script=/home/shemminger/DPDK/lto/build-lto/lib/ethdev_exports.map /usr/lib/x86_64-linux-gnu/libbsd.so /usr/lib/x86_64-linux-gnu/libarchive.so -Wl,--end-group
> /tmp/cc3RQyqL.s: Assembler messages:
> /tmp/cc3RQyqL.s: Error: invalid attempt to declare external version name as default in symbol `rte_eth_dev_get_name_by_port@@DPDK_27'
> make: *** [/tmp/ccVzgiZ2.mk:2: /tmp/ccTlGfA9.ltrans0.ltrans.o] Error 1
> make: *** Waiting for unfinished jobs....
> lto-wrapper: fatal error: make returned 2 exit status
> compilation terminated.
>


-- 
David Marchand


^ permalink raw reply

* Re: [PATCH v3 0/6] Make VA reservation limits configurable
From: Thomas Monjalon @ 2026-06-04  8:22 UTC (permalink / raw)
  To: Anatoly Burakov; +Cc: dev, Bruce Richardson
In-Reply-To: <cover.1780071269.git.anatoly.burakov@intel.com>

> Anatoly Burakov (6):
>   eal: reject non-numeric input in str to size
>   eal/memory: remove per-list segment and memory limits
>   eal/memory: allocate all VA space in one go
>   eal/memory: get rid of global VA space limits
>   eal/memory: store default segment limits in config
>   eal/memory: add page size VA limits EAL parameter

Thank you for the simplification and the new runtime option.

Applied with release notes added, thanks.



^ permalink raw reply

* Re: [PATCH] net/mlx5: improve error when group table type mismatch
From: Raslan Darawsheh @ 2026-06-04  9:26 UTC (permalink / raw)
  To: Maayan Kashani, dev
  Cc: dsosnowski, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
	Suanming Mou, Matan Azrad
In-Reply-To: <20260325215426.9519-1-mkashani@nvidia.com>

Hi,


On 25/03/2026 11:54 PM, Maayan Kashani wrote:
> HWS fixes a flow group's DR table type (FDB_UNIFIED,
> FDB_RX, FDB_TX, etc.) on first use.
> If a later table uses the same group with a different domain
> (e.g. transfer wire_orig) the driver returns a generic type mismatch.
> 
> - Add mlx5dr_table_type_name() to map table type enum to readable strings
> (e.g. FDB_RX(wire_orig), FDB_UNIFIED).
> 
> This makes it easier to fix ordering issues
> (e.g. create wire_origtable before the table that jumps to the group).
> 
> Signed-off-by: Maayan Kashani <mkashani@nvidia.com>
> Acked-by: Dariusz Sosnowski <dsosnowski@nvidia.com>

Patch applied to next-net-mlx,

Kindest regards
Raslan Darawsheh


^ permalink raw reply

* Re: [PATCH 1/1] net/mlx5: fix crash if malloc FCQS fails
From: Raslan Darawsheh @ 2026-06-04  9:27 UTC (permalink / raw)
  To: Yunjian Wang, dev
  Cc: matan, suanmingm, viacheslavo, dsosnowski, jerry.lilijun, stable
In-Reply-To: <1777027713-91888-1-git-send-email-wangyunjian@huawei.com>

Hi,

On 24/04/2026 1:48 PM, Yunjian Wang wrote:
> A crash is triggered when memory malloc for FCQS fails. Currently,
> the abnormal branch releases the txq, and it removes the 'txq_ctrl->obj'
> from the linked list, but the 'txq_ctrl->obj' has not actually been
> added to the linked list yet. This triggers a null pointer reference
> issue.
> 
> The call stack is as follows:
> Program terminated with signal 11, Segmentation fault.
> 1210			LIST_REMOVE(txq_ctrl->obj, next);
> (gdb) bt
>   #0 mlx5_txq_release
>   #1 mlx5_txq_start
>   #2 mlx5_dev_start
>   #3 rte_eth_dev_start
>   #4 member_start
>   #5 bond_ethdev_start
> 
> Fixes: f49f44839df3 ("net/mlx5: share Tx control code")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Yunjian Wang <wangyunjian@huawei.com>

Patch applied to next-net-mlx,

Kindest regards
Raslan Darawsheh


^ permalink raw reply

* Re: [PATCH v2] net/mlx5: query hardware capability for max lro size
From: Raslan Darawsheh @ 2026-06-04  9:28 UTC (permalink / raw)
  To: Rayane Boussanni, dsosnowski
  Cc: bingz, dev, matan, orika, suanmingm, viacheslavo
In-Reply-To: <20260424142732.1904-1-rboussanni@gmail.com>

Hi,


On 24/04/2026 5:27 PM, Rayane Boussanni wrote:
> Resolve a FIXME in mlx5_dev_infos_get() by dynamically checking the
> lro_allowed flag instead of unconditionally advertising
> MLX5_MAX_LRO_SIZE.
> 
> Signed-off-by: Rayane Boussanni <rboussanni@gmail.com>
> ---

Patch applied to next-net-mlx,

Kindest regards
Raslan Darawsheh


^ permalink raw reply

* Re: [PATCH v3] net/mlx5: add validation for indirect actions
From: Raslan Darawsheh @ 2026-06-04  9:32 UTC (permalink / raw)
  To: Rayane Boussanni, dev; +Cc: dsosnowski
In-Reply-To: <20260514193359.195017-1-rboussanni@gmail.com>

Hi,


On 14/05/2026 10:33 PM, Rayane Boussanni wrote:
> This patch implements missing validation logic for RSS and Connection
> Tracking (ConnTrack) indirect actions in the Hardware Steering (HWS)
> flow engine.
> 
> Previously, these actions were accepted without being validated
> against hardware capabilities, which could lead to unexpected behavior
> when applying flow rules. The specialist validation functions
> (mlx5_hw_validate_action_rss and mlx5_hw_validate_action_conntrack)
> already existed but were not wired up to the indirect action handler.
> 
> The signature of flow_hw_validate_action_indirect was updated to
> include the actions template attributes (attr), allowing it to pass
> the necessary traffic direction context (ingress/egress/transfer)
> to the underlying validation specialists. For indirect RSS, only the
> template attributes are validated, as the RSS configuration itself is
> already validated when the indirect action handle is created.
> 
> Reported-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
> Signed-off-by: Rayane Boussanni <rboussanni@gmail.com>
> ---
> v3:
> - Fix segfault reported by Dariusz Sosnowski when an actions template
>    references an indirect RSS action. v2 called
>    mlx5_hw_validate_action_rss() on the indirect path, which
>    dereferences action->conf as struct rte_flow_action_rss. For indirect
>    actions action->conf is an opaque action handle, not an RSS config.
>    Add bool is_indirect to mlx5_hw_validate_action_rss() so the indirect
>    path validates only the template attributes
>    (ingress/egress/transfer).
> 
>   drivers/net/mlx5/mlx5_flow_hw.c | 36 ++++++++++++++++++++++++++++++---
>   1 file changed, 33 insertions(+), 3 deletions(-)
> 

Patch applied to next-net-mlx,


Kindest regards
Raslan Darawsheh


^ permalink raw reply

* Re: [PATCH] net/mlx5: redirect LACP traffic for legacy E-Switch
From: Raslan Darawsheh @ 2026-06-04  9:34 UTC (permalink / raw)
  To: Dariusz Sosnowski, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
	Suanming Mou, Matan Azrad
  Cc: dev, stable
In-Reply-To: <20260515123700.354341-1-dsosnowski@nvidia.com>

Hi,


On 15/05/2026 3:37 PM, Dariusz Sosnowski wrote:
> Offending patch fixed the LACP miss rule logic for NICs where
> switchdev is enabled. In this case, LACP miss rules should be inserted
> if and only if started port is a main port on the embedded switch.
> Side effect of that change was that LACP miss rules are not inserted
> when switchdev is disabled and legacy SR-IOV switch mode is used.
> 
> This patch addresses that:
> 
> - Fix the LACP rule insertion condition.
> - Move HWS table for LACP rule creation out of FDB rules,
>    so they can be created separately.
> 
> Fixes: 87e4384d2662 ("net/mlx5: fix condition of LACP miss flow")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>

Patch applied to next-net-mlx,

Kindest regards
Raslan Darawsheh


^ permalink raw reply

* Re: [PATCH] net/mlx5: fix uninitialized skip count
From: Raslan Darawsheh @ 2026-06-04  9:35 UTC (permalink / raw)
  To: Dariusz Sosnowski, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
	Suanming Mou, Matan Azrad, Alexander Kozyrev
  Cc: dev, Kiran Vedere, stable
In-Reply-To: <20260515123358.354191-1-dsosnowski@nvidia.com>

Hi,


On 15/05/2026 3:33 PM, Dariusz Sosnowski wrote:
> From: Kiran Vedere <kiranv@nvidia.com>
> 
> mlx5_rx_poll_len() may return MLX5_ERROR_CQE_MASK when
> mlx5_rx_err_handle() reports MLX5_CQE_STATUS_HW_OWN while the Rx queue
> is in IGNORE error state. In this HW_OWN case mlx5_rx_err_handle()
> does not necessarily write to *skip_cnt, yet the caller (mlx5_rx_burst)
> unconditionally uses skip_cnt to advance rq_ci.
> 
> This can cause rq_ci to jump by an undefined value, desynchronizing the
> RQ and CQ rings and leading to persistent bad packet delivery until the
> queue is reset.
> 
> Fixes: aa67ed308458 ("net/mlx5: ignore non-critical syndromes for Rx queue")
> Cc: akozyrev@nvidia.com
> Cc: stable@dpdk.org
> 
> Signed-off-by: Kiran Vedere <kiranv@nvidia.com>
> Acked-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Patch applied to next-net-mlx,

Kindest regards
Raslan Darawsheh


^ permalink raw reply

* Re: [PATCH] net/mlx5: remove nonsensical flow action class_id checks
From: Raslan Darawsheh @ 2026-06-04  9:36 UTC (permalink / raw)
  To: Adrian Schollmeyer, Dariusz Sosnowski, Viacheslav Ovsiienko,
	Bing Zhao, Ori Kam, Suanming Mou, Matan Azrad, Michael Baum
  Cc: dev, Michael Pfeiffer, stable
In-Reply-To: <20260520132533.159996-1-a.schollmeyer@syseleven.de>

Hi,


On 20/05/2026 4:25 PM, Adrian Schollmeyer wrote:
> From: Michael Pfeiffer <m.pfeiffer@syseleven.de>
> 
> For a MODIFY_FIELD action, flow_hw_validate_action_modify_field() is
> invoked and enforces class_id == 0 in the action's source and
> destination, if the modified field is none of
> RTE_FLOW_FIELD_GENEVE_OPT_*, as the value is used solely for GENEVE
> fields.
> 
> However, this check is flawed due to the way rte_flow_field_data is
> initialized. As it consists of unions and anonymous structs as members,
> empty initialization of this struct or initializing just the tag_index
> only guarantees initialization of the first union member, while the
> remaining member's default initialization behavior is unspecified.
> Therefore, depending on the compiler type, version and configuration,
> the remaining members may either be default-initialized as well or
> contain bytes from uninitialized memory. This causes the check to fail
> depending on how the struct is initialized wherever it is used.
> 
> For example, rte_flow_configure() sometimes fails on mlx5 under these
> circumstances with an error "destination class id is not supported"
> during creation of representor tagging rules, as these internally use
> MODIFY_FIELD actions in the following call stack:
> 
>    1. rte_flow_configure
>    2. mlx5_flow_port_configure
>    3. flow_hw_configure
>    4. __flow_hw_configure
>    5. flow_hw_setup_tx_repr_tagging
>    6. flow_hw_create_tx_repr_tag_jump_acts_tmpl
>       --> various rte_flow_action_modify_field are initialized here, but
>           class_id remains uninitialized
>    7. __flow_hw_actions_template_create
>    8. mlx5_flow_hw_actions_validate
>    9. flow_hw_validate_action_modify_field
>       --> invoked with class_id containing uninitialized bytes and
>           non-GENEVE field type
> 
> Remove the two checks for class_id in the non-GENEVE case, as this field
> is unused for these actions and avoids additional implicit dependencies
> on the correct ordering of union members.
> 
> Fixes: 1caa89ec1891 ("net/mlx5: support GENEVE options modification")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Michael Pfeiffer <m.pfeiffer@syseleven.de>
> Signed-off-by: Adrian Schollmeyer <a.schollmeyer@syseleven.de>

Patch applied to next-net-mlx,

Kindest regards
Raslan Darawsheh


^ permalink raw reply

* Re: [PATCH v2] net/mlx5: use port index as representor index
From: Raslan Darawsheh @ 2026-06-04  9:36 UTC (permalink / raw)
  To: Dariusz Sosnowski, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
	Suanming Mou, Matan Azrad
  Cc: dev, stable
In-Reply-To: <20260525091733.558838-1-dsosnowski@nvidia.com>

Hi,


On 25/05/2026 12:17 PM, Dariusz Sosnowski wrote:
> Since the offending commit, mlx5 driver supports probing
> representors on BlueField DPUs with Socket Direct (SD).
> Such card can be connected to 2 different CPUs on the host system.
> On DPU, user would see the following network devices:
> 
> - p0 and p1 - physical ports
> - pf0hpf and pf2hpf - PF0 on CPU 0 and CPU 1 respectively
> - pf1hpf and pf3hpf - PF1 on CPU 0 and CPU 1 respectively
> 
> mlx5 driver finds the relevant netdev by matching information
> provided in representor devarg to phys_port_name
> reported by Linux kernel.
> For the above interfaces phys_port_name's would be reported
> and probed as:
> 
> - p0 -> p0, no need for representor devarg
> - p1 -> p1, with representor=pf1
> - pf0hpf -> c1pf0, with representor=c1pf0vf65535
> - pf1hpf -> c1pf1, with representor=c1pf1vf65535
> - pf2hpf -> c2pf0, with representor=c2pf0vf65535
> - pf3hpf -> c2pf1, with representor=c2pf1vf65535
> 
> Although hot-plugging all these representors is successful,
> RTE_ETH_FOREACH_MATCHING_DEV() macro would not find DPDK ports.
> This is caused missing information reported by mlx5 driver,
> through rte_eth_representor_info_get() API.
> Specifically, mlx5 driver did not report controller index for all
> representor ranges.
> 
> Until now mlx5 driver used static encoding for 16-bit representor_id:
> 
> - 2 bits for representor type
> - 2 bits for PF index
> - 12 bits for representor index (either VF or SF number)
> 
> Controller index was not encoded. This caused the mentioned issue
> and on top of that:
> 
> - limits the number of PFs
> - limits the number of SFs
> 
> This patch changes the mlx5 driver logic for
> rte_eth_representor_info_get().
> Instead of static encoding:
> 
> - representor_id's will be dynamically assigned
>    to each probed representor.
> - rte_eth_representor_info_get() will report N ranges:
>      - N == number of probed ports on single embedded switch
>      - Each range will define single representor_id
>        for given controller/PF/VF/SF.
> 
> Fixes: 2f7cdd821b1b ("net/mlx5: fix probing to allow BlueField Socket Direct")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
> Acked-by: Bing Zhao <bingz@nvidia.com>
> ---
> v2:
> - Added missing "not" in "RTE_ETH_FOREACH_MATCHING_DEV() macro would not find DPDK ports"
>    in the commit message.
> - Fixed typo in number of bits for representor index.
>    Should be 12, not 2.
> 
>   drivers/net/mlx5/linux/mlx5_os.c |   6 +-
>   drivers/net/mlx5/mlx5.h          |  19 +++
>   drivers/net/mlx5/mlx5_ethdev.c   | 284 +++++++++++++++++++------------
>   3 files changed, 199 insertions(+), 110 deletions(-)
> 
--

Patch applied to next-net-mlx,

Kindest regards
Raslan Darawsheh


^ permalink raw reply

* Re: [PATCH v5] net/mlx5: prepend implicit items in sync flow creation path
From: Raslan Darawsheh @ 2026-06-04  9:37 UTC (permalink / raw)
  To: Maxime Peim, dev; +Cc: dsosnowski, viacheslavo, bingz, orika, suanmingm, matan
In-Reply-To: <20260527103531.1266488-1-maxime.peim@gmail.com>

Hi,


On 27/05/2026 1:35 PM, Maxime Peim wrote:
> In eSwitch mode, the async (template) flow creation path automatically
> prepends implicit match items to scope flow rules to the correct
> representor port:
>    - Ingress: REPRESENTED_PORT item matching dev->data->port_id
>    - Egress: REG_C_0 TAG item matching the port's tx tag value
> 
> The sync path (flow_hw_list_create) was missing this logic, causing all
> flow rules created via the non-template API to match traffic from all
> ports rather than being scoped to the specific representor.
> 
> Add the same implicit item prepending to flow_hw_list_create, right
> after pattern validation and before any branching (sample/RSS/single/
> prefix), mirroring the behavior of flow_hw_pattern_template_create
> and flow_hw_get_rule_items. The ingress case prepends
> REPRESENTED_PORT with the current port_id; the egress case prepends
> MLX5_RTE_FLOW_ITEM_TYPE_TAG with REG_C_0 value/mask (skipped when
> user provides an explicit SQ item).
> 
> Also fix a pre-existing bug where 'return split' on metadata split
> failure returned a negative int cast to uintptr_t, which callers
> would treat as a valid flow handle instead of an error.
> 
> Fixes: e38776c36c8a ("net/mlx5: introduce HWS for non-template flow API")
> Fixes: 821a6a5cc495 ("net/mlx5: add metadata split for compatibility")
> Signed-off-by: Maxime Peim <maxime.peim@gmail.com>
> ---
> v3:
>    - Factor the implicit-item prepend logic out of
>      flow_hw_pattern_template_create() into a new helper
>      flow_hw_adjust_pattern() and reuse it from flow_hw_list_create(),
>      instead of duplicating the prepend logic inline in the sync path.
>    - Zero-initialize item_flags in both callers. The validator is
>      read-modify-write on item_flags (reads MLX5_FLOW_LAYER_TUNNEL on
>      the first iteration), so leaving it uninitialized was UB.
>    - Call __flow_hw_pattern_validate() with nt_flow=true from the sync
>      path (was effectively nt_flow=false via the wrapper), restoring the
>      previous behavior that skips GENEVE_OPT TLV parser validation on
>      the non-template path.
>    - Document flow_hw_adjust_pattern(): the dual role of the nt_flow
>      parameter (template spec-left-zero vs. sync spec-filled + validator
>      flag), the three-way return, and the caller's ownership of
>      *copied_items across every exit path.
>    - Clarify the "omitting implicit REG_C_0 match" debug log now that
>      the helper runs on both the template and sync paths.
>    - Add Fixes: tags for the two original commits.
> 
> v4:
>    - Fix items in case splitted metadata are not needed.
> 
> v5:
>    - Make flow_hw_prepend_item() return a self-contained array. The
>      helper used to shallow-copy the prepended item, leaving its
>      .spec/.mask pointing at flow_hw_adjust_pattern()'s stack locals
>      (port_spec, tag_v, tag_m); once that frame returned, the
>      consumers in flow_hw_list_create() (sample / RSS / single create)
>      and the post-extraction template path dereferenced dangling
>      pointers. The prepended item is now deep-copied via
>      rte_flow_conv(RTE_FLOW_CONV_OP_ITEM, ...) into the tail of the
>      same mlx5_malloc() block, so the lifetime of every byte the
>      consumer can reach equals the lifetime of the returned array.
>      items[] continue to be shallow-copied (their spec/mask blobs are
>      application-owned and outlive the call). One alloc, one free; no
>      call-site or signature changes.
>    - Fix the &item_flags / &orig_item_nb argument order at both
>      flow_hw_adjust_pattern() call sites (introduced in v3 by the
>      helper extraction): the prior order silently stored the item
>      count into it->item_flags / the layer-flag arguments forwarded
>      into mlx5_nta_sample_flow_list_create / mlx5_flow_nta_handle_rss /
>      mlx5_flow_hw_create_flow, and stored the OR-accumulated layer
>      flags into it->orig_item_nb / per-rule item-count uses.
> 
>   drivers/net/mlx5/mlx5_flow_hw.c | 262 +++++++++++++++++++++++---------
>   1 file changed, 194 insertions(+), 68 deletions(-)
> 
--
Patch applied to next-net-mlx,

Kindest regards
Raslan Darawsheh


^ permalink raw reply

* Re: [PATCH v2] net/mlx5: promote private API to stable
From: Raslan Darawsheh @ 2026-06-04  9:38 UTC (permalink / raw)
  To: Dariusz Sosnowski, Viacheslav Ovsiienko, Bing Zhao, Ori Kam,
	Suanming Mou, Matan Azrad
  Cc: dev
In-Reply-To: <20260529073255.689808-1-dsosnowski@nvidia.com>

Hi,


On 29/05/2026 10:32 AM, Dariusz Sosnowski wrote:
> Following experimental functions are exposed by mlx5 PMD
> since 25.11 release:
> 
> - rte_pmd_mlx5_driver_event_cb_register
> - rte_pmd_mlx5_driver_event_cb_unregister
> - rte_pmd_mlx5_enable_steering
> - rte_pmd_mlx5_disable_steering
> 
> First two are used to register callbacks for driver events
> (when Rx/Tx queues are created or destroyed).
> Other two are used to enable/disable flow steering in mlx5 PMD.
> No changes were made and no changes are planned to these symbols.
> 
> These are currently used by NVIDIA DOCA SDK since version 3.3,
> which started depending on upstream DPDK releases [1].
> Purpose of their use is to:
> 
> - expose HW identifiers of Rx/Tx mlx5 queues managed by DPDK and
> - allow flow steering to happen outside of DPDK.
> 
> Also, some of these symbols will be used by netdev-doca backend
> in Open vSwitch [2].
> Whenever a DOCA netdev would be added/removed in Open vSwitch,
> it will have to disable/enable steering for mlx5 driver.
> Stabilizing these symbols is required by current OVS policy
> to remove the need for ALLOW_EXPERIMENTAL_API [3].
> 
> This patch promotes aforementioned symbols to stable.
> 
> [1]: https://docs.nvidia.com/doca/sdk/customer-affecting-changes/index.html
> [2]: https://patchwork.ozlabs.org/project/openvswitch/list/?series=504726&state=%2A&archive=both
> [3]: https://mail.openvswitch.org/pipermail/ovs-dev/2026-May/432066.html
> 
> Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
> ---
> v2:
> - Updated 26.07 release notes.
> 
>   doc/guides/rel_notes/release_26_07.rst | 9 +++++++++
>   drivers/net/mlx5/mlx5_driver_event.c   | 4 ++--
>   drivers/net/mlx5/mlx5_flow.c           | 4 ++--
>   drivers/net/mlx5/rte_pmd_mlx5.h        | 4 ----
>   4 files changed, 13 insertions(+), 8 deletions(-)
> 
--

Patch applied to next-net-mlx,

Kindest regards
Raslan Darawsheh


^ permalink raw reply


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