Skip to contentSkip to conversation

Consolidate ice and iavf vector Tx paths

PATCH Superseded Bruce Richardson 3 participants 69 messages Sep 3 – Sep 16

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Consolidate ice and iavf vector Tx paths

This patchset consolidates the ice and iavf vector Tx paths, moving the code to net/intel/common. The iavf code is used as the basis for the move, because it has a superset of the features. When the common code is adopted by the ice driver, it then gains features such as QinQ support and tunneling support.

Depends-on: series-39162 ("VLAN and QinQ fixes for iavf")

Bruce Richardson (13):
net/iavf: remove unnecessary alignment calls net/intel: make Tx context flag common
net/iavf: use separate params for VLAN and QinQ position net/iavf: deduplicate tunnel field fill functions net/intel: define common macros for tunneling bit-shifts net/intel: move iavf descriptor writing functions to common net/intel: use function callback for lldp net/ice: use common descriptor creation functions net/intel: move vector Tx paths to common net/ice: use common AVX Tx functions
net/intel: add common vector Tx fns with context handling net/intel: improve Tx path selection logic net/ice: enable context desc offloads for vector Tx

 doc/guides/rel_notes/release_26_11.rst        |   6 +
 drivers/net/intel/common/tx.h                 |  77 +-
 drivers/net/intel/common/tx_vec_x86.h         | 783 ++++++++++++++++++
 drivers/net/intel/cpfl/cpfl_rxtx.c            |   3 +-
 drivers/net/intel/i40e/i40e_rxtx.c            |   2 +-
 drivers/net/intel/iavf/iavf_rxtx.c            |  76 +-
 drivers/net/intel/iavf/iavf_rxtx.h            |  34 -
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 496 +----------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 495 +----------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  76 +-
 drivers/net/intel/ice/ice_ethdev.h            |   3 +
 drivers/net/intel/ice/ice_rxtx.c              |  34 +-
 drivers/net/intel/ice/ice_rxtx.h              |  11 +
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c     | 159 +---
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c   | 154 +---
 drivers/net/intel/ice/ice_rxtx_vec_common.h   |  59 --
 drivers/net/intel/idpf/idpf_rxtx.c            |   3 +-
 17 files changed, 1025 insertions(+), 1446 deletions(-)
 create mode 100644 drivers/net/intel/common/tx_vec_x86.h

--
2.53.0

#1 lore raw

PATCH 1/13 net/iavf: remove unnecessary alignment calls

When we have a context descriptor on Tx of a packet from the vector paths, that means that we always have 32-bytes being written per descriptor/per packet, so the stores are always 32-bit aligned. This means we can use aligned stores for each single descriptor store, and that we never need to do an initial descriptor write for alignment when doing a burst of descriptors.

---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 9 ++-------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 9 ++-------
 2 files changed, 4 insertions(+), 14 deletions(-)
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +2 -7
index 7217f32cef..9b62ef53d3 100644
@@ -1933,7 +1933,8 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
 							high_ctx_qw, low_ctx_qw);
 
-	_mm256_storeu_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
 }
 
 static __rte_always_inline void
@@ -1944,12 +1945,6 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 	uint64_t hi_data_qw_tmpl = (IAVF_TX_DESC_DTYPE_DATA |
 					((uint64_t)flags  << IAVF_TXD_QW1_CMD_SHIFT));
 
-	/* if unaligned on 32-bit boundary, do one to align */
-	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		ctx_vtx1(txdp, *pkt, flags, offload, vlan_flag, ptype_lldp_enabled);
-		nb_pkts--; txdp++; pkt++;
-	}
-
 	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
 		uint64_t hi_ctx_qw1 = IAVF_TX_DESC_DTYPE_CONTEXT;
 		uint64_t hi_ctx_qw0 = IAVF_TX_DESC_DTYPE_CONTEXT;
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +2 -7
index bf0245e8f4..4609c2245a 100644
@@ -2078,7 +2078,8 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
 							high_ctx_qw, low_ctx_qw);
 
-	_mm256_storeu_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
 }
 
 static __rte_always_inline void
@@ -2088,12 +2089,6 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 {
 	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
 
-	/* if unaligned on 32-bit boundary, do one to align */
-	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		ctx_vtx1(txdp, *pkt, flags, offload, vlan_flag, lldp_enabled);
-		nb_pkts--; txdp++; pkt++;
-	}
-
 	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
 		uint64_t hi_ctx_qw1 = IAVF_TX_DESC_DTYPE_CONTEXT;
 		uint64_t hi_ctx_qw0 = IAVF_TX_DESC_DTYPE_CONTEXT;
Signature · 1 line
2.53.0
Acked-by on v1 1/13
#2 lore raw

RE: [PATCH 01/13] net/iavf: remove unnecessary alignment calls

Quoted 10 lines

Subject: [PATCH 01/13] net/iavf: remove unnecessary alignment calls

When we have a context descriptor on Tx of a packet from the vector paths, that means that we always have 32-bytes being written per descriptor/per packet, so the stores are always 32-bit aligned. This means we can use aligned stores for each single descriptor store, and that we never need to do an initial descriptor write for alignment when doing a burst of descriptors.

Quoted 5 lines
---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 9 ++-------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 9 ++-------
 2 files changed, 4 insertions(+), 14 deletions(-)
#3 lore raw

PATCH 2/13 net/intel: make Tx context flag common

In reply to Bruce Richardson

The flag for enabling context descriptors in the vector paths should not be limited to just the iavf driver, as other drivers may use context paths in future also. Therefore move the flag out of the iavf-specific part of the Tx queue structure, to put with other standard queue flags.

---
 drivers/net/intel/common/tx.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/intel/common/tx.h +1 -1
index 2d4a8b5d3c..fb5268c972 100644
@@ -173,6 +173,7 @@ struct ci_tx_queue {
 	bool tx_deferred_start; /* don't start this queue in dev start */
 	bool q_set;             /* indicate if tx queue has been configured */
 	bool use_vec_entry;     /* use sw_ring_vec (true for vector and simple paths) */
+	bool use_ctx;           /* with ctx info, each pkt needs two desc in vec paths */
 	union {                  /* the VSI this queue belongs to */
 		struct i40e_vsi *i40e_vsi;
 		struct iavf_vsi *iavf_vsi;
@@ -194,7 +195,6 @@ struct ci_tx_queue {
 #define IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 BIT(1)
 			uint8_t vlan_flag;
 			uint8_t tc;
-			bool use_ctx;  /* with ctx info, each pkt needs two descriptors */
 			bool lldp_enabled;
 		};
 		struct { /* ixgbe specific values */
Signature · 1 line
2.53.0
Acked-by on v1 2/13
#4 lore raw

RE: [PATCH 02/13] net/intel: make Tx context flag common

Quoted 8 lines

Subject: [PATCH 02/13] net/intel: make Tx context flag common

The flag for enabling context descriptors in the vector paths should not be limited to just the iavf driver, as other drivers may use context paths in future also. Therefore move the flag out of the iavf-specific part of the Tx queue structure, to put with other standard queue flags.

Quoted 27 lines
---
 drivers/net/intel/common/tx.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/intel/common/tx.h +0 -0
index 2d4a8b5d3c..fb5268c972 100644
@@ -173,6 +173,7 @@ struct ci_tx_queue {
 	bool tx_deferred_start; /* don't start this queue in dev start */
 	bool q_set;             /* indicate if tx queue has been configured */
 	bool use_vec_entry;     /* use sw_ring_vec (true for vector and simple

paths) */

drivers/net/intel/common/tx.h +1 -0
+	bool use_ctx;           /* with ctx info, each pkt needs two desc in vec

paths */

drivers/net/intel/common/tx.h +0 -1
 	union {                  /* the VSI this queue belongs to */
 		struct i40e_vsi *i40e_vsi;
 		struct iavf_vsi *iavf_vsi;
@@ -194,7 +195,6 @@ struct ci_tx_queue {
 #define IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 BIT(1)
 			uint8_t vlan_flag;
 			uint8_t tc;
-			bool use_ctx;  /* with ctx info, each pkt needs two

descriptors */

drivers/net/intel/common/tx.h +0 -0
 			bool lldp_enabled;
 		};
 		struct { /* ixgbe specific values */
#5 lore raw

PATCH 3/13 net/iavf: use separate params for VLAN and QinQ position

In reply to Bruce Richardson

Like is the case with the scalar path, use separate offload parameters for the vector path to distinguish between the position of the single VLAN tag and the QinQ outer tag. With iavf these are currently always the same, but other drivers - with whom we may want to share code - have different positions for these.

---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 64 +++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 62 ++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h | 13 ++--
 3 files changed, 79 insertions(+), 60 deletions(-)
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +37 -27
index 9b62ef53d3..2aaa713702 100644
@@ -1619,13 +1619,14 @@ iavf_recv_scattered_pkts_vec_avx2_flex_rxd_offload(void *rx_queue,
 
 static __rte_always_inline void
 iavf_vtx1(volatile struct ci_tx_desc *txdp,
-	  struct rte_mbuf *pkt, uint64_t flags, bool offload, uint8_t vlan_flag)
+	  struct rte_mbuf *pkt, uint64_t flags, bool offload,
+	  enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
 {
 	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
 		 ((uint64_t)flags << CI_TXD_QW1_CMD_S) |
 		 ((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
 	if (offload)
-		iavf_txd_enable_offload(pkt, &high_qw, vlan_flag);
+		iavf_txd_enable_offload(pkt, &high_qw, single_vlan_pos, qinq_outer_pos);
 
 	__m128i descriptor = _mm_set_epi64x(high_qw,
 				pkt->buf_iova + pkt->data_off);
@@ -1634,13 +1635,14 @@ iavf_vtx1(volatile struct ci_tx_desc *txdp,
 
 static __rte_always_inline void
 iavf_vtx(volatile struct ci_tx_desc *txdp,
-	 struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload, uint8_t vlan_flag)
+	 struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload,
+	 enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
 {
 	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
 
 	/* if unaligned on 32-bit boundary, do one to align */
 	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		iavf_vtx1(txdp, *pkt, flags, offload, vlan_flag);
+		iavf_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
 		nb_pkts--; txdp++; pkt++;
 	}
 
@@ -1649,19 +1651,19 @@ iavf_vtx(volatile struct ci_tx_desc *txdp,
 		uint64_t hi_qw3 = hi_qw_tmpl |
 			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[3], &hi_qw3, vlan_flag);
+			iavf_txd_enable_offload(pkt[3], &hi_qw3, single_vlan_pos, qinq_outer_pos);
 		uint64_t hi_qw2 = hi_qw_tmpl |
 			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[2], &hi_qw2, vlan_flag);
+			iavf_txd_enable_offload(pkt[2], &hi_qw2, single_vlan_pos, qinq_outer_pos);
 		uint64_t hi_qw1 = hi_qw_tmpl |
 			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[1], &hi_qw1, vlan_flag);
+			iavf_txd_enable_offload(pkt[1], &hi_qw1, single_vlan_pos, qinq_outer_pos);
 		uint64_t hi_qw0 = hi_qw_tmpl |
 			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[0], &hi_qw0, vlan_flag);
+			iavf_txd_enable_offload(pkt[0], &hi_qw0, single_vlan_pos, qinq_outer_pos);
 
 		__m256i desc2_3 =
 			_mm256_set_epi64x
@@ -1681,7 +1683,7 @@ iavf_vtx(volatile struct ci_tx_desc *txdp,
 
 	/* do any last ones */
 	while (nb_pkts) {
-		iavf_vtx1(txdp, *pkt, flags, offload, vlan_flag);
+		iavf_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
 		txdp++; pkt++; nb_pkts--;
 	}
 }
@@ -1697,6 +1699,9 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	/* bit2 is reserved and must be set to 1 according to Spec */
 	uint64_t flags = CI_TX_DESC_CMD_EOP | CI_TX_DESC_CMD_ICRC;
 	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
+	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
+	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
+			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
 
 	if (txq->nb_tx_free < txq->tx_free_thresh)
 		ci_tx_free_bufs_vec(txq, iavf_tx_desc_done, false);
@@ -1716,11 +1721,11 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	if (nb_commit >= n) {
 		ci_tx_backlog_entry_vec(txep, tx_pkts, n);
 
-		iavf_vtx(txdp, tx_pkts, n - 1, flags, offload, txq->vlan_flag);
+		iavf_vtx(txdp, tx_pkts, n - 1, flags, offload, vlan_pos, vlan_pos);
 		tx_pkts += (n - 1);
 		txdp += (n - 1);
 
-		iavf_vtx1(txdp, *tx_pkts++, rs, offload, txq->vlan_flag);
+		iavf_vtx1(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -1734,7 +1739,7 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_commit);
 
-	iavf_vtx(txdp, tx_pkts, nb_commit, flags, offload, txq->vlan_flag);
+	iavf_vtx(txdp, tx_pkts, nb_commit, flags, offload, vlan_pos, vlan_pos);
 
 	tx_id = (uint16_t)(tx_id + nb_commit);
 	if (tx_id > txq->tx_next_rs) {
@@ -1903,7 +1908,8 @@ iavf_fill_ctx_desc_tunneling_field(volatile uint64_t *qw0,
 
 static __rte_always_inline void
 ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
-		uint64_t flags, bool offload, uint8_t vlan_flag, bool ptype_lldp_enabled)
+		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
+		enum ci_l2tag_pos qinq_outer_pos, bool ptype_lldp_enabled)
 {
 	uint64_t high_ctx_qw = IAVF_TX_DESC_DTYPE_CONTEXT;
 	uint64_t low_ctx_qw = 0;
@@ -1911,13 +1917,13 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	if (offload) {
 		iavf_fill_ctx_desc_tunneling_avx2(&low_ctx_qw, pkt);
 		if (pkt->ol_flags & RTE_MBUF_F_TX_QINQ) {
-			uint64_t qinq_tag = vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 ?
+			uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 				(uint64_t)pkt->vlan_tci_outer :
 				(uint64_t)pkt->vlan_tci;
 			high_ctx_qw |= IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 			low_ctx_qw |= qinq_tag << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 		} else if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) &&
-				vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2) {
+				single_vlan_pos == CI_TAG_IN_CTX_DESC) {
 			high_ctx_qw |= IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 			low_ctx_qw |= (uint64_t)pkt->vlan_tci << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 		}
@@ -1928,7 +1934,7 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 				((uint64_t)flags  << IAVF_TXD_QW1_CMD_SHIFT) |
 				((uint64_t)pkt->data_len << IAVF_TXD_QW1_TX_BUF_SZ_SHIFT));
 	if (offload)
-		iavf_txd_enable_offload(pkt, &high_data_qw, vlan_flag);
+		iavf_txd_enable_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
 
 	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
 							high_ctx_qw, low_ctx_qw);
@@ -1940,7 +1946,8 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 static __rte_always_inline void
 ctx_vtx(volatile struct ci_tx_desc *txdp,
 		struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags,
-		bool offload, uint8_t vlan_flag, bool ptype_lldp_enabled)
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		bool ptype_lldp_enabled)
 {
 	uint64_t hi_data_qw_tmpl = (IAVF_TX_DESC_DTYPE_DATA |
 					((uint64_t)flags  << IAVF_TXD_QW1_CMD_SHIFT));
@@ -1964,14 +1971,14 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
 			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw1, pkt[1]);
 			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
-				uint64_t qinq_tag = vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 ?
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[1]->vlan_tci_outer :
 					(uint64_t)pkt[1]->vlan_tci;
 				hi_ctx_qw1 |= IAVF_TX_CTX_DESC_IL2TAG2 <<
 						IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw1 |= qinq_tag << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 			} else if (pkt[1]->ol_flags & RTE_MBUF_F_TX_VLAN &&
-					vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2) {
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
 				hi_ctx_qw1 |=
 					IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw1 |=
@@ -1985,14 +1992,14 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
 			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw0, pkt[0]);
 			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
-				uint64_t qinq_tag = vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 ?
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[0]->vlan_tci_outer :
 					(uint64_t)pkt[0]->vlan_tci;
 				hi_ctx_qw0 |= IAVF_TX_CTX_DESC_IL2TAG2 <<
 						IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw0 |= qinq_tag << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 			} else if (pkt[0]->ol_flags & RTE_MBUF_F_TX_VLAN &&
-					vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2) {
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
 				hi_ctx_qw0 |=
 					IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw0 |=
@@ -2003,8 +2010,8 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 
 		if (offload) {
-			iavf_txd_enable_offload(pkt[1], &hi_data_qw1, vlan_flag);
-			iavf_txd_enable_offload(pkt[0], &hi_data_qw0, vlan_flag);
+			iavf_txd_enable_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
+			iavf_txd_enable_offload(pkt[0], &hi_data_qw0, single_vlan_pos, qinq_outer_pos);
 		}
 
 		__m256i desc2_3 =
@@ -2020,7 +2027,7 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 	}
 
 	if (nb_pkts)
-		ctx_vtx1(txdp, *pkt, flags, offload, vlan_flag, ptype_lldp_enabled);
+		ctx_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos, ptype_lldp_enabled);
 }
 
 static __rte_always_inline uint16_t
@@ -2035,6 +2042,9 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	uint64_t flags = IAVF_TX_DESC_CMD_EOP | IAVF_TX_DESC_CMD_ICRC;
 	uint64_t rs = IAVF_TX_DESC_CMD_RS | flags;
 	bool lldp_enabled = txq->lldp_enabled;
+	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
+	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
+			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
 
 	if (txq->nb_tx_free < txq->tx_free_thresh)
 		ci_tx_free_bufs_vec(txq, iavf_tx_desc_done, true);
@@ -2057,10 +2067,10 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 		nb_mbuf = n >> 1;
 		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
-		ctx_vtx(txdp, tx_pkts, nb_mbuf - 1, flags, offload, txq->vlan_flag, lldp_enabled);
+		ctx_vtx(txdp, tx_pkts, nb_mbuf - 1, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
 		tx_pkts += (nb_mbuf - 1);
 		txdp += (n - 2);
-		ctx_vtx1(txdp, *tx_pkts++, rs, offload, txq->vlan_flag, lldp_enabled);
+		ctx_vtx1(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_enabled);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -2074,7 +2084,7 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	nb_mbuf = nb_commit >> 1;
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
-	ctx_vtx(txdp, tx_pkts, nb_mbuf, flags, offload, txq->vlan_flag, lldp_enabled);
+	ctx_vtx(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
 	tx_id = (uint16_t)(tx_id + nb_commit);
 
 	if (tx_id > txq->tx_next_rs) {
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +35 -27

200 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_common.h +7 -6
index 1e9ce924ee..74446fcf4a 100644
@@ -121,14 +121,13 @@ iavf_tx_vec_dev_check_default(struct rte_eth_dev *dev)
 
 static __rte_always_inline void
 iavf_txd_enable_offload(__rte_unused struct rte_mbuf *tx_pkt,
-			uint64_t *txd_hi, uint8_t vlan_flag)
+			uint64_t *txd_hi, enum ci_l2tag_pos single_vlan_pos,
+			enum ci_l2tag_pos qinq_outer_pos)
 {
 	uint64_t ol_flags = tx_pkt->ol_flags;
 	uint32_t td_cmd = 0;
 	uint32_t td_offset = 0;
 
-	RTE_SET_USED(vlan_flag);
-
 	/* Set MACLEN */
 	if (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)
 		td_offset |= (tx_pkt->outer_l2_len >> 1)
@@ -179,12 +178,14 @@ iavf_txd_enable_offload(__rte_unused struct rte_mbuf *tx_pkt,
 
 	if (ol_flags & RTE_MBUF_F_TX_QINQ) {
 		td_cmd |= IAVF_TX_DESC_CMD_IL2TAG1;
-		/* vlan_flag specifies outer tag location for QinQ. */
-		if (vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1)
+		/* L2Tag1 always carries a tag for QinQ: the outer tag if that's
+		 * where it is placed, otherwise the inner.
+		 */
+		if (qinq_outer_pos == CI_TAG_IN_DATA_DESC)
 			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci_outer << CI_TXD_QW1_L2TAG1_S);
 		else
 			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
-	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) {
+	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && single_vlan_pos == CI_TAG_IN_DATA_DESC) {
 		td_cmd |= CI_TX_DESC_CMD_IL2TAG1;
 		*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
 	}
Signature · 1 line
2.53.0
Acked-by on v1 3/13
#6 lore raw

RE: [PATCH 03/13] net/iavf: use separate params for VLAN and QinQ position

Quoted 16 lines

Subject: [PATCH 03/13] net/iavf: use separate params for VLAN and QinQ position

Like is the case with the scalar path, use separate offload parameters for the vector path to distinguish between the position of the single VLAN tag and the QinQ outer tag. With iavf these are currently always the same, but other drivers - with whom we may want to share code - have different positions for these.

---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 64 +++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 62 ++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h | 13 ++--
 3 files changed, 79 insertions(+), 60 deletions(-)

<snip>

Quoted 24 lines
drivers/net/intel/iavf/iavf_rxtx_vec_common.h +2 -3
index 1e9ce924ee..74446fcf4a 100644
@@ -121,14 +121,13 @@ iavf_tx_vec_dev_check_default(struct rte_eth_dev
 *dev)
 
 static __rte_always_inline void
 iavf_txd_enable_offload(__rte_unused struct rte_mbuf *tx_pkt,
-			uint64_t *txd_hi, uint8_t vlan_flag)
+			uint64_t *txd_hi, enum ci_l2tag_pos single_vlan_pos,
+			enum ci_l2tag_pos qinq_outer_pos)
 {
 	uint64_t ol_flags = tx_pkt->ol_flags;
 	uint32_t td_cmd = 0;
 	uint32_t td_offset = 0;
 
-	RTE_SET_USED(vlan_flag);
-
 	/* Set MACLEN */
 	if (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)
drivers/net/intel/iavf/iavf_rxtx_vec_common.h +0 -0
 		td_offset |= (tx_pkt->outer_l2_len >> 1)

drivers/net/intel/iavf/iavf_rxtx_vec_common.h iavf_txd_enable_offload(__rte_unused struct · line 184

Quoted 9 lines
drivers/net/intel/iavf/iavf_rxtx_vec_common.h +3 -2
@@ -179,12 +178,14 @@ iavf_txd_enable_offload(__rte_unused struct
 rte_mbuf *tx_pkt,
 
 	if (ol_flags & RTE_MBUF_F_TX_QINQ) {
 		td_cmd |= IAVF_TX_DESC_CMD_IL2TAG1;
-		/* vlan_flag specifies outer tag location for QinQ. */
-		if (vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1)
+		/* L2Tag1 always carries a tag for QinQ: the outer tag if that's
+		 * where it is placed, otherwise the inner.
+		 */

Nit: I feel like the sentence after the colon is unnecessary and states the obvious. Code LGTM.

Quoted 14 lines
drivers/net/intel/iavf/iavf_rxtx_vec_common.h +1 -1
+		if (qinq_outer_pos == CI_TAG_IN_DATA_DESC)
 			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci_outer <<
 CI_TXD_QW1_L2TAG1_S);
 		else
 			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci <<
 CI_TXD_QW1_L2TAG1_S);
-	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && vlan_flag &

IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) {

drivers/net/intel/iavf/iavf_rxtx_vec_common.h +1 -0
+	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && single_vlan_pos ==

CI_TAG_IN_DATA_DESC) {

drivers/net/intel/iavf/iavf_rxtx_vec_common.h +0 -0
 		td_cmd |= CI_TX_DESC_CMD_IL2TAG1;
 		*txd_hi |= ((uint64_t)tx_pkt->vlan_tci <<

CI_TXD_QW1_L2TAG1_S);
}

#7 lore raw

PATCH 4/13 net/iavf: deduplicate tunnel field fill functions

In reply to Bruce Richardson

Each of the avx2 and avx512 Tx functions used two separate subfunctions to insert the tunneling fields into the context descriptor. Except for some minor differences (a flags guard on one) the two were identical, so remove the one missing the additional guard.

---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 77 +------------------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 77 +------------------
 2 files changed, 4 insertions(+), 150 deletions(-)
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +2 -75
index 2aaa713702..10e96a8510 100644
@@ -1833,79 +1833,6 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 	}
 }
 
-static inline void
-iavf_fill_ctx_desc_tunneling_field(volatile uint64_t *qw0,
-		const struct rte_mbuf *m)
-{
-	uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
-	uint64_t eip_len = 0;
-	uint64_t eip_noinc = 0;
-	/* Default - IP_ID is increment in each segment of LSO */
-
-	switch (m->ol_flags & (RTE_MBUF_F_TX_OUTER_IPV4 |
-			RTE_MBUF_F_TX_OUTER_IPV6 |
-			RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
-	case RTE_MBUF_F_TX_OUTER_IPV4:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
-		eip_len = m->outer_l3_len >> 2;
-	break;
-	case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
-		eip_len = m->outer_l3_len >> 2;
-	break;
-	case RTE_MBUF_F_TX_OUTER_IPV6:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
-		eip_len = m->outer_l3_len >> 2;
-	break;
-	}
-
-	/* L4TUNT: L4 Tunneling Type */
-	switch (m->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
-	case RTE_MBUF_F_TX_TUNNEL_IPIP:
-		/* for non UDP / GRE tunneling, set to 00b */
-		break;
-	case RTE_MBUF_F_TX_TUNNEL_VXLAN:
-	case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
-	case RTE_MBUF_F_TX_TUNNEL_GTP:
-	case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-		eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
-		break;
-	case RTE_MBUF_F_TX_TUNNEL_GRE:
-		eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
-		break;
-	default:
-		PMD_TX_LOG(ERR, "Tunnel type not supported");
-		return;
-	}
-
-	/* L4TUNLEN: L4 Tunneling Length, in Words
-	 *
-	 * We depend on app to set rte_mbuf.l2_len correctly.
-	 * For IP in GRE it should be set to the length of the GRE
-	 * header;
-	 * For MAC in GRE or MAC in UDP it should be set to the length
-	 * of the GRE or UDP headers plus the inner MAC up to including
-	 * its last Ethertype.
-	 * If MPLS labels exists, it should include them as well.
-	 */
-	eip_typ |= (m->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
-
-	/**
-	 * Calculate the tunneling UDP checksum.
-	 * Shall be set only if L4TUNT = 01b and EIPT is not zero
-	 */
-	if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV6 |
-				IAVF_TX_CTX_EXT_IP_IPV4 |
-				IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-			(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
-			(m->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-		eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
-
-	*qw0 = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-		eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-		eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
-}
-
 static __rte_always_inline void
 ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
@@ -1969,7 +1896,7 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
-			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw1, pkt[1]);
+			iavf_fill_ctx_desc_tunneling_avx2(&low_ctx_qw1, pkt[1]);
 			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
 				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[1]->vlan_tci_outer :
@@ -1990,7 +1917,7 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
-			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw0, pkt[0]);
+			iavf_fill_ctx_desc_tunneling_avx2(&low_ctx_qw0, pkt[0]);
 			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
 				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[0]->vlan_tci_outer :
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +2 -75

95 lines not on this page · raw message

Signature · 1 line
2.53.0
Reviewed-by on v1 4/13
#8 lore raw

Re: [PATCH 04/13] net/iavf: deduplicate tunnel field fill functions

Quoted 7 lines · Bruce Richardson

Each of the avx2 and avx512 Tx functions used two separate subfunctions to insert the tunneling fields into the context descriptor. Except for some minor differences (a flags guard on one) the two were identical, so remove the one missing the additional guard.

Thanks for the cleanup.

Signature · 1 line
David Marchand
#9 lore raw

PATCH 5/13 net/intel: define common macros for tunneling bit-shifts

In reply to Bruce Richardson

Define common macros for use in iavf (for now) and other drivers (future) defining the shifts needed for tunnel packet Tx

---
 drivers/net/intel/common/tx.h                 | 24 +++++++++++++
 drivers/net/intel/iavf/iavf_rxtx.c            | 30 ++++++++--------
 drivers/net/intel/iavf/iavf_rxtx.h            | 34 -------------------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 30 ++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 30 ++++++++--------
 5 files changed, 69 insertions(+), 79 deletions(-)
drivers/net/intel/common/tx.h +24 -0
index fb5268c972..c8fadee712 100644
@@ -45,6 +45,30 @@
 #define CI_TX_CTX_DESC_TSYN             0x02
 #define CI_TX_CTX_DESC_IL2TAG2          0x04
 
+/* Common TX Context Descriptor QW0 Field Shifts */
+#define CI_TXD_CTX_QW0_L2TAG2_S         32
+#define CI_TXD_CTX_QW0_EIPT_S           0  /* 2 BITS - external IP type */
+#define CI_TXD_CTX_QW0_EIPLEN_S         2  /* 7 BITS - external IP header length */
+#define CI_TXD_CTX_QW0_NATT_S           9  /* 2 BITS - L4 tunnel type */
+#define CI_TXD_CTX_QW0_EIP_NOINC_S      11 /* 1 BIT  - external IP ID not incremented */
+#define CI_TXD_CTX_QW0_NATLEN_S         12 /* 7 BITS - L4 tunnel header length */
+#define CI_TXD_CTX_QW0_L4T_CS_S         23 /* 1 BIT  - tunnel UDP checksum enable */
+
+/**
+ * Enum for the external (outer) IP type field of a Tx context descriptor's
+ * tunnel parameters (QW0 bits 0-1).
+ */
+enum ci_tx_ctx_eipt {
+	CI_TX_CTX_EIPT_NONE,
+	CI_TX_CTX_EIPT_IPV6,
+	CI_TX_CTX_EIPT_IPV4_NO_CSUM,
+	CI_TX_CTX_EIPT_IPV4,
+};
+
+#define CI_TXD_CTX_UDP_TUNNELING        (0x1ULL << CI_TXD_CTX_QW0_NATT_S)
+#define CI_TXD_CTX_GRE_TUNNELING        (0x2ULL << CI_TXD_CTX_QW0_NATT_S)
+#define CI_TXD_CTX_QW0_L4T_CS_M         (0x1ULL << CI_TXD_CTX_QW0_L4T_CS_S)
+
 /**
  * Enum to specify where a VLAN tag is to be placed for packet Tx.
  */
drivers/net/intel/iavf/iavf_rxtx.c +15 -15
index 80c9912ccc..849fc33dac 100644
@@ -2345,7 +2345,7 @@ iavf_calc_context_desc(const struct rte_mbuf *mb, uint8_t vlan_flag, bool lldp_e
 static inline void
 iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const struct rte_mbuf *m)
 {
-	uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
+	uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
 	uint64_t eip_len = 0;
 	uint64_t eip_noinc = 0;
 	/* Default - IP_ID is increment in each segment of LSO */
@@ -2354,15 +2354,15 @@ iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const stru
 			RTE_MBUF_F_TX_OUTER_IPV6 |
 			RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
 	case RTE_MBUF_F_TX_OUTER_IPV4:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
+		eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
 		eip_len = m->outer_l3_len >> 2;
 	break;
 	case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
+		eip_typ = CI_TX_CTX_EIPT_IPV4;
 		eip_len = m->outer_l3_len >> 2;
 	break;
 	case RTE_MBUF_F_TX_OUTER_IPV6:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
+		eip_typ = CI_TX_CTX_EIPT_IPV6;
 		eip_len = m->outer_l3_len >> 2;
 	break;
 	}
@@ -2377,10 +2377,10 @@ iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const stru
 		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
 		case RTE_MBUF_F_TX_TUNNEL_GTP:
 		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-			eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
 			break;
 		case RTE_MBUF_F_TX_TUNNEL_GRE:
-			eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
 			break;
 		default:
 			PMD_TX_LOG(ERR, "Tunnel type not supported");
@@ -2397,23 +2397,23 @@ iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const stru
 		 * its last Ethertype.
 		 * If MPLS labels exists, it should include them as well.
 		 */
-		eip_typ |= (m->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
+		eip_typ |= (m->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
 
 		/**
 		 * Calculate the tunneling UDP checksum.
 		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
 		 */
-		if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV6 |
-					IAVF_TX_CTX_EXT_IP_IPV4 |
-					IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-				(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
 				(ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-			eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
 	}
 
-	*qw0 = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-		eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-		eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
+	*qw0 = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+		eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+		eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
 }
 
 static inline uint16_t
drivers/net/intel/iavf/iavf_rxtx.h +0 -34
index 3ff49b94b4..19931f5f7c 100644
@@ -444,40 +444,6 @@ enum iavf_rx_flex_desc_ipsec_crypto_status {
 #define IAVF_TXD_CTX_QW1_SEG_PARAMS_MSS_MASK		\
 	(0x3FFFUL << IAVF_TXD_CTX_QW1_SEG_PARAMS_MSS_SHIFT)
 
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT		(0)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_MASK		(0x3UL)
-
-enum iavf_tx_ctx_desc_tunnel_external_ip_type {
-	IAVF_TX_CTX_DESC_EIPT_NONE,
-	IAVF_TX_CTX_DESC_EIPT_IPV6,
-	IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD,
-	IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD
-};
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT	(2)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_MASK		(0x7FUL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNT_SHIFT	(9)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNT_MASK		(0x3UL)
-
-enum iavf_tx_ctx_desc_tunnel_l4_tunnel_type {
-	IAVF_TX_CTX_DESC_L4_TUN_TYP_NO_UDP_GRE,
-	IAVF_TX_CTX_DESC_L4_TUN_TYP_UDP,
-	IAVF_TX_CTX_DESC_L4_TUN_TYP_GRE
-};
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT	(11)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_MASK	(0x1UL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNLEN_SHIFT	(12)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNLEN_MASK	(0x7FUL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_DECTTL_SHIFT	(19)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_DECTTL_MASK		(0xFUL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4T_CS_SHIFT	(23)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4T_CS_MASK		(0x1UL)
-
 #define IAVF_TXD_CTX_QW0_L2TAG2_PARAM			(32)
 #define IAVF_TXD_CTX_QW0_L2TAG2_MASK			(0xFFFFUL)
 
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +15 -15
index 10e96a8510..f95aabe577 100644
@@ -1760,7 +1760,7 @@ static inline void
 iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 {
 	if (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
-		uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
+		uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
 		uint64_t eip_len = 0;
 		uint64_t eip_noinc = 0;
 		/* Default - IP_ID is increment in each segment of LSO */
@@ -1769,15 +1769,15 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 				RTE_MBUF_F_TX_OUTER_IPV6 |
 				RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
 		case RTE_MBUF_F_TX_OUTER_IPV4:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV6:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
+			eip_typ = CI_TX_CTX_EIPT_IPV6;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		}
@@ -1791,10 +1791,10 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
 		case RTE_MBUF_F_TX_TUNNEL_GTP:
 		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-			eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
 			break;
 		case RTE_MBUF_F_TX_TUNNEL_GRE:
-			eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
 			break;
 		default:
 			PMD_TX_LOG(ERR, "Tunnel type not supported");
@@ -1811,22 +1811,22 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		 * its last Ethertype.
 		 * If MPLS labels exists, it should include them as well.
 		 */
-		eip_typ |= (pkt->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
+		eip_typ |= (pkt->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
 
 		/**
 		 * Calculate the tunneling UDP checksum.
 		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
 		 */
-		if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV4 |
-					IAVF_TX_CTX_EXT_IP_IPV6 |
-					IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-				(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
 				(pkt->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-			eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
 
-		*low_ctx_qw = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-			eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-			eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
+		*low_ctx_qw = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+			eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+			eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
 
 	} else {
 		*low_ctx_qw = 0;
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +15 -15
index 58ed89a72a..74d91fff31 100644
@@ -1899,7 +1899,7 @@ static __rte_always_inline void
 iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 {
 	if (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
-		uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
+		uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
 		uint64_t eip_len = 0;
 		uint64_t eip_noinc = 0;
 		/* Default - IP_ID is increment in each segment of LSO */
@@ -1908,15 +1908,15 @@ iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 				RTE_MBUF_F_TX_OUTER_IPV6 |
 				RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
 		case RTE_MBUF_F_TX_OUTER_IPV4:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV6:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
+			eip_typ = CI_TX_CTX_EIPT_IPV6;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		}
@@ -1930,10 +1930,10 @@ iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
 		case RTE_MBUF_F_TX_TUNNEL_GTP:
 		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-			eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
 			break;
 		case RTE_MBUF_F_TX_TUNNEL_GRE:
-			eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
 			break;
 		default:
 			PMD_TX_LOG(ERR, "Tunnel type not supported");
@@ -1950,22 +1950,22 @@ iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		 * its last Ethertype.
 		 * If MPLS labels exists, it should include them as well.
 		 */
-		eip_typ |= (pkt->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
+		eip_typ |= (pkt->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
 
 		/**
 		 * Calculate the tunneling UDP checksum.
 		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
 		 */
-		if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV4 |
-					IAVF_TX_CTX_EXT_IP_IPV6 |
-					IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-				(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
 				(pkt->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-			eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
 
-		*low_ctx_qw = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-			eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-			eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
+		*low_ctx_qw = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+			eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+			eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
 
 	} else {
 		*low_ctx_qw = 0;
Signature · 1 line
2.53.0
Acked-by on v1 5/13
#10 lore raw

RE: [PATCH 05/13] net/intel: define common macros for tunneling bit-shifts

Quoted 7 lines

Subject: [PATCH 05/13] net/intel: define common macros for tunneling bit- shifts

Define common macros for use in iavf (for now) and other drivers (future) defining the shifts needed for tunnel packet Tx

Quoted 8 lines
---
 drivers/net/intel/common/tx.h                 | 24 +++++++++++++
 drivers/net/intel/iavf/iavf_rxtx.c            | 30 ++++++++--------
 drivers/net/intel/iavf/iavf_rxtx.h            | 34 -------------------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 30 ++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 30 ++++++++--------
 5 files changed, 69 insertions(+), 79 deletions(-)
#11 lore raw

PATCH 6/13 net/intel: move iavf descriptor writing functions to common

In reply to Bruce Richardson

In order to promote reuse of code, move the Tx vector functions for writing descriptors from the iavf driver to the common folder in a new tx_vec_x86.h file. This will allow reuse in later commits by other drivers such as ice.

---
 drivers/net/intel/common/tx_vec_x86.h         | 513 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 285 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 272 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  77 +--
 4 files changed, 532 insertions(+), 615 deletions(-)
 create mode 100644 drivers/net/intel/common/tx_vec_x86.h
drivers/net/intel/common/tx_vec_x86.h new file +513 -0
new file mode 100644
index 0000000000..b65bc9fc78
@@ -0,0 +1,513 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2026 Intel Corporation
+ */
+
+#ifndef _COMMON_INTEL_TX_VEC_X86_H_
+#define _COMMON_INTEL_TX_VEC_X86_H_
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "tx.h"
+
+static __rte_always_inline void
+ci_fill_ctx_desc_tunneling(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
+{
+	if (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
+		uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
+		uint64_t eip_len = 0;
+		uint64_t eip_noinc = 0;
+		/* Default - IP_ID is increment in each segment of LSO */
+
+		switch (pkt->ol_flags & (RTE_MBUF_F_TX_OUTER_IPV4 |
+				RTE_MBUF_F_TX_OUTER_IPV6 |
+				RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
+		case RTE_MBUF_F_TX_OUTER_IPV4:
+			eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
+			eip_len = pkt->outer_l3_len >> 2;
+		break;
+		case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
+			eip_typ = CI_TX_CTX_EIPT_IPV4;
+			eip_len = pkt->outer_l3_len >> 2;
+		break;
+		case RTE_MBUF_F_TX_OUTER_IPV6:
+			eip_typ = CI_TX_CTX_EIPT_IPV6;
+			eip_len = pkt->outer_l3_len >> 2;
+		break;
+		}
+
+		/* L4TUNT: L4 Tunneling Type */
+		switch (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
+		case RTE_MBUF_F_TX_TUNNEL_IPIP:
+			/* for non UDP / GRE tunneling, set to 00b */
+			break;
+		case RTE_MBUF_F_TX_TUNNEL_VXLAN:
+		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
+		case RTE_MBUF_F_TX_TUNNEL_GTP:
+		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
+			break;
+		case RTE_MBUF_F_TX_TUNNEL_GRE:
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
+			break;
+		default:
+			PMD_TX_LOG(ERR, "Tunnel type not supported");
+			return;
+		}
+
+		/* L4TUNLEN: L4 Tunneling Length, in Words
+		 *
+		 * We depend on app to set rte_mbuf.l2_len correctly.
+		 * For IP in GRE it should be set to the length of the GRE
+		 * header;
+		 * For MAC in GRE or MAC in UDP it should be set to the length
+		 * of the GRE or UDP headers plus the inner MAC up to including
+		 * its last Ethertype.
+		 * If MPLS labels exists, it should include them as well.
+		 */
+		eip_typ |= (pkt->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
+
+		/**
+		 * Calculate the tunneling UDP checksum.
+		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
+		 */
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
+				(pkt->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
+
+		*low_ctx_qw = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+			eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+			eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
+
+	} else {
+		*low_ctx_qw = 0;
+	}
+}
+
+static __rte_always_inline void
+ci_tx_vec_offload(struct rte_mbuf *tx_pkt, uint64_t *txd_hi,
+		enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	uint64_t ol_flags = tx_pkt->ol_flags;
+	uint32_t td_cmd = 0;
+	uint32_t td_offset = 0;
+
+	/* Set MACLEN */
+	if (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)
+		td_offset |= (tx_pkt->outer_l2_len >> 1) << CI_TX_DESC_LEN_MACLEN_S;
+	else
+		td_offset |= (tx_pkt->l2_len >> 1) << CI_TX_DESC_LEN_MACLEN_S;
+
+	/* Enable L3 checksum offloads */
+	if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
+		if (ol_flags & RTE_MBUF_F_TX_IPV4) {
+			td_cmd |= CI_TX_DESC_CMD_IIPT_IPV4_CSUM;
+			td_offset |= (tx_pkt->l3_len >> 2) << CI_TX_DESC_LEN_IPLEN_S;
+		}
+	} else if (ol_flags & RTE_MBUF_F_TX_IPV4) {
+		td_cmd |= CI_TX_DESC_CMD_IIPT_IPV4;
+		td_offset |= (tx_pkt->l3_len >> 2) << CI_TX_DESC_LEN_IPLEN_S;
+	} else if (ol_flags & RTE_MBUF_F_TX_IPV6) {
+		td_cmd |= CI_TX_DESC_CMD_IIPT_IPV6;
+		td_offset |= (tx_pkt->l3_len >> 2) << CI_TX_DESC_LEN_IPLEN_S;
+	}
+
+	/* Enable L4 checksum offloads */
+	switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) {
+	case RTE_MBUF_F_TX_TCP_CKSUM:
+		td_cmd |= CI_TX_DESC_CMD_L4T_EOFT_TCP;
+		td_offset |= (sizeof(struct rte_tcp_hdr) >> 2) << CI_TX_DESC_LEN_L4_LEN_S;
+		break;
+	case RTE_MBUF_F_TX_SCTP_CKSUM:
+		td_cmd |= CI_TX_DESC_CMD_L4T_EOFT_SCTP;
+		td_offset |= (sizeof(struct rte_sctp_hdr) >> 2) << CI_TX_DESC_LEN_L4_LEN_S;
+		break;
+	case RTE_MBUF_F_TX_UDP_CKSUM:
+		td_cmd |= CI_TX_DESC_CMD_L4T_EOFT_UDP;
+		td_offset |= (sizeof(struct rte_udp_hdr) >> 2) << CI_TX_DESC_LEN_L4_LEN_S;
+		break;
+	default:
+		break;
+	}
+
+	*txd_hi |= ((uint64_t)td_offset) << CI_TXD_QW1_OFFSET_S;
+
+	if (ol_flags & RTE_MBUF_F_TX_QINQ) {
+		td_cmd |= CI_TX_DESC_CMD_IL2TAG1;
+		/* L2Tag1 always carries a tag for QinQ: the outer tag if that's
+		 * where it is placed, otherwise the inner.
+		 */
+		if (qinq_outer_pos == CI_TAG_IN_DATA_DESC)
+			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci_outer << CI_TXD_QW1_L2TAG1_S);
+		else
+			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
+	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && single_vlan_pos == CI_TAG_IN_DATA_DESC) {
+		td_cmd |= CI_TX_DESC_CMD_IL2TAG1;
+		*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
+	}
+
+	*txd_hi |= ((uint64_t)td_cmd) << CI_TXD_QW1_CMD_S;
+}
+
+static __rte_always_inline void
+ci_vtx1(volatile struct ci_tx_desc *txdp,
+	  struct rte_mbuf *pkt, uint64_t flags, bool offload,
+	  enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
+			((uint64_t)flags << CI_TXD_QW1_CMD_S) |
+			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
+	if (offload)
+		ci_tx_vec_offload(pkt, &high_qw, single_vlan_pos, qinq_outer_pos);
+
+	__m128i descriptor = _mm_set_epi64x(high_qw, pkt->buf_iova + pkt->data_off);
+	_mm_store_si128(RTE_CAST_PTR(__m128i *, txdp), descriptor);
+}
+
+#ifdef __AVX2__
+
+static __rte_always_inline void
+ci_vtx_avx2(volatile struct ci_tx_desc *txdp,
+	 struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload,
+	 enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
+
+	/* if unaligned on 32-bit boundary, do one to align */
+	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		nb_pkts--; txdp++; pkt++;
+	}
+
+	/* do two at a time while possible, in bursts */
+	for (; nb_pkts > 3; txdp += 4, pkt += 4, nb_pkts -= 4) {
+		uint64_t hi_qw3 = hi_qw_tmpl |
+			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[3], &hi_qw3, single_vlan_pos, qinq_outer_pos);
+		uint64_t hi_qw2 = hi_qw_tmpl |
+			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[2], &hi_qw2, single_vlan_pos, qinq_outer_pos);
+		uint64_t hi_qw1 = hi_qw_tmpl |
+			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[1], &hi_qw1, single_vlan_pos, qinq_outer_pos);
+		uint64_t hi_qw0 = hi_qw_tmpl |
+			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[0], &hi_qw0, single_vlan_pos, qinq_outer_pos);
+
+		__m256i desc2_3 =
+			_mm256_set_epi64x
+				(hi_qw3,
+				 pkt[3]->buf_iova + pkt[3]->data_off,
+				 hi_qw2,
+				 pkt[2]->buf_iova + pkt[2]->data_off);
+		__m256i desc0_1 =
+			_mm256_set_epi64x
+				(hi_qw1,
+				 pkt[1]->buf_iova + pkt[1]->data_off,
+				 hi_qw0,
+				 pkt[0]->buf_iova + pkt[0]->data_off);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
+	}
+
+	/* do any last ones */
+	while (nb_pkts) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		txdp++; pkt++; nb_pkts--;
+	}
+}
+
+static __rte_always_inline void
+ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
+		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
+		enum ci_l2tag_pos qinq_outer_pos, bool ptype_lldp_enabled)
+{
+	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
+	uint64_t low_ctx_qw = 0;
+
+	if (offload) {
+		ci_fill_ctx_desc_tunneling(&low_ctx_qw, pkt);
+		if (pkt->ol_flags & RTE_MBUF_F_TX_QINQ) {
+			uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+				(uint64_t)pkt->vlan_tci_outer :
+				(uint64_t)pkt->vlan_tci;
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+		} else if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) &&
+				single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+		}
+	}
+	if (IAVF_CHECK_TX_LLDP(pkt, ptype_lldp_enabled))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
+			((uint64_t)flags  << CI_TXD_QW1_CMD_S) |
+			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
+	if (offload)
+		ci_tx_vec_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
+
+	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
+							high_ctx_qw, low_ctx_qw);
+
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+}
+
+static __rte_always_inline void
+ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
+		struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags,
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		bool ptype_lldp_enabled)
+{
+	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags  << CI_TXD_QW1_CMD_S));
+
+	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
+		uint64_t hi_ctx_qw1 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t hi_ctx_qw0 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t low_ctx_qw1 = 0;
+		uint64_t low_ctx_qw0 = 0;
+		uint64_t hi_data_qw1 = 0;
+		uint64_t hi_data_qw0 = 0;
+
+		hi_data_qw1 = hi_data_qw_tmpl |
+				((uint64_t)pkt[1]->data_len <<
+					CI_TXD_QW1_TX_BUF_SZ_S);
+		hi_data_qw0 = hi_data_qw_tmpl |
+				((uint64_t)pkt[0]->data_len <<
+					CI_TXD_QW1_TX_BUF_SZ_S);
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw1, pkt[1]);
+			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[1]->vlan_tci_outer :
+					(uint64_t)pkt[1]->vlan_tci;
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[1]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[1], ptype_lldp_enabled))
+			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw0, pkt[0]);
+			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[0]->vlan_tci_outer :
+					(uint64_t)pkt[0]->vlan_tci;
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[0]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[0], ptype_lldp_enabled))
+			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[0], &hi_data_qw0, single_vlan_pos, qinq_outer_pos);
+		}
+
+		__m256i desc2_3 = _mm256_set_epi64x
+				(hi_data_qw1, pkt[1]->buf_iova + pkt[1]->data_off,
+				 hi_ctx_qw1, low_ctx_qw1);
+		__m256i desc0_1 = _mm256_set_epi64x
+				(hi_data_qw0, pkt[0]->buf_iova + pkt[0]->data_off,
+				 hi_ctx_qw0, low_ctx_qw0);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
+	}
+
+	if (nb_pkts)
+		ci_vtx1_ctx_avx2(txdp, *pkt, flags, offload,
+				single_vlan_pos, qinq_outer_pos, ptype_lldp_enabled);
+}
+
+#endif /* __AVX2__ */
+
+#ifdef __AVX512VL__
+
+static __rte_always_inline void
+ci_vtx_avx512(volatile struct ci_tx_desc *txdp,
+		struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags,
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
+
+	/* if unaligned on 32-bit boundary, do one to align */
+	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		nb_pkts--; txdp++; pkt++;
+	}
+
+	/* do 4 at a time while possible, in bursts */
+	for (; nb_pkts > 3; txdp += 4, pkt += 4, nb_pkts -= 4) {
+		uint64_t hi_qw3 = hi_qw_tmpl |
+			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		uint64_t hi_qw2 = hi_qw_tmpl |
+			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		uint64_t hi_qw1 = hi_qw_tmpl |
+			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		uint64_t hi_qw0 = hi_qw_tmpl |
+			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload) {
+			ci_tx_vec_offload(pkt[3], &hi_qw3, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[2], &hi_qw2, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[1], &hi_qw1, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[0], &hi_qw0, single_vlan_pos, qinq_outer_pos);
+		}
+
+		__m512i desc0_3 =
+			_mm512_set_epi64
+				(hi_qw3,
+				 pkt[3]->buf_iova + pkt[3]->data_off,
+				 hi_qw2,
+				 pkt[2]->buf_iova + pkt[2]->data_off,
+				 hi_qw1,
+				 pkt[1]->buf_iova + pkt[1]->data_off,
+				 hi_qw0,
+				 pkt[0]->buf_iova + pkt[0]->data_off);
+		_mm512_storeu_si512(RTE_CAST_PTR(void *, txdp), desc0_3);
+	}
+
+	/* do any last ones */
+	while (nb_pkts) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		txdp++; pkt++; nb_pkts--;
+	}
+}
+
+static __rte_always_inline void
+ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
+		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
+		enum ci_l2tag_pos qinq_outer_pos, bool lldp_enabled)
+{
+	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
+	uint64_t low_ctx_qw = 0;
+
+	if (offload) {
+		ci_fill_ctx_desc_tunneling(&low_ctx_qw, pkt);
+		if (pkt->ol_flags & RTE_MBUF_F_TX_QINQ) {
+			uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+				(uint64_t)pkt->vlan_tci_outer :
+				(uint64_t)pkt->vlan_tci;
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+		} else if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) &&
+				single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+		}
+	}
+	if (IAVF_CHECK_TX_LLDP(pkt, lldp_enabled))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
+			((uint64_t)flags << CI_TXD_QW1_CMD_S) |
+			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
+	if (offload)
+		ci_tx_vec_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
+
+	__m256i ctx_data_desc = _mm256_set_epi64x
+			(high_data_qw, pkt->buf_iova + pkt->data_off,
+			high_ctx_qw, low_ctx_qw);
+
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+}
+
+static __rte_always_inline void
+ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
+		struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags,
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		bool lldp_enabled)
+{
+	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
+
+	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
+		uint64_t hi_ctx_qw1 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t hi_ctx_qw0 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t low_ctx_qw1 = 0;
+		uint64_t low_ctx_qw0 = 0;
+		uint64_t hi_data_qw1 = 0;
+		uint64_t hi_data_qw0 = 0;
+
+		hi_data_qw1 = hi_data_qw_tmpl |
+				((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		hi_data_qw0 = hi_data_qw_tmpl |
+				((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw1, pkt[1]);
+			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[1]->vlan_tci_outer :
+					(uint64_t)pkt[1]->vlan_tci;
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[1]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[1], lldp_enabled))
+			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw0, pkt[0]);
+			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[0]->vlan_tci_outer :
+					(uint64_t)pkt[0]->vlan_tci;
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[0]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[0], lldp_enabled))
+			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[0], &hi_data_qw0, single_vlan_pos, qinq_outer_pos);
+		}
+
+		__m512i desc0_3 = _mm512_set_epi64
+				(hi_data_qw1, pkt[1]->buf_iova + pkt[1]->data_off,
+				hi_ctx_qw1, low_ctx_qw1,
+				hi_data_qw0, pkt[0]->buf_iova + pkt[0]->data_off,
+				hi_ctx_qw0, low_ctx_qw0);
+		_mm512_storeu_si512(RTE_CAST_PTR(void *, txdp), desc0_3);
+	}
+
+	if (nb_pkts)
+		ci_vtx1_ctx_avx512(txdp, *pkt, flags, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_enabled);
+}
+
+#endif /* __AVX512VL__ */
+
+#endif /* _COMMON_INTEL_TX_VEC_X86_H_ */
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +7 -278

326 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +8 -264

309 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_common.h +4 -73

87 lines not on this page · raw message

Signature · 1 line
2.53.0
Acked-by on v1 6/13
#12 lore raw

RE: [PATCH 06/13] net/intel: move iavf descriptor writing functions to common

Quoted 9 lines

Subject: [PATCH 06/13] net/intel: move iavf descriptor writing functions to common

In order to promote reuse of code, move the Tx vector functions for writing descriptors from the iavf driver to the common folder in a new tx_vec_x86.h file. This will allow reuse in later commits by other drivers such as ice.

Quoted 8 lines
---
 drivers/net/intel/common/tx_vec_x86.h         | 513 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 285 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 272 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  77 +--
 4 files changed, 532 insertions(+), 615 deletions(-)
 create mode 100644 drivers/net/intel/common/tx_vec_x86.h
#13 lore raw

PATCH 7/13 net/intel: use function callback for lldp

In reply to Bruce Richardson

Limit LLDP support for iavf drivers for now, by using a callback to handle its processing. Drivers not supporting this pass a NULL pointer and the compiler will optimize away the branches. For iavf, the compiler can inline the subfunction directly as it's known at compile-time.

---
 drivers/net/intel/common/tx_vec_x86.h         | 42 +++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 16 +++++--
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 17 +++++---
 3 files changed, 48 insertions(+), 27 deletions(-)
drivers/net/intel/common/tx_vec_x86.h +24 -18
index b65bc9fc78..f769765cba 100644
@@ -11,6 +11,12 @@
 
 #include "tx.h"
 
+/* Optional per-driver LLDP switch-uplink check for ctx descriptors.
+ * Takes the ctx-desc high qword and returns it with the LLDP bit applied
+ * if appropriate. NULL disables the check.
+ */
+typedef uint64_t (*ci_tx_ctx_lldp_fn)(struct rte_mbuf *pkt, uint64_t high_ctx_qw);
+
 static __rte_always_inline void
 ci_fill_ctx_desc_tunneling(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 {
@@ -228,7 +234,7 @@ ci_vtx_avx2(volatile struct ci_tx_desc *txdp,
 static __rte_always_inline void
 ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
-		enum ci_l2tag_pos qinq_outer_pos, bool ptype_lldp_enabled)
+		enum ci_l2tag_pos qinq_outer_pos, ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
 	uint64_t low_ctx_qw = 0;
@@ -247,8 +253,8 @@ ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 		}
 	}
-	if (IAVF_CHECK_TX_LLDP(pkt, ptype_lldp_enabled))
-		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	if (lldp_check != NULL)
+		high_ctx_qw = lldp_check(pkt, high_ctx_qw);
 	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
 			((uint64_t)flags  << CI_TXD_QW1_CMD_S) |
 			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
@@ -266,7 +272,7 @@ static __rte_always_inline void
 ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 		struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags,
 		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
-		bool ptype_lldp_enabled)
+		ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags  << CI_TXD_QW1_CMD_S));
 
@@ -300,8 +306,8 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[1], ptype_lldp_enabled))
-			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw1 = lldp_check(pkt[1], hi_ctx_qw1);
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
@@ -318,8 +324,8 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[0], ptype_lldp_enabled))
-			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw0 = lldp_check(pkt[0], hi_ctx_qw0);
 
 		if (offload) {
 			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
@@ -338,7 +344,7 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 
 	if (nb_pkts)
 		ci_vtx1_ctx_avx2(txdp, *pkt, flags, offload,
-				single_vlan_pos, qinq_outer_pos, ptype_lldp_enabled);
+				single_vlan_pos, qinq_outer_pos, lldp_check);
 }
 
 #endif /* __AVX2__ */
@@ -398,7 +404,7 @@ ci_vtx_avx512(volatile struct ci_tx_desc *txdp,
 static __rte_always_inline void
 ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
-		enum ci_l2tag_pos qinq_outer_pos, bool lldp_enabled)
+		enum ci_l2tag_pos qinq_outer_pos, ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
 	uint64_t low_ctx_qw = 0;
@@ -417,8 +423,8 @@ ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 		}
 	}
-	if (IAVF_CHECK_TX_LLDP(pkt, lldp_enabled))
-		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	if (lldp_check != NULL)
+		high_ctx_qw = lldp_check(pkt, high_ctx_qw);
 	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
 			((uint64_t)flags << CI_TXD_QW1_CMD_S) |
 			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
@@ -437,7 +443,7 @@ static __rte_always_inline void
 ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 		struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags,
 		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
-		bool lldp_enabled)
+		ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
 
@@ -469,8 +475,8 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[1], lldp_enabled))
-			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw1 = lldp_check(pkt[1], hi_ctx_qw1);
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
@@ -487,8 +493,8 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[0], lldp_enabled))
-			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw0 = lldp_check(pkt[0], hi_ctx_qw0);
 
 		if (offload) {
 			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
@@ -505,7 +511,7 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 
 	if (nb_pkts)
 		ci_vtx1_ctx_avx512(txdp, *pkt, flags, offload,
-				single_vlan_pos, qinq_outer_pos, lldp_enabled);
+					single_vlan_pos, qinq_outer_pos, lldp_check);
 }
 
 #endif /* __AVX512VL__ */
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +12 -4
index 1d0492edd9..813611015d 100644
@@ -1685,6 +1685,14 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return nb_pkts;
 }
 
+static __rte_always_inline uint64_t
+iavf_tx_ctx_lldp_check(struct rte_mbuf *pkt, uint64_t high_ctx_qw)
+{
+	if (IAVF_CHECK_TX_LLDP(pkt, true))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	return high_ctx_qw;
+}
+
 static __rte_always_inline uint16_t
 iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 				 uint16_t nb_pkts, bool offload)
@@ -1696,7 +1704,7 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	/* bit2 is reserved and must be set to 1 according to Spec */
 	uint64_t flags = IAVF_TX_DESC_CMD_EOP | IAVF_TX_DESC_CMD_ICRC;
 	uint64_t rs = IAVF_TX_DESC_CMD_RS | flags;
-	bool lldp_enabled = txq->lldp_enabled;
+	ci_tx_ctx_lldp_fn lldp_check = txq->lldp_enabled ? iavf_tx_ctx_lldp_check : NULL;
 	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
 	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
 			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
@@ -1723,10 +1731,10 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
 		ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
-				vlan_pos, vlan_pos, lldp_enabled);
+				vlan_pos, vlan_pos, lldp_check);
 		tx_pkts += (nb_mbuf - 1);
 		txdp += (n - 2);
-		ci_vtx1_ctx_avx2(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_enabled);
+		ci_vtx1_ctx_avx2(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_check);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -1740,7 +1748,7 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	nb_mbuf = nb_commit >> 1;
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
-	ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
+	ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_check);
 	tx_id = (uint16_t)(tx_id + nb_commit);
 
 	if (tx_id > txq->tx_next_rs) {
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +12 -5
index 0c738e4882..fe00416660 100644
@@ -1900,6 +1900,14 @@ iavf_xmit_fixed_burst_vec_avx512(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return nb_pkts;
 }
 
+static __rte_always_inline uint64_t
+iavf_tx_ctx_lldp_check(struct rte_mbuf *pkt, uint64_t high_ctx_qw)
+{
+	if (IAVF_CHECK_TX_LLDP(pkt, true))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	return high_ctx_qw;
+}
+
 static __rte_always_inline uint16_t
 iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 				 uint16_t nb_pkts, bool offload)
@@ -1911,7 +1919,7 @@ iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	/* bit2 is reserved and must be set to 1 according to Spec */
 	uint64_t flags = CI_TX_DESC_CMD_EOP | CI_TX_DESC_CMD_ICRC;
 	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
-	bool lldp_enabled = txq->lldp_enabled;
+	ci_tx_ctx_lldp_fn lldp_check = txq->lldp_enabled ? iavf_tx_ctx_lldp_check : NULL;
 	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
 	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
 			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
@@ -1938,11 +1946,10 @@ iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 		tx_backlog_entry_avx512(txep, tx_pkts, nb_mbuf);
 
 		ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
-				vlan_pos, vlan_pos, lldp_enabled);
+				vlan_pos, vlan_pos, lldp_check);
 		tx_pkts += (nb_mbuf - 1);
 		txdp += (n - 2);
-		ci_vtx1_ctx_avx512(txdp, *tx_pkts++, rs, offload,
-				vlan_pos, vlan_pos, lldp_enabled);
+		ci_vtx1_ctx_avx512(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_check);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -1956,7 +1963,7 @@ iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	nb_mbuf = nb_commit >> 1;
 	tx_backlog_entry_avx512(txep, tx_pkts, nb_mbuf);
 
-	ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
+	ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_check);
 	tx_id = (uint16_t)(tx_id + nb_commit);
 
 	if (tx_id > txq->tx_next_rs) {
Signature · 1 line
2.53.0
#14 lore raw

PATCH 8/13 net/ice: use common descriptor creation functions

In reply to Bruce Richardson

Update ice driver to use the descriptor creation functions from common rather than having it maintain its own copies of them.

---
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 73 ++-------------------
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 64 ++----------------
 drivers/net/intel/ice/ice_rxtx_vec_common.h | 59 -----------------
 3 files changed, 12 insertions(+), 184 deletions(-)
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +6 -67
index b72f69a47b..68401560ce 100644
@@ -5,6 +5,7 @@
 #include "ice_rxtx_vec_common.h"
 
 #include "../common/rx_vec_x86.h"
+#include "../common/tx_vec_x86.h"
 
 #include <rte_vect.h>
 
@@ -773,70 +774,6 @@ ice_recv_scattered_pkts_vec_avx2_offload(void *rx_queue,
 						       true);
 }
 
-static __rte_always_inline void
-ice_vtx1(volatile struct ci_tx_desc *txdp,
-	 struct rte_mbuf *pkt, uint64_t flags, bool offload)
-{
-	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
-		 ((uint64_t)flags << CI_TXD_QW1_CMD_S) |
-		 ((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
-	if (offload)
-		ice_txd_enable_offload(pkt, &high_qw);
-
-	__m128i descriptor = _mm_set_epi64x(high_qw, rte_pktmbuf_iova(pkt));
-	_mm_store_si128(RTE_CAST_PTR(__m128i *, txdp), descriptor);
-}
-
-static __rte_always_inline void
-ice_vtx(volatile struct ci_tx_desc *txdp,
-	struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload)
-{
-	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
-
-	/* if unaligned on 32-bit boundary, do one to align */
-	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		ice_vtx1(txdp, *pkt, flags, offload);
-		nb_pkts--; txdp++; pkt++;
-	}
-
-	/* do four at a time while possible, in bursts */
-	for (; nb_pkts > 3; txdp += 4, pkt += 4, nb_pkts -= 4) {
-		uint64_t hi_qw3 = hi_qw_tmpl |
-			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[3], &hi_qw3);
-		uint64_t hi_qw2 = hi_qw_tmpl |
-			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[2], &hi_qw2);
-		uint64_t hi_qw1 = hi_qw_tmpl |
-			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[1], &hi_qw1);
-		uint64_t hi_qw0 = hi_qw_tmpl |
-			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[0], &hi_qw0);
-
-		__m256i desc2_3 =
-			_mm256_set_epi64x
-				(hi_qw3, rte_pktmbuf_iova(pkt[3]),
-				 hi_qw2, rte_pktmbuf_iova(pkt[2]));
-		__m256i desc0_1 =
-			_mm256_set_epi64x
-				(hi_qw1, rte_pktmbuf_iova(pkt[1]),
-				 hi_qw0, rte_pktmbuf_iova(pkt[0]));
-		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
-		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
-	}
-
-	/* do any last ones */
-	while (nb_pkts) {
-		ice_vtx1(txdp, *pkt, flags, offload);
-		txdp++; pkt++; nb_pkts--;
-	}
-}
-
 static __rte_always_inline uint16_t
 ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 			      uint16_t nb_pkts, bool offload)
@@ -868,11 +805,12 @@ ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	if (nb_commit >= n) {
 		ci_tx_backlog_entry_vec(txep, tx_pkts, n);
 
-		ice_vtx(txdp, tx_pkts, n - 1, flags, offload);
+		ci_vtx_avx2(txdp, tx_pkts, n - 1, flags, offload,
+			CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 		tx_pkts += (n - 1);
 		txdp += (n - 1);
 
-		ice_vtx1(txdp, *tx_pkts++, rs, offload);
+		ci_vtx1(txdp, *tx_pkts++, rs, offload, CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -886,7 +824,8 @@ ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_commit);
 
-	ice_vtx(txdp, tx_pkts, nb_commit, flags, offload);
+	ci_vtx_avx2(txdp, tx_pkts, nb_commit, flags, offload,
+		CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 
 	tx_id = (uint16_t)(tx_id + nb_commit);
 	if (tx_id > txq->tx_next_rs) {
drivers/net/intel/ice/ice_rxtx_vec_avx512.c +6 -58

91 lines not on this page · raw message

drivers/net/intel/ice/ice_rxtx_vec_common.h +0 -59

63 lines not on this page · raw message

Signature · 1 line
2.53.0
#15 lore raw

RE: [PATCH 08/13] net/ice: use common descriptor creation functions

Quoted 32 lines

Subject: [PATCH 08/13] net/ice: use common descriptor creation functions

Update ice driver to use the descriptor creation functions from common rather than having it maintain its own copies of them.

---
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 73 ++-------------------
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 64 ++----------------
 drivers/net/intel/ice/ice_rxtx_vec_common.h | 59 -----------------
 3 files changed, 12 insertions(+), 184 deletions(-)
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +1 -2
index b72f69a47b..68401560ce 100644
@@ -5,6 +5,7 @@
 #include "ice_rxtx_vec_common.h"
 
 #include "../common/rx_vec_x86.h"
+#include "../common/tx_vec_x86.h"
 
 #include <rte_vect.h>
 
@@ -773,70 +774,6 @@ ice_recv_scattered_pkts_vec_avx2_offload(void
 *rx_queue,
 						       true);
 }
 
-static __rte_always_inline void
-ice_vtx1(volatile struct ci_tx_desc *txdp,

drivers/net/intel/ice/ice_rxtx_vec_avx2.c ice_recv_scattered_pkts_vec_avx2_offload(void · line 778

Quoted 10 lines
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +0 -9
-	 struct rte_mbuf *pkt, uint64_t flags, bool offload)
-{
-	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
-		 ((uint64_t)flags << CI_TXD_QW1_CMD_S) |
-		 ((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
-	if (offload)
-		ice_txd_enable_offload(pkt, &high_qw);
-
-	__m128i descriptor = _mm_set_epi64x(high_qw,
 rte_pktmbuf_iova(pkt));

AI caught this for me on review, and I was able to reproduce it:
When you build with -Denable_iova_as_pa=false the ice driver build will fail. "require_iova_in_mbuf = false" is set in the ice meson.build file. So either that needs to be flipped to true, or ice needs to keep using rte_pktmbuf_iova.

Quoted 7 lines
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +0 -7
-	_mm_store_si128(RTE_CAST_PTR(__m128i *, txdp), descriptor);
-}
-
-static __rte_always_inline void
-ice_vtx(volatile struct ci_tx_desc *txdp,
-	struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload)
-{
#16 lore raw

Re: [PATCH 08/13] net/ice: use common descriptor creation functions

Quoted 39 lines · Ciara
Quoted 39 lines

Subject: [PATCH 08/13] net/ice: use common descriptor creation functions

Update ice driver to use the descriptor creation functions from common rather than having it maintain its own copies of them.

---
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 73 ++-------------------
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 64 ++----------------
 drivers/net/intel/ice/ice_rxtx_vec_common.h | 59 -----------------
 3 files changed, 12 insertions(+), 184 deletions(-)
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +1 -9
index b72f69a47b..68401560ce 100644
@@ -5,6 +5,7 @@
 #include "ice_rxtx_vec_common.h"
 
 #include "../common/rx_vec_x86.h"
+#include "../common/tx_vec_x86.h"
 
 #include <rte_vect.h>
 
@@ -773,70 +774,6 @@ ice_recv_scattered_pkts_vec_avx2_offload(void
 *rx_queue,
 						       true);
 }
 
-static __rte_always_inline void
-ice_vtx1(volatile struct ci_tx_desc *txdp,
-	 struct rte_mbuf *pkt, uint64_t flags, bool offload)
-{
-	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
-		 ((uint64_t)flags << CI_TXD_QW1_CMD_S) |
-		 ((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
-	if (offload)
-		ice_txd_enable_offload(pkt, &high_qw);
Quoted 9 lines

drivers/net/intel/ice/ice_rxtx_vec_avx2.c ice_recv_scattered_pkts_vec_avx2_offload(void · line 778

Quoted 3 lines
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +0 -2
-
-	__m128i descriptor = _mm_set_epi64x(high_qw,
 rte_pktmbuf_iova(pkt));

AI caught this for me on review, and I was able to reproduce it:
When you build with -Denable_iova_as_pa=false the ice driver build will fail. "require_iova_in_mbuf = false" is set in the ice meson.build file. So either that needs to be flipped to true, or ice needs to keep using rte_pktmbuf_iova.

Good catch by the AI. Changing the code to use the proper macro not only ensure ice isn't broken, but also allows us to enable iavf builds when the iova-in-mbuf setting is disabled. Will fix in next version.

/Bruce

#17 lore raw

PATCH 9/13 net/intel: move vector Tx paths to common

In reply to Bruce Richardson

The main loops for vector Tx, both avx2 and avx512 are almost identical across a couple of drivers, so move the iavf copies to common for later reuse by other drivers.

---
 drivers/net/intel/common/tx.h                 |  10 ++
 drivers/net/intel/common/tx_vec_x86.h         | 128 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   |  75 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c |  77 +----------
 4 files changed, 148 insertions(+), 142 deletions(-)
drivers/net/intel/common/tx.h +10 -0
index c8fadee712..630df8cb19 100644
@@ -9,6 +9,8 @@
 #include <rte_mbuf.h>
 #include <rte_ethdev.h>
 #include <rte_vect.h>
+#include <rte_io.h>
+#include <rte_byteorder.h>
 
 /* Common TX Descriptor QW1 Field Definitions */
 #define CI_TXD_QW1_DTYPE_S      0
@@ -273,6 +275,14 @@ ci_tx_backlog_entry_vec(struct ci_tx_entry_vec *txep, struct rte_mbuf **tx_pkts,
 		txep[i].mbuf = tx_pkts[i];
 }
 
+
+/* Write the Tx tail register, byte-swapped for hardware regardless of host endianness. */
+static __rte_always_inline void
+ci_tx_qtx_tail_write(struct ci_tx_queue *txq, uint16_t tx_id)
+{
+	rte_write32_wc(rte_cpu_to_le_32((uint32_t)tx_id), txq->qtx_tail);
+}
+
 #define IETH_VPMD_TX_MAX_FREE_BUF 64
 
 typedef int (*ci_desc_done_fn)(struct ci_tx_queue *txq, uint16_t idx);
drivers/net/intel/common/tx_vec_x86.h +128 -0

140 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +5 -70

93 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +5 -72

95 lines not on this page · raw message

Signature · 1 line
2.53.0
Acked-by on v1 9/13
#18 lore raw

RE: [PATCH 09/13] net/intel: move vector Tx paths to common

Quoted 7 lines

Subject: [PATCH 09/13] net/intel: move vector Tx paths to common

The main loops for vector Tx, both avx2 and avx512 are almost identical across a couple of drivers, so move the iavf copies to common for later reuse by other drivers.

Quoted 7 lines
---
 drivers/net/intel/common/tx.h                 |  10 ++
 drivers/net/intel/common/tx_vec_x86.h         | 128 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   |  75 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c |  77 +----------
 4 files changed, 148 insertions(+), 142 deletions(-)
#19 lore raw

PATCH 10/13 net/ice: use common AVX Tx functions

In reply to Bruce Richardson

Use the newly created common Tx functions in the vector path.

---
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   |  72 +-------------
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 102 +++-----------------
 2 files changed, 14 insertions(+), 160 deletions(-)
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +2 -70
index 68401560ce..00b5d51aab 100644
@@ -774,74 +774,6 @@ ice_recv_scattered_pkts_vec_avx2_offload(void *rx_queue,
 						       true);
 }
 
-static __rte_always_inline uint16_t
-ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
-			      uint16_t nb_pkts, bool offload)
-{
-	struct ci_tx_queue *txq = (struct ci_tx_queue *)tx_queue;
-	volatile struct ci_tx_desc *txdp;
-	struct ci_tx_entry_vec *txep;
-	uint16_t n, nb_commit, tx_id;
-	uint64_t flags = CI_TX_DESC_CMD_DEFAULT;
-	uint64_t rs = CI_TX_DESC_CMD_RS | CI_TX_DESC_CMD_DEFAULT;
-
-	/* cross rx_thresh boundary is not allowed */
-	nb_pkts = RTE_MIN(nb_pkts, txq->tx_rs_thresh);
-
-	if (txq->nb_tx_free < txq->tx_free_thresh)
-		ci_tx_free_bufs_vec(txq, ice_tx_desc_done, false);
-
-	nb_commit = nb_pkts = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts);
-	if (unlikely(nb_pkts == 0))
-		return 0;
-
-	tx_id = txq->tx_tail;
-	txdp = &txq->ci_tx_ring[tx_id];
-	txep = &txq->sw_ring_vec[tx_id];
-
-	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_pkts);
-
-	n = (uint16_t)(txq->nb_tx_desc - tx_id);
-	if (nb_commit >= n) {
-		ci_tx_backlog_entry_vec(txep, tx_pkts, n);
-
-		ci_vtx_avx2(txdp, tx_pkts, n - 1, flags, offload,
-			CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
-		tx_pkts += (n - 1);
-		txdp += (n - 1);
-
-		ci_vtx1(txdp, *tx_pkts++, rs, offload, CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
-
-		nb_commit = (uint16_t)(nb_commit - n);
-
-		tx_id = 0;
-		txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1);
-
-		/* avoid reach the end of ring */
-		txdp = &txq->ci_tx_ring[tx_id];
-		txep = &txq->sw_ring_vec[tx_id];
-	}
-
-	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_commit);
-
-	ci_vtx_avx2(txdp, tx_pkts, nb_commit, flags, offload,
-		CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
-
-	tx_id = (uint16_t)(tx_id + nb_commit);
-	if (tx_id > txq->tx_next_rs) {
-		txq->ci_tx_ring[txq->tx_next_rs].cmd_type_offset_bsz |=
-			rte_cpu_to_le_64(((uint64_t)CI_TX_DESC_CMD_RS) << CI_TXD_QW1_CMD_S);
-		txq->tx_next_rs =
-			(uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh);
-	}
-
-	txq->tx_tail = tx_id;
-
-	ICE_PCI_REG_WC_WRITE(txq->qtx_tail, txq->tx_tail);
-
-	return nb_pkts;
-}
-
 static __rte_always_inline uint16_t
 ice_xmit_pkts_vec_avx2_common(void *tx_queue, struct rte_mbuf **tx_pkts,
 			      uint16_t nb_pkts, bool offload)
@@ -853,8 +785,8 @@ ice_xmit_pkts_vec_avx2_common(void *tx_queue, struct rte_mbuf **tx_pkts,
 		uint16_t ret, num;
 
 		num = (uint16_t)RTE_MIN(nb_pkts, txq->tx_rs_thresh);
-		ret = ice_xmit_fixed_burst_vec_avx2(tx_queue, &tx_pkts[nb_tx],
-						    num, offload);
+		ret = ci_xmit_fixed_burst_vec_avx2(tx_queue, &tx_pkts[nb_tx], num,
+				offload, CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 		nb_tx += ret;
 		nb_pkts -= ret;
 		if (ret < num)
drivers/net/intel/ice/ice_rxtx_vec_avx512.c +12 -90

122 lines not on this page · raw message

Signature · 1 line
2.53.0
Acked-by on v1 10/13
#20 lore raw

RE: [PATCH 10/13] net/ice: use common AVX Tx functions

Quoted 5 lines

Subject: [PATCH 10/13] net/ice: use common AVX Tx functions

Use the newly created common Tx functions in the vector path.

Quoted 5 lines
---
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   |  72 +-------------
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 102 +++-----------------
 2 files changed, 14 insertions(+), 160 deletions(-)
#21 lore raw

PATCH 11/13 net/intel: add common vector Tx fns with context handling

In reply to Bruce Richardson

The iavf vector driver has support for more Tx offloads because it has Tx functions which handle transmit context descriptors. Move those context-handling functions to the common folder for reuse by other drivers.

---
 drivers/net/intel/common/tx_vec_x86.h         | 136 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   |  78 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c |  89 +-----------
 3 files changed, 147 insertions(+), 156 deletions(-)
drivers/net/intel/common/tx_vec_x86.h +136 -0
index 87386df8cd..f361137d23 100644
@@ -410,6 +410,74 @@ ci_xmit_fixed_burst_vec_avx2(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkts,
 	return nb_pkts;
 }
 
+static __rte_always_inline uint16_t
+ci_xmit_fixed_burst_vec_ctx_avx2(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkts,
+		uint16_t nb_pkts, bool offload,
+		enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		ci_tx_ctx_lldp_fn lldp_check)
+{
+	volatile struct ci_tx_desc *txdp;
+	struct ci_tx_entry_vec *txep;
+	uint16_t n, nb_commit, nb_mbuf, tx_id;
+	uint64_t flags = CI_TX_DESC_CMD_DEFAULT;
+	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
+
+	if (txq->nb_tx_free < txq->tx_free_thresh)
+		ci_tx_free_bufs_vec(txq, ci_tx_desc_done_simple, true);
+
+	nb_commit = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts << 1);
+	nb_commit &= 0xFFFE;
+	if (unlikely(nb_commit == 0))
+		return 0;
+
+	nb_pkts = nb_commit >> 1;
+	tx_id = txq->tx_tail;
+	txdp = &txq->ci_tx_ring[tx_id];
+	txep = (void *)txq->sw_ring;
+	txep += (tx_id >> 1);
+
+	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_commit);
+	n = (uint16_t)(txq->nb_tx_desc - tx_id);
+
+	if (n != 0 && nb_commit >= n) {
+		nb_mbuf = n >> 1;
+		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+		ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+		tx_pkts += (nb_mbuf - 1);
+		txdp += (n - 2);
+		ci_vtx1_ctx_avx2(txdp, *tx_pkts++, rs, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+
+		nb_commit = (uint16_t)(nb_commit - n);
+
+		txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1);
+		tx_id = 0;
+		/* avoid reach the end of ring */
+		txdp = txq->ci_tx_ring;
+		txep = (void *)txq->sw_ring;
+	}
+
+	nb_mbuf = nb_commit >> 1;
+	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+	ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf, flags, offload,
+			single_vlan_pos, qinq_outer_pos, lldp_check);
+	tx_id = (uint16_t)(tx_id + nb_commit);
+
+	if (tx_id > txq->tx_next_rs) {
+		txq->ci_tx_ring[txq->tx_next_rs].cmd_type_offset_bsz |=
+			rte_cpu_to_le_64(((uint64_t)CI_TX_DESC_CMD_RS) << CI_TXD_QW1_CMD_S);
+		txq->tx_next_rs = (uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh);
+	}
+
+	txq->tx_tail = tx_id;
+
+	ci_tx_qtx_tail_write(txq, tx_id);
+	return nb_pkts;
+}
+
 #endif /* __AVX2__ */
 
 #ifdef __AVX512VL__
@@ -642,6 +710,74 @@ ci_xmit_fixed_burst_vec_avx512(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkt
 	return nb_pkts;
 }
 
+static __rte_always_inline uint16_t
+ci_xmit_fixed_burst_vec_ctx_avx512(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkts,
+		uint16_t nb_pkts, bool offload,
+		enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		ci_tx_ctx_lldp_fn lldp_check)
+{
+	volatile struct ci_tx_desc *txdp;
+	struct ci_tx_entry_vec *txep;
+	uint16_t n, nb_commit, nb_mbuf, tx_id;
+	uint64_t flags = CI_TX_DESC_CMD_DEFAULT;
+	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
+
+	if (txq->nb_tx_free < txq->tx_free_thresh)
+		ci_tx_free_bufs_vec(txq, ci_tx_desc_done_simple, true);
+
+	nb_commit = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts << 1);
+	nb_commit &= 0xFFFE;
+	if (unlikely(nb_commit == 0))
+		return 0;
+
+	nb_pkts = nb_commit >> 1;
+	tx_id = txq->tx_tail;
+	txdp = &txq->ci_tx_ring[tx_id];
+	txep = (void *)txq->sw_ring;
+	txep += (tx_id >> 1);
+
+	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_commit);
+	n = (uint16_t)(txq->nb_tx_desc - tx_id);
+
+	if (n != 0 && nb_commit >= n) {
+		nb_mbuf = n >> 1;
+		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+		ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+		tx_pkts += (nb_mbuf - 1);
+		txdp += (n - 2);
+		ci_vtx1_ctx_avx512(txdp, *tx_pkts++, rs, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+
+		nb_commit = (uint16_t)(nb_commit - n);
+
+		txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1);
+		tx_id = 0;
+		/* avoid reach the end of ring */
+		txdp = txq->ci_tx_ring;
+		txep = (void *)txq->sw_ring;
+	}
+
+	nb_mbuf = nb_commit >> 1;
+	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+	ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf, flags, offload,
+			single_vlan_pos, qinq_outer_pos, lldp_check);
+	tx_id = (uint16_t)(tx_id + nb_commit);
+
+	if (tx_id > txq->tx_next_rs) {
+		txq->ci_tx_ring[txq->tx_next_rs].cmd_type_offset_bsz |=
+			rte_cpu_to_le_64(((uint64_t)CI_TX_DESC_CMD_RS) << CI_TXD_QW1_CMD_S);
+		txq->tx_next_rs = (uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh);
+	}
+
+	txq->tx_tail = tx_id;
+
+	ci_tx_qtx_tail_write(txq, tx_id);
+	return nb_pkts;
+}
+
 #endif /* __AVX512VL__ */
 
 #endif /* _COMMON_INTEL_TX_VEC_X86_H_ */
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +5 -73

97 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +6 -83

113 lines not on this page · raw message

Signature · 1 line
2.53.0
Acked-by on v1 11/13
#22 lore raw

RE: [PATCH 11/13] net/intel: add common vector Tx fns with context handling

Quoted 9 lines

Subject: [PATCH 11/13] net/intel: add common vector Tx fns with context handling

The iavf vector driver has support for more Tx offloads because it has Tx functions which handle transmit context descriptors. Move those context-handling functions to the common folder for reuse by other drivers.

Quoted 6 lines
---
 drivers/net/intel/common/tx_vec_x86.h         | 136 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   |  78 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c |  89 +-----------
 3 files changed, 147 insertions(+), 156 deletions(-)
#23 lore raw

PATCH 12/13 net/intel: improve Tx path selection logic

In reply to Bruce Richardson

Rework the relevant priority of context descriptor vs SIMD width when selecting a Tx path so that presence of context descriptors is only considered when all else is equal.

Normally, path select takes place without having to worry about context descriptors, since offloads requiring context descriptors are specified using the offloads bitmap for each Tx path. However, in some cases, the need to use a context descriptor is not encodable via this offload path, e.g. VLAN offload for iavf can sometimes use the data descriptor and sometimes the context depending on what PF specifies at runtime. To account for those cases, we separate out the use of contexts from the path features, but instead note it as part of the path information, and add an additional parameter to the Tx path selection for drivers to mandate a context descriptor be present. Otherwise, ctx is largely ignored in path selection, except as a last-resort tie-breaker between two paths.

---
 drivers/net/intel/common/tx.h      | 41 +++++++++++++++++---------
 drivers/net/intel/cpfl/cpfl_rxtx.c |  3 +-
 drivers/net/intel/i40e/i40e_rxtx.c |  2 +-
 drivers/net/intel/iavf/iavf_rxtx.c | 46 ++++++++++++++++--------------
 drivers/net/intel/ice/ice_rxtx.c   |  3 +-
 drivers/net/intel/idpf/idpf_rxtx.c |  3 +-
 6 files changed, 58 insertions(+), 40 deletions(-)
drivers/net/intel/common/tx.h +27 -14
index 630df8cb19..0f36989b32 100644
@@ -249,7 +249,6 @@ struct ci_tx_path_features {
 	uint32_t tx_offloads;
 	enum rte_vect_max_simd simd_width;
 	bool simple_tx;
-	bool ctx_desc;
 	bool disabled;
 	bool single_queue;
 };
@@ -259,6 +258,7 @@ struct ci_tx_path_info {
 	const char *info;
 	struct ci_tx_path_features features;
 	eth_tx_prep_t pkt_prep;
+	bool supports_ctx;
 };
 
 static __rte_always_inline void
@@ -411,6 +411,11 @@ ci_txq_release_all_mbufs(struct ci_tx_queue *txq, bool use_ctx)
  *   Number of available paths in the infos array
  * @param default_path
  *   Index of the default path to use if no suitable path is found
+ * @param force_ctx
+ *   If true, only paths that support context descriptors may be selected.
+ *   Use this for offloads that require a context descriptor but cannot be
+ *   discovered purely from req_features->tx_offloads (e.g. a driver-specific
+ *   devarg, or a runtime/hardware-negotiated tag placement).
  *
  * @return
  *   The packet burst function index that best matches the requested features,
@@ -420,10 +425,12 @@ static inline int
 ci_tx_path_select(const struct ci_tx_path_features *req_features,
 			const struct ci_tx_path_info *infos,
 			size_t num_paths,
-			int default_path)
+			int default_path,
+			bool force_ctx)
 {
 	int idx = default_path;
 	const struct ci_tx_path_features *chosen_path_features = NULL;
+	bool chosen_supports_ctx = false;
 
 	for (unsigned int i = 0; i < num_paths; i++) {
 		const struct ci_tx_path_features *path_features = &infos[i].features;
@@ -440,8 +447,8 @@ ci_tx_path_select(const struct ci_tx_path_features *req_features,
 		if (path_features->simple_tx && !req_features->simple_tx)
 			continue;
 
-		/* If a context descriptor is requested, ensure the path supports it. */
-		if (!path_features->ctx_desc && req_features->ctx_desc)
+		/* If a context descriptor is required, ensure the path supports it. */
+		if (!infos[i].supports_ctx && force_ctx)
 			continue;
 
 		/* If requested, ensure the path supports single queue TX. */
@@ -462,22 +469,28 @@ ci_tx_path_select(const struct ci_tx_path_features *req_features,
 			/* Do not select paths with lower SIMD width than the chosen path. */
 			if (path_features->simd_width < chosen_path_features->simd_width)
 				continue;
-			/* Do not select paths with more offloads enabled than the chosen path if
-			 * the SIMD widths are the same.
+			/* The following tie-breaks only matter when SIMD widths are tied;
+			 * a strictly wider path is always preferred regardless of offload
+			 * count or ctx-descriptor use.
 			 */
-			if (path_features->simd_width == chosen_path_features->simd_width &&
-					rte_popcount32(path_features->tx_offloads) >
-					rte_popcount32(chosen_path_features->tx_offloads))
-				continue;
-
-			/* Don't use a context descriptor unless necessary */
-			if (path_features->ctx_desc && !chosen_path_features->ctx_desc)
-				continue;
+			if (path_features->simd_width == chosen_path_features->simd_width) {
+				/* Do not select paths with more offloads enabled than the
+				 * chosen path.
+				 */
+				if (rte_popcount32(path_features->tx_offloads) >
+						rte_popcount32(chosen_path_features->tx_offloads))
+					continue;
+
+				/* Don't use a context descriptor unless necessary */
+				if (infos[i].supports_ctx && !chosen_supports_ctx)
+					continue;
+			}
 		}
 
 		/* Finally, select the path since it has met all the requirements. */
 		idx = i;
 		chosen_path_features = &infos[idx].features;
+		chosen_supports_ctx = infos[idx].supports_ctx;
 	}
 
 	return idx;
drivers/net/intel/cpfl/cpfl_rxtx.c +2 -1
index 2f1641ea76..aba3a5e916 100644
@@ -1542,7 +1542,8 @@ cpfl_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_func_type = ci_tx_path_select(&req_features,
 					&idpf_tx_path_infos[0],
 					IDPF_TX_MAX,
-					IDPF_TX_DEFAULT);
+					IDPF_TX_DEFAULT,
+					false);
 
 	/* Set use_vec_entry for single queue mode - only IDPF_TX_SINGLEQ uses regular entries */
 	if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
drivers/net/intel/i40e/i40e_rxtx.c +1 -1
index e2fffdb70a..f289d26790 100644
@@ -3120,7 +3120,7 @@ i40e_set_tx_function(struct rte_eth_dev *dev)
 	}
 
 	ad->tx_func_type = ci_tx_path_select(&req_features, &i40e_tx_path_infos[0],
-						RTE_DIM(i40e_tx_path_infos), I40E_TX_DEFAULT);
+			RTE_DIM(i40e_tx_path_infos), I40E_TX_DEFAULT, false);
 
 out:
 	dev->tx_pkt_burst = mbuf_check ? i40e_xmit_pkts_check :
drivers/net/intel/iavf/iavf_rxtx.c +24 -22

112 lines not on this page · raw message

drivers/net/intel/ice/ice_rxtx.c +2 -1
index 3569ffcf82..313cbd25d5 100644
@@ -3777,7 +3777,8 @@ ice_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_func_type = ci_tx_path_select(&req_features,
 						&ice_tx_path_infos[0],
 						RTE_DIM(ice_tx_path_infos),
-						ICE_TX_DEFAULT);
+						ICE_TX_DEFAULT,
+						false);
 
 out:
 #if defined(RTE_ARCH_X86)
drivers/net/intel/idpf/idpf_rxtx.c +2 -1
index bc3f9a0798..077a92a8a9 100644
@@ -887,7 +887,8 @@ idpf_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_func_type = ci_tx_path_select(&req_features,
 					&idpf_tx_path_infos[0],
 					IDPF_TX_MAX,
-					IDPF_TX_DEFAULT);
+					IDPF_TX_DEFAULT,
+					false);
 
 	/* Set use_vec_entry for single queue mode - only IDPF_TX_SINGLEQ uses regular entries */
 	if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
Signature · 1 line
2.53.0
Acked-by on v1 12/13
#24 lore raw

RE: [PATCH 12/13] net/intel: improve Tx path selection logic

Quoted 19 lines

Subject: [PATCH 12/13] net/intel: improve Tx path selection logic

Rework the relevant priority of context descriptor vs SIMD width when selecting a Tx path so that presence of context descriptors is only considered when all else is equal.

Normally, path select takes place without having to worry about context descriptors, since offloads requiring context descriptors are specified using the offloads bitmap for each Tx path. However, in some cases, the need to use a context descriptor is not encodable via this offload path, e.g. VLAN offload for iavf can sometimes use the data descriptor and sometimes the context depending on what PF specifies at runtime. To account for those cases, we separate out the use of contexts from the path features, but instead note it as part of the path information, and add an additional parameter to the Tx path selection for drivers to mandate a context descriptor be present. Otherwise, ctx is largely ignored in path selection, except as a last-resort tie-breaker between two paths.

Quoted 1 line
Quoted 9 lines
---
 drivers/net/intel/common/tx.h      | 41 +++++++++++++++++---------
 drivers/net/intel/cpfl/cpfl_rxtx.c |  3 +-
 drivers/net/intel/i40e/i40e_rxtx.c |  2 +-
 drivers/net/intel/iavf/iavf_rxtx.c | 46 ++++++++++++++++--------------
 drivers/net/intel/ice/ice_rxtx.c   |  3 +-
 drivers/net/intel/idpf/idpf_rxtx.c |  3 +-
 6 files changed, 58 insertions(+), 40 deletions(-)
#25 lore raw

PATCH 13/13 net/ice: enable context desc offloads for vector Tx

In reply to Bruce Richardson

Use the context descriptor Tx vector paths from intel/common in ice driver to enable more offloads on the vector path for ice driver.

---
 doc/guides/rel_notes/release_26_11.rst      |  6 ++++
 drivers/net/intel/ice/ice_ethdev.h          |  3 ++
 drivers/net/intel/ice/ice_rxtx.c            | 31 ++++++++++++++++++---
 drivers/net/intel/ice/ice_rxtx.h            | 11 ++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 24 ++++++++++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 24 ++++++++++++++++
 6 files changed, 95 insertions(+), 4 deletions(-)
doc/guides/rel_notes/release_26_11.rst +6 -0
index 907f9013ff..47eccd9401 100644
@@ -64,6 +64,12 @@ New Features
   * Renamed the ``enable_ptype_lldp`` devarg to ``enable_lldp``.
     The old name is no longer accepted.
 
+* **Updated Intel ice driver.**
+
+  * Added Tx context descriptor support to the AVX2 and AVX512 vector Tx
+    paths, enabling QinQ tag insertion and outer IPv4/UDP checksum
+    offloads on those paths.
+
 
 Removed Items
 -------------
drivers/net/intel/ice/ice_ethdev.h +3 -0
index 7ee3ea8a70..d357181a2a 100644
@@ -213,8 +213,10 @@ enum ice_tx_func_type {
 	ICE_TX_SIMPLE,
 	ICE_TX_AVX2,
 	ICE_TX_AVX2_OFFLOAD,
+	ICE_TX_AVX2_CTX_OFFLOAD,
 	ICE_TX_AVX512,
 	ICE_TX_AVX512_OFFLOAD,
+	ICE_TX_AVX512_CTX_OFFLOAD,
 	ICE_TX_NEON,
 };
 
@@ -673,6 +675,7 @@ struct ice_adapter {
 	bool rx_bulk_alloc_allowed;
 	bool tx_vec_allowed;
 	bool tx_simple_allowed;
+	bool use_ctx;
 	enum ice_rx_func_type rx_func_type;
 	enum ice_tx_func_type tx_func_type;
 	/* ptype mapping table */
drivers/net/intel/ice/ice_rxtx.c +27 -4
index 313cbd25d5..c6a464b2c1 100644
@@ -883,6 +883,7 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 
 	/* record what kind of descriptor cleanup we need on teardown */
 	txq->use_vec_entry = ad->tx_vec_allowed || ad->tx_simple_allowed;
+	txq->use_ctx = ad->use_ctx;
 
 	if (txq->tsq != NULL && txq->tsq->ts_flag > 0) {
 		struct ice_aqc_set_txtime_qgrp *ts_elem;
@@ -1193,7 +1194,7 @@ ice_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 		return -EINVAL;
 	}
 
-	ci_txq_release_all_mbufs(txq, false);
+	ci_txq_release_all_mbufs(txq, txq->use_ctx);
 	ice_reset_tx_queue(txq);
 	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
 
@@ -1256,7 +1257,7 @@ ice_fdir_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 		return -EINVAL;
 	}
 
-	ci_txq_release_all_mbufs(txq, false);
+	ci_txq_release_all_mbufs(txq, txq->use_ctx);
 	txq->qtx_tail = NULL;
 
 	return 0;
@@ -1744,7 +1745,7 @@ ice_tx_queue_release(void *txq)
 		return;
 	}
 
-	ci_txq_release_all_mbufs(q, false);
+	ci_txq_release_all_mbufs(q, q->use_ctx);
 	rte_free(q->sw_ring);
 	rte_free(q->rs_last_id);
 	if (q->tsq) {
@@ -3526,7 +3527,8 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.features = {
 			.tx_offloads = ICE_TX_SCALAR_OFFLOADS
 		},
-		.pkt_prep = ice_prep_pkts
+		.pkt_prep = ice_prep_pkts,
+		.supports_ctx = true
 	},
 	[ICE_TX_SIMPLE] = {
 		.pkt_burst = ice_xmit_pkts_simple,
@@ -3556,6 +3558,16 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		},
 		.pkt_prep = ice_prep_pkts
 	},
+	[ICE_TX_AVX2_CTX_OFFLOAD] = {
+		.pkt_burst = ice_xmit_pkts_vec_avx2_ctx_offload,
+		.info = "Offload Vector AVX2 Ctx",
+		.features = {
+			.tx_offloads = ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.simd_width = RTE_VECT_SIMD_256
+		},
+		.pkt_prep = ice_prep_pkts,
+		.supports_ctx = true
+	},
 #ifdef CC_AVX512_SUPPORT
 	[ICE_TX_AVX512] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx512,
@@ -3575,6 +3587,16 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		},
 		.pkt_prep = ice_prep_pkts
 	},
+	[ICE_TX_AVX512_CTX_OFFLOAD] = {
+		.pkt_burst = ice_xmit_pkts_vec_avx512_ctx_offload,
+		.info = "Offload Vector AVX512 Ctx",
+		.features = {
+			.tx_offloads = ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.simd_width = RTE_VECT_SIMD_512
+		},
+		.pkt_prep = ice_prep_pkts,
+		.supports_ctx = true
+	},
 #endif
 #elif defined(RTE_ARCH_ARM64)
 	[ICE_TX_NEON] = {
@@ -3788,6 +3810,7 @@ ice_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_vec_allowed =
 		(ice_tx_path_infos[ad->tx_func_type].features.simd_width >= RTE_VECT_SIMD_128);
 #endif
+	ad->use_ctx = ice_tx_path_infos[ad->tx_func_type].supports_ctx;
 
 	dev->tx_pkt_burst = mbuf_check ? ice_xmit_pkts_check :
 					 ice_tx_path_infos[ad->tx_func_type].pkt_burst;
drivers/net/intel/ice/ice_rxtx.h +11 -0
index 999b6b30d6..bee8a464f5 100644
@@ -135,6 +135,12 @@
 	RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
 	RTE_ETH_TX_OFFLOAD_TCP_CKSUM |		\
 	RTE_ETH_TX_OFFLOAD_SCTP_CKSUM)
+/* vector ctx offload path: QinQ outer tag + outer/tunnel checksum via ctx desc */
+#define ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS (	\
+	ICE_TX_VECTOR_OFFLOAD_OFFLOADS |	\
+	RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
+	RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
+	RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
 
 /* Max header size can be 2K - 64 bytes */
 #define ICE_RX_HDR_BUF_SIZE    (2048 - 64)
@@ -284,6 +290,8 @@ uint16_t ice_xmit_pkts_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 				uint16_t nb_pkts);
 uint16_t ice_xmit_pkts_vec_avx2_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
 					uint16_t nb_pkts);
+uint16_t ice_xmit_pkts_vec_avx2_ctx_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
+					uint16_t nb_pkts);
 uint16_t ice_recv_pkts_vec_avx512(void *rx_queue, struct rte_mbuf **rx_pkts,
 				  uint16_t nb_pkts);
 uint16_t ice_recv_pkts_vec_avx512_offload(void *rx_queue,
@@ -300,6 +308,9 @@ uint16_t ice_xmit_pkts_vec_avx512(void *tx_queue, struct rte_mbuf **tx_pkts,
 uint16_t ice_xmit_pkts_vec_avx512_offload(void *tx_queue,
 					  struct rte_mbuf **tx_pkts,
 					  uint16_t nb_pkts);
+uint16_t ice_xmit_pkts_vec_avx512_ctx_offload(void *tx_queue,
+					  struct rte_mbuf **tx_pkts,
+					  uint16_t nb_pkts);
 int ice_fdir_programming(struct ice_pf *pf, struct ice_fltr_desc *fdir_desc);
 int ice_tx_done_cleanup(void *txq, uint32_t free_cnt);
 int ice_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc);
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +24 -0
index 00b5d51aab..056b2dc49b 100644
@@ -810,6 +810,30 @@ ice_xmit_pkts_vec_avx2_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return ice_xmit_pkts_vec_avx2_common(tx_queue, tx_pkts, nb_pkts, true);
 }
 
+uint16_t
+ice_xmit_pkts_vec_avx2_ctx_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
+				   uint16_t nb_pkts)
+{
+	uint16_t nb_tx = 0;
+	struct ci_tx_queue *txq = (struct ci_tx_queue *)tx_queue;
+
+	while (nb_pkts) {
+		uint16_t ret, num;
+
+		/* cross rs_thresh boundary is not allowed */
+		num = (uint16_t)RTE_MIN(nb_pkts << 1, txq->tx_rs_thresh);
+		num = num >> 1;
+		ret = ci_xmit_fixed_burst_vec_ctx_avx2(tx_queue, &tx_pkts[nb_tx], num,
+				true, CI_TAG_IN_DATA_DESC, CI_TAG_IN_CTX_DESC, NULL);
+		nb_tx += ret;
+		nb_pkts -= ret;
+		if (ret < num)
+			break;
+	}
+
+	return nb_tx;
+}
+
 int __rte_cold
 ice_rxq_vec_setup(struct ci_rx_queue *rxq)
 {
drivers/net/intel/ice/ice_rxtx_vec_avx512.c +24 -0
index d8ede5cb42..0548c293bb 100644
@@ -882,3 +882,27 @@ ice_xmit_pkts_vec_avx512_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
 {
 	return ice_xmit_pkts_vec_avx512_common(tx_queue, tx_pkts, nb_pkts, true);
 }
+
+uint16_t
+ice_xmit_pkts_vec_avx512_ctx_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
+				     uint16_t nb_pkts)
+{
+	uint16_t nb_tx = 0;
+	struct ci_tx_queue *txq = (struct ci_tx_queue *)tx_queue;
+
+	while (nb_pkts) {
+		uint16_t ret, num;
+
+		/* cross rs_thresh boundary is not allowed */
+		num = (uint16_t)RTE_MIN(nb_pkts << 1, txq->tx_rs_thresh);
+		num = num >> 1;
+		ret = ci_xmit_fixed_burst_vec_ctx_avx512(tx_queue, &tx_pkts[nb_tx], num,
+				true, CI_TAG_IN_DATA_DESC, CI_TAG_IN_CTX_DESC, NULL);
+		nb_tx += ret;
+		nb_pkts -= ret;
+		if (ret < num)
+			break;
+	}
+
+	return nb_tx;
+}
Signature · 1 line
2.53.0
#26 lore raw

RE: [PATCH 13/13] net/ice: enable context desc offloads for vector Tx

Quoted 15 lines

Subject: [PATCH 13/13] net/ice: enable context desc offloads for vector Tx

Use the context descriptor Tx vector paths from intel/common in ice driver to enable more offloads on the vector path for ice driver.

---
 doc/guides/rel_notes/release_26_11.rst      |  6 ++++
 drivers/net/intel/ice/ice_ethdev.h          |  3 ++
 drivers/net/intel/ice/ice_rxtx.c            | 31 ++++++++++++++++++---
 drivers/net/intel/ice/ice_rxtx.h            | 11 ++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 24 ++++++++++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 24 ++++++++++++++++
 6 files changed, 95 insertions(+), 4 deletions(-)

<snip>

Quoted 10 lines
drivers/net/intel/ice/ice_rxtx.h +1 -0
index 999b6b30d6..bee8a464f5 100644
@@ -135,6 +135,12 @@
 	RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
 	RTE_ETH_TX_OFFLOAD_TCP_CKSUM |		\
 	RTE_ETH_TX_OFFLOAD_SCTP_CKSUM)
+/* vector ctx offload path: QinQ outer tag + outer/tunnel checksum via ctx

desc */

drivers/net/intel/ice/ice_rxtx.h line 143

Quoted 5 lines
drivers/net/intel/ice/ice_rxtx.h +5 -0
+#define ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS (	\
+	ICE_TX_VECTOR_OFFLOAD_OFFLOADS |	\
+	RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
+	RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
+	RTE_ETH_TX_OFFLOAD_QINQ_INSERT)

Now that the paths and thus offloads are shared, is it worth creating common OFFLOADS masks? I assume IAVF_TX_VECTOR_CTX_OFFLOAD_OFFLOADS is an exact match for ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS

Quoted 1 line
#27 lore raw

Re: [PATCH 13/13] net/ice: enable context desc offloads for vector Tx

Quoted 30 lines · Ciara
Quoted 15 lines

Subject: [PATCH 13/13] net/ice: enable context desc offloads for vector Tx

Use the context descriptor Tx vector paths from intel/common in ice driver to enable more offloads on the vector path for ice driver.

---
 doc/guides/rel_notes/release_26_11.rst      |  6 ++++
 drivers/net/intel/ice/ice_ethdev.h          |  3 ++
 drivers/net/intel/ice/ice_rxtx.c            | 31 ++++++++++++++++++---
 drivers/net/intel/ice/ice_rxtx.h            | 11 ++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 24 ++++++++++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 24 ++++++++++++++++
 6 files changed, 95 insertions(+), 4 deletions(-)

<snip>

Quoted 12 lines
drivers/net/intel/ice/ice_rxtx.h +1 -0
index 999b6b30d6..bee8a464f5 100644
@@ -135,6 +135,12 @@
 	RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
 	RTE_ETH_TX_OFFLOAD_TCP_CKSUM |		\
 	RTE_ETH_TX_OFFLOAD_SCTP_CKSUM)
+/* vector ctx offload path: QinQ outer tag + outer/tunnel checksum via ctx

desc */

drivers/net/intel/ice/ice_rxtx.h +2 -0
+#define ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS (	\
+	ICE_TX_VECTOR_OFFLOAD_OFFLOADS |	\
Quoted 9 lines

drivers/net/intel/ice/ice_rxtx.h line 143

Quoted 3 lines
drivers/net/intel/ice/ice_rxtx.h +3 -0
+	RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
+	RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
+	RTE_ETH_TX_OFFLOAD_QINQ_INSERT)

Now that the paths and thus offloads are shared, is it worth creating common OFFLOADS masks? I assume IAVF_TX_VECTOR_CTX_OFFLOAD_OFFLOADS is an exact match for ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS

Yes, it is probably worth doing. Not sure if it's best in this patchset or not. Let me investigate.

/Bruce

#28 lore raw
In reply to Bruce Richardson
Quoted 35 lines · Bruce Richardson

This patchset consolidates the ice and iavf vector Tx paths, moving the code to net/intel/common. The iavf code is used as the basis for the move, because it has a superset of the features. When the common code is adopted by the ice driver, it then gains features such as QinQ support and tunneling support.

Depends-on: series-39162 ("VLAN and QinQ fixes for iavf")

Bruce Richardson (13):
net/iavf: remove unnecessary alignment calls net/intel: make Tx context flag common
net/iavf: use separate params for VLAN and QinQ position net/iavf: deduplicate tunnel field fill functions net/intel: define common macros for tunneling bit-shifts net/intel: move iavf descriptor writing functions to common net/intel: use function callback for lldp net/ice: use common descriptor creation functions net/intel: move vector Tx paths to common net/ice: use common AVX Tx functions
net/intel: add common vector Tx fns with context handling net/intel: improve Tx path selection logic net/ice: enable context desc offloads for vector Tx

 doc/guides/rel_notes/release_26_11.rst        |   6 +
 drivers/net/intel/common/tx.h                 |  77 +-
 drivers/net/intel/common/tx_vec_x86.h         | 783 ++++++++++++++++++
 drivers/net/intel/cpfl/cpfl_rxtx.c            |   3 +-
 drivers/net/intel/i40e/i40e_rxtx.c            |   2 +-
 drivers/net/intel/iavf/iavf_rxtx.c            |  76 +-
 drivers/net/intel/iavf/iavf_rxtx.h            |  34 -
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 496 +----------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 495 +----------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  76 +-
 drivers/net/intel/ice/ice_ethdev.h            |   3 +
Quoted 8 lines
 drivers/net/intel/ice/ice_rxtx.c              |  34 +-
 drivers/net/intel/ice/ice_rxtx.h              |  11 +
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c     | 159 +---
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c   | 154 +---
 drivers/net/intel/ice/ice_rxtx_vec_common.h   |  59 --
 drivers/net/intel/idpf/idpf_rxtx.c            |   3 +-
 17 files changed, 1025 insertions(+), 1446 deletions(-)
 create mode 100644 drivers/net/intel/common/tx_vec_x86.h

I do not have the time to review in detail but this series looks good to me. My bench setup is unavailable and I am busy on other topics, so I won't be able to test it soon.

But in any case, thank you Bruce, nice cleanup again.

Signature · 1 line
David Marchand
#29 lore raw

v2 cover consolidate ice and iavf Tx vector paths

In reply to Bruce Richardson

This patchset consolidates the ice and iavf vector Tx paths, moving the code to net/intel/common. The iavf code is used as the basis for the move, because it has a superset of the features. When the common code is adopted by the ice driver, it then gains features such as QinQ support and tunneling support.

V2:
* fix build when iova not in mbuf
* add extra patch to consolidate the offload flags

Bruce Richardson (15):
net/iavf: remove unnecessary alignment calls net/intel: make Tx context flag common
net/iavf: use separate params for VLAN and QinQ position net/iavf: deduplicate tunnel field fill functions net/intel: define common macros for tunneling bit-shifts net/intel: move iavf descriptor writing functions to common net/intel: use function callback for lldp net/intel: allow building without IOVA in mbuf net/ice: use common descriptor creation functions net/intel: move vector Tx paths to common net/ice: use common AVX Tx functions
net/intel: add common vector Tx fns with context handling net/intel: improve Tx path selection logic net/ice: enable context desc offloads for vector Tx net/intel: consolidate Tx vector offload path checks

 doc/guides/rel_notes/release_26_11.rst        |   6 +
 drivers/net/intel/common/tx.h                 | 107 ++-
 drivers/net/intel/common/tx_vec_x86.h         | 781 ++++++++++++++++++
 drivers/net/intel/cpfl/cpfl_rxtx.c            |   3 +-
 drivers/net/intel/i40e/i40e_rxtx.c            |   2 +-
 drivers/net/intel/iavf/iavf_rxtx.c            |  94 +--
 drivers/net/intel/iavf/iavf_rxtx.h            |  53 --
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 496 +----------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 495 +----------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  79 +-
 drivers/net/intel/iavf/meson.build            |   4 +-
 drivers/net/intel/ice/ice_ethdev.h            |   3 +
 drivers/net/intel/ice/ice_rxtx.c              |  44 +-
 drivers/net/intel/ice/ice_rxtx.h              |  17 +-
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c     | 159 +---
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c   | 154 +---
 drivers/net/intel/ice/ice_rxtx_vec_common.h   |  62 +-
 drivers/net/intel/idpf/idpf_rxtx.c            |   3 +-
 18 files changed, 1064 insertions(+), 1498 deletions(-)
 create mode 100644 drivers/net/intel/common/tx_vec_x86.h

--
2.53.0

#30 lore raw

PATCH v2 1/15 net/iavf: remove unnecessary alignment calls

When we have a context descriptor on Tx of a packet from the vector paths, that means that we always have 32-bytes being written per descriptor/per packet, so the stores are always 32-bit aligned. This means we can use aligned stores for each single descriptor store, and that we never need to do an initial descriptor write for alignment when doing a burst of descriptors.

---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 9 ++-------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 9 ++-------
 2 files changed, 4 insertions(+), 14 deletions(-)
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +2 -7
index 7217f32cef..9b62ef53d3 100644
@@ -1933,7 +1933,8 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
 							high_ctx_qw, low_ctx_qw);
 
-	_mm256_storeu_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
 }
 
 static __rte_always_inline void
@@ -1944,12 +1945,6 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 	uint64_t hi_data_qw_tmpl = (IAVF_TX_DESC_DTYPE_DATA |
 					((uint64_t)flags  << IAVF_TXD_QW1_CMD_SHIFT));
 
-	/* if unaligned on 32-bit boundary, do one to align */
-	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		ctx_vtx1(txdp, *pkt, flags, offload, vlan_flag, ptype_lldp_enabled);
-		nb_pkts--; txdp++; pkt++;
-	}
-
 	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
 		uint64_t hi_ctx_qw1 = IAVF_TX_DESC_DTYPE_CONTEXT;
 		uint64_t hi_ctx_qw0 = IAVF_TX_DESC_DTYPE_CONTEXT;
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +2 -7
index bf0245e8f4..4609c2245a 100644
@@ -2078,7 +2078,8 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
 							high_ctx_qw, low_ctx_qw);
 
-	_mm256_storeu_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
 }
 
 static __rte_always_inline void
@@ -2088,12 +2089,6 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 {
 	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
 
-	/* if unaligned on 32-bit boundary, do one to align */
-	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		ctx_vtx1(txdp, *pkt, flags, offload, vlan_flag, lldp_enabled);
-		nb_pkts--; txdp++; pkt++;
-	}
-
 	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
 		uint64_t hi_ctx_qw1 = IAVF_TX_DESC_DTYPE_CONTEXT;
 		uint64_t hi_ctx_qw0 = IAVF_TX_DESC_DTYPE_CONTEXT;
Signature · 1 line
2.53.0
#31 lore raw

PATCH v2 2/15 net/intel: make Tx context flag common

In reply to Bruce Richardson

The flag for enabling context descriptors in the vector paths should not be limited to just the iavf driver, as other drivers may use context paths in future also. Therefore move the flag out of the iavf-specific part of the Tx queue structure, to put with other standard queue flags.

---
 drivers/net/intel/common/tx.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/intel/common/tx.h +1 -1
index 2d4a8b5d3c..fb5268c972 100644
@@ -173,6 +173,7 @@ struct ci_tx_queue {
 	bool tx_deferred_start; /* don't start this queue in dev start */
 	bool q_set;             /* indicate if tx queue has been configured */
 	bool use_vec_entry;     /* use sw_ring_vec (true for vector and simple paths) */
+	bool use_ctx;           /* with ctx info, each pkt needs two desc in vec paths */
 	union {                  /* the VSI this queue belongs to */
 		struct i40e_vsi *i40e_vsi;
 		struct iavf_vsi *iavf_vsi;
@@ -194,7 +195,6 @@ struct ci_tx_queue {
 #define IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 BIT(1)
 			uint8_t vlan_flag;
 			uint8_t tc;
-			bool use_ctx;  /* with ctx info, each pkt needs two descriptors */
 			bool lldp_enabled;
 		};
 		struct { /* ixgbe specific values */
Signature · 1 line
2.53.0
#32 lore raw

PATCH v2 3/15 net/iavf: use separate params for VLAN and QinQ position

In reply to Bruce Richardson

Like is the case with the scalar path, use separate offload parameters for the vector path to distinguish between the position of the single VLAN tag and the QinQ outer tag. With iavf these are currently always the same, but other drivers - with whom we may want to share code - have different positions for these.

---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 64 +++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 62 ++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h | 11 ++--
 3 files changed, 77 insertions(+), 60 deletions(-)
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +37 -27
index 9b62ef53d3..2aaa713702 100644
@@ -1619,13 +1619,14 @@ iavf_recv_scattered_pkts_vec_avx2_flex_rxd_offload(void *rx_queue,
 
 static __rte_always_inline void
 iavf_vtx1(volatile struct ci_tx_desc *txdp,
-	  struct rte_mbuf *pkt, uint64_t flags, bool offload, uint8_t vlan_flag)
+	  struct rte_mbuf *pkt, uint64_t flags, bool offload,
+	  enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
 {
 	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
 		 ((uint64_t)flags << CI_TXD_QW1_CMD_S) |
 		 ((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
 	if (offload)
-		iavf_txd_enable_offload(pkt, &high_qw, vlan_flag);
+		iavf_txd_enable_offload(pkt, &high_qw, single_vlan_pos, qinq_outer_pos);
 
 	__m128i descriptor = _mm_set_epi64x(high_qw,
 				pkt->buf_iova + pkt->data_off);
@@ -1634,13 +1635,14 @@ iavf_vtx1(volatile struct ci_tx_desc *txdp,
 
 static __rte_always_inline void
 iavf_vtx(volatile struct ci_tx_desc *txdp,
-	 struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload, uint8_t vlan_flag)
+	 struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload,
+	 enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
 {
 	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
 
 	/* if unaligned on 32-bit boundary, do one to align */
 	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		iavf_vtx1(txdp, *pkt, flags, offload, vlan_flag);
+		iavf_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
 		nb_pkts--; txdp++; pkt++;
 	}
 
@@ -1649,19 +1651,19 @@ iavf_vtx(volatile struct ci_tx_desc *txdp,
 		uint64_t hi_qw3 = hi_qw_tmpl |
 			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[3], &hi_qw3, vlan_flag);
+			iavf_txd_enable_offload(pkt[3], &hi_qw3, single_vlan_pos, qinq_outer_pos);
 		uint64_t hi_qw2 = hi_qw_tmpl |
 			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[2], &hi_qw2, vlan_flag);
+			iavf_txd_enable_offload(pkt[2], &hi_qw2, single_vlan_pos, qinq_outer_pos);
 		uint64_t hi_qw1 = hi_qw_tmpl |
 			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[1], &hi_qw1, vlan_flag);
+			iavf_txd_enable_offload(pkt[1], &hi_qw1, single_vlan_pos, qinq_outer_pos);
 		uint64_t hi_qw0 = hi_qw_tmpl |
 			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[0], &hi_qw0, vlan_flag);
+			iavf_txd_enable_offload(pkt[0], &hi_qw0, single_vlan_pos, qinq_outer_pos);
 
 		__m256i desc2_3 =
 			_mm256_set_epi64x
@@ -1681,7 +1683,7 @@ iavf_vtx(volatile struct ci_tx_desc *txdp,
 
 	/* do any last ones */
 	while (nb_pkts) {
-		iavf_vtx1(txdp, *pkt, flags, offload, vlan_flag);
+		iavf_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
 		txdp++; pkt++; nb_pkts--;
 	}
 }
@@ -1697,6 +1699,9 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	/* bit2 is reserved and must be set to 1 according to Spec */
 	uint64_t flags = CI_TX_DESC_CMD_EOP | CI_TX_DESC_CMD_ICRC;
 	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
+	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
+	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
+			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
 
 	if (txq->nb_tx_free < txq->tx_free_thresh)
 		ci_tx_free_bufs_vec(txq, iavf_tx_desc_done, false);
@@ -1716,11 +1721,11 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	if (nb_commit >= n) {
 		ci_tx_backlog_entry_vec(txep, tx_pkts, n);
 
-		iavf_vtx(txdp, tx_pkts, n - 1, flags, offload, txq->vlan_flag);
+		iavf_vtx(txdp, tx_pkts, n - 1, flags, offload, vlan_pos, vlan_pos);
 		tx_pkts += (n - 1);
 		txdp += (n - 1);
 
-		iavf_vtx1(txdp, *tx_pkts++, rs, offload, txq->vlan_flag);
+		iavf_vtx1(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -1734,7 +1739,7 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_commit);
 
-	iavf_vtx(txdp, tx_pkts, nb_commit, flags, offload, txq->vlan_flag);
+	iavf_vtx(txdp, tx_pkts, nb_commit, flags, offload, vlan_pos, vlan_pos);
 
 	tx_id = (uint16_t)(tx_id + nb_commit);
 	if (tx_id > txq->tx_next_rs) {
@@ -1903,7 +1908,8 @@ iavf_fill_ctx_desc_tunneling_field(volatile uint64_t *qw0,
 
 static __rte_always_inline void
 ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
-		uint64_t flags, bool offload, uint8_t vlan_flag, bool ptype_lldp_enabled)
+		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
+		enum ci_l2tag_pos qinq_outer_pos, bool ptype_lldp_enabled)
 {
 	uint64_t high_ctx_qw = IAVF_TX_DESC_DTYPE_CONTEXT;
 	uint64_t low_ctx_qw = 0;
@@ -1911,13 +1917,13 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	if (offload) {
 		iavf_fill_ctx_desc_tunneling_avx2(&low_ctx_qw, pkt);
 		if (pkt->ol_flags & RTE_MBUF_F_TX_QINQ) {
-			uint64_t qinq_tag = vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 ?
+			uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 				(uint64_t)pkt->vlan_tci_outer :
 				(uint64_t)pkt->vlan_tci;
 			high_ctx_qw |= IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 			low_ctx_qw |= qinq_tag << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 		} else if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) &&
-				vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2) {
+				single_vlan_pos == CI_TAG_IN_CTX_DESC) {
 			high_ctx_qw |= IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 			low_ctx_qw |= (uint64_t)pkt->vlan_tci << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 		}
@@ -1928,7 +1934,7 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 				((uint64_t)flags  << IAVF_TXD_QW1_CMD_SHIFT) |
 				((uint64_t)pkt->data_len << IAVF_TXD_QW1_TX_BUF_SZ_SHIFT));
 	if (offload)
-		iavf_txd_enable_offload(pkt, &high_data_qw, vlan_flag);
+		iavf_txd_enable_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
 
 	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
 							high_ctx_qw, low_ctx_qw);
@@ -1940,7 +1946,8 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 static __rte_always_inline void
 ctx_vtx(volatile struct ci_tx_desc *txdp,
 		struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags,
-		bool offload, uint8_t vlan_flag, bool ptype_lldp_enabled)
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		bool ptype_lldp_enabled)
 {
 	uint64_t hi_data_qw_tmpl = (IAVF_TX_DESC_DTYPE_DATA |
 					((uint64_t)flags  << IAVF_TXD_QW1_CMD_SHIFT));
@@ -1964,14 +1971,14 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
 			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw1, pkt[1]);
 			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
-				uint64_t qinq_tag = vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 ?
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[1]->vlan_tci_outer :
 					(uint64_t)pkt[1]->vlan_tci;
 				hi_ctx_qw1 |= IAVF_TX_CTX_DESC_IL2TAG2 <<
 						IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw1 |= qinq_tag << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 			} else if (pkt[1]->ol_flags & RTE_MBUF_F_TX_VLAN &&
-					vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2) {
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
 				hi_ctx_qw1 |=
 					IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw1 |=
@@ -1985,14 +1992,14 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
 			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw0, pkt[0]);
 			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
-				uint64_t qinq_tag = vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 ?
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[0]->vlan_tci_outer :
 					(uint64_t)pkt[0]->vlan_tci;
 				hi_ctx_qw0 |= IAVF_TX_CTX_DESC_IL2TAG2 <<
 						IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw0 |= qinq_tag << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 			} else if (pkt[0]->ol_flags & RTE_MBUF_F_TX_VLAN &&
-					vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2) {
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
 				hi_ctx_qw0 |=
 					IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw0 |=
@@ -2003,8 +2010,8 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 
 		if (offload) {
-			iavf_txd_enable_offload(pkt[1], &hi_data_qw1, vlan_flag);
-			iavf_txd_enable_offload(pkt[0], &hi_data_qw0, vlan_flag);
+			iavf_txd_enable_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
+			iavf_txd_enable_offload(pkt[0], &hi_data_qw0, single_vlan_pos, qinq_outer_pos);
 		}
 
 		__m256i desc2_3 =
@@ -2020,7 +2027,7 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 	}
 
 	if (nb_pkts)
-		ctx_vtx1(txdp, *pkt, flags, offload, vlan_flag, ptype_lldp_enabled);
+		ctx_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos, ptype_lldp_enabled);
 }
 
 static __rte_always_inline uint16_t
@@ -2035,6 +2042,9 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	uint64_t flags = IAVF_TX_DESC_CMD_EOP | IAVF_TX_DESC_CMD_ICRC;
 	uint64_t rs = IAVF_TX_DESC_CMD_RS | flags;
 	bool lldp_enabled = txq->lldp_enabled;
+	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
+	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
+			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
 
 	if (txq->nb_tx_free < txq->tx_free_thresh)
 		ci_tx_free_bufs_vec(txq, iavf_tx_desc_done, true);
@@ -2057,10 +2067,10 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 		nb_mbuf = n >> 1;
 		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
-		ctx_vtx(txdp, tx_pkts, nb_mbuf - 1, flags, offload, txq->vlan_flag, lldp_enabled);
+		ctx_vtx(txdp, tx_pkts, nb_mbuf - 1, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
 		tx_pkts += (nb_mbuf - 1);
 		txdp += (n - 2);
-		ctx_vtx1(txdp, *tx_pkts++, rs, offload, txq->vlan_flag, lldp_enabled);
+		ctx_vtx1(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_enabled);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -2074,7 +2084,7 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	nb_mbuf = nb_commit >> 1;
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
-	ctx_vtx(txdp, tx_pkts, nb_mbuf, flags, offload, txq->vlan_flag, lldp_enabled);
+	ctx_vtx(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
 	tx_id = (uint16_t)(tx_id + nb_commit);
 
 	if (tx_id > txq->tx_next_rs) {
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +35 -27

200 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_common.h +5 -6
index 1e9ce924ee..e99964eaef 100644
@@ -121,14 +121,13 @@ iavf_tx_vec_dev_check_default(struct rte_eth_dev *dev)
 
 static __rte_always_inline void
 iavf_txd_enable_offload(__rte_unused struct rte_mbuf *tx_pkt,
-			uint64_t *txd_hi, uint8_t vlan_flag)
+			uint64_t *txd_hi, enum ci_l2tag_pos single_vlan_pos,
+			enum ci_l2tag_pos qinq_outer_pos)
 {
 	uint64_t ol_flags = tx_pkt->ol_flags;
 	uint32_t td_cmd = 0;
 	uint32_t td_offset = 0;
 
-	RTE_SET_USED(vlan_flag);
-
 	/* Set MACLEN */
 	if (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)
 		td_offset |= (tx_pkt->outer_l2_len >> 1)
@@ -179,12 +178,12 @@ iavf_txd_enable_offload(__rte_unused struct rte_mbuf *tx_pkt,
 
 	if (ol_flags & RTE_MBUF_F_TX_QINQ) {
 		td_cmd |= IAVF_TX_DESC_CMD_IL2TAG1;
-		/* vlan_flag specifies outer tag location for QinQ. */
-		if (vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1)
+		/* L2Tag1 always carries a tag for QinQ */
+		if (qinq_outer_pos == CI_TAG_IN_DATA_DESC)
 			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci_outer << CI_TXD_QW1_L2TAG1_S);
 		else
 			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
-	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) {
+	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && single_vlan_pos == CI_TAG_IN_DATA_DESC) {
 		td_cmd |= CI_TX_DESC_CMD_IL2TAG1;
 		*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
 	}
Signature · 1 line
2.53.0
#33 lore raw

PATCH v2 4/15 net/iavf: deduplicate tunnel field fill functions

In reply to Bruce Richardson

Each of the avx2 and avx512 Tx functions used two separate subfunctions to insert the tunneling fields into the context descriptor. Except for some minor differences (a flags guard on one) the two were identical, so remove the one missing the additional guard.

---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 77 +------------------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 77 +------------------
 2 files changed, 4 insertions(+), 150 deletions(-)
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +2 -75
index 2aaa713702..10e96a8510 100644
@@ -1833,79 +1833,6 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 	}
 }
 
-static inline void
-iavf_fill_ctx_desc_tunneling_field(volatile uint64_t *qw0,
-		const struct rte_mbuf *m)
-{
-	uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
-	uint64_t eip_len = 0;
-	uint64_t eip_noinc = 0;
-	/* Default - IP_ID is increment in each segment of LSO */
-
-	switch (m->ol_flags & (RTE_MBUF_F_TX_OUTER_IPV4 |
-			RTE_MBUF_F_TX_OUTER_IPV6 |
-			RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
-	case RTE_MBUF_F_TX_OUTER_IPV4:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
-		eip_len = m->outer_l3_len >> 2;
-	break;
-	case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
-		eip_len = m->outer_l3_len >> 2;
-	break;
-	case RTE_MBUF_F_TX_OUTER_IPV6:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
-		eip_len = m->outer_l3_len >> 2;
-	break;
-	}
-
-	/* L4TUNT: L4 Tunneling Type */
-	switch (m->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
-	case RTE_MBUF_F_TX_TUNNEL_IPIP:
-		/* for non UDP / GRE tunneling, set to 00b */
-		break;
-	case RTE_MBUF_F_TX_TUNNEL_VXLAN:
-	case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
-	case RTE_MBUF_F_TX_TUNNEL_GTP:
-	case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-		eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
-		break;
-	case RTE_MBUF_F_TX_TUNNEL_GRE:
-		eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
-		break;
-	default:
-		PMD_TX_LOG(ERR, "Tunnel type not supported");
-		return;
-	}
-
-	/* L4TUNLEN: L4 Tunneling Length, in Words
-	 *
-	 * We depend on app to set rte_mbuf.l2_len correctly.
-	 * For IP in GRE it should be set to the length of the GRE
-	 * header;
-	 * For MAC in GRE or MAC in UDP it should be set to the length
-	 * of the GRE or UDP headers plus the inner MAC up to including
-	 * its last Ethertype.
-	 * If MPLS labels exists, it should include them as well.
-	 */
-	eip_typ |= (m->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
-
-	/**
-	 * Calculate the tunneling UDP checksum.
-	 * Shall be set only if L4TUNT = 01b and EIPT is not zero
-	 */
-	if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV6 |
-				IAVF_TX_CTX_EXT_IP_IPV4 |
-				IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-			(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
-			(m->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-		eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
-
-	*qw0 = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-		eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-		eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
-}
-
 static __rte_always_inline void
 ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
@@ -1969,7 +1896,7 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
-			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw1, pkt[1]);
+			iavf_fill_ctx_desc_tunneling_avx2(&low_ctx_qw1, pkt[1]);
 			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
 				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[1]->vlan_tci_outer :
@@ -1990,7 +1917,7 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
-			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw0, pkt[0]);
+			iavf_fill_ctx_desc_tunneling_avx2(&low_ctx_qw0, pkt[0]);
 			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
 				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[0]->vlan_tci_outer :
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +2 -75

95 lines not on this page · raw message

Signature · 1 line
2.53.0
#34 lore raw

PATCH v2 5/15 net/intel: define common macros for tunneling bit-shifts

In reply to Bruce Richardson

Define common macros for use in iavf (for now) and other drivers (future) defining the shifts needed for tunnel packet Tx

---
 drivers/net/intel/common/tx.h                 | 24 +++++++++++++
 drivers/net/intel/iavf/iavf_rxtx.c            | 30 ++++++++--------
 drivers/net/intel/iavf/iavf_rxtx.h            | 34 -------------------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 30 ++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 30 ++++++++--------
 5 files changed, 69 insertions(+), 79 deletions(-)
drivers/net/intel/common/tx.h +24 -0
index fb5268c972..c8fadee712 100644
@@ -45,6 +45,30 @@
 #define CI_TX_CTX_DESC_TSYN             0x02
 #define CI_TX_CTX_DESC_IL2TAG2          0x04
 
+/* Common TX Context Descriptor QW0 Field Shifts */
+#define CI_TXD_CTX_QW0_L2TAG2_S         32
+#define CI_TXD_CTX_QW0_EIPT_S           0  /* 2 BITS - external IP type */
+#define CI_TXD_CTX_QW0_EIPLEN_S         2  /* 7 BITS - external IP header length */
+#define CI_TXD_CTX_QW0_NATT_S           9  /* 2 BITS - L4 tunnel type */
+#define CI_TXD_CTX_QW0_EIP_NOINC_S      11 /* 1 BIT  - external IP ID not incremented */
+#define CI_TXD_CTX_QW0_NATLEN_S         12 /* 7 BITS - L4 tunnel header length */
+#define CI_TXD_CTX_QW0_L4T_CS_S         23 /* 1 BIT  - tunnel UDP checksum enable */
+
+/**
+ * Enum for the external (outer) IP type field of a Tx context descriptor's
+ * tunnel parameters (QW0 bits 0-1).
+ */
+enum ci_tx_ctx_eipt {
+	CI_TX_CTX_EIPT_NONE,
+	CI_TX_CTX_EIPT_IPV6,
+	CI_TX_CTX_EIPT_IPV4_NO_CSUM,
+	CI_TX_CTX_EIPT_IPV4,
+};
+
+#define CI_TXD_CTX_UDP_TUNNELING        (0x1ULL << CI_TXD_CTX_QW0_NATT_S)
+#define CI_TXD_CTX_GRE_TUNNELING        (0x2ULL << CI_TXD_CTX_QW0_NATT_S)
+#define CI_TXD_CTX_QW0_L4T_CS_M         (0x1ULL << CI_TXD_CTX_QW0_L4T_CS_S)
+
 /**
  * Enum to specify where a VLAN tag is to be placed for packet Tx.
  */
drivers/net/intel/iavf/iavf_rxtx.c +15 -15
index 80c9912ccc..849fc33dac 100644
@@ -2345,7 +2345,7 @@ iavf_calc_context_desc(const struct rte_mbuf *mb, uint8_t vlan_flag, bool lldp_e
 static inline void
 iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const struct rte_mbuf *m)
 {
-	uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
+	uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
 	uint64_t eip_len = 0;
 	uint64_t eip_noinc = 0;
 	/* Default - IP_ID is increment in each segment of LSO */
@@ -2354,15 +2354,15 @@ iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const stru
 			RTE_MBUF_F_TX_OUTER_IPV6 |
 			RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
 	case RTE_MBUF_F_TX_OUTER_IPV4:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
+		eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
 		eip_len = m->outer_l3_len >> 2;
 	break;
 	case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
+		eip_typ = CI_TX_CTX_EIPT_IPV4;
 		eip_len = m->outer_l3_len >> 2;
 	break;
 	case RTE_MBUF_F_TX_OUTER_IPV6:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
+		eip_typ = CI_TX_CTX_EIPT_IPV6;
 		eip_len = m->outer_l3_len >> 2;
 	break;
 	}
@@ -2377,10 +2377,10 @@ iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const stru
 		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
 		case RTE_MBUF_F_TX_TUNNEL_GTP:
 		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-			eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
 			break;
 		case RTE_MBUF_F_TX_TUNNEL_GRE:
-			eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
 			break;
 		default:
 			PMD_TX_LOG(ERR, "Tunnel type not supported");
@@ -2397,23 +2397,23 @@ iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const stru
 		 * its last Ethertype.
 		 * If MPLS labels exists, it should include them as well.
 		 */
-		eip_typ |= (m->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
+		eip_typ |= (m->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
 
 		/**
 		 * Calculate the tunneling UDP checksum.
 		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
 		 */
-		if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV6 |
-					IAVF_TX_CTX_EXT_IP_IPV4 |
-					IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-				(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
 				(ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-			eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
 	}
 
-	*qw0 = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-		eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-		eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
+	*qw0 = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+		eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+		eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
 }
 
 static inline uint16_t
drivers/net/intel/iavf/iavf_rxtx.h +0 -34
index 3ff49b94b4..19931f5f7c 100644
@@ -444,40 +444,6 @@ enum iavf_rx_flex_desc_ipsec_crypto_status {
 #define IAVF_TXD_CTX_QW1_SEG_PARAMS_MSS_MASK		\
 	(0x3FFFUL << IAVF_TXD_CTX_QW1_SEG_PARAMS_MSS_SHIFT)
 
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT		(0)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_MASK		(0x3UL)
-
-enum iavf_tx_ctx_desc_tunnel_external_ip_type {
-	IAVF_TX_CTX_DESC_EIPT_NONE,
-	IAVF_TX_CTX_DESC_EIPT_IPV6,
-	IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD,
-	IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD
-};
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT	(2)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_MASK		(0x7FUL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNT_SHIFT	(9)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNT_MASK		(0x3UL)
-
-enum iavf_tx_ctx_desc_tunnel_l4_tunnel_type {
-	IAVF_TX_CTX_DESC_L4_TUN_TYP_NO_UDP_GRE,
-	IAVF_TX_CTX_DESC_L4_TUN_TYP_UDP,
-	IAVF_TX_CTX_DESC_L4_TUN_TYP_GRE
-};
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT	(11)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_MASK	(0x1UL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNLEN_SHIFT	(12)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNLEN_MASK	(0x7FUL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_DECTTL_SHIFT	(19)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_DECTTL_MASK		(0xFUL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4T_CS_SHIFT	(23)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4T_CS_MASK		(0x1UL)
-
 #define IAVF_TXD_CTX_QW0_L2TAG2_PARAM			(32)
 #define IAVF_TXD_CTX_QW0_L2TAG2_MASK			(0xFFFFUL)
 
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +15 -15
index 10e96a8510..f95aabe577 100644
@@ -1760,7 +1760,7 @@ static inline void
 iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 {
 	if (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
-		uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
+		uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
 		uint64_t eip_len = 0;
 		uint64_t eip_noinc = 0;
 		/* Default - IP_ID is increment in each segment of LSO */
@@ -1769,15 +1769,15 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 				RTE_MBUF_F_TX_OUTER_IPV6 |
 				RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
 		case RTE_MBUF_F_TX_OUTER_IPV4:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV6:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
+			eip_typ = CI_TX_CTX_EIPT_IPV6;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		}
@@ -1791,10 +1791,10 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
 		case RTE_MBUF_F_TX_TUNNEL_GTP:
 		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-			eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
 			break;
 		case RTE_MBUF_F_TX_TUNNEL_GRE:
-			eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
 			break;
 		default:
 			PMD_TX_LOG(ERR, "Tunnel type not supported");
@@ -1811,22 +1811,22 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		 * its last Ethertype.
 		 * If MPLS labels exists, it should include them as well.
 		 */
-		eip_typ |= (pkt->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
+		eip_typ |= (pkt->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
 
 		/**
 		 * Calculate the tunneling UDP checksum.
 		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
 		 */
-		if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV4 |
-					IAVF_TX_CTX_EXT_IP_IPV6 |
-					IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-				(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
 				(pkt->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-			eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
 
-		*low_ctx_qw = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-			eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-			eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
+		*low_ctx_qw = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+			eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+			eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
 
 	} else {
 		*low_ctx_qw = 0;
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +15 -15
index 58ed89a72a..74d91fff31 100644
@@ -1899,7 +1899,7 @@ static __rte_always_inline void
 iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 {
 	if (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
-		uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
+		uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
 		uint64_t eip_len = 0;
 		uint64_t eip_noinc = 0;
 		/* Default - IP_ID is increment in each segment of LSO */
@@ -1908,15 +1908,15 @@ iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 				RTE_MBUF_F_TX_OUTER_IPV6 |
 				RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
 		case RTE_MBUF_F_TX_OUTER_IPV4:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV6:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
+			eip_typ = CI_TX_CTX_EIPT_IPV6;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		}
@@ -1930,10 +1930,10 @@ iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
 		case RTE_MBUF_F_TX_TUNNEL_GTP:
 		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-			eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
 			break;
 		case RTE_MBUF_F_TX_TUNNEL_GRE:
-			eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
 			break;
 		default:
 			PMD_TX_LOG(ERR, "Tunnel type not supported");
@@ -1950,22 +1950,22 @@ iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		 * its last Ethertype.
 		 * If MPLS labels exists, it should include them as well.
 		 */
-		eip_typ |= (pkt->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
+		eip_typ |= (pkt->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
 
 		/**
 		 * Calculate the tunneling UDP checksum.
 		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
 		 */
-		if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV4 |
-					IAVF_TX_CTX_EXT_IP_IPV6 |
-					IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-				(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
 				(pkt->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-			eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
 
-		*low_ctx_qw = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-			eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-			eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
+		*low_ctx_qw = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+			eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+			eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
 
 	} else {
 		*low_ctx_qw = 0;
Signature · 1 line
2.53.0
#35 lore raw

PATCH v2 6/15 net/intel: move iavf descriptor writing functions to common

In reply to Bruce Richardson

In order to promote reuse of code, move the Tx vector functions for writing descriptors from the iavf driver to the common folder in a new tx_vec_x86.h file. This will allow reuse in later commits by other drivers such as ice.

---
 drivers/net/intel/common/tx_vec_x86.h         | 511 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 285 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 272 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  75 +--
 4 files changed, 530 insertions(+), 613 deletions(-)
 create mode 100644 drivers/net/intel/common/tx_vec_x86.h
drivers/net/intel/common/tx_vec_x86.h new file +511 -0
new file mode 100644
index 0000000000..36e855eb26
@@ -0,0 +1,511 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2026 Intel Corporation
+ */
+
+#ifndef _COMMON_INTEL_TX_VEC_X86_H_
+#define _COMMON_INTEL_TX_VEC_X86_H_
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "tx.h"
+
+static __rte_always_inline void
+ci_fill_ctx_desc_tunneling(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
+{
+	if (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
+		uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
+		uint64_t eip_len = 0;
+		uint64_t eip_noinc = 0;
+		/* Default - IP_ID is increment in each segment of LSO */
+
+		switch (pkt->ol_flags & (RTE_MBUF_F_TX_OUTER_IPV4 |
+				RTE_MBUF_F_TX_OUTER_IPV6 |
+				RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
+		case RTE_MBUF_F_TX_OUTER_IPV4:
+			eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
+			eip_len = pkt->outer_l3_len >> 2;
+		break;
+		case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
+			eip_typ = CI_TX_CTX_EIPT_IPV4;
+			eip_len = pkt->outer_l3_len >> 2;
+		break;
+		case RTE_MBUF_F_TX_OUTER_IPV6:
+			eip_typ = CI_TX_CTX_EIPT_IPV6;
+			eip_len = pkt->outer_l3_len >> 2;
+		break;
+		}
+
+		/* L4TUNT: L4 Tunneling Type */
+		switch (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
+		case RTE_MBUF_F_TX_TUNNEL_IPIP:
+			/* for non UDP / GRE tunneling, set to 00b */
+			break;
+		case RTE_MBUF_F_TX_TUNNEL_VXLAN:
+		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
+		case RTE_MBUF_F_TX_TUNNEL_GTP:
+		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
+			break;
+		case RTE_MBUF_F_TX_TUNNEL_GRE:
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
+			break;
+		default:
+			PMD_TX_LOG(ERR, "Tunnel type not supported");
+			return;
+		}
+
+		/* L4TUNLEN: L4 Tunneling Length, in Words
+		 *
+		 * We depend on app to set rte_mbuf.l2_len correctly.
+		 * For IP in GRE it should be set to the length of the GRE
+		 * header;
+		 * For MAC in GRE or MAC in UDP it should be set to the length
+		 * of the GRE or UDP headers plus the inner MAC up to including
+		 * its last Ethertype.
+		 * If MPLS labels exists, it should include them as well.
+		 */
+		eip_typ |= (pkt->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
+
+		/**
+		 * Calculate the tunneling UDP checksum.
+		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
+		 */
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
+				(pkt->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
+
+		*low_ctx_qw = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+			eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+			eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
+
+	} else {
+		*low_ctx_qw = 0;
+	}
+}
+
+static __rte_always_inline void
+ci_tx_vec_offload(struct rte_mbuf *tx_pkt, uint64_t *txd_hi,
+		enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	uint64_t ol_flags = tx_pkt->ol_flags;
+	uint32_t td_cmd = 0;
+	uint32_t td_offset = 0;
+
+	/* Set MACLEN */
+	if (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)
+		td_offset |= (tx_pkt->outer_l2_len >> 1) << CI_TX_DESC_LEN_MACLEN_S;
+	else
+		td_offset |= (tx_pkt->l2_len >> 1) << CI_TX_DESC_LEN_MACLEN_S;
+
+	/* Enable L3 checksum offloads */
+	if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
+		if (ol_flags & RTE_MBUF_F_TX_IPV4) {
+			td_cmd |= CI_TX_DESC_CMD_IIPT_IPV4_CSUM;
+			td_offset |= (tx_pkt->l3_len >> 2) << CI_TX_DESC_LEN_IPLEN_S;
+		}
+	} else if (ol_flags & RTE_MBUF_F_TX_IPV4) {
+		td_cmd |= CI_TX_DESC_CMD_IIPT_IPV4;
+		td_offset |= (tx_pkt->l3_len >> 2) << CI_TX_DESC_LEN_IPLEN_S;
+	} else if (ol_flags & RTE_MBUF_F_TX_IPV6) {
+		td_cmd |= CI_TX_DESC_CMD_IIPT_IPV6;
+		td_offset |= (tx_pkt->l3_len >> 2) << CI_TX_DESC_LEN_IPLEN_S;
+	}
+
+	/* Enable L4 checksum offloads */
+	switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) {
+	case RTE_MBUF_F_TX_TCP_CKSUM:
+		td_cmd |= CI_TX_DESC_CMD_L4T_EOFT_TCP;
+		td_offset |= (sizeof(struct rte_tcp_hdr) >> 2) << CI_TX_DESC_LEN_L4_LEN_S;
+		break;
+	case RTE_MBUF_F_TX_SCTP_CKSUM:
+		td_cmd |= CI_TX_DESC_CMD_L4T_EOFT_SCTP;
+		td_offset |= (sizeof(struct rte_sctp_hdr) >> 2) << CI_TX_DESC_LEN_L4_LEN_S;
+		break;
+	case RTE_MBUF_F_TX_UDP_CKSUM:
+		td_cmd |= CI_TX_DESC_CMD_L4T_EOFT_UDP;
+		td_offset |= (sizeof(struct rte_udp_hdr) >> 2) << CI_TX_DESC_LEN_L4_LEN_S;
+		break;
+	default:
+		break;
+	}
+
+	*txd_hi |= ((uint64_t)td_offset) << CI_TXD_QW1_OFFSET_S;
+
+	if (ol_flags & RTE_MBUF_F_TX_QINQ) {
+		td_cmd |= CI_TX_DESC_CMD_IL2TAG1;
+		/* L2Tag1 always carries a tag for QinQ */
+		if (qinq_outer_pos == CI_TAG_IN_DATA_DESC)
+			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci_outer << CI_TXD_QW1_L2TAG1_S);
+		else
+			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
+	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && single_vlan_pos == CI_TAG_IN_DATA_DESC) {
+		td_cmd |= CI_TX_DESC_CMD_IL2TAG1;
+		*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
+	}
+
+	*txd_hi |= ((uint64_t)td_cmd) << CI_TXD_QW1_CMD_S;
+}
+
+static __rte_always_inline void
+ci_vtx1(volatile struct ci_tx_desc *txdp,
+	  struct rte_mbuf *pkt, uint64_t flags, bool offload,
+	  enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
+			((uint64_t)flags << CI_TXD_QW1_CMD_S) |
+			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
+	if (offload)
+		ci_tx_vec_offload(pkt, &high_qw, single_vlan_pos, qinq_outer_pos);
+
+	__m128i descriptor = _mm_set_epi64x(high_qw, pkt->buf_iova + pkt->data_off);
+	_mm_store_si128(RTE_CAST_PTR(__m128i *, txdp), descriptor);
+}
+
+#ifdef __AVX2__
+
+static __rte_always_inline void
+ci_vtx_avx2(volatile struct ci_tx_desc *txdp,
+	 struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload,
+	 enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
+
+	/* if unaligned on 32-bit boundary, do one to align */
+	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		nb_pkts--; txdp++; pkt++;
+	}
+
+	/* do two at a time while possible, in bursts */
+	for (; nb_pkts > 3; txdp += 4, pkt += 4, nb_pkts -= 4) {
+		uint64_t hi_qw3 = hi_qw_tmpl |
+			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[3], &hi_qw3, single_vlan_pos, qinq_outer_pos);
+		uint64_t hi_qw2 = hi_qw_tmpl |
+			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[2], &hi_qw2, single_vlan_pos, qinq_outer_pos);
+		uint64_t hi_qw1 = hi_qw_tmpl |
+			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[1], &hi_qw1, single_vlan_pos, qinq_outer_pos);
+		uint64_t hi_qw0 = hi_qw_tmpl |
+			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[0], &hi_qw0, single_vlan_pos, qinq_outer_pos);
+
+		__m256i desc2_3 =
+			_mm256_set_epi64x
+				(hi_qw3,
+				 pkt[3]->buf_iova + pkt[3]->data_off,
+				 hi_qw2,
+				 pkt[2]->buf_iova + pkt[2]->data_off);
+		__m256i desc0_1 =
+			_mm256_set_epi64x
+				(hi_qw1,
+				 pkt[1]->buf_iova + pkt[1]->data_off,
+				 hi_qw0,
+				 pkt[0]->buf_iova + pkt[0]->data_off);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
+	}
+
+	/* do any last ones */
+	while (nb_pkts) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		txdp++; pkt++; nb_pkts--;
+	}
+}
+
+static __rte_always_inline void
+ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
+		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
+		enum ci_l2tag_pos qinq_outer_pos, bool ptype_lldp_enabled)
+{
+	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
+	uint64_t low_ctx_qw = 0;
+
+	if (offload) {
+		ci_fill_ctx_desc_tunneling(&low_ctx_qw, pkt);
+		if (pkt->ol_flags & RTE_MBUF_F_TX_QINQ) {
+			uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+				(uint64_t)pkt->vlan_tci_outer :
+				(uint64_t)pkt->vlan_tci;
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+		} else if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) &&
+				single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+		}
+	}
+	if (IAVF_CHECK_TX_LLDP(pkt, ptype_lldp_enabled))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
+			((uint64_t)flags  << CI_TXD_QW1_CMD_S) |
+			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
+	if (offload)
+		ci_tx_vec_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
+
+	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
+							high_ctx_qw, low_ctx_qw);
+
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+}
+
+static __rte_always_inline void
+ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
+		struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags,
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		bool ptype_lldp_enabled)
+{
+	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags  << CI_TXD_QW1_CMD_S));
+
+	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
+		uint64_t hi_ctx_qw1 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t hi_ctx_qw0 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t low_ctx_qw1 = 0;
+		uint64_t low_ctx_qw0 = 0;
+		uint64_t hi_data_qw1 = 0;
+		uint64_t hi_data_qw0 = 0;
+
+		hi_data_qw1 = hi_data_qw_tmpl |
+				((uint64_t)pkt[1]->data_len <<
+					CI_TXD_QW1_TX_BUF_SZ_S);
+		hi_data_qw0 = hi_data_qw_tmpl |
+				((uint64_t)pkt[0]->data_len <<
+					CI_TXD_QW1_TX_BUF_SZ_S);
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw1, pkt[1]);
+			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[1]->vlan_tci_outer :
+					(uint64_t)pkt[1]->vlan_tci;
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[1]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[1], ptype_lldp_enabled))
+			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw0, pkt[0]);
+			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[0]->vlan_tci_outer :
+					(uint64_t)pkt[0]->vlan_tci;
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[0]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[0], ptype_lldp_enabled))
+			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[0], &hi_data_qw0, single_vlan_pos, qinq_outer_pos);
+		}
+
+		__m256i desc2_3 = _mm256_set_epi64x
+				(hi_data_qw1, pkt[1]->buf_iova + pkt[1]->data_off,
+				 hi_ctx_qw1, low_ctx_qw1);
+		__m256i desc0_1 = _mm256_set_epi64x
+				(hi_data_qw0, pkt[0]->buf_iova + pkt[0]->data_off,
+				 hi_ctx_qw0, low_ctx_qw0);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
+	}
+
+	if (nb_pkts)
+		ci_vtx1_ctx_avx2(txdp, *pkt, flags, offload,
+				single_vlan_pos, qinq_outer_pos, ptype_lldp_enabled);
+}
+
+#endif /* __AVX2__ */
+
+#ifdef __AVX512VL__
+
+static __rte_always_inline void
+ci_vtx_avx512(volatile struct ci_tx_desc *txdp,
+		struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags,
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
+
+	/* if unaligned on 32-bit boundary, do one to align */
+	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		nb_pkts--; txdp++; pkt++;
+	}
+
+	/* do 4 at a time while possible, in bursts */
+	for (; nb_pkts > 3; txdp += 4, pkt += 4, nb_pkts -= 4) {
+		uint64_t hi_qw3 = hi_qw_tmpl |
+			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		uint64_t hi_qw2 = hi_qw_tmpl |
+			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		uint64_t hi_qw1 = hi_qw_tmpl |
+			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		uint64_t hi_qw0 = hi_qw_tmpl |
+			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload) {
+			ci_tx_vec_offload(pkt[3], &hi_qw3, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[2], &hi_qw2, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[1], &hi_qw1, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[0], &hi_qw0, single_vlan_pos, qinq_outer_pos);
+		}
+
+		__m512i desc0_3 =
+			_mm512_set_epi64
+				(hi_qw3,
+				 pkt[3]->buf_iova + pkt[3]->data_off,
+				 hi_qw2,
+				 pkt[2]->buf_iova + pkt[2]->data_off,
+				 hi_qw1,
+				 pkt[1]->buf_iova + pkt[1]->data_off,
+				 hi_qw0,
+				 pkt[0]->buf_iova + pkt[0]->data_off);
+		_mm512_storeu_si512(RTE_CAST_PTR(void *, txdp), desc0_3);
+	}
+
+	/* do any last ones */
+	while (nb_pkts) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		txdp++; pkt++; nb_pkts--;
+	}
+}
+
+static __rte_always_inline void
+ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
+		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
+		enum ci_l2tag_pos qinq_outer_pos, bool lldp_enabled)
+{
+	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
+	uint64_t low_ctx_qw = 0;
+
+	if (offload) {
+		ci_fill_ctx_desc_tunneling(&low_ctx_qw, pkt);
+		if (pkt->ol_flags & RTE_MBUF_F_TX_QINQ) {
+			uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+				(uint64_t)pkt->vlan_tci_outer :
+				(uint64_t)pkt->vlan_tci;
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+		} else if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) &&
+				single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+		}
+	}
+	if (IAVF_CHECK_TX_LLDP(pkt, lldp_enabled))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
+			((uint64_t)flags << CI_TXD_QW1_CMD_S) |
+			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
+	if (offload)
+		ci_tx_vec_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
+
+	__m256i ctx_data_desc = _mm256_set_epi64x
+			(high_data_qw, pkt->buf_iova + pkt->data_off,
+			high_ctx_qw, low_ctx_qw);
+
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+}
+
+static __rte_always_inline void
+ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
+		struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags,
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		bool lldp_enabled)
+{
+	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
+
+	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
+		uint64_t hi_ctx_qw1 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t hi_ctx_qw0 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t low_ctx_qw1 = 0;
+		uint64_t low_ctx_qw0 = 0;
+		uint64_t hi_data_qw1 = 0;
+		uint64_t hi_data_qw0 = 0;
+
+		hi_data_qw1 = hi_data_qw_tmpl |
+				((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		hi_data_qw0 = hi_data_qw_tmpl |
+				((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw1, pkt[1]);
+			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[1]->vlan_tci_outer :
+					(uint64_t)pkt[1]->vlan_tci;
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[1]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[1], lldp_enabled))
+			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw0, pkt[0]);
+			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[0]->vlan_tci_outer :
+					(uint64_t)pkt[0]->vlan_tci;
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[0]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[0], lldp_enabled))
+			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[0], &hi_data_qw0, single_vlan_pos, qinq_outer_pos);
+		}
+
+		__m512i desc0_3 = _mm512_set_epi64
+				(hi_data_qw1, pkt[1]->buf_iova + pkt[1]->data_off,
+				hi_ctx_qw1, low_ctx_qw1,
+				hi_data_qw0, pkt[0]->buf_iova + pkt[0]->data_off,
+				hi_ctx_qw0, low_ctx_qw0);
+		_mm512_storeu_si512(RTE_CAST_PTR(void *, txdp), desc0_3);
+	}
+
+	if (nb_pkts)
+		ci_vtx1_ctx_avx512(txdp, *pkt, flags, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_enabled);
+}
+
+#endif /* __AVX512VL__ */
+
+#endif /* _COMMON_INTEL_TX_VEC_X86_H_ */
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +7 -278

326 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +8 -264

309 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_common.h +4 -71

85 lines not on this page · raw message

Signature · 1 line
2.53.0
#36 lore raw

PATCH v2 7/15 net/intel: use function callback for lldp

In reply to Bruce Richardson

Limit LLDP support for iavf drivers for now, by using a callback to handle its processing. Drivers not supporting this pass a NULL pointer and the compiler will optimize away the branches. For iavf, the compiler can inline the subfunction directly as it's known at compile-time.

---
 drivers/net/intel/common/tx_vec_x86.h         | 42 +++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 16 +++++--
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 17 +++++---
 3 files changed, 48 insertions(+), 27 deletions(-)
drivers/net/intel/common/tx_vec_x86.h +24 -18
index 36e855eb26..0c6c60a21e 100644
@@ -11,6 +11,12 @@
 
 #include "tx.h"
 
+/* Optional per-driver LLDP switch-uplink check for ctx descriptors.
+ * Takes the ctx-desc high qword and returns it with the LLDP bit applied
+ * if appropriate. NULL disables the check.
+ */
+typedef uint64_t (*ci_tx_ctx_lldp_fn)(struct rte_mbuf *pkt, uint64_t high_ctx_qw);
+
 static __rte_always_inline void
 ci_fill_ctx_desc_tunneling(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 {
@@ -226,7 +232,7 @@ ci_vtx_avx2(volatile struct ci_tx_desc *txdp,
 static __rte_always_inline void
 ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
-		enum ci_l2tag_pos qinq_outer_pos, bool ptype_lldp_enabled)
+		enum ci_l2tag_pos qinq_outer_pos, ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
 	uint64_t low_ctx_qw = 0;
@@ -245,8 +251,8 @@ ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 		}
 	}
-	if (IAVF_CHECK_TX_LLDP(pkt, ptype_lldp_enabled))
-		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	if (lldp_check != NULL)
+		high_ctx_qw = lldp_check(pkt, high_ctx_qw);
 	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
 			((uint64_t)flags  << CI_TXD_QW1_CMD_S) |
 			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
@@ -264,7 +270,7 @@ static __rte_always_inline void
 ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 		struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags,
 		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
-		bool ptype_lldp_enabled)
+		ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags  << CI_TXD_QW1_CMD_S));
 
@@ -298,8 +304,8 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[1], ptype_lldp_enabled))
-			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw1 = lldp_check(pkt[1], hi_ctx_qw1);
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
@@ -316,8 +322,8 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[0], ptype_lldp_enabled))
-			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw0 = lldp_check(pkt[0], hi_ctx_qw0);
 
 		if (offload) {
 			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
@@ -336,7 +342,7 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 
 	if (nb_pkts)
 		ci_vtx1_ctx_avx2(txdp, *pkt, flags, offload,
-				single_vlan_pos, qinq_outer_pos, ptype_lldp_enabled);
+				single_vlan_pos, qinq_outer_pos, lldp_check);
 }
 
 #endif /* __AVX2__ */
@@ -396,7 +402,7 @@ ci_vtx_avx512(volatile struct ci_tx_desc *txdp,
 static __rte_always_inline void
 ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
-		enum ci_l2tag_pos qinq_outer_pos, bool lldp_enabled)
+		enum ci_l2tag_pos qinq_outer_pos, ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
 	uint64_t low_ctx_qw = 0;
@@ -415,8 +421,8 @@ ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 		}
 	}
-	if (IAVF_CHECK_TX_LLDP(pkt, lldp_enabled))
-		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	if (lldp_check != NULL)
+		high_ctx_qw = lldp_check(pkt, high_ctx_qw);
 	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
 			((uint64_t)flags << CI_TXD_QW1_CMD_S) |
 			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
@@ -435,7 +441,7 @@ static __rte_always_inline void
 ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 		struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags,
 		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
-		bool lldp_enabled)
+		ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
 
@@ -467,8 +473,8 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[1], lldp_enabled))
-			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw1 = lldp_check(pkt[1], hi_ctx_qw1);
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
@@ -485,8 +491,8 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[0], lldp_enabled))
-			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw0 = lldp_check(pkt[0], hi_ctx_qw0);
 
 		if (offload) {
 			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
@@ -503,7 +509,7 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 
 	if (nb_pkts)
 		ci_vtx1_ctx_avx512(txdp, *pkt, flags, offload,
-				single_vlan_pos, qinq_outer_pos, lldp_enabled);
+					single_vlan_pos, qinq_outer_pos, lldp_check);
 }
 
 #endif /* __AVX512VL__ */
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +12 -4
index 1d0492edd9..813611015d 100644
@@ -1685,6 +1685,14 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return nb_pkts;
 }
 
+static __rte_always_inline uint64_t
+iavf_tx_ctx_lldp_check(struct rte_mbuf *pkt, uint64_t high_ctx_qw)
+{
+	if (IAVF_CHECK_TX_LLDP(pkt, true))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	return high_ctx_qw;
+}
+
 static __rte_always_inline uint16_t
 iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 				 uint16_t nb_pkts, bool offload)
@@ -1696,7 +1704,7 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	/* bit2 is reserved and must be set to 1 according to Spec */
 	uint64_t flags = IAVF_TX_DESC_CMD_EOP | IAVF_TX_DESC_CMD_ICRC;
 	uint64_t rs = IAVF_TX_DESC_CMD_RS | flags;
-	bool lldp_enabled = txq->lldp_enabled;
+	ci_tx_ctx_lldp_fn lldp_check = txq->lldp_enabled ? iavf_tx_ctx_lldp_check : NULL;
 	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
 	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
 			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
@@ -1723,10 +1731,10 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
 		ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
-				vlan_pos, vlan_pos, lldp_enabled);
+				vlan_pos, vlan_pos, lldp_check);
 		tx_pkts += (nb_mbuf - 1);
 		txdp += (n - 2);
-		ci_vtx1_ctx_avx2(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_enabled);
+		ci_vtx1_ctx_avx2(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_check);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -1740,7 +1748,7 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	nb_mbuf = nb_commit >> 1;
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
-	ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
+	ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_check);
 	tx_id = (uint16_t)(tx_id + nb_commit);
 
 	if (tx_id > txq->tx_next_rs) {
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +12 -5
index 0c738e4882..fe00416660 100644
@@ -1900,6 +1900,14 @@ iavf_xmit_fixed_burst_vec_avx512(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return nb_pkts;
 }
 
+static __rte_always_inline uint64_t
+iavf_tx_ctx_lldp_check(struct rte_mbuf *pkt, uint64_t high_ctx_qw)
+{
+	if (IAVF_CHECK_TX_LLDP(pkt, true))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	return high_ctx_qw;
+}
+
 static __rte_always_inline uint16_t
 iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 				 uint16_t nb_pkts, bool offload)
@@ -1911,7 +1919,7 @@ iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	/* bit2 is reserved and must be set to 1 according to Spec */
 	uint64_t flags = CI_TX_DESC_CMD_EOP | CI_TX_DESC_CMD_ICRC;
 	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
-	bool lldp_enabled = txq->lldp_enabled;
+	ci_tx_ctx_lldp_fn lldp_check = txq->lldp_enabled ? iavf_tx_ctx_lldp_check : NULL;
 	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
 	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
 			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
@@ -1938,11 +1946,10 @@ iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 		tx_backlog_entry_avx512(txep, tx_pkts, nb_mbuf);
 
 		ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
-				vlan_pos, vlan_pos, lldp_enabled);
+				vlan_pos, vlan_pos, lldp_check);
 		tx_pkts += (nb_mbuf - 1);
 		txdp += (n - 2);
-		ci_vtx1_ctx_avx512(txdp, *tx_pkts++, rs, offload,
-				vlan_pos, vlan_pos, lldp_enabled);
+		ci_vtx1_ctx_avx512(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_check);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -1956,7 +1963,7 @@ iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	nb_mbuf = nb_commit >> 1;
 	tx_backlog_entry_avx512(txep, tx_pkts, nb_mbuf);
 
-	ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
+	ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_check);
 	tx_id = (uint16_t)(tx_id + nb_commit);
 
 	if (tx_id > txq->tx_next_rs) {
Signature · 1 line
2.53.0
Acked-by on v2 7/15
#37 lore raw

RE: [PATCH v2 07/15] net/intel: use function callback for lldp

Quoted 8 lines

Subject: [PATCH v2 07/15] net/intel: use function callback for lldp

Limit LLDP support for iavf drivers for now, by using a callback to handle its processing. Drivers not supporting this pass a NULL pointer and the compiler will optimize away the branches. For iavf, the compiler can inline the subfunction directly as it's known at compile-time.

Quoted 6 lines
---
 drivers/net/intel/common/tx_vec_x86.h         | 42 +++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 16 +++++--
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 17 +++++---
 3 files changed, 48 insertions(+), 27 deletions(-)
#38 lore raw

PATCH v2 8/15 net/intel: allow building without IOVA in mbuf

In reply to Bruce Richardson

Ensure correct macros are used to build the vector Tx code without the IOVA stored explicitly in the mbuf. This allows the iavf driver to build when the config setting for IOVA in mbuf is disabled.

---
 drivers/net/intel/common/tx_vec_x86.h | 30 +++++++++++++--------------
 drivers/net/intel/iavf/meson.build    |  4 +---
 2 files changed, 16 insertions(+), 18 deletions(-)
drivers/net/intel/common/tx_vec_x86.h +15 -15
index 0c6c60a21e..56efe1d1ec 100644
@@ -168,7 +168,7 @@ ci_vtx1(volatile struct ci_tx_desc *txdp,
 	if (offload)
 		ci_tx_vec_offload(pkt, &high_qw, single_vlan_pos, qinq_outer_pos);
 
-	__m128i descriptor = _mm_set_epi64x(high_qw, pkt->buf_iova + pkt->data_off);
+	__m128i descriptor = _mm_set_epi64x(high_qw, rte_pktmbuf_iova(pkt));
 	_mm_store_si128(RTE_CAST_PTR(__m128i *, txdp), descriptor);
 }
 
@@ -209,15 +209,15 @@ ci_vtx_avx2(volatile struct ci_tx_desc *txdp,
 		__m256i desc2_3 =
 			_mm256_set_epi64x
 				(hi_qw3,
-				 pkt[3]->buf_iova + pkt[3]->data_off,
+				 rte_pktmbuf_iova(pkt[3]),
 				 hi_qw2,
-				 pkt[2]->buf_iova + pkt[2]->data_off);
+				 rte_pktmbuf_iova(pkt[2]));
 		__m256i desc0_1 =
 			_mm256_set_epi64x
 				(hi_qw1,
-				 pkt[1]->buf_iova + pkt[1]->data_off,
+				 rte_pktmbuf_iova(pkt[1]),
 				 hi_qw0,
-				 pkt[0]->buf_iova + pkt[0]->data_off);
+				 rte_pktmbuf_iova(pkt[0]));
 		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
 		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
 	}
@@ -259,7 +259,7 @@ ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	if (offload)
 		ci_tx_vec_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
 
-	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
+	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, rte_pktmbuf_iova(pkt),
 							high_ctx_qw, low_ctx_qw);
 
 	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
@@ -331,10 +331,10 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 		}
 
 		__m256i desc2_3 = _mm256_set_epi64x
-				(hi_data_qw1, pkt[1]->buf_iova + pkt[1]->data_off,
+				(hi_data_qw1, rte_pktmbuf_iova(pkt[1]),
 				 hi_ctx_qw1, low_ctx_qw1);
 		__m256i desc0_1 = _mm256_set_epi64x
-				(hi_data_qw0, pkt[0]->buf_iova + pkt[0]->data_off,
+				(hi_data_qw0, rte_pktmbuf_iova(pkt[0]),
 				 hi_ctx_qw0, low_ctx_qw0);
 		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
 		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
@@ -382,13 +382,13 @@ ci_vtx_avx512(volatile struct ci_tx_desc *txdp,
 		__m512i desc0_3 =
 			_mm512_set_epi64
 				(hi_qw3,
-				 pkt[3]->buf_iova + pkt[3]->data_off,
+				 rte_pktmbuf_iova(pkt[3]),
 				 hi_qw2,
-				 pkt[2]->buf_iova + pkt[2]->data_off,
+				 rte_pktmbuf_iova(pkt[2]),
 				 hi_qw1,
-				 pkt[1]->buf_iova + pkt[1]->data_off,
+				 rte_pktmbuf_iova(pkt[1]),
 				 hi_qw0,
-				 pkt[0]->buf_iova + pkt[0]->data_off);
+				 rte_pktmbuf_iova(pkt[0]));
 		_mm512_storeu_si512(RTE_CAST_PTR(void *, txdp), desc0_3);
 	}
 
@@ -430,7 +430,7 @@ ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		ci_tx_vec_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
 
 	__m256i ctx_data_desc = _mm256_set_epi64x
-			(high_data_qw, pkt->buf_iova + pkt->data_off,
+			(high_data_qw, rte_pktmbuf_iova(pkt),
 			high_ctx_qw, low_ctx_qw);
 
 	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
@@ -500,9 +500,9 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 		}
 
 		__m512i desc0_3 = _mm512_set_epi64
-				(hi_data_qw1, pkt[1]->buf_iova + pkt[1]->data_off,
+				(hi_data_qw1, rte_pktmbuf_iova(pkt[1]),
 				hi_ctx_qw1, low_ctx_qw1,
-				hi_data_qw0, pkt[0]->buf_iova + pkt[0]->data_off,
+				hi_data_qw0, rte_pktmbuf_iova(pkt[0]),
 				hi_ctx_qw0, low_ctx_qw0);
 		_mm512_storeu_si512(RTE_CAST_PTR(void *, txdp), desc0_3);
 	}
drivers/net/intel/iavf/meson.build +1 -3
index 9b071a3a4b..3884043ae6 100644
@@ -1,9 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2018 Luca Boccassi <[email protected]>
 
-if dpdk_conf.get('RTE_IOVA_IN_MBUF') == 0
-    subdir_done()
-endif
+require_iova_in_mbuf = false
 
 testpmd_sources = files('iavf_testpmd.c')
 
Signature · 1 line
2.53.0
Acked-by on v2 8/15
#39 lore raw

RE: [PATCH v2 08/15] net/intel: allow building without IOVA in mbuf

Quoted 7 lines

Subject: [PATCH v2 08/15] net/intel: allow building without IOVA in mbuf

Ensure correct macros are used to build the vector Tx code without the IOVA stored explicitly in the mbuf. This allows the iavf driver to build when the config setting for IOVA in mbuf is disabled.

Quoted 5 lines
---
 drivers/net/intel/common/tx_vec_x86.h | 30 +++++++++++++--------------
 drivers/net/intel/iavf/meson.build    |  4 +---
 2 files changed, 16 insertions(+), 18 deletions(-)
#40 lore raw

PATCH v2 9/15 net/ice: use common descriptor creation functions

In reply to Bruce Richardson

Update ice driver to use the descriptor creation functions from common rather than having it maintain its own copies of them.

---
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 73 ++-------------------
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 64 ++----------------
 drivers/net/intel/ice/ice_rxtx_vec_common.h | 59 -----------------
 3 files changed, 12 insertions(+), 184 deletions(-)
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +6 -67
index b72f69a47b..68401560ce 100644
@@ -5,6 +5,7 @@
 #include "ice_rxtx_vec_common.h"
 
 #include "../common/rx_vec_x86.h"
+#include "../common/tx_vec_x86.h"
 
 #include <rte_vect.h>
 
@@ -773,70 +774,6 @@ ice_recv_scattered_pkts_vec_avx2_offload(void *rx_queue,
 						       true);
 }
 
-static __rte_always_inline void
-ice_vtx1(volatile struct ci_tx_desc *txdp,
-	 struct rte_mbuf *pkt, uint64_t flags, bool offload)
-{
-	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
-		 ((uint64_t)flags << CI_TXD_QW1_CMD_S) |
-		 ((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
-	if (offload)
-		ice_txd_enable_offload(pkt, &high_qw);
-
-	__m128i descriptor = _mm_set_epi64x(high_qw, rte_pktmbuf_iova(pkt));
-	_mm_store_si128(RTE_CAST_PTR(__m128i *, txdp), descriptor);
-}
-
-static __rte_always_inline void
-ice_vtx(volatile struct ci_tx_desc *txdp,
-	struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload)
-{
-	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
-
-	/* if unaligned on 32-bit boundary, do one to align */
-	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		ice_vtx1(txdp, *pkt, flags, offload);
-		nb_pkts--; txdp++; pkt++;
-	}
-
-	/* do four at a time while possible, in bursts */
-	for (; nb_pkts > 3; txdp += 4, pkt += 4, nb_pkts -= 4) {
-		uint64_t hi_qw3 = hi_qw_tmpl |
-			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[3], &hi_qw3);
-		uint64_t hi_qw2 = hi_qw_tmpl |
-			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[2], &hi_qw2);
-		uint64_t hi_qw1 = hi_qw_tmpl |
-			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[1], &hi_qw1);
-		uint64_t hi_qw0 = hi_qw_tmpl |
-			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[0], &hi_qw0);
-
-		__m256i desc2_3 =
-			_mm256_set_epi64x
-				(hi_qw3, rte_pktmbuf_iova(pkt[3]),
-				 hi_qw2, rte_pktmbuf_iova(pkt[2]));
-		__m256i desc0_1 =
-			_mm256_set_epi64x
-				(hi_qw1, rte_pktmbuf_iova(pkt[1]),
-				 hi_qw0, rte_pktmbuf_iova(pkt[0]));
-		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
-		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
-	}
-
-	/* do any last ones */
-	while (nb_pkts) {
-		ice_vtx1(txdp, *pkt, flags, offload);
-		txdp++; pkt++; nb_pkts--;
-	}
-}
-
 static __rte_always_inline uint16_t
 ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 			      uint16_t nb_pkts, bool offload)
@@ -868,11 +805,12 @@ ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	if (nb_commit >= n) {
 		ci_tx_backlog_entry_vec(txep, tx_pkts, n);
 
-		ice_vtx(txdp, tx_pkts, n - 1, flags, offload);
+		ci_vtx_avx2(txdp, tx_pkts, n - 1, flags, offload,
+			CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 		tx_pkts += (n - 1);
 		txdp += (n - 1);
 
-		ice_vtx1(txdp, *tx_pkts++, rs, offload);
+		ci_vtx1(txdp, *tx_pkts++, rs, offload, CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -886,7 +824,8 @@ ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_commit);
 
-	ice_vtx(txdp, tx_pkts, nb_commit, flags, offload);
+	ci_vtx_avx2(txdp, tx_pkts, nb_commit, flags, offload,
+		CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 
 	tx_id = (uint16_t)(tx_id + nb_commit);
 	if (tx_id > txq->tx_next_rs) {
drivers/net/intel/ice/ice_rxtx_vec_avx512.c +6 -58

91 lines not on this page · raw message

drivers/net/intel/ice/ice_rxtx_vec_common.h +0 -59

63 lines not on this page · raw message

Signature · 1 line
2.53.0
Acked-by on v2 9/15
#41 lore raw

RE: [PATCH v2 09/15] net/ice: use common descriptor creation functions

Quoted 6 lines

Subject: [PATCH v2 09/15] net/ice: use common descriptor creation functions

Update ice driver to use the descriptor creation functions from common rather than having it maintain its own copies of them.

Quoted 6 lines
---
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 73 ++-------------------
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 64 ++----------------
 drivers/net/intel/ice/ice_rxtx_vec_common.h | 59 -----------------
 3 files changed, 12 insertions(+), 184 deletions(-)
#42 lore raw

PATCH v2 10/15 net/intel: move vector Tx paths to common

In reply to Bruce Richardson

The main loops for vector Tx, both avx2 and avx512 are almost identical across a couple of drivers, so move the iavf copies to common for later reuse by other drivers.

---
 drivers/net/intel/common/tx.h                 |  10 ++
 drivers/net/intel/common/tx_vec_x86.h         | 128 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   |  75 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c |  77 +----------
 4 files changed, 148 insertions(+), 142 deletions(-)
drivers/net/intel/common/tx.h +10 -0
index c8fadee712..630df8cb19 100644
@@ -9,6 +9,8 @@
 #include <rte_mbuf.h>
 #include <rte_ethdev.h>
 #include <rte_vect.h>
+#include <rte_io.h>
+#include <rte_byteorder.h>
 
 /* Common TX Descriptor QW1 Field Definitions */
 #define CI_TXD_QW1_DTYPE_S      0
@@ -273,6 +275,14 @@ ci_tx_backlog_entry_vec(struct ci_tx_entry_vec *txep, struct rte_mbuf **tx_pkts,
 		txep[i].mbuf = tx_pkts[i];
 }
 
+
+/* Write the Tx tail register, byte-swapped for hardware regardless of host endianness. */
+static __rte_always_inline void
+ci_tx_qtx_tail_write(struct ci_tx_queue *txq, uint16_t tx_id)
+{
+	rte_write32_wc(rte_cpu_to_le_32((uint32_t)tx_id), txq->qtx_tail);
+}
+
 #define IETH_VPMD_TX_MAX_FREE_BUF 64
 
 typedef int (*ci_desc_done_fn)(struct ci_tx_queue *txq, uint16_t idx);
drivers/net/intel/common/tx_vec_x86.h +128 -0

140 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +5 -70

93 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +5 -72

95 lines not on this page · raw message

Signature · 1 line
2.53.0
#43 lore raw

PATCH v2 11/15 net/ice: use common AVX Tx functions

In reply to Bruce Richardson

Use the newly created common Tx functions in the vector path.

---
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   |  72 +-------------
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 102 +++-----------------
 2 files changed, 14 insertions(+), 160 deletions(-)
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +2 -70
index 68401560ce..00b5d51aab 100644
@@ -774,74 +774,6 @@ ice_recv_scattered_pkts_vec_avx2_offload(void *rx_queue,
 						       true);
 }
 
-static __rte_always_inline uint16_t
-ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
-			      uint16_t nb_pkts, bool offload)
-{
-	struct ci_tx_queue *txq = (struct ci_tx_queue *)tx_queue;
-	volatile struct ci_tx_desc *txdp;
-	struct ci_tx_entry_vec *txep;
-	uint16_t n, nb_commit, tx_id;
-	uint64_t flags = CI_TX_DESC_CMD_DEFAULT;
-	uint64_t rs = CI_TX_DESC_CMD_RS | CI_TX_DESC_CMD_DEFAULT;
-
-	/* cross rx_thresh boundary is not allowed */
-	nb_pkts = RTE_MIN(nb_pkts, txq->tx_rs_thresh);
-
-	if (txq->nb_tx_free < txq->tx_free_thresh)
-		ci_tx_free_bufs_vec(txq, ice_tx_desc_done, false);
-
-	nb_commit = nb_pkts = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts);
-	if (unlikely(nb_pkts == 0))
-		return 0;
-
-	tx_id = txq->tx_tail;
-	txdp = &txq->ci_tx_ring[tx_id];
-	txep = &txq->sw_ring_vec[tx_id];
-
-	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_pkts);
-
-	n = (uint16_t)(txq->nb_tx_desc - tx_id);
-	if (nb_commit >= n) {
-		ci_tx_backlog_entry_vec(txep, tx_pkts, n);
-
-		ci_vtx_avx2(txdp, tx_pkts, n - 1, flags, offload,
-			CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
-		tx_pkts += (n - 1);
-		txdp += (n - 1);
-
-		ci_vtx1(txdp, *tx_pkts++, rs, offload, CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
-
-		nb_commit = (uint16_t)(nb_commit - n);
-
-		tx_id = 0;
-		txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1);
-
-		/* avoid reach the end of ring */
-		txdp = &txq->ci_tx_ring[tx_id];
-		txep = &txq->sw_ring_vec[tx_id];
-	}
-
-	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_commit);
-
-	ci_vtx_avx2(txdp, tx_pkts, nb_commit, flags, offload,
-		CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
-
-	tx_id = (uint16_t)(tx_id + nb_commit);
-	if (tx_id > txq->tx_next_rs) {
-		txq->ci_tx_ring[txq->tx_next_rs].cmd_type_offset_bsz |=
-			rte_cpu_to_le_64(((uint64_t)CI_TX_DESC_CMD_RS) << CI_TXD_QW1_CMD_S);
-		txq->tx_next_rs =
-			(uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh);
-	}
-
-	txq->tx_tail = tx_id;
-
-	ICE_PCI_REG_WC_WRITE(txq->qtx_tail, txq->tx_tail);
-
-	return nb_pkts;
-}
-
 static __rte_always_inline uint16_t
 ice_xmit_pkts_vec_avx2_common(void *tx_queue, struct rte_mbuf **tx_pkts,
 			      uint16_t nb_pkts, bool offload)
@@ -853,8 +785,8 @@ ice_xmit_pkts_vec_avx2_common(void *tx_queue, struct rte_mbuf **tx_pkts,
 		uint16_t ret, num;
 
 		num = (uint16_t)RTE_MIN(nb_pkts, txq->tx_rs_thresh);
-		ret = ice_xmit_fixed_burst_vec_avx2(tx_queue, &tx_pkts[nb_tx],
-						    num, offload);
+		ret = ci_xmit_fixed_burst_vec_avx2(tx_queue, &tx_pkts[nb_tx], num,
+				offload, CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 		nb_tx += ret;
 		nb_pkts -= ret;
 		if (ret < num)
drivers/net/intel/ice/ice_rxtx_vec_avx512.c +12 -90

122 lines not on this page · raw message

Signature · 1 line
2.53.0
#44 lore raw

PATCH v2 12/15 net/intel: add common vector Tx fns with context handling

In reply to Bruce Richardson

The iavf vector driver has support for more Tx offloads because it has Tx functions which handle transmit context descriptors. Move those context-handling functions to the common folder for reuse by other drivers.

---
 drivers/net/intel/common/tx_vec_x86.h         | 136 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   |  78 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c |  89 +-----------
 3 files changed, 147 insertions(+), 156 deletions(-)
drivers/net/intel/common/tx_vec_x86.h +136 -0
index 946dcc1f2e..cbc7855f99 100644
@@ -408,6 +408,74 @@ ci_xmit_fixed_burst_vec_avx2(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkts,
 	return nb_pkts;
 }
 
+static __rte_always_inline uint16_t
+ci_xmit_fixed_burst_vec_ctx_avx2(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkts,
+		uint16_t nb_pkts, bool offload,
+		enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		ci_tx_ctx_lldp_fn lldp_check)
+{
+	volatile struct ci_tx_desc *txdp;
+	struct ci_tx_entry_vec *txep;
+	uint16_t n, nb_commit, nb_mbuf, tx_id;
+	uint64_t flags = CI_TX_DESC_CMD_DEFAULT;
+	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
+
+	if (txq->nb_tx_free < txq->tx_free_thresh)
+		ci_tx_free_bufs_vec(txq, ci_tx_desc_done_simple, true);
+
+	nb_commit = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts << 1);
+	nb_commit &= 0xFFFE;
+	if (unlikely(nb_commit == 0))
+		return 0;
+
+	nb_pkts = nb_commit >> 1;
+	tx_id = txq->tx_tail;
+	txdp = &txq->ci_tx_ring[tx_id];
+	txep = (void *)txq->sw_ring;
+	txep += (tx_id >> 1);
+
+	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_commit);
+	n = (uint16_t)(txq->nb_tx_desc - tx_id);
+
+	if (n != 0 && nb_commit >= n) {
+		nb_mbuf = n >> 1;
+		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+		ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+		tx_pkts += (nb_mbuf - 1);
+		txdp += (n - 2);
+		ci_vtx1_ctx_avx2(txdp, *tx_pkts++, rs, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+
+		nb_commit = (uint16_t)(nb_commit - n);
+
+		txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1);
+		tx_id = 0;
+		/* avoid reach the end of ring */
+		txdp = txq->ci_tx_ring;
+		txep = (void *)txq->sw_ring;
+	}
+
+	nb_mbuf = nb_commit >> 1;
+	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+	ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf, flags, offload,
+			single_vlan_pos, qinq_outer_pos, lldp_check);
+	tx_id = (uint16_t)(tx_id + nb_commit);
+
+	if (tx_id > txq->tx_next_rs) {
+		txq->ci_tx_ring[txq->tx_next_rs].cmd_type_offset_bsz |=
+			rte_cpu_to_le_64(((uint64_t)CI_TX_DESC_CMD_RS) << CI_TXD_QW1_CMD_S);
+		txq->tx_next_rs = (uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh);
+	}
+
+	txq->tx_tail = tx_id;
+
+	ci_tx_qtx_tail_write(txq, tx_id);
+	return nb_pkts;
+}
+
 #endif /* __AVX2__ */
 
 #ifdef __AVX512VL__
@@ -640,6 +708,74 @@ ci_xmit_fixed_burst_vec_avx512(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkt
 	return nb_pkts;
 }
 
+static __rte_always_inline uint16_t
+ci_xmit_fixed_burst_vec_ctx_avx512(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkts,
+		uint16_t nb_pkts, bool offload,
+		enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		ci_tx_ctx_lldp_fn lldp_check)
+{
+	volatile struct ci_tx_desc *txdp;
+	struct ci_tx_entry_vec *txep;
+	uint16_t n, nb_commit, nb_mbuf, tx_id;
+	uint64_t flags = CI_TX_DESC_CMD_DEFAULT;
+	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
+
+	if (txq->nb_tx_free < txq->tx_free_thresh)
+		ci_tx_free_bufs_vec(txq, ci_tx_desc_done_simple, true);
+
+	nb_commit = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts << 1);
+	nb_commit &= 0xFFFE;
+	if (unlikely(nb_commit == 0))
+		return 0;
+
+	nb_pkts = nb_commit >> 1;
+	tx_id = txq->tx_tail;
+	txdp = &txq->ci_tx_ring[tx_id];
+	txep = (void *)txq->sw_ring;
+	txep += (tx_id >> 1);
+
+	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_commit);
+	n = (uint16_t)(txq->nb_tx_desc - tx_id);
+
+	if (n != 0 && nb_commit >= n) {
+		nb_mbuf = n >> 1;
+		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+		ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+		tx_pkts += (nb_mbuf - 1);
+		txdp += (n - 2);
+		ci_vtx1_ctx_avx512(txdp, *tx_pkts++, rs, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+
+		nb_commit = (uint16_t)(nb_commit - n);
+
+		txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1);
+		tx_id = 0;
+		/* avoid reach the end of ring */
+		txdp = txq->ci_tx_ring;
+		txep = (void *)txq->sw_ring;
+	}
+
+	nb_mbuf = nb_commit >> 1;
+	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+	ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf, flags, offload,
+			single_vlan_pos, qinq_outer_pos, lldp_check);
+	tx_id = (uint16_t)(tx_id + nb_commit);
+
+	if (tx_id > txq->tx_next_rs) {
+		txq->ci_tx_ring[txq->tx_next_rs].cmd_type_offset_bsz |=
+			rte_cpu_to_le_64(((uint64_t)CI_TX_DESC_CMD_RS) << CI_TXD_QW1_CMD_S);
+		txq->tx_next_rs = (uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh);
+	}
+
+	txq->tx_tail = tx_id;
+
+	ci_tx_qtx_tail_write(txq, tx_id);
+	return nb_pkts;
+}
+
 #endif /* __AVX512VL__ */
 
 #endif /* _COMMON_INTEL_TX_VEC_X86_H_ */
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +5 -73

97 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +6 -83

113 lines not on this page · raw message

Signature · 1 line
2.53.0
#45 lore raw

PATCH v2 13/15 net/intel: improve Tx path selection logic

In reply to Bruce Richardson

Rework the relevant priority of context descriptor vs SIMD width when selecting a Tx path so that presence of context descriptors is only considered when all else is equal.

Normally, path select takes place without having to worry about context descriptors, since offloads requiring context descriptors are specified using the offloads bitmap for each Tx path. However, in some cases, the need to use a context descriptor is not encodable via this offload path, e.g. VLAN offload for iavf can sometimes use the data descriptor and sometimes the context depending on what PF specifies at runtime. To account for those cases, we separate out the use of contexts from the path features, but instead note it as part of the path information, and add an additional parameter to the Tx path selection for drivers to mandate a context descriptor be present. Otherwise, ctx is largely ignored in path selection, except as a last-resort tie-breaker between two paths.

---
 drivers/net/intel/common/tx.h      | 41 +++++++++++++++++---------
 drivers/net/intel/cpfl/cpfl_rxtx.c |  3 +-
 drivers/net/intel/i40e/i40e_rxtx.c |  2 +-
 drivers/net/intel/iavf/iavf_rxtx.c | 46 ++++++++++++++++--------------
 drivers/net/intel/ice/ice_rxtx.c   |  3 +-
 drivers/net/intel/idpf/idpf_rxtx.c |  3 +-
 6 files changed, 58 insertions(+), 40 deletions(-)
drivers/net/intel/common/tx.h +27 -14
index 630df8cb19..0f36989b32 100644
@@ -249,7 +249,6 @@ struct ci_tx_path_features {
 	uint32_t tx_offloads;
 	enum rte_vect_max_simd simd_width;
 	bool simple_tx;
-	bool ctx_desc;
 	bool disabled;
 	bool single_queue;
 };
@@ -259,6 +258,7 @@ struct ci_tx_path_info {
 	const char *info;
 	struct ci_tx_path_features features;
 	eth_tx_prep_t pkt_prep;
+	bool supports_ctx;
 };
 
 static __rte_always_inline void
@@ -411,6 +411,11 @@ ci_txq_release_all_mbufs(struct ci_tx_queue *txq, bool use_ctx)
  *   Number of available paths in the infos array
  * @param default_path
  *   Index of the default path to use if no suitable path is found
+ * @param force_ctx
+ *   If true, only paths that support context descriptors may be selected.
+ *   Use this for offloads that require a context descriptor but cannot be
+ *   discovered purely from req_features->tx_offloads (e.g. a driver-specific
+ *   devarg, or a runtime/hardware-negotiated tag placement).
  *
  * @return
  *   The packet burst function index that best matches the requested features,
@@ -420,10 +425,12 @@ static inline int
 ci_tx_path_select(const struct ci_tx_path_features *req_features,
 			const struct ci_tx_path_info *infos,
 			size_t num_paths,
-			int default_path)
+			int default_path,
+			bool force_ctx)
 {
 	int idx = default_path;
 	const struct ci_tx_path_features *chosen_path_features = NULL;
+	bool chosen_supports_ctx = false;
 
 	for (unsigned int i = 0; i < num_paths; i++) {
 		const struct ci_tx_path_features *path_features = &infos[i].features;
@@ -440,8 +447,8 @@ ci_tx_path_select(const struct ci_tx_path_features *req_features,
 		if (path_features->simple_tx && !req_features->simple_tx)
 			continue;
 
-		/* If a context descriptor is requested, ensure the path supports it. */
-		if (!path_features->ctx_desc && req_features->ctx_desc)
+		/* If a context descriptor is required, ensure the path supports it. */
+		if (!infos[i].supports_ctx && force_ctx)
 			continue;
 
 		/* If requested, ensure the path supports single queue TX. */
@@ -462,22 +469,28 @@ ci_tx_path_select(const struct ci_tx_path_features *req_features,
 			/* Do not select paths with lower SIMD width than the chosen path. */
 			if (path_features->simd_width < chosen_path_features->simd_width)
 				continue;
-			/* Do not select paths with more offloads enabled than the chosen path if
-			 * the SIMD widths are the same.
+			/* The following tie-breaks only matter when SIMD widths are tied;
+			 * a strictly wider path is always preferred regardless of offload
+			 * count or ctx-descriptor use.
 			 */
-			if (path_features->simd_width == chosen_path_features->simd_width &&
-					rte_popcount32(path_features->tx_offloads) >
-					rte_popcount32(chosen_path_features->tx_offloads))
-				continue;
-
-			/* Don't use a context descriptor unless necessary */
-			if (path_features->ctx_desc && !chosen_path_features->ctx_desc)
-				continue;
+			if (path_features->simd_width == chosen_path_features->simd_width) {
+				/* Do not select paths with more offloads enabled than the
+				 * chosen path.
+				 */
+				if (rte_popcount32(path_features->tx_offloads) >
+						rte_popcount32(chosen_path_features->tx_offloads))
+					continue;
+
+				/* Don't use a context descriptor unless necessary */
+				if (infos[i].supports_ctx && !chosen_supports_ctx)
+					continue;
+			}
 		}
 
 		/* Finally, select the path since it has met all the requirements. */
 		idx = i;
 		chosen_path_features = &infos[idx].features;
+		chosen_supports_ctx = infos[idx].supports_ctx;
 	}
 
 	return idx;
drivers/net/intel/cpfl/cpfl_rxtx.c +2 -1
index 2f1641ea76..aba3a5e916 100644
@@ -1542,7 +1542,8 @@ cpfl_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_func_type = ci_tx_path_select(&req_features,
 					&idpf_tx_path_infos[0],
 					IDPF_TX_MAX,
-					IDPF_TX_DEFAULT);
+					IDPF_TX_DEFAULT,
+					false);
 
 	/* Set use_vec_entry for single queue mode - only IDPF_TX_SINGLEQ uses regular entries */
 	if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
drivers/net/intel/i40e/i40e_rxtx.c +1 -1
index e2fffdb70a..f289d26790 100644
@@ -3120,7 +3120,7 @@ i40e_set_tx_function(struct rte_eth_dev *dev)
 	}
 
 	ad->tx_func_type = ci_tx_path_select(&req_features, &i40e_tx_path_infos[0],
-						RTE_DIM(i40e_tx_path_infos), I40E_TX_DEFAULT);
+			RTE_DIM(i40e_tx_path_infos), I40E_TX_DEFAULT, false);
 
 out:
 	dev->tx_pkt_burst = mbuf_check ? i40e_xmit_pkts_check :
drivers/net/intel/iavf/iavf_rxtx.c +24 -22

112 lines not on this page · raw message

drivers/net/intel/ice/ice_rxtx.c +2 -1
index 52d6984214..06920745ed 100644
@@ -3784,7 +3784,8 @@ ice_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_func_type = ci_tx_path_select(&req_features,
 						&ice_tx_path_infos[0],
 						RTE_DIM(ice_tx_path_infos),
-						ICE_TX_DEFAULT);
+						ICE_TX_DEFAULT,
+						false);
 
 out:
 #if defined(RTE_ARCH_X86)
drivers/net/intel/idpf/idpf_rxtx.c +2 -1
index bc3f9a0798..077a92a8a9 100644
@@ -887,7 +887,8 @@ idpf_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_func_type = ci_tx_path_select(&req_features,
 					&idpf_tx_path_infos[0],
 					IDPF_TX_MAX,
-					IDPF_TX_DEFAULT);
+					IDPF_TX_DEFAULT,
+					false);
 
 	/* Set use_vec_entry for single queue mode - only IDPF_TX_SINGLEQ uses regular entries */
 	if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
Signature · 1 line
2.53.0
#46 lore raw

PATCH v2 14/15 net/ice: enable context desc offloads for vector Tx

In reply to Bruce Richardson

Use the context descriptor Tx vector paths from intel/common in ice driver to enable more offloads on the vector path for ice driver.

---
 doc/guides/rel_notes/release_26_11.rst      |  6 ++++
 drivers/net/intel/ice/ice_ethdev.h          |  3 ++
 drivers/net/intel/ice/ice_rxtx.c            | 31 ++++++++++++++++++---
 drivers/net/intel/ice/ice_rxtx.h            | 11 ++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 24 ++++++++++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 24 ++++++++++++++++
 6 files changed, 95 insertions(+), 4 deletions(-)
doc/guides/rel_notes/release_26_11.rst +6 -0
index 6c29513041..c1c51c62ec 100644
@@ -69,6 +69,12 @@ New Features
   Added ``fdir_buffer_size`` devarg to select the Flow Director table size
   (``64k``, ``128k`` or ``256k``) at probe time. The default remains ``64k``.
 
+* **Updated Intel ice driver.**
+
+  * Added Tx context descriptor support to the AVX2 and AVX512 vector Tx
+    paths, enabling QinQ tag insertion and outer IPv4/UDP checksum
+    offloads on those paths.
+
 
 Removed Items
 -------------
drivers/net/intel/ice/ice_ethdev.h +3 -0
index 1d038016af..3cfd7afbae 100644
@@ -213,8 +213,10 @@ enum ice_tx_func_type {
 	ICE_TX_SIMPLE,
 	ICE_TX_AVX2,
 	ICE_TX_AVX2_OFFLOAD,
+	ICE_TX_AVX2_CTX_OFFLOAD,
 	ICE_TX_AVX512,
 	ICE_TX_AVX512_OFFLOAD,
+	ICE_TX_AVX512_CTX_OFFLOAD,
 	ICE_TX_NEON,
 };
 
@@ -676,6 +678,7 @@ struct ice_adapter {
 	bool rx_bulk_alloc_allowed;
 	bool tx_vec_allowed;
 	bool tx_simple_allowed;
+	bool use_ctx;
 	enum ice_rx_func_type rx_func_type;
 	enum ice_tx_func_type tx_func_type;
 	/* ptype mapping table */
drivers/net/intel/ice/ice_rxtx.c +27 -4
index 06920745ed..50cacadc44 100644
@@ -890,6 +890,7 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 
 	/* record what kind of descriptor cleanup we need on teardown */
 	txq->use_vec_entry = ad->tx_vec_allowed || ad->tx_simple_allowed;
+	txq->use_ctx = ad->use_ctx;
 
 	if (txq->tsq != NULL && txq->tsq->ts_flag > 0) {
 		struct ice_aqc_set_txtime_qgrp *ts_elem;
@@ -1200,7 +1201,7 @@ ice_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 		return -EINVAL;
 	}
 
-	ci_txq_release_all_mbufs(txq, false);
+	ci_txq_release_all_mbufs(txq, txq->use_ctx);
 	ice_reset_tx_queue(txq);
 	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
 
@@ -1263,7 +1264,7 @@ ice_fdir_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 		return -EINVAL;
 	}
 
-	ci_txq_release_all_mbufs(txq, false);
+	ci_txq_release_all_mbufs(txq, txq->use_ctx);
 	txq->qtx_tail = NULL;
 
 	return 0;
@@ -1751,7 +1752,7 @@ ice_tx_queue_release(void *txq)
 		return;
 	}
 
-	ci_txq_release_all_mbufs(q, false);
+	ci_txq_release_all_mbufs(q, q->use_ctx);
 	rte_free(q->sw_ring);
 	rte_free(q->rs_last_id);
 	if (q->tsq) {
@@ -3533,7 +3534,8 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.features = {
 			.tx_offloads = ICE_TX_SCALAR_OFFLOADS
 		},
-		.pkt_prep = ice_prep_pkts
+		.pkt_prep = ice_prep_pkts,
+		.supports_ctx = true
 	},
 	[ICE_TX_SIMPLE] = {
 		.pkt_burst = ice_xmit_pkts_simple,
@@ -3563,6 +3565,16 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		},
 		.pkt_prep = ice_prep_pkts
 	},
+	[ICE_TX_AVX2_CTX_OFFLOAD] = {
+		.pkt_burst = ice_xmit_pkts_vec_avx2_ctx_offload,
+		.info = "Offload Vector AVX2 Ctx",
+		.features = {
+			.tx_offloads = ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.simd_width = RTE_VECT_SIMD_256
+		},
+		.pkt_prep = ice_prep_pkts,
+		.supports_ctx = true
+	},
 #ifdef CC_AVX512_SUPPORT
 	[ICE_TX_AVX512] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx512,
@@ -3582,6 +3594,16 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		},
 		.pkt_prep = ice_prep_pkts
 	},
+	[ICE_TX_AVX512_CTX_OFFLOAD] = {
+		.pkt_burst = ice_xmit_pkts_vec_avx512_ctx_offload,
+		.info = "Offload Vector AVX512 Ctx",
+		.features = {
+			.tx_offloads = ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.simd_width = RTE_VECT_SIMD_512
+		},
+		.pkt_prep = ice_prep_pkts,
+		.supports_ctx = true
+	},
 #endif
 #elif defined(RTE_ARCH_ARM64)
 	[ICE_TX_NEON] = {
@@ -3795,6 +3817,7 @@ ice_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_vec_allowed =
 		(ice_tx_path_infos[ad->tx_func_type].features.simd_width >= RTE_VECT_SIMD_128);
 #endif
+	ad->use_ctx = ice_tx_path_infos[ad->tx_func_type].supports_ctx;
 
 	dev->tx_pkt_burst = mbuf_check ? ice_xmit_pkts_check :
 					 ice_tx_path_infos[ad->tx_func_type].pkt_burst;
drivers/net/intel/ice/ice_rxtx.h +11 -0
index 999b6b30d6..bee8a464f5 100644
@@ -135,6 +135,12 @@
 	RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
 	RTE_ETH_TX_OFFLOAD_TCP_CKSUM |		\
 	RTE_ETH_TX_OFFLOAD_SCTP_CKSUM)
+/* vector ctx offload path: QinQ outer tag + outer/tunnel checksum via ctx desc */
+#define ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS (	\
+	ICE_TX_VECTOR_OFFLOAD_OFFLOADS |	\
+	RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
+	RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
+	RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
 
 /* Max header size can be 2K - 64 bytes */
 #define ICE_RX_HDR_BUF_SIZE    (2048 - 64)
@@ -284,6 +290,8 @@ uint16_t ice_xmit_pkts_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 				uint16_t nb_pkts);
 uint16_t ice_xmit_pkts_vec_avx2_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
 					uint16_t nb_pkts);
+uint16_t ice_xmit_pkts_vec_avx2_ctx_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
+					uint16_t nb_pkts);
 uint16_t ice_recv_pkts_vec_avx512(void *rx_queue, struct rte_mbuf **rx_pkts,
 				  uint16_t nb_pkts);
 uint16_t ice_recv_pkts_vec_avx512_offload(void *rx_queue,
@@ -300,6 +308,9 @@ uint16_t ice_xmit_pkts_vec_avx512(void *tx_queue, struct rte_mbuf **tx_pkts,
 uint16_t ice_xmit_pkts_vec_avx512_offload(void *tx_queue,
 					  struct rte_mbuf **tx_pkts,
 					  uint16_t nb_pkts);
+uint16_t ice_xmit_pkts_vec_avx512_ctx_offload(void *tx_queue,
+					  struct rte_mbuf **tx_pkts,
+					  uint16_t nb_pkts);
 int ice_fdir_programming(struct ice_pf *pf, struct ice_fltr_desc *fdir_desc);
 int ice_tx_done_cleanup(void *txq, uint32_t free_cnt);
 int ice_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc);
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +24 -0
index 00b5d51aab..056b2dc49b 100644
@@ -810,6 +810,30 @@ ice_xmit_pkts_vec_avx2_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return ice_xmit_pkts_vec_avx2_common(tx_queue, tx_pkts, nb_pkts, true);
 }
 
+uint16_t
+ice_xmit_pkts_vec_avx2_ctx_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
+				   uint16_t nb_pkts)
+{
+	uint16_t nb_tx = 0;
+	struct ci_tx_queue *txq = (struct ci_tx_queue *)tx_queue;
+
+	while (nb_pkts) {
+		uint16_t ret, num;
+
+		/* cross rs_thresh boundary is not allowed */
+		num = (uint16_t)RTE_MIN(nb_pkts << 1, txq->tx_rs_thresh);
+		num = num >> 1;
+		ret = ci_xmit_fixed_burst_vec_ctx_avx2(tx_queue, &tx_pkts[nb_tx], num,
+				true, CI_TAG_IN_DATA_DESC, CI_TAG_IN_CTX_DESC, NULL);
+		nb_tx += ret;
+		nb_pkts -= ret;
+		if (ret < num)
+			break;
+	}
+
+	return nb_tx;
+}
+
 int __rte_cold
 ice_rxq_vec_setup(struct ci_rx_queue *rxq)
 {
drivers/net/intel/ice/ice_rxtx_vec_avx512.c +24 -0
index d8ede5cb42..0548c293bb 100644
@@ -882,3 +882,27 @@ ice_xmit_pkts_vec_avx512_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
 {
 	return ice_xmit_pkts_vec_avx512_common(tx_queue, tx_pkts, nb_pkts, true);
 }
+
+uint16_t
+ice_xmit_pkts_vec_avx512_ctx_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
+				     uint16_t nb_pkts)
+{
+	uint16_t nb_tx = 0;
+	struct ci_tx_queue *txq = (struct ci_tx_queue *)tx_queue;
+
+	while (nb_pkts) {
+		uint16_t ret, num;
+
+		/* cross rs_thresh boundary is not allowed */
+		num = (uint16_t)RTE_MIN(nb_pkts << 1, txq->tx_rs_thresh);
+		num = num >> 1;
+		ret = ci_xmit_fixed_burst_vec_ctx_avx512(tx_queue, &tx_pkts[nb_tx], num,
+				true, CI_TAG_IN_DATA_DESC, CI_TAG_IN_CTX_DESC, NULL);
+		nb_tx += ret;
+		nb_pkts -= ret;
+		if (ret < num)
+			break;
+	}
+
+	return nb_tx;
+}
Signature · 1 line
2.53.0
Acked-by on v2 14/15
#47 lore raw

RE: [PATCH v2 14/15] net/ice: enable context desc offloads for vector Tx

Quoted 21 lines

Subject: [PATCH v2 14/15] net/ice: enable context desc offloads for vector Tx

Use the context descriptor Tx vector paths from intel/common in ice driver to enable more offloads on the vector path for ice driver.

---
 doc/guides/rel_notes/release_26_11.rst      |  6 ++++
 drivers/net/intel/ice/ice_ethdev.h          |  3 ++
 drivers/net/intel/ice/ice_rxtx.c            | 31 ++++++++++++++++++---
 drivers/net/intel/ice/ice_rxtx.h            | 11 ++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 24 ++++++++++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 24 ++++++++++++++++
 6 files changed, 95 insertions(+), 4 deletions(-)
doc/guides/rel_notes/release_26_11.rst +0 -0
index 6c29513041..c1c51c62ec 100644

doc/guides/rel_notes/release_26_11.rst New Features · line 76

Quoted 8 lines
doc/guides/rel_notes/release_26_11.rst +5 -0
@@ -69,6 +69,12 @@ New Features
   Added ``fdir_buffer_size`` devarg to select the Flow Director table size
   (``64k``, ``128k`` or ``256k``) at probe time. The default remains ``64k``.
 
+* **Updated Intel ice driver.**
+
+  * Added Tx context descriptor support to the AVX2 and AVX512 vector Tx
+    paths, enabling QinQ tag insertion and outer IPv4/UDP checksum
+    offloads on those paths.

Check if any updates are needed to the ice.ini features file, now that these new offloads are supported.

Quoted 2 lines
doc/guides/rel_notes/release_26_11.rst +1 -0
+
 
#48 lore raw

PATCH v2 15/15 net/intel: consolidate Tx vector offload path checks

In reply to Bruce Richardson

Since iavf and ice drivers now have common Tx vector paths, we can consolidate the path decisions a little, including replacing the per-driver offload flags with common ones.

---
 drivers/net/intel/common/tx.h                 | 30 +++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx.c            | 18 +++++------
 drivers/net/intel/iavf/iavf_rxtx.h            | 19 ------------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  3 +-
 drivers/net/intel/ice/ice_rxtx.c              | 14 ++++-----
 drivers/net/intel/ice/ice_rxtx.h              | 18 -----------
 drivers/net/intel/ice/ice_rxtx_vec_common.h   |  3 +-
 7 files changed, 48 insertions(+), 57 deletions(-)
drivers/net/intel/common/tx.h +30 -0
index 0f36989b32..867892f306 100644
@@ -12,6 +12,27 @@
 #include <rte_io.h>
 #include <rte_byteorder.h>
 
+#define CI_VPMD_TX_BURST            32
+#define CI_VPMD_TX_MAX_FREE_BUF     64
+
+/* basic vector path */
+#define CI_TX_VECTOR_OFFLOADS RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
+/* offload vector path */
+#define CI_TX_VEC_OFFLOAD_PATH_OFFLOADS (	\
+		CI_TX_VECTOR_OFFLOADS |		\
+		RTE_ETH_TX_OFFLOAD_VLAN_INSERT |	\
+		RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |		\
+		RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |		\
+		RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
+		RTE_ETH_TX_OFFLOAD_TCP_CKSUM)
+/* offload vector path with context descriptor */
+#define CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS (	\
+		CI_TX_VECTOR_OFFLOADS |		\
+		CI_TX_VEC_OFFLOAD_PATH_OFFLOADS |	\
+		RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
+		RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
+		RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
+
 /* Common TX Descriptor QW1 Field Definitions */
 #define CI_TXD_QW1_DTYPE_S      0
 #define CI_TXD_QW1_DTYPE_M      (0xFUL << CI_TXD_QW1_DTYPE_S)
@@ -261,6 +282,15 @@ struct ci_tx_path_info {
 	bool supports_ctx;
 };
 
+/* basic check for a vector-driver capable Tx queue.
+ * Individual drivers may have other further tests beyond this.
+ */
+static inline bool
+ci_txq_vec_capable(uint16_t tx_rs_thresh)
+{
+	return tx_rs_thresh >= CI_VPMD_TX_BURST && tx_rs_thresh <= CI_VPMD_TX_MAX_FREE_BUF;
+}
+
 static __rte_always_inline void
 ci_tx_backlog_entry(struct ci_tx_entry *txep, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 {
drivers/net/intel/iavf/iavf_rxtx.c +9 -9
index 3be8b00bbd..9b776a6391 100644
@@ -3620,7 +3620,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx2,
 		.info = "Vector AVX2",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		}
 	},
@@ -3628,7 +3628,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx2_offload,
 		.info = "Vector AVX2 Offload",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		}
 	},
@@ -3636,7 +3636,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx2_ctx,
 		.info = "Vector AVX2 Ctx",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		},
 		.supports_ctx = true
@@ -3645,7 +3645,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx2_ctx_offload,
 		.info = "Vector AVX2 Ctx Offload",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		},
 		.supports_ctx = true
@@ -3655,7 +3655,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx512,
 		.info = "Vector AVX512",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		}
 	},
@@ -3663,7 +3663,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx512_offload,
 		.info = "Vector AVX512 Offload",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		}
 	},
@@ -3671,7 +3671,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx512_ctx,
 		.info = "Vector AVX512 Ctx",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		},
 		.supports_ctx = true
@@ -3680,7 +3680,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx512_ctx_offload,
 		.info = "Vector AVX512 Ctx Offload",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		},
 		.supports_ctx = true
@@ -3691,7 +3691,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec,
 		.info = "Vector Neon",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_128
 		}
 	},
drivers/net/intel/iavf/iavf_rxtx.h +0 -19
index 19931f5f7c..812d7e23ee 100644
@@ -29,11 +29,9 @@
 
 /* used for Vector PMD */
 #define IAVF_VPMD_RX_BURST             CI_VPMD_RX_BURST
-#define IAVF_VPMD_TX_BURST             32
 #define IAVF_VPMD_RXQ_REARM_THRESH     CI_VPMD_RX_REARM_THRESH
 #define IAVF_VPMD_DESCS_PER_LOOP       CI_VPMD_DESCS_PER_LOOP
 #define IAVF_VPMD_DESCS_PER_LOOP_WIDE  CI_VPMD_DESCS_PER_LOOP_WIDE
-#define IAVF_VPMD_TX_MAX_FREE_BUF      64
 
 /* basic scalar path */
 #define IAVF_TX_SCALAR_OFFLOADS (			\
@@ -54,23 +52,6 @@
 		RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |	\
 		RTE_ETH_TX_OFFLOAD_SECURITY |		\
 		RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
-/* basic vector path */
-#define IAVF_TX_VECTOR_OFFLOADS RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
-/* offload vector path */
-#define IAVF_TX_VECTOR_OFFLOAD_OFFLOADS (		\
-		IAVF_TX_VECTOR_OFFLOADS |		\
-		RTE_ETH_TX_OFFLOAD_VLAN_INSERT |	\
-		RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |		\
-		RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |		\
-		RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
-		RTE_ETH_TX_OFFLOAD_TCP_CKSUM)
-/* offload vector path with context descriptor */
-#define IAVF_TX_VECTOR_CTX_OFFLOAD_OFFLOADS (		\
-		IAVF_TX_VECTOR_OFFLOADS |		\
-		IAVF_TX_VECTOR_OFFLOAD_OFFLOADS |	\
-		RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
-		RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
-		RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
 
 /* basic scalar path */
 #define IAVF_RX_SCALAR_OFFLOADS (			\
drivers/net/intel/iavf/iavf_rxtx_vec_common.h +1 -2
index 61478036ec..e0a67fedc6 100644
@@ -80,8 +80,7 @@ iavf_tx_vec_queue_default(struct ci_tx_queue *txq)
 	if (!txq)
 		return -1;
 
-	if (txq->tx_rs_thresh < IAVF_VPMD_TX_BURST ||
-	    txq->tx_rs_thresh > IAVF_VPMD_TX_MAX_FREE_BUF)
+	if (!ci_txq_vec_capable(txq->tx_rs_thresh))
 		return -1;
 
 	return 0;
drivers/net/intel/ice/ice_rxtx.c +7 -7
index 50cacadc44..2db1fe16bf 100644
@@ -3551,7 +3551,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx2,
 		.info = "Vector AVX2",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		},
 		.pkt_prep = rte_eth_tx_pkt_prepare_dummy
@@ -3560,7 +3560,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx2_offload,
 		.info = "Offload Vector AVX2",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		},
 		.pkt_prep = ice_prep_pkts
@@ -3569,7 +3569,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx2_ctx_offload,
 		.info = "Offload Vector AVX2 Ctx",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		},
 		.pkt_prep = ice_prep_pkts,
@@ -3580,7 +3580,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx512,
 		.info = "Vector AVX512",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		},
 		.pkt_prep = rte_eth_tx_pkt_prepare_dummy
@@ -3589,7 +3589,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx512_offload,
 		.info = "Offload Vector AVX512",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		},
 		.pkt_prep = ice_prep_pkts
@@ -3598,7 +3598,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx512_ctx_offload,
 		.info = "Offload Vector AVX512 Ctx",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		},
 		.pkt_prep = ice_prep_pkts,
@@ -3610,7 +3610,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec,
 		.info = "Vector Neon",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_128
 		},
 		.pkt_prep = rte_eth_tx_pkt_prepare_dummy
drivers/net/intel/ice/ice_rxtx.h +0 -18
index bee8a464f5..cd23f7c56f 100644
@@ -47,9 +47,7 @@
 #define ICE_SUPPORT_CHAIN_NUM 5
 
 #define ICE_VPMD_RX_BURST            CI_VPMD_RX_BURST
-#define ICE_VPMD_TX_BURST            32
 #define ICE_VPMD_RXQ_REARM_THRESH    CI_VPMD_RX_REARM_THRESH
-#define ICE_TX_MAX_FREE_BUF_SZ       64
 #define ICE_VPMD_DESCS_PER_LOOP      CI_VPMD_DESCS_PER_LOOP
 #define ICE_VPMD_DESCS_PER_LOOP_WIDE CI_VPMD_DESCS_PER_LOOP_WIDE
 
@@ -125,22 +123,6 @@
 	RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO |	\
 	RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |	\
 	RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP)
-/* basic vector path */
-#define ICE_TX_VECTOR_OFFLOADS RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
-/* vector offload paths */
-#define ICE_TX_VECTOR_OFFLOAD_OFFLOADS (	\
-	ICE_TX_VECTOR_OFFLOADS |		\
-	RTE_ETH_TX_OFFLOAD_VLAN_INSERT |	\
-	RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |		\
-	RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
-	RTE_ETH_TX_OFFLOAD_TCP_CKSUM |		\
-	RTE_ETH_TX_OFFLOAD_SCTP_CKSUM)
-/* vector ctx offload path: QinQ outer tag + outer/tunnel checksum via ctx desc */
-#define ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS (	\
-	ICE_TX_VECTOR_OFFLOAD_OFFLOADS |	\
-	RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
-	RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
-	RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
 
 /* Max header size can be 2K - 64 bytes */
 #define ICE_RX_HDR_BUF_SIZE    (2048 - 64)
drivers/net/intel/ice/ice_rxtx_vec_common.h +1 -2
index 53d1eb42a3..d5ef213e08 100644
@@ -72,8 +72,7 @@ ice_tx_vec_queue_default(struct ci_tx_queue *txq)
 	if (!txq)
 		return -1;
 
-	if (txq->tx_rs_thresh < ICE_VPMD_TX_BURST ||
-	    txq->tx_rs_thresh > ICE_TX_MAX_FREE_BUF_SZ)
+	if (!ci_txq_vec_capable(txq->tx_rs_thresh))
 		return -1;
 
 	return 0;
Signature · 1 line
2.53.0
Acked-by on v2 15/15
#49 lore raw

RE: [PATCH v2 15/15] net/intel: consolidate Tx vector offload path checks

Quoted 7 lines

Subject: [PATCH v2 15/15] net/intel: consolidate Tx vector offload path checks

Since iavf and ice drivers now have common Tx vector paths, we can consolidate the path decisions a little, including replacing the per-driver offload flags with common ones.

Quoted 10 lines
---
 drivers/net/intel/common/tx.h                 | 30 +++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx.c            | 18 +++++------
 drivers/net/intel/iavf/iavf_rxtx.h            | 19 ------------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  3 +-
 drivers/net/intel/ice/ice_rxtx.c              | 14 ++++-----
 drivers/net/intel/ice/ice_rxtx.h              | 18 -----------
 drivers/net/intel/ice/ice_rxtx_vec_common.h   |  3 +-
 7 files changed, 48 insertions(+), 57 deletions(-)
#50 lore raw

v3 cover consolidate ice and iavf Tx vector paths

In reply to Bruce Richardson

This patchset consolidates the ice and iavf vector Tx paths, moving the code to net/intel/common. The iavf code is used as the basis for the move, because it has a superset of the features. When the common code is adopted by the ice driver, it then gains features such as QinQ support and tunneling support.

V3:
* fix variable shadowing issue in patch 15 (ci_txq_vec_capable param)
* update ice.ini with new features

V2:
* fix build when iova not in mbuf
* add extra patch to consolidate the offload flags

Bruce Richardson (15):
net/iavf: remove unnecessary alignment calls net/intel: make Tx context flag common
net/iavf: use separate params for VLAN and QinQ position net/iavf: deduplicate tunnel field fill functions net/intel: define common macros for tunneling bit-shifts net/intel: move iavf descriptor writing functions to common net/intel: use function callback for lldp net/intel: allow building without IOVA in mbuf net/ice: use common descriptor creation functions net/intel: move vector Tx paths to common net/ice: use common AVX Tx functions
net/intel: add common vector Tx fns with context handling net/intel: improve Tx path selection logic net/ice: enable context desc offloads for vector Tx net/intel: consolidate Tx vector offload path checks

 doc/guides/nics/features/ice.ini              |   8 +-
 doc/guides/rel_notes/release_26_11.rst        |   6 +
 drivers/net/intel/common/tx.h                 | 107 ++-
 drivers/net/intel/common/tx_vec_x86.h         | 781 ++++++++++++++++++
 drivers/net/intel/cpfl/cpfl_rxtx.c            |   3 +-
 drivers/net/intel/i40e/i40e_rxtx.c            |   2 +-
 drivers/net/intel/iavf/iavf_rxtx.c            |  94 +--
 drivers/net/intel/iavf/iavf_rxtx.h            |  53 --
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 496 +----------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 495 +----------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  79 +-
 drivers/net/intel/iavf/meson.build            |   4 +-
 drivers/net/intel/ice/ice_ethdev.h            |   3 +
 drivers/net/intel/ice/ice_rxtx.c              |  44 +-
 drivers/net/intel/ice/ice_rxtx.h              |  17 +-
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c     | 159 +---
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c   | 154 +---
 drivers/net/intel/ice/ice_rxtx_vec_common.h   |  62 +-
 drivers/net/intel/idpf/idpf_rxtx.c            |   3 +-
 19 files changed, 1068 insertions(+), 1502 deletions(-)
 create mode 100644 drivers/net/intel/common/tx_vec_x86.h

--
2.53.0

#51 lore raw

PATCH v3 1/15 net/iavf: remove unnecessary alignment calls

When we have a context descriptor on Tx of a packet from the vector paths, that means that we always have 32-bytes being written per descriptor/per packet, so the stores are always 32-bit aligned. This means we can use aligned stores for each single descriptor store, and that we never need to do an initial descriptor write for alignment when doing a burst of descriptors.

---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 9 ++-------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 9 ++-------
 2 files changed, 4 insertions(+), 14 deletions(-)
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +2 -7
index 7217f32cef..9b62ef53d3 100644
@@ -1933,7 +1933,8 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
 							high_ctx_qw, low_ctx_qw);
 
-	_mm256_storeu_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
 }
 
 static __rte_always_inline void
@@ -1944,12 +1945,6 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 	uint64_t hi_data_qw_tmpl = (IAVF_TX_DESC_DTYPE_DATA |
 					((uint64_t)flags  << IAVF_TXD_QW1_CMD_SHIFT));
 
-	/* if unaligned on 32-bit boundary, do one to align */
-	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		ctx_vtx1(txdp, *pkt, flags, offload, vlan_flag, ptype_lldp_enabled);
-		nb_pkts--; txdp++; pkt++;
-	}
-
 	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
 		uint64_t hi_ctx_qw1 = IAVF_TX_DESC_DTYPE_CONTEXT;
 		uint64_t hi_ctx_qw0 = IAVF_TX_DESC_DTYPE_CONTEXT;
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +2 -7
index bf0245e8f4..4609c2245a 100644
@@ -2078,7 +2078,8 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
 							high_ctx_qw, low_ctx_qw);
 
-	_mm256_storeu_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
 }
 
 static __rte_always_inline void
@@ -2088,12 +2089,6 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 {
 	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
 
-	/* if unaligned on 32-bit boundary, do one to align */
-	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		ctx_vtx1(txdp, *pkt, flags, offload, vlan_flag, lldp_enabled);
-		nb_pkts--; txdp++; pkt++;
-	}
-
 	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
 		uint64_t hi_ctx_qw1 = IAVF_TX_DESC_DTYPE_CONTEXT;
 		uint64_t hi_ctx_qw0 = IAVF_TX_DESC_DTYPE_CONTEXT;
Signature · 1 line
2.53.0
#52 lore raw

PATCH v3 2/15 net/intel: make Tx context flag common

In reply to Bruce Richardson

The flag for enabling context descriptors in the vector paths should not be limited to just the iavf driver, as other drivers may use context paths in future also. Therefore move the flag out of the iavf-specific part of the Tx queue structure, to put with other standard queue flags.

---
 drivers/net/intel/common/tx.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/intel/common/tx.h +1 -1
index 2d4a8b5d3c..fb5268c972 100644
@@ -173,6 +173,7 @@ struct ci_tx_queue {
 	bool tx_deferred_start; /* don't start this queue in dev start */
 	bool q_set;             /* indicate if tx queue has been configured */
 	bool use_vec_entry;     /* use sw_ring_vec (true for vector and simple paths) */
+	bool use_ctx;           /* with ctx info, each pkt needs two desc in vec paths */
 	union {                  /* the VSI this queue belongs to */
 		struct i40e_vsi *i40e_vsi;
 		struct iavf_vsi *iavf_vsi;
@@ -194,7 +195,6 @@ struct ci_tx_queue {
 #define IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 BIT(1)
 			uint8_t vlan_flag;
 			uint8_t tc;
-			bool use_ctx;  /* with ctx info, each pkt needs two descriptors */
 			bool lldp_enabled;
 		};
 		struct { /* ixgbe specific values */
Signature · 1 line
2.53.0
#53 lore raw

PATCH v3 3/15 net/iavf: use separate params for VLAN and QinQ position

In reply to Bruce Richardson

Like is the case with the scalar path, use separate offload parameters for the vector path to distinguish between the position of the single VLAN tag and the QinQ outer tag. With iavf these are currently always the same, but other drivers - with whom we may want to share code - have different positions for these.

---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 64 +++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 62 ++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h | 11 ++--
 3 files changed, 77 insertions(+), 60 deletions(-)
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +37 -27
index 9b62ef53d3..2aaa713702 100644
@@ -1619,13 +1619,14 @@ iavf_recv_scattered_pkts_vec_avx2_flex_rxd_offload(void *rx_queue,
 
 static __rte_always_inline void
 iavf_vtx1(volatile struct ci_tx_desc *txdp,
-	  struct rte_mbuf *pkt, uint64_t flags, bool offload, uint8_t vlan_flag)
+	  struct rte_mbuf *pkt, uint64_t flags, bool offload,
+	  enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
 {
 	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
 		 ((uint64_t)flags << CI_TXD_QW1_CMD_S) |
 		 ((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
 	if (offload)
-		iavf_txd_enable_offload(pkt, &high_qw, vlan_flag);
+		iavf_txd_enable_offload(pkt, &high_qw, single_vlan_pos, qinq_outer_pos);
 
 	__m128i descriptor = _mm_set_epi64x(high_qw,
 				pkt->buf_iova + pkt->data_off);
@@ -1634,13 +1635,14 @@ iavf_vtx1(volatile struct ci_tx_desc *txdp,
 
 static __rte_always_inline void
 iavf_vtx(volatile struct ci_tx_desc *txdp,
-	 struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload, uint8_t vlan_flag)
+	 struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload,
+	 enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
 {
 	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
 
 	/* if unaligned on 32-bit boundary, do one to align */
 	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		iavf_vtx1(txdp, *pkt, flags, offload, vlan_flag);
+		iavf_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
 		nb_pkts--; txdp++; pkt++;
 	}
 
@@ -1649,19 +1651,19 @@ iavf_vtx(volatile struct ci_tx_desc *txdp,
 		uint64_t hi_qw3 = hi_qw_tmpl |
 			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[3], &hi_qw3, vlan_flag);
+			iavf_txd_enable_offload(pkt[3], &hi_qw3, single_vlan_pos, qinq_outer_pos);
 		uint64_t hi_qw2 = hi_qw_tmpl |
 			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[2], &hi_qw2, vlan_flag);
+			iavf_txd_enable_offload(pkt[2], &hi_qw2, single_vlan_pos, qinq_outer_pos);
 		uint64_t hi_qw1 = hi_qw_tmpl |
 			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[1], &hi_qw1, vlan_flag);
+			iavf_txd_enable_offload(pkt[1], &hi_qw1, single_vlan_pos, qinq_outer_pos);
 		uint64_t hi_qw0 = hi_qw_tmpl |
 			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
 		if (offload)
-			iavf_txd_enable_offload(pkt[0], &hi_qw0, vlan_flag);
+			iavf_txd_enable_offload(pkt[0], &hi_qw0, single_vlan_pos, qinq_outer_pos);
 
 		__m256i desc2_3 =
 			_mm256_set_epi64x
@@ -1681,7 +1683,7 @@ iavf_vtx(volatile struct ci_tx_desc *txdp,
 
 	/* do any last ones */
 	while (nb_pkts) {
-		iavf_vtx1(txdp, *pkt, flags, offload, vlan_flag);
+		iavf_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
 		txdp++; pkt++; nb_pkts--;
 	}
 }
@@ -1697,6 +1699,9 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	/* bit2 is reserved and must be set to 1 according to Spec */
 	uint64_t flags = CI_TX_DESC_CMD_EOP | CI_TX_DESC_CMD_ICRC;
 	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
+	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
+	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
+			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
 
 	if (txq->nb_tx_free < txq->tx_free_thresh)
 		ci_tx_free_bufs_vec(txq, iavf_tx_desc_done, false);
@@ -1716,11 +1721,11 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	if (nb_commit >= n) {
 		ci_tx_backlog_entry_vec(txep, tx_pkts, n);
 
-		iavf_vtx(txdp, tx_pkts, n - 1, flags, offload, txq->vlan_flag);
+		iavf_vtx(txdp, tx_pkts, n - 1, flags, offload, vlan_pos, vlan_pos);
 		tx_pkts += (n - 1);
 		txdp += (n - 1);
 
-		iavf_vtx1(txdp, *tx_pkts++, rs, offload, txq->vlan_flag);
+		iavf_vtx1(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -1734,7 +1739,7 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_commit);
 
-	iavf_vtx(txdp, tx_pkts, nb_commit, flags, offload, txq->vlan_flag);
+	iavf_vtx(txdp, tx_pkts, nb_commit, flags, offload, vlan_pos, vlan_pos);
 
 	tx_id = (uint16_t)(tx_id + nb_commit);
 	if (tx_id > txq->tx_next_rs) {
@@ -1903,7 +1908,8 @@ iavf_fill_ctx_desc_tunneling_field(volatile uint64_t *qw0,
 
 static __rte_always_inline void
 ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
-		uint64_t flags, bool offload, uint8_t vlan_flag, bool ptype_lldp_enabled)
+		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
+		enum ci_l2tag_pos qinq_outer_pos, bool ptype_lldp_enabled)
 {
 	uint64_t high_ctx_qw = IAVF_TX_DESC_DTYPE_CONTEXT;
 	uint64_t low_ctx_qw = 0;
@@ -1911,13 +1917,13 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	if (offload) {
 		iavf_fill_ctx_desc_tunneling_avx2(&low_ctx_qw, pkt);
 		if (pkt->ol_flags & RTE_MBUF_F_TX_QINQ) {
-			uint64_t qinq_tag = vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 ?
+			uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 				(uint64_t)pkt->vlan_tci_outer :
 				(uint64_t)pkt->vlan_tci;
 			high_ctx_qw |= IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 			low_ctx_qw |= qinq_tag << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 		} else if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) &&
-				vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2) {
+				single_vlan_pos == CI_TAG_IN_CTX_DESC) {
 			high_ctx_qw |= IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 			low_ctx_qw |= (uint64_t)pkt->vlan_tci << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 		}
@@ -1928,7 +1934,7 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 				((uint64_t)flags  << IAVF_TXD_QW1_CMD_SHIFT) |
 				((uint64_t)pkt->data_len << IAVF_TXD_QW1_TX_BUF_SZ_SHIFT));
 	if (offload)
-		iavf_txd_enable_offload(pkt, &high_data_qw, vlan_flag);
+		iavf_txd_enable_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
 
 	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
 							high_ctx_qw, low_ctx_qw);
@@ -1940,7 +1946,8 @@ ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 static __rte_always_inline void
 ctx_vtx(volatile struct ci_tx_desc *txdp,
 		struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags,
-		bool offload, uint8_t vlan_flag, bool ptype_lldp_enabled)
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		bool ptype_lldp_enabled)
 {
 	uint64_t hi_data_qw_tmpl = (IAVF_TX_DESC_DTYPE_DATA |
 					((uint64_t)flags  << IAVF_TXD_QW1_CMD_SHIFT));
@@ -1964,14 +1971,14 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
 			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw1, pkt[1]);
 			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
-				uint64_t qinq_tag = vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 ?
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[1]->vlan_tci_outer :
 					(uint64_t)pkt[1]->vlan_tci;
 				hi_ctx_qw1 |= IAVF_TX_CTX_DESC_IL2TAG2 <<
 						IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw1 |= qinq_tag << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 			} else if (pkt[1]->ol_flags & RTE_MBUF_F_TX_VLAN &&
-					vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2) {
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
 				hi_ctx_qw1 |=
 					IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw1 |=
@@ -1985,14 +1992,14 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
 			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw0, pkt[0]);
 			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
-				uint64_t qinq_tag = vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2 ?
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[0]->vlan_tci_outer :
 					(uint64_t)pkt[0]->vlan_tci;
 				hi_ctx_qw0 |= IAVF_TX_CTX_DESC_IL2TAG2 <<
 						IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw0 |= qinq_tag << IAVF_TXD_CTX_QW0_L2TAG2_PARAM;
 			} else if (pkt[0]->ol_flags & RTE_MBUF_F_TX_VLAN &&
-					vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG2) {
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
 				hi_ctx_qw0 |=
 					IAVF_TX_CTX_DESC_IL2TAG2 << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 				low_ctx_qw0 |=
@@ -2003,8 +2010,8 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << IAVF_TXD_CTX_QW1_CMD_SHIFT;
 
 		if (offload) {
-			iavf_txd_enable_offload(pkt[1], &hi_data_qw1, vlan_flag);
-			iavf_txd_enable_offload(pkt[0], &hi_data_qw0, vlan_flag);
+			iavf_txd_enable_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
+			iavf_txd_enable_offload(pkt[0], &hi_data_qw0, single_vlan_pos, qinq_outer_pos);
 		}
 
 		__m256i desc2_3 =
@@ -2020,7 +2027,7 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 	}
 
 	if (nb_pkts)
-		ctx_vtx1(txdp, *pkt, flags, offload, vlan_flag, ptype_lldp_enabled);
+		ctx_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos, ptype_lldp_enabled);
 }
 
 static __rte_always_inline uint16_t
@@ -2035,6 +2042,9 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	uint64_t flags = IAVF_TX_DESC_CMD_EOP | IAVF_TX_DESC_CMD_ICRC;
 	uint64_t rs = IAVF_TX_DESC_CMD_RS | flags;
 	bool lldp_enabled = txq->lldp_enabled;
+	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
+	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
+			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
 
 	if (txq->nb_tx_free < txq->tx_free_thresh)
 		ci_tx_free_bufs_vec(txq, iavf_tx_desc_done, true);
@@ -2057,10 +2067,10 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 		nb_mbuf = n >> 1;
 		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
-		ctx_vtx(txdp, tx_pkts, nb_mbuf - 1, flags, offload, txq->vlan_flag, lldp_enabled);
+		ctx_vtx(txdp, tx_pkts, nb_mbuf - 1, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
 		tx_pkts += (nb_mbuf - 1);
 		txdp += (n - 2);
-		ctx_vtx1(txdp, *tx_pkts++, rs, offload, txq->vlan_flag, lldp_enabled);
+		ctx_vtx1(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_enabled);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -2074,7 +2084,7 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	nb_mbuf = nb_commit >> 1;
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
-	ctx_vtx(txdp, tx_pkts, nb_mbuf, flags, offload, txq->vlan_flag, lldp_enabled);
+	ctx_vtx(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
 	tx_id = (uint16_t)(tx_id + nb_commit);
 
 	if (tx_id > txq->tx_next_rs) {
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +35 -27

200 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_common.h +5 -6
index 1e9ce924ee..e99964eaef 100644
@@ -121,14 +121,13 @@ iavf_tx_vec_dev_check_default(struct rte_eth_dev *dev)
 
 static __rte_always_inline void
 iavf_txd_enable_offload(__rte_unused struct rte_mbuf *tx_pkt,
-			uint64_t *txd_hi, uint8_t vlan_flag)
+			uint64_t *txd_hi, enum ci_l2tag_pos single_vlan_pos,
+			enum ci_l2tag_pos qinq_outer_pos)
 {
 	uint64_t ol_flags = tx_pkt->ol_flags;
 	uint32_t td_cmd = 0;
 	uint32_t td_offset = 0;
 
-	RTE_SET_USED(vlan_flag);
-
 	/* Set MACLEN */
 	if (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)
 		td_offset |= (tx_pkt->outer_l2_len >> 1)
@@ -179,12 +178,12 @@ iavf_txd_enable_offload(__rte_unused struct rte_mbuf *tx_pkt,
 
 	if (ol_flags & RTE_MBUF_F_TX_QINQ) {
 		td_cmd |= IAVF_TX_DESC_CMD_IL2TAG1;
-		/* vlan_flag specifies outer tag location for QinQ. */
-		if (vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1)
+		/* L2Tag1 always carries a tag for QinQ */
+		if (qinq_outer_pos == CI_TAG_IN_DATA_DESC)
 			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci_outer << CI_TXD_QW1_L2TAG1_S);
 		else
 			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
-	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) {
+	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && single_vlan_pos == CI_TAG_IN_DATA_DESC) {
 		td_cmd |= CI_TX_DESC_CMD_IL2TAG1;
 		*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
 	}
Signature · 1 line
2.53.0
#54 lore raw

PATCH v3 4/15 net/iavf: deduplicate tunnel field fill functions

In reply to Bruce Richardson

Each of the avx2 and avx512 Tx functions used two separate subfunctions to insert the tunneling fields into the context descriptor. Except for some minor differences (a flags guard on one) the two were identical, so remove the one missing the additional guard.

---
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 77 +------------------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 77 +------------------
 2 files changed, 4 insertions(+), 150 deletions(-)
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +2 -75
index 2aaa713702..10e96a8510 100644
@@ -1833,79 +1833,6 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 	}
 }
 
-static inline void
-iavf_fill_ctx_desc_tunneling_field(volatile uint64_t *qw0,
-		const struct rte_mbuf *m)
-{
-	uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
-	uint64_t eip_len = 0;
-	uint64_t eip_noinc = 0;
-	/* Default - IP_ID is increment in each segment of LSO */
-
-	switch (m->ol_flags & (RTE_MBUF_F_TX_OUTER_IPV4 |
-			RTE_MBUF_F_TX_OUTER_IPV6 |
-			RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
-	case RTE_MBUF_F_TX_OUTER_IPV4:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
-		eip_len = m->outer_l3_len >> 2;
-	break;
-	case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
-		eip_len = m->outer_l3_len >> 2;
-	break;
-	case RTE_MBUF_F_TX_OUTER_IPV6:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
-		eip_len = m->outer_l3_len >> 2;
-	break;
-	}
-
-	/* L4TUNT: L4 Tunneling Type */
-	switch (m->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
-	case RTE_MBUF_F_TX_TUNNEL_IPIP:
-		/* for non UDP / GRE tunneling, set to 00b */
-		break;
-	case RTE_MBUF_F_TX_TUNNEL_VXLAN:
-	case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
-	case RTE_MBUF_F_TX_TUNNEL_GTP:
-	case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-		eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
-		break;
-	case RTE_MBUF_F_TX_TUNNEL_GRE:
-		eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
-		break;
-	default:
-		PMD_TX_LOG(ERR, "Tunnel type not supported");
-		return;
-	}
-
-	/* L4TUNLEN: L4 Tunneling Length, in Words
-	 *
-	 * We depend on app to set rte_mbuf.l2_len correctly.
-	 * For IP in GRE it should be set to the length of the GRE
-	 * header;
-	 * For MAC in GRE or MAC in UDP it should be set to the length
-	 * of the GRE or UDP headers plus the inner MAC up to including
-	 * its last Ethertype.
-	 * If MPLS labels exists, it should include them as well.
-	 */
-	eip_typ |= (m->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
-
-	/**
-	 * Calculate the tunneling UDP checksum.
-	 * Shall be set only if L4TUNT = 01b and EIPT is not zero
-	 */
-	if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV6 |
-				IAVF_TX_CTX_EXT_IP_IPV4 |
-				IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-			(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
-			(m->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-		eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
-
-	*qw0 = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-		eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-		eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
-}
-
 static __rte_always_inline void
 ctx_vtx1(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
@@ -1969,7 +1896,7 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
-			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw1, pkt[1]);
+			iavf_fill_ctx_desc_tunneling_avx2(&low_ctx_qw1, pkt[1]);
 			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
 				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[1]->vlan_tci_outer :
@@ -1990,7 +1917,7 @@ ctx_vtx(volatile struct ci_tx_desc *txdp,
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
-			iavf_fill_ctx_desc_tunneling_field(&low_ctx_qw0, pkt[0]);
+			iavf_fill_ctx_desc_tunneling_avx2(&low_ctx_qw0, pkt[0]);
 			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
 				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
 					(uint64_t)pkt[0]->vlan_tci_outer :
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +2 -75

95 lines not on this page · raw message

Signature · 1 line
2.53.0
#55 lore raw

PATCH v3 5/15 net/intel: define common macros for tunneling bit-shifts

In reply to Bruce Richardson

Define common macros for use in iavf (for now) and other drivers (future) defining the shifts needed for tunnel packet Tx

---
 drivers/net/intel/common/tx.h                 | 24 +++++++++++++
 drivers/net/intel/iavf/iavf_rxtx.c            | 30 ++++++++--------
 drivers/net/intel/iavf/iavf_rxtx.h            | 34 -------------------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 30 ++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 30 ++++++++--------
 5 files changed, 69 insertions(+), 79 deletions(-)
drivers/net/intel/common/tx.h +24 -0
index fb5268c972..c8fadee712 100644
@@ -45,6 +45,30 @@
 #define CI_TX_CTX_DESC_TSYN             0x02
 #define CI_TX_CTX_DESC_IL2TAG2          0x04
 
+/* Common TX Context Descriptor QW0 Field Shifts */
+#define CI_TXD_CTX_QW0_L2TAG2_S         32
+#define CI_TXD_CTX_QW0_EIPT_S           0  /* 2 BITS - external IP type */
+#define CI_TXD_CTX_QW0_EIPLEN_S         2  /* 7 BITS - external IP header length */
+#define CI_TXD_CTX_QW0_NATT_S           9  /* 2 BITS - L4 tunnel type */
+#define CI_TXD_CTX_QW0_EIP_NOINC_S      11 /* 1 BIT  - external IP ID not incremented */
+#define CI_TXD_CTX_QW0_NATLEN_S         12 /* 7 BITS - L4 tunnel header length */
+#define CI_TXD_CTX_QW0_L4T_CS_S         23 /* 1 BIT  - tunnel UDP checksum enable */
+
+/**
+ * Enum for the external (outer) IP type field of a Tx context descriptor's
+ * tunnel parameters (QW0 bits 0-1).
+ */
+enum ci_tx_ctx_eipt {
+	CI_TX_CTX_EIPT_NONE,
+	CI_TX_CTX_EIPT_IPV6,
+	CI_TX_CTX_EIPT_IPV4_NO_CSUM,
+	CI_TX_CTX_EIPT_IPV4,
+};
+
+#define CI_TXD_CTX_UDP_TUNNELING        (0x1ULL << CI_TXD_CTX_QW0_NATT_S)
+#define CI_TXD_CTX_GRE_TUNNELING        (0x2ULL << CI_TXD_CTX_QW0_NATT_S)
+#define CI_TXD_CTX_QW0_L4T_CS_M         (0x1ULL << CI_TXD_CTX_QW0_L4T_CS_S)
+
 /**
  * Enum to specify where a VLAN tag is to be placed for packet Tx.
  */
drivers/net/intel/iavf/iavf_rxtx.c +15 -15
index 80c9912ccc..849fc33dac 100644
@@ -2345,7 +2345,7 @@ iavf_calc_context_desc(const struct rte_mbuf *mb, uint8_t vlan_flag, bool lldp_e
 static inline void
 iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const struct rte_mbuf *m)
 {
-	uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
+	uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
 	uint64_t eip_len = 0;
 	uint64_t eip_noinc = 0;
 	/* Default - IP_ID is increment in each segment of LSO */
@@ -2354,15 +2354,15 @@ iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const stru
 			RTE_MBUF_F_TX_OUTER_IPV6 |
 			RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
 	case RTE_MBUF_F_TX_OUTER_IPV4:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
+		eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
 		eip_len = m->outer_l3_len >> 2;
 	break;
 	case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
+		eip_typ = CI_TX_CTX_EIPT_IPV4;
 		eip_len = m->outer_l3_len >> 2;
 	break;
 	case RTE_MBUF_F_TX_OUTER_IPV6:
-		eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
+		eip_typ = CI_TX_CTX_EIPT_IPV6;
 		eip_len = m->outer_l3_len >> 2;
 	break;
 	}
@@ -2377,10 +2377,10 @@ iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const stru
 		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
 		case RTE_MBUF_F_TX_TUNNEL_GTP:
 		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-			eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
 			break;
 		case RTE_MBUF_F_TX_TUNNEL_GRE:
-			eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
 			break;
 		default:
 			PMD_TX_LOG(ERR, "Tunnel type not supported");
@@ -2397,23 +2397,23 @@ iavf_fill_ctx_desc_tunnelling_field(uint64_t *qw0, uint64_t ol_flags, const stru
 		 * its last Ethertype.
 		 * If MPLS labels exists, it should include them as well.
 		 */
-		eip_typ |= (m->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
+		eip_typ |= (m->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
 
 		/**
 		 * Calculate the tunneling UDP checksum.
 		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
 		 */
-		if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV6 |
-					IAVF_TX_CTX_EXT_IP_IPV4 |
-					IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-				(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
 				(ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-			eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
 	}
 
-	*qw0 = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-		eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-		eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
+	*qw0 = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+		eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+		eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
 }
 
 static inline uint16_t
drivers/net/intel/iavf/iavf_rxtx.h +0 -34
index 3ff49b94b4..19931f5f7c 100644
@@ -444,40 +444,6 @@ enum iavf_rx_flex_desc_ipsec_crypto_status {
 #define IAVF_TXD_CTX_QW1_SEG_PARAMS_MSS_MASK		\
 	(0x3FFFUL << IAVF_TXD_CTX_QW1_SEG_PARAMS_MSS_SHIFT)
 
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT		(0)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_MASK		(0x3UL)
-
-enum iavf_tx_ctx_desc_tunnel_external_ip_type {
-	IAVF_TX_CTX_DESC_EIPT_NONE,
-	IAVF_TX_CTX_DESC_EIPT_IPV6,
-	IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD,
-	IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD
-};
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT	(2)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_MASK		(0x7FUL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNT_SHIFT	(9)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNT_MASK		(0x3UL)
-
-enum iavf_tx_ctx_desc_tunnel_l4_tunnel_type {
-	IAVF_TX_CTX_DESC_L4_TUN_TYP_NO_UDP_GRE,
-	IAVF_TX_CTX_DESC_L4_TUN_TYP_UDP,
-	IAVF_TX_CTX_DESC_L4_TUN_TYP_GRE
-};
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT	(11)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_MASK	(0x1UL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNLEN_SHIFT	(12)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4TUNLEN_MASK	(0x7FUL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_DECTTL_SHIFT	(19)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_DECTTL_MASK		(0xFUL)
-
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4T_CS_SHIFT	(23)
-#define IAVF_TXD_CTX_QW0_TUN_PARAMS_L4T_CS_MASK		(0x1UL)
-
 #define IAVF_TXD_CTX_QW0_L2TAG2_PARAM			(32)
 #define IAVF_TXD_CTX_QW0_L2TAG2_MASK			(0xFFFFUL)
 
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +15 -15
index 10e96a8510..f95aabe577 100644
@@ -1760,7 +1760,7 @@ static inline void
 iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 {
 	if (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
-		uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
+		uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
 		uint64_t eip_len = 0;
 		uint64_t eip_noinc = 0;
 		/* Default - IP_ID is increment in each segment of LSO */
@@ -1769,15 +1769,15 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 				RTE_MBUF_F_TX_OUTER_IPV6 |
 				RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
 		case RTE_MBUF_F_TX_OUTER_IPV4:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV6:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
+			eip_typ = CI_TX_CTX_EIPT_IPV6;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		}
@@ -1791,10 +1791,10 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
 		case RTE_MBUF_F_TX_TUNNEL_GTP:
 		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-			eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
 			break;
 		case RTE_MBUF_F_TX_TUNNEL_GRE:
-			eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
 			break;
 		default:
 			PMD_TX_LOG(ERR, "Tunnel type not supported");
@@ -1811,22 +1811,22 @@ iavf_fill_ctx_desc_tunneling_avx2(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		 * its last Ethertype.
 		 * If MPLS labels exists, it should include them as well.
 		 */
-		eip_typ |= (pkt->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
+		eip_typ |= (pkt->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
 
 		/**
 		 * Calculate the tunneling UDP checksum.
 		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
 		 */
-		if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV4 |
-					IAVF_TX_CTX_EXT_IP_IPV6 |
-					IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-				(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
 				(pkt->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-			eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
 
-		*low_ctx_qw = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-			eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-			eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
+		*low_ctx_qw = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+			eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+			eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
 
 	} else {
 		*low_ctx_qw = 0;
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +15 -15
index 58ed89a72a..74d91fff31 100644
@@ -1899,7 +1899,7 @@ static __rte_always_inline void
 iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 {
 	if (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
-		uint64_t eip_typ = IAVF_TX_CTX_DESC_EIPT_NONE;
+		uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
 		uint64_t eip_len = 0;
 		uint64_t eip_noinc = 0;
 		/* Default - IP_ID is increment in each segment of LSO */
@@ -1908,15 +1908,15 @@ iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 				RTE_MBUF_F_TX_OUTER_IPV6 |
 				RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
 		case RTE_MBUF_F_TX_OUTER_IPV4:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_NO_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV4_CHECKSUM_OFFLOAD;
+			eip_typ = CI_TX_CTX_EIPT_IPV4;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		case RTE_MBUF_F_TX_OUTER_IPV6:
-			eip_typ = IAVF_TX_CTX_DESC_EIPT_IPV6;
+			eip_typ = CI_TX_CTX_EIPT_IPV6;
 			eip_len = pkt->outer_l3_len >> 2;
 		break;
 		}
@@ -1930,10 +1930,10 @@ iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
 		case RTE_MBUF_F_TX_TUNNEL_GTP:
 		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
-			eip_typ |= IAVF_TXD_CTX_UDP_TUNNELING;
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
 			break;
 		case RTE_MBUF_F_TX_TUNNEL_GRE:
-			eip_typ |= IAVF_TXD_CTX_GRE_TUNNELING;
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
 			break;
 		default:
 			PMD_TX_LOG(ERR, "Tunnel type not supported");
@@ -1950,22 +1950,22 @@ iavf_fill_ctx_desc_tunneling_avx512(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 		 * its last Ethertype.
 		 * If MPLS labels exists, it should include them as well.
 		 */
-		eip_typ |= (pkt->l2_len >> 1) << IAVF_TXD_CTX_QW0_NATLEN_SHIFT;
+		eip_typ |= (pkt->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
 
 		/**
 		 * Calculate the tunneling UDP checksum.
 		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
 		 */
-		if ((eip_typ & (IAVF_TX_CTX_EXT_IP_IPV4 |
-					IAVF_TX_CTX_EXT_IP_IPV6 |
-					IAVF_TX_CTX_EXT_IP_IPV4_NO_CSUM)) &&
-				(eip_typ & IAVF_TXD_CTX_UDP_TUNNELING) &&
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
 				(pkt->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
-			eip_typ |= IAVF_TXD_CTX_QW0_L4T_CS_MASK;
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
 
-		*low_ctx_qw = eip_typ << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPT_SHIFT |
-			eip_len << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIPLEN_SHIFT |
-			eip_noinc << IAVF_TXD_CTX_QW0_TUN_PARAMS_EIP_NOINC_SHIFT;
+		*low_ctx_qw = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+			eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+			eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
 
 	} else {
 		*low_ctx_qw = 0;
Signature · 1 line
2.53.0
#56 lore raw

PATCH v3 6/15 net/intel: move iavf descriptor writing functions to common

In reply to Bruce Richardson

In order to promote reuse of code, move the Tx vector functions for writing descriptors from the iavf driver to the common folder in a new tx_vec_x86.h file. This will allow reuse in later commits by other drivers such as ice.

---
 drivers/net/intel/common/tx_vec_x86.h         | 511 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 285 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 272 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  75 +--
 4 files changed, 530 insertions(+), 613 deletions(-)
 create mode 100644 drivers/net/intel/common/tx_vec_x86.h
drivers/net/intel/common/tx_vec_x86.h new file +511 -0
new file mode 100644
index 0000000000..36e855eb26
@@ -0,0 +1,511 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2026 Intel Corporation
+ */
+
+#ifndef _COMMON_INTEL_TX_VEC_X86_H_
+#define _COMMON_INTEL_TX_VEC_X86_H_
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+
+#include "tx.h"
+
+static __rte_always_inline void
+ci_fill_ctx_desc_tunneling(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
+{
+	if (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
+		uint64_t eip_typ = CI_TX_CTX_EIPT_NONE;
+		uint64_t eip_len = 0;
+		uint64_t eip_noinc = 0;
+		/* Default - IP_ID is increment in each segment of LSO */
+
+		switch (pkt->ol_flags & (RTE_MBUF_F_TX_OUTER_IPV4 |
+				RTE_MBUF_F_TX_OUTER_IPV6 |
+				RTE_MBUF_F_TX_OUTER_IP_CKSUM)) {
+		case RTE_MBUF_F_TX_OUTER_IPV4:
+			eip_typ = CI_TX_CTX_EIPT_IPV4_NO_CSUM;
+			eip_len = pkt->outer_l3_len >> 2;
+		break;
+		case RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM:
+			eip_typ = CI_TX_CTX_EIPT_IPV4;
+			eip_len = pkt->outer_l3_len >> 2;
+		break;
+		case RTE_MBUF_F_TX_OUTER_IPV6:
+			eip_typ = CI_TX_CTX_EIPT_IPV6;
+			eip_len = pkt->outer_l3_len >> 2;
+		break;
+		}
+
+		/* L4TUNT: L4 Tunneling Type */
+		switch (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK) {
+		case RTE_MBUF_F_TX_TUNNEL_IPIP:
+			/* for non UDP / GRE tunneling, set to 00b */
+			break;
+		case RTE_MBUF_F_TX_TUNNEL_VXLAN:
+		case RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE:
+		case RTE_MBUF_F_TX_TUNNEL_GTP:
+		case RTE_MBUF_F_TX_TUNNEL_GENEVE:
+			eip_typ |= CI_TXD_CTX_UDP_TUNNELING;
+			break;
+		case RTE_MBUF_F_TX_TUNNEL_GRE:
+			eip_typ |= CI_TXD_CTX_GRE_TUNNELING;
+			break;
+		default:
+			PMD_TX_LOG(ERR, "Tunnel type not supported");
+			return;
+		}
+
+		/* L4TUNLEN: L4 Tunneling Length, in Words
+		 *
+		 * We depend on app to set rte_mbuf.l2_len correctly.
+		 * For IP in GRE it should be set to the length of the GRE
+		 * header;
+		 * For MAC in GRE or MAC in UDP it should be set to the length
+		 * of the GRE or UDP headers plus the inner MAC up to including
+		 * its last Ethertype.
+		 * If MPLS labels exists, it should include them as well.
+		 */
+		eip_typ |= (pkt->l2_len >> 1) << CI_TXD_CTX_QW0_NATLEN_S;
+
+		/**
+		 * Calculate the tunneling UDP checksum.
+		 * Shall be set only if L4TUNT = 01b and EIPT is not zero
+		 */
+		if ((eip_typ & (CI_TX_CTX_EIPT_IPV4 |
+					CI_TX_CTX_EIPT_IPV6 |
+					CI_TX_CTX_EIPT_IPV4_NO_CSUM)) &&
+				(eip_typ & CI_TXD_CTX_UDP_TUNNELING) &&
+				(pkt->ol_flags & RTE_MBUF_F_TX_OUTER_UDP_CKSUM))
+			eip_typ |= CI_TXD_CTX_QW0_L4T_CS_M;
+
+		*low_ctx_qw = eip_typ << CI_TXD_CTX_QW0_EIPT_S |
+			eip_len << CI_TXD_CTX_QW0_EIPLEN_S |
+			eip_noinc << CI_TXD_CTX_QW0_EIP_NOINC_S;
+
+	} else {
+		*low_ctx_qw = 0;
+	}
+}
+
+static __rte_always_inline void
+ci_tx_vec_offload(struct rte_mbuf *tx_pkt, uint64_t *txd_hi,
+		enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	uint64_t ol_flags = tx_pkt->ol_flags;
+	uint32_t td_cmd = 0;
+	uint32_t td_offset = 0;
+
+	/* Set MACLEN */
+	if (ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)
+		td_offset |= (tx_pkt->outer_l2_len >> 1) << CI_TX_DESC_LEN_MACLEN_S;
+	else
+		td_offset |= (tx_pkt->l2_len >> 1) << CI_TX_DESC_LEN_MACLEN_S;
+
+	/* Enable L3 checksum offloads */
+	if (ol_flags & RTE_MBUF_F_TX_IP_CKSUM) {
+		if (ol_flags & RTE_MBUF_F_TX_IPV4) {
+			td_cmd |= CI_TX_DESC_CMD_IIPT_IPV4_CSUM;
+			td_offset |= (tx_pkt->l3_len >> 2) << CI_TX_DESC_LEN_IPLEN_S;
+		}
+	} else if (ol_flags & RTE_MBUF_F_TX_IPV4) {
+		td_cmd |= CI_TX_DESC_CMD_IIPT_IPV4;
+		td_offset |= (tx_pkt->l3_len >> 2) << CI_TX_DESC_LEN_IPLEN_S;
+	} else if (ol_flags & RTE_MBUF_F_TX_IPV6) {
+		td_cmd |= CI_TX_DESC_CMD_IIPT_IPV6;
+		td_offset |= (tx_pkt->l3_len >> 2) << CI_TX_DESC_LEN_IPLEN_S;
+	}
+
+	/* Enable L4 checksum offloads */
+	switch (ol_flags & RTE_MBUF_F_TX_L4_MASK) {
+	case RTE_MBUF_F_TX_TCP_CKSUM:
+		td_cmd |= CI_TX_DESC_CMD_L4T_EOFT_TCP;
+		td_offset |= (sizeof(struct rte_tcp_hdr) >> 2) << CI_TX_DESC_LEN_L4_LEN_S;
+		break;
+	case RTE_MBUF_F_TX_SCTP_CKSUM:
+		td_cmd |= CI_TX_DESC_CMD_L4T_EOFT_SCTP;
+		td_offset |= (sizeof(struct rte_sctp_hdr) >> 2) << CI_TX_DESC_LEN_L4_LEN_S;
+		break;
+	case RTE_MBUF_F_TX_UDP_CKSUM:
+		td_cmd |= CI_TX_DESC_CMD_L4T_EOFT_UDP;
+		td_offset |= (sizeof(struct rte_udp_hdr) >> 2) << CI_TX_DESC_LEN_L4_LEN_S;
+		break;
+	default:
+		break;
+	}
+
+	*txd_hi |= ((uint64_t)td_offset) << CI_TXD_QW1_OFFSET_S;
+
+	if (ol_flags & RTE_MBUF_F_TX_QINQ) {
+		td_cmd |= CI_TX_DESC_CMD_IL2TAG1;
+		/* L2Tag1 always carries a tag for QinQ */
+		if (qinq_outer_pos == CI_TAG_IN_DATA_DESC)
+			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci_outer << CI_TXD_QW1_L2TAG1_S);
+		else
+			*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
+	} else if (ol_flags & RTE_MBUF_F_TX_VLAN && single_vlan_pos == CI_TAG_IN_DATA_DESC) {
+		td_cmd |= CI_TX_DESC_CMD_IL2TAG1;
+		*txd_hi |= ((uint64_t)tx_pkt->vlan_tci << CI_TXD_QW1_L2TAG1_S);
+	}
+
+	*txd_hi |= ((uint64_t)td_cmd) << CI_TXD_QW1_CMD_S;
+}
+
+static __rte_always_inline void
+ci_vtx1(volatile struct ci_tx_desc *txdp,
+	  struct rte_mbuf *pkt, uint64_t flags, bool offload,
+	  enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
+			((uint64_t)flags << CI_TXD_QW1_CMD_S) |
+			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
+	if (offload)
+		ci_tx_vec_offload(pkt, &high_qw, single_vlan_pos, qinq_outer_pos);
+
+	__m128i descriptor = _mm_set_epi64x(high_qw, pkt->buf_iova + pkt->data_off);
+	_mm_store_si128(RTE_CAST_PTR(__m128i *, txdp), descriptor);
+}
+
+#ifdef __AVX2__
+
+static __rte_always_inline void
+ci_vtx_avx2(volatile struct ci_tx_desc *txdp,
+	 struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload,
+	 enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
+
+	/* if unaligned on 32-bit boundary, do one to align */
+	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		nb_pkts--; txdp++; pkt++;
+	}
+
+	/* do two at a time while possible, in bursts */
+	for (; nb_pkts > 3; txdp += 4, pkt += 4, nb_pkts -= 4) {
+		uint64_t hi_qw3 = hi_qw_tmpl |
+			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[3], &hi_qw3, single_vlan_pos, qinq_outer_pos);
+		uint64_t hi_qw2 = hi_qw_tmpl |
+			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[2], &hi_qw2, single_vlan_pos, qinq_outer_pos);
+		uint64_t hi_qw1 = hi_qw_tmpl |
+			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[1], &hi_qw1, single_vlan_pos, qinq_outer_pos);
+		uint64_t hi_qw0 = hi_qw_tmpl |
+			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload)
+			ci_tx_vec_offload(pkt[0], &hi_qw0, single_vlan_pos, qinq_outer_pos);
+
+		__m256i desc2_3 =
+			_mm256_set_epi64x
+				(hi_qw3,
+				 pkt[3]->buf_iova + pkt[3]->data_off,
+				 hi_qw2,
+				 pkt[2]->buf_iova + pkt[2]->data_off);
+		__m256i desc0_1 =
+			_mm256_set_epi64x
+				(hi_qw1,
+				 pkt[1]->buf_iova + pkt[1]->data_off,
+				 hi_qw0,
+				 pkt[0]->buf_iova + pkt[0]->data_off);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
+	}
+
+	/* do any last ones */
+	while (nb_pkts) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		txdp++; pkt++; nb_pkts--;
+	}
+}
+
+static __rte_always_inline void
+ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
+		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
+		enum ci_l2tag_pos qinq_outer_pos, bool ptype_lldp_enabled)
+{
+	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
+	uint64_t low_ctx_qw = 0;
+
+	if (offload) {
+		ci_fill_ctx_desc_tunneling(&low_ctx_qw, pkt);
+		if (pkt->ol_flags & RTE_MBUF_F_TX_QINQ) {
+			uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+				(uint64_t)pkt->vlan_tci_outer :
+				(uint64_t)pkt->vlan_tci;
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+		} else if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) &&
+				single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+		}
+	}
+	if (IAVF_CHECK_TX_LLDP(pkt, ptype_lldp_enabled))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
+			((uint64_t)flags  << CI_TXD_QW1_CMD_S) |
+			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
+	if (offload)
+		ci_tx_vec_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
+
+	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
+							high_ctx_qw, low_ctx_qw);
+
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+}
+
+static __rte_always_inline void
+ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
+		struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags,
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		bool ptype_lldp_enabled)
+{
+	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags  << CI_TXD_QW1_CMD_S));
+
+	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
+		uint64_t hi_ctx_qw1 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t hi_ctx_qw0 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t low_ctx_qw1 = 0;
+		uint64_t low_ctx_qw0 = 0;
+		uint64_t hi_data_qw1 = 0;
+		uint64_t hi_data_qw0 = 0;
+
+		hi_data_qw1 = hi_data_qw_tmpl |
+				((uint64_t)pkt[1]->data_len <<
+					CI_TXD_QW1_TX_BUF_SZ_S);
+		hi_data_qw0 = hi_data_qw_tmpl |
+				((uint64_t)pkt[0]->data_len <<
+					CI_TXD_QW1_TX_BUF_SZ_S);
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw1, pkt[1]);
+			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[1]->vlan_tci_outer :
+					(uint64_t)pkt[1]->vlan_tci;
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[1]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[1], ptype_lldp_enabled))
+			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw0, pkt[0]);
+			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[0]->vlan_tci_outer :
+					(uint64_t)pkt[0]->vlan_tci;
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[0]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[0], ptype_lldp_enabled))
+			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[0], &hi_data_qw0, single_vlan_pos, qinq_outer_pos);
+		}
+
+		__m256i desc2_3 = _mm256_set_epi64x
+				(hi_data_qw1, pkt[1]->buf_iova + pkt[1]->data_off,
+				 hi_ctx_qw1, low_ctx_qw1);
+		__m256i desc0_1 = _mm256_set_epi64x
+				(hi_data_qw0, pkt[0]->buf_iova + pkt[0]->data_off,
+				 hi_ctx_qw0, low_ctx_qw0);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
+		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
+	}
+
+	if (nb_pkts)
+		ci_vtx1_ctx_avx2(txdp, *pkt, flags, offload,
+				single_vlan_pos, qinq_outer_pos, ptype_lldp_enabled);
+}
+
+#endif /* __AVX2__ */
+
+#ifdef __AVX512VL__
+
+static __rte_always_inline void
+ci_vtx_avx512(volatile struct ci_tx_desc *txdp,
+		struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags,
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos)
+{
+	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
+
+	/* if unaligned on 32-bit boundary, do one to align */
+	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		nb_pkts--; txdp++; pkt++;
+	}
+
+	/* do 4 at a time while possible, in bursts */
+	for (; nb_pkts > 3; txdp += 4, pkt += 4, nb_pkts -= 4) {
+		uint64_t hi_qw3 = hi_qw_tmpl |
+			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		uint64_t hi_qw2 = hi_qw_tmpl |
+			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		uint64_t hi_qw1 = hi_qw_tmpl |
+			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		uint64_t hi_qw0 = hi_qw_tmpl |
+			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		if (offload) {
+			ci_tx_vec_offload(pkt[3], &hi_qw3, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[2], &hi_qw2, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[1], &hi_qw1, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[0], &hi_qw0, single_vlan_pos, qinq_outer_pos);
+		}
+
+		__m512i desc0_3 =
+			_mm512_set_epi64
+				(hi_qw3,
+				 pkt[3]->buf_iova + pkt[3]->data_off,
+				 hi_qw2,
+				 pkt[2]->buf_iova + pkt[2]->data_off,
+				 hi_qw1,
+				 pkt[1]->buf_iova + pkt[1]->data_off,
+				 hi_qw0,
+				 pkt[0]->buf_iova + pkt[0]->data_off);
+		_mm512_storeu_si512(RTE_CAST_PTR(void *, txdp), desc0_3);
+	}
+
+	/* do any last ones */
+	while (nb_pkts) {
+		ci_vtx1(txdp, *pkt, flags, offload, single_vlan_pos, qinq_outer_pos);
+		txdp++; pkt++; nb_pkts--;
+	}
+}
+
+static __rte_always_inline void
+ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
+		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
+		enum ci_l2tag_pos qinq_outer_pos, bool lldp_enabled)
+{
+	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
+	uint64_t low_ctx_qw = 0;
+
+	if (offload) {
+		ci_fill_ctx_desc_tunneling(&low_ctx_qw, pkt);
+		if (pkt->ol_flags & RTE_MBUF_F_TX_QINQ) {
+			uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+				(uint64_t)pkt->vlan_tci_outer :
+				(uint64_t)pkt->vlan_tci;
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+		} else if ((pkt->ol_flags & RTE_MBUF_F_TX_VLAN) &&
+				single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+			high_ctx_qw |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+		}
+	}
+	if (IAVF_CHECK_TX_LLDP(pkt, lldp_enabled))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
+			((uint64_t)flags << CI_TXD_QW1_CMD_S) |
+			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
+	if (offload)
+		ci_tx_vec_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
+
+	__m256i ctx_data_desc = _mm256_set_epi64x
+			(high_data_qw, pkt->buf_iova + pkt->data_off,
+			high_ctx_qw, low_ctx_qw);
+
+	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
+	_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), ctx_data_desc);
+}
+
+static __rte_always_inline void
+ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
+		struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags,
+		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		bool lldp_enabled)
+{
+	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
+
+	for (; nb_pkts > 1; txdp += 4, pkt += 2, nb_pkts -= 2) {
+		uint64_t hi_ctx_qw1 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t hi_ctx_qw0 = CI_TX_DESC_DTYPE_CTX;
+		uint64_t low_ctx_qw1 = 0;
+		uint64_t low_ctx_qw0 = 0;
+		uint64_t hi_data_qw1 = 0;
+		uint64_t hi_data_qw0 = 0;
+
+		hi_data_qw1 = hi_data_qw_tmpl |
+				((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+		hi_data_qw0 = hi_data_qw_tmpl |
+				((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw1; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw1, pkt[1]);
+			if (pkt[1]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[1]->vlan_tci_outer :
+					(uint64_t)pkt[1]->vlan_tci;
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[1]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw1 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[1], lldp_enabled))
+			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
+			ci_fill_ctx_desc_tunneling(&low_ctx_qw0, pkt[0]);
+			if (pkt[0]->ol_flags & RTE_MBUF_F_TX_QINQ) {
+				uint64_t qinq_tag = qinq_outer_pos == CI_TAG_IN_CTX_DESC ?
+					(uint64_t)pkt[0]->vlan_tci_outer :
+					(uint64_t)pkt[0]->vlan_tci;
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= qinq_tag << CI_TXD_CTX_QW0_L2TAG2_S;
+			} else if (pkt[0]->ol_flags & RTE_MBUF_F_TX_VLAN &&
+					single_vlan_pos == CI_TAG_IN_CTX_DESC) {
+				hi_ctx_qw0 |= CI_TX_CTX_DESC_IL2TAG2 << CI_TXD_QW1_CMD_S;
+				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
+			}
+		}
+		if (IAVF_CHECK_TX_LLDP(pkt[0], lldp_enabled))
+			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+
+		if (offload) {
+			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
+			ci_tx_vec_offload(pkt[0], &hi_data_qw0, single_vlan_pos, qinq_outer_pos);
+		}
+
+		__m512i desc0_3 = _mm512_set_epi64
+				(hi_data_qw1, pkt[1]->buf_iova + pkt[1]->data_off,
+				hi_ctx_qw1, low_ctx_qw1,
+				hi_data_qw0, pkt[0]->buf_iova + pkt[0]->data_off,
+				hi_ctx_qw0, low_ctx_qw0);
+		_mm512_storeu_si512(RTE_CAST_PTR(void *, txdp), desc0_3);
+	}
+
+	if (nb_pkts)
+		ci_vtx1_ctx_avx512(txdp, *pkt, flags, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_enabled);
+}
+
+#endif /* __AVX512VL__ */
+
+#endif /* _COMMON_INTEL_TX_VEC_X86_H_ */
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +7 -278

326 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +8 -264

309 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_common.h +4 -71

85 lines not on this page · raw message

Signature · 1 line
2.53.0
#57 lore raw

PATCH v3 7/15 net/intel: use function callback for lldp

In reply to Bruce Richardson

Limit LLDP support for iavf drivers for now, by using a callback to handle its processing. Drivers not supporting this pass a NULL pointer and the compiler will optimize away the branches. For iavf, the compiler can inline the subfunction directly as it's known at compile-time.

---
 drivers/net/intel/common/tx_vec_x86.h         | 42 +++++++++++--------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 16 +++++--
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 17 +++++---
 3 files changed, 48 insertions(+), 27 deletions(-)
drivers/net/intel/common/tx_vec_x86.h +24 -18
index 36e855eb26..0c6c60a21e 100644
@@ -11,6 +11,12 @@
 
 #include "tx.h"
 
+/* Optional per-driver LLDP switch-uplink check for ctx descriptors.
+ * Takes the ctx-desc high qword and returns it with the LLDP bit applied
+ * if appropriate. NULL disables the check.
+ */
+typedef uint64_t (*ci_tx_ctx_lldp_fn)(struct rte_mbuf *pkt, uint64_t high_ctx_qw);
+
 static __rte_always_inline void
 ci_fill_ctx_desc_tunneling(uint64_t *low_ctx_qw, struct rte_mbuf *pkt)
 {
@@ -226,7 +232,7 @@ ci_vtx_avx2(volatile struct ci_tx_desc *txdp,
 static __rte_always_inline void
 ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
-		enum ci_l2tag_pos qinq_outer_pos, bool ptype_lldp_enabled)
+		enum ci_l2tag_pos qinq_outer_pos, ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
 	uint64_t low_ctx_qw = 0;
@@ -245,8 +251,8 @@ ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 		}
 	}
-	if (IAVF_CHECK_TX_LLDP(pkt, ptype_lldp_enabled))
-		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	if (lldp_check != NULL)
+		high_ctx_qw = lldp_check(pkt, high_ctx_qw);
 	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
 			((uint64_t)flags  << CI_TXD_QW1_CMD_S) |
 			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
@@ -264,7 +270,7 @@ static __rte_always_inline void
 ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 		struct rte_mbuf **pkt, uint16_t nb_pkts, uint64_t flags,
 		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
-		bool ptype_lldp_enabled)
+		ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags  << CI_TXD_QW1_CMD_S));
 
@@ -298,8 +304,8 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[1], ptype_lldp_enabled))
-			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw1 = lldp_check(pkt[1], hi_ctx_qw1);
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
@@ -316,8 +322,8 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[0], ptype_lldp_enabled))
-			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw0 = lldp_check(pkt[0], hi_ctx_qw0);
 
 		if (offload) {
 			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
@@ -336,7 +342,7 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 
 	if (nb_pkts)
 		ci_vtx1_ctx_avx2(txdp, *pkt, flags, offload,
-				single_vlan_pos, qinq_outer_pos, ptype_lldp_enabled);
+				single_vlan_pos, qinq_outer_pos, lldp_check);
 }
 
 #endif /* __AVX2__ */
@@ -396,7 +402,7 @@ ci_vtx_avx512(volatile struct ci_tx_desc *txdp,
 static __rte_always_inline void
 ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		uint64_t flags, bool offload, enum ci_l2tag_pos single_vlan_pos,
-		enum ci_l2tag_pos qinq_outer_pos, bool lldp_enabled)
+		enum ci_l2tag_pos qinq_outer_pos, ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t high_ctx_qw = CI_TX_DESC_DTYPE_CTX;
 	uint64_t low_ctx_qw = 0;
@@ -415,8 +421,8 @@ ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 			low_ctx_qw |= (uint64_t)pkt->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 		}
 	}
-	if (IAVF_CHECK_TX_LLDP(pkt, lldp_enabled))
-		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	if (lldp_check != NULL)
+		high_ctx_qw = lldp_check(pkt, high_ctx_qw);
 	uint64_t high_data_qw = (CI_TX_DESC_DTYPE_DATA |
 			((uint64_t)flags << CI_TXD_QW1_CMD_S) |
 			((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
@@ -435,7 +441,7 @@ static __rte_always_inline void
 ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 		struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags,
 		bool offload, enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
-		bool lldp_enabled)
+		ci_tx_ctx_lldp_fn lldp_check)
 {
 	uint64_t hi_data_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
 
@@ -467,8 +473,8 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw1 |= (uint64_t)pkt[1]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[1], lldp_enabled))
-			hi_ctx_qw1 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw1 = lldp_check(pkt[1], hi_ctx_qw1);
 
 		if (offload) {
 			/* tunnel fill assigns low_ctx_qw0; must run before QinQ/VLAN OR below */
@@ -485,8 +491,8 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 				low_ctx_qw0 |= (uint64_t)pkt[0]->vlan_tci << CI_TXD_CTX_QW0_L2TAG2_S;
 			}
 		}
-		if (IAVF_CHECK_TX_LLDP(pkt[0], lldp_enabled))
-			hi_ctx_qw0 |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+		if (lldp_check != NULL)
+			hi_ctx_qw0 = lldp_check(pkt[0], hi_ctx_qw0);
 
 		if (offload) {
 			ci_tx_vec_offload(pkt[1], &hi_data_qw1, single_vlan_pos, qinq_outer_pos);
@@ -503,7 +509,7 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 
 	if (nb_pkts)
 		ci_vtx1_ctx_avx512(txdp, *pkt, flags, offload,
-				single_vlan_pos, qinq_outer_pos, lldp_enabled);
+					single_vlan_pos, qinq_outer_pos, lldp_check);
 }
 
 #endif /* __AVX512VL__ */
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +12 -4
index 1d0492edd9..813611015d 100644
@@ -1685,6 +1685,14 @@ iavf_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return nb_pkts;
 }
 
+static __rte_always_inline uint64_t
+iavf_tx_ctx_lldp_check(struct rte_mbuf *pkt, uint64_t high_ctx_qw)
+{
+	if (IAVF_CHECK_TX_LLDP(pkt, true))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	return high_ctx_qw;
+}
+
 static __rte_always_inline uint16_t
 iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 				 uint16_t nb_pkts, bool offload)
@@ -1696,7 +1704,7 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	/* bit2 is reserved and must be set to 1 according to Spec */
 	uint64_t flags = IAVF_TX_DESC_CMD_EOP | IAVF_TX_DESC_CMD_ICRC;
 	uint64_t rs = IAVF_TX_DESC_CMD_RS | flags;
-	bool lldp_enabled = txq->lldp_enabled;
+	ci_tx_ctx_lldp_fn lldp_check = txq->lldp_enabled ? iavf_tx_ctx_lldp_check : NULL;
 	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
 	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
 			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
@@ -1723,10 +1731,10 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
 		ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
-				vlan_pos, vlan_pos, lldp_enabled);
+				vlan_pos, vlan_pos, lldp_check);
 		tx_pkts += (nb_mbuf - 1);
 		txdp += (n - 2);
-		ci_vtx1_ctx_avx2(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_enabled);
+		ci_vtx1_ctx_avx2(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_check);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -1740,7 +1748,7 @@ iavf_xmit_fixed_burst_vec_avx2_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	nb_mbuf = nb_commit >> 1;
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
 
-	ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
+	ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_check);
 	tx_id = (uint16_t)(tx_id + nb_commit);
 
 	if (tx_id > txq->tx_next_rs) {
drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +12 -5
index 0c738e4882..fe00416660 100644
@@ -1900,6 +1900,14 @@ iavf_xmit_fixed_burst_vec_avx512(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return nb_pkts;
 }
 
+static __rte_always_inline uint64_t
+iavf_tx_ctx_lldp_check(struct rte_mbuf *pkt, uint64_t high_ctx_qw)
+{
+	if (IAVF_CHECK_TX_LLDP(pkt, true))
+		high_ctx_qw |= IAVF_TX_CTX_DESC_SWTCH_UPLINK << CI_TXD_QW1_CMD_S;
+	return high_ctx_qw;
+}
+
 static __rte_always_inline uint16_t
 iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 				 uint16_t nb_pkts, bool offload)
@@ -1911,7 +1919,7 @@ iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	/* bit2 is reserved and must be set to 1 according to Spec */
 	uint64_t flags = CI_TX_DESC_CMD_EOP | CI_TX_DESC_CMD_ICRC;
 	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
-	bool lldp_enabled = txq->lldp_enabled;
+	ci_tx_ctx_lldp_fn lldp_check = txq->lldp_enabled ? iavf_tx_ctx_lldp_check : NULL;
 	/* vlan_flag gives both the single-VLAN and the QinQ outer tag position */
 	enum ci_l2tag_pos vlan_pos = (txq->vlan_flag & IAVF_TX_FLAGS_VLAN_TAG_LOC_L2TAG1) ?
 			CI_TAG_IN_DATA_DESC : CI_TAG_IN_CTX_DESC;
@@ -1938,11 +1946,10 @@ iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 		tx_backlog_entry_avx512(txep, tx_pkts, nb_mbuf);
 
 		ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
-				vlan_pos, vlan_pos, lldp_enabled);
+				vlan_pos, vlan_pos, lldp_check);
 		tx_pkts += (nb_mbuf - 1);
 		txdp += (n - 2);
-		ci_vtx1_ctx_avx512(txdp, *tx_pkts++, rs, offload,
-				vlan_pos, vlan_pos, lldp_enabled);
+		ci_vtx1_ctx_avx512(txdp, *tx_pkts++, rs, offload, vlan_pos, vlan_pos, lldp_check);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -1956,7 +1963,7 @@ iavf_xmit_fixed_burst_vec_avx512_ctx(void *tx_queue, struct rte_mbuf **tx_pkts,
 	nb_mbuf = nb_commit >> 1;
 	tx_backlog_entry_avx512(txep, tx_pkts, nb_mbuf);
 
-	ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_enabled);
+	ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf, flags, offload, vlan_pos, vlan_pos, lldp_check);
 	tx_id = (uint16_t)(tx_id + nb_commit);
 
 	if (tx_id > txq->tx_next_rs) {
Signature · 1 line
2.53.0
#58 lore raw

PATCH v3 8/15 net/intel: allow building without IOVA in mbuf

In reply to Bruce Richardson

Ensure correct macros are used to build the vector Tx code without the IOVA stored explicitly in the mbuf. This allows the iavf driver to build when the config setting for IOVA in mbuf is disabled.

---
 drivers/net/intel/common/tx_vec_x86.h | 30 +++++++++++++--------------
 drivers/net/intel/iavf/meson.build    |  4 +---
 2 files changed, 16 insertions(+), 18 deletions(-)
drivers/net/intel/common/tx_vec_x86.h +15 -15
index 0c6c60a21e..56efe1d1ec 100644
@@ -168,7 +168,7 @@ ci_vtx1(volatile struct ci_tx_desc *txdp,
 	if (offload)
 		ci_tx_vec_offload(pkt, &high_qw, single_vlan_pos, qinq_outer_pos);
 
-	__m128i descriptor = _mm_set_epi64x(high_qw, pkt->buf_iova + pkt->data_off);
+	__m128i descriptor = _mm_set_epi64x(high_qw, rte_pktmbuf_iova(pkt));
 	_mm_store_si128(RTE_CAST_PTR(__m128i *, txdp), descriptor);
 }
 
@@ -209,15 +209,15 @@ ci_vtx_avx2(volatile struct ci_tx_desc *txdp,
 		__m256i desc2_3 =
 			_mm256_set_epi64x
 				(hi_qw3,
-				 pkt[3]->buf_iova + pkt[3]->data_off,
+				 rte_pktmbuf_iova(pkt[3]),
 				 hi_qw2,
-				 pkt[2]->buf_iova + pkt[2]->data_off);
+				 rte_pktmbuf_iova(pkt[2]));
 		__m256i desc0_1 =
 			_mm256_set_epi64x
 				(hi_qw1,
-				 pkt[1]->buf_iova + pkt[1]->data_off,
+				 rte_pktmbuf_iova(pkt[1]),
 				 hi_qw0,
-				 pkt[0]->buf_iova + pkt[0]->data_off);
+				 rte_pktmbuf_iova(pkt[0]));
 		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
 		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
 	}
@@ -259,7 +259,7 @@ ci_vtx1_ctx_avx2(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 	if (offload)
 		ci_tx_vec_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
 
-	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, pkt->buf_iova + pkt->data_off,
+	__m256i ctx_data_desc = _mm256_set_epi64x(high_data_qw, rte_pktmbuf_iova(pkt),
 							high_ctx_qw, low_ctx_qw);
 
 	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
@@ -331,10 +331,10 @@ ci_vtx_ctx_avx2(volatile struct ci_tx_desc *txdp,
 		}
 
 		__m256i desc2_3 = _mm256_set_epi64x
-				(hi_data_qw1, pkt[1]->buf_iova + pkt[1]->data_off,
+				(hi_data_qw1, rte_pktmbuf_iova(pkt[1]),
 				 hi_ctx_qw1, low_ctx_qw1);
 		__m256i desc0_1 = _mm256_set_epi64x
-				(hi_data_qw0, pkt[0]->buf_iova + pkt[0]->data_off,
+				(hi_data_qw0, rte_pktmbuf_iova(pkt[0]),
 				 hi_ctx_qw0, low_ctx_qw0);
 		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
 		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
@@ -382,13 +382,13 @@ ci_vtx_avx512(volatile struct ci_tx_desc *txdp,
 		__m512i desc0_3 =
 			_mm512_set_epi64
 				(hi_qw3,
-				 pkt[3]->buf_iova + pkt[3]->data_off,
+				 rte_pktmbuf_iova(pkt[3]),
 				 hi_qw2,
-				 pkt[2]->buf_iova + pkt[2]->data_off,
+				 rte_pktmbuf_iova(pkt[2]),
 				 hi_qw1,
-				 pkt[1]->buf_iova + pkt[1]->data_off,
+				 rte_pktmbuf_iova(pkt[1]),
 				 hi_qw0,
-				 pkt[0]->buf_iova + pkt[0]->data_off);
+				 rte_pktmbuf_iova(pkt[0]));
 		_mm512_storeu_si512(RTE_CAST_PTR(void *, txdp), desc0_3);
 	}
 
@@ -430,7 +430,7 @@ ci_vtx1_ctx_avx512(volatile struct ci_tx_desc *txdp, struct rte_mbuf *pkt,
 		ci_tx_vec_offload(pkt, &high_data_qw, single_vlan_pos, qinq_outer_pos);
 
 	__m256i ctx_data_desc = _mm256_set_epi64x
-			(high_data_qw, pkt->buf_iova + pkt->data_off,
+			(high_data_qw, rte_pktmbuf_iova(pkt),
 			high_ctx_qw, low_ctx_qw);
 
 	/* tx_id is always even in ctx mode, so txdp is always 32-byte aligned */
@@ -500,9 +500,9 @@ ci_vtx_ctx_avx512(volatile struct ci_tx_desc *txdp,
 		}
 
 		__m512i desc0_3 = _mm512_set_epi64
-				(hi_data_qw1, pkt[1]->buf_iova + pkt[1]->data_off,
+				(hi_data_qw1, rte_pktmbuf_iova(pkt[1]),
 				hi_ctx_qw1, low_ctx_qw1,
-				hi_data_qw0, pkt[0]->buf_iova + pkt[0]->data_off,
+				hi_data_qw0, rte_pktmbuf_iova(pkt[0]),
 				hi_ctx_qw0, low_ctx_qw0);
 		_mm512_storeu_si512(RTE_CAST_PTR(void *, txdp), desc0_3);
 	}
drivers/net/intel/iavf/meson.build +1 -3
index 9b071a3a4b..3884043ae6 100644
@@ -1,9 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2018 Luca Boccassi <[email protected]>
 
-if dpdk_conf.get('RTE_IOVA_IN_MBUF') == 0
-    subdir_done()
-endif
+require_iova_in_mbuf = false
 
 testpmd_sources = files('iavf_testpmd.c')
 
Signature · 1 line
2.53.0
#59 lore raw

PATCH v3 9/15 net/ice: use common descriptor creation functions

In reply to Bruce Richardson

Update ice driver to use the descriptor creation functions from common rather than having it maintain its own copies of them.

---
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 73 ++-------------------
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 64 ++----------------
 drivers/net/intel/ice/ice_rxtx_vec_common.h | 59 -----------------
 3 files changed, 12 insertions(+), 184 deletions(-)
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +6 -67
index b72f69a47b..68401560ce 100644
@@ -5,6 +5,7 @@
 #include "ice_rxtx_vec_common.h"
 
 #include "../common/rx_vec_x86.h"
+#include "../common/tx_vec_x86.h"
 
 #include <rte_vect.h>
 
@@ -773,70 +774,6 @@ ice_recv_scattered_pkts_vec_avx2_offload(void *rx_queue,
 						       true);
 }
 
-static __rte_always_inline void
-ice_vtx1(volatile struct ci_tx_desc *txdp,
-	 struct rte_mbuf *pkt, uint64_t flags, bool offload)
-{
-	uint64_t high_qw = (CI_TX_DESC_DTYPE_DATA |
-		 ((uint64_t)flags << CI_TXD_QW1_CMD_S) |
-		 ((uint64_t)pkt->data_len << CI_TXD_QW1_TX_BUF_SZ_S));
-	if (offload)
-		ice_txd_enable_offload(pkt, &high_qw);
-
-	__m128i descriptor = _mm_set_epi64x(high_qw, rte_pktmbuf_iova(pkt));
-	_mm_store_si128(RTE_CAST_PTR(__m128i *, txdp), descriptor);
-}
-
-static __rte_always_inline void
-ice_vtx(volatile struct ci_tx_desc *txdp,
-	struct rte_mbuf **pkt, uint16_t nb_pkts,  uint64_t flags, bool offload)
-{
-	const uint64_t hi_qw_tmpl = (CI_TX_DESC_DTYPE_DATA | (flags << CI_TXD_QW1_CMD_S));
-
-	/* if unaligned on 32-bit boundary, do one to align */
-	if (((uintptr_t)txdp & 0x1F) != 0 && nb_pkts != 0) {
-		ice_vtx1(txdp, *pkt, flags, offload);
-		nb_pkts--; txdp++; pkt++;
-	}
-
-	/* do four at a time while possible, in bursts */
-	for (; nb_pkts > 3; txdp += 4, pkt += 4, nb_pkts -= 4) {
-		uint64_t hi_qw3 = hi_qw_tmpl |
-			((uint64_t)pkt[3]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[3], &hi_qw3);
-		uint64_t hi_qw2 = hi_qw_tmpl |
-			((uint64_t)pkt[2]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[2], &hi_qw2);
-		uint64_t hi_qw1 = hi_qw_tmpl |
-			((uint64_t)pkt[1]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[1], &hi_qw1);
-		uint64_t hi_qw0 = hi_qw_tmpl |
-			((uint64_t)pkt[0]->data_len << CI_TXD_QW1_TX_BUF_SZ_S);
-		if (offload)
-			ice_txd_enable_offload(pkt[0], &hi_qw0);
-
-		__m256i desc2_3 =
-			_mm256_set_epi64x
-				(hi_qw3, rte_pktmbuf_iova(pkt[3]),
-				 hi_qw2, rte_pktmbuf_iova(pkt[2]));
-		__m256i desc0_1 =
-			_mm256_set_epi64x
-				(hi_qw1, rte_pktmbuf_iova(pkt[1]),
-				 hi_qw0, rte_pktmbuf_iova(pkt[0]));
-		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp + 2), desc2_3);
-		_mm256_store_si256(RTE_CAST_PTR(__m256i *, txdp), desc0_1);
-	}
-
-	/* do any last ones */
-	while (nb_pkts) {
-		ice_vtx1(txdp, *pkt, flags, offload);
-		txdp++; pkt++; nb_pkts--;
-	}
-}
-
 static __rte_always_inline uint16_t
 ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 			      uint16_t nb_pkts, bool offload)
@@ -868,11 +805,12 @@ ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 	if (nb_commit >= n) {
 		ci_tx_backlog_entry_vec(txep, tx_pkts, n);
 
-		ice_vtx(txdp, tx_pkts, n - 1, flags, offload);
+		ci_vtx_avx2(txdp, tx_pkts, n - 1, flags, offload,
+			CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 		tx_pkts += (n - 1);
 		txdp += (n - 1);
 
-		ice_vtx1(txdp, *tx_pkts++, rs, offload);
+		ci_vtx1(txdp, *tx_pkts++, rs, offload, CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 
 		nb_commit = (uint16_t)(nb_commit - n);
 
@@ -886,7 +824,8 @@ ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_commit);
 
-	ice_vtx(txdp, tx_pkts, nb_commit, flags, offload);
+	ci_vtx_avx2(txdp, tx_pkts, nb_commit, flags, offload,
+		CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 
 	tx_id = (uint16_t)(tx_id + nb_commit);
 	if (tx_id > txq->tx_next_rs) {
drivers/net/intel/ice/ice_rxtx_vec_avx512.c +6 -58

91 lines not on this page · raw message

drivers/net/intel/ice/ice_rxtx_vec_common.h +0 -59

63 lines not on this page · raw message

Signature · 1 line
2.53.0
#60 lore raw

PATCH v3 10/15 net/intel: move vector Tx paths to common

In reply to Bruce Richardson

The main loops for vector Tx, both avx2 and avx512 are almost identical across a couple of drivers, so move the iavf copies to common for later reuse by other drivers.

---
 drivers/net/intel/common/tx.h                 |  10 ++
 drivers/net/intel/common/tx_vec_x86.h         | 128 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   |  75 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c |  77 +----------
 4 files changed, 148 insertions(+), 142 deletions(-)
drivers/net/intel/common/tx.h +10 -0
index c8fadee712..630df8cb19 100644
@@ -9,6 +9,8 @@
 #include <rte_mbuf.h>
 #include <rte_ethdev.h>
 #include <rte_vect.h>
+#include <rte_io.h>
+#include <rte_byteorder.h>
 
 /* Common TX Descriptor QW1 Field Definitions */
 #define CI_TXD_QW1_DTYPE_S      0
@@ -273,6 +275,14 @@ ci_tx_backlog_entry_vec(struct ci_tx_entry_vec *txep, struct rte_mbuf **tx_pkts,
 		txep[i].mbuf = tx_pkts[i];
 }
 
+
+/* Write the Tx tail register, byte-swapped for hardware regardless of host endianness. */
+static __rte_always_inline void
+ci_tx_qtx_tail_write(struct ci_tx_queue *txq, uint16_t tx_id)
+{
+	rte_write32_wc(rte_cpu_to_le_32((uint32_t)tx_id), txq->qtx_tail);
+}
+
 #define IETH_VPMD_TX_MAX_FREE_BUF 64
 
 typedef int (*ci_desc_done_fn)(struct ci_tx_queue *txq, uint16_t idx);
drivers/net/intel/common/tx_vec_x86.h +128 -0

140 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +5 -70

93 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +5 -72

95 lines not on this page · raw message

Signature · 1 line
2.53.0
#61 lore raw

PATCH v3 11/15 net/ice: use common AVX Tx functions

In reply to Bruce Richardson

Use the newly created common Tx functions in the vector path.

---
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   |  72 +-------------
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 102 +++-----------------
 2 files changed, 14 insertions(+), 160 deletions(-)
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +2 -70
index 68401560ce..00b5d51aab 100644
@@ -774,74 +774,6 @@ ice_recv_scattered_pkts_vec_avx2_offload(void *rx_queue,
 						       true);
 }
 
-static __rte_always_inline uint16_t
-ice_xmit_fixed_burst_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
-			      uint16_t nb_pkts, bool offload)
-{
-	struct ci_tx_queue *txq = (struct ci_tx_queue *)tx_queue;
-	volatile struct ci_tx_desc *txdp;
-	struct ci_tx_entry_vec *txep;
-	uint16_t n, nb_commit, tx_id;
-	uint64_t flags = CI_TX_DESC_CMD_DEFAULT;
-	uint64_t rs = CI_TX_DESC_CMD_RS | CI_TX_DESC_CMD_DEFAULT;
-
-	/* cross rx_thresh boundary is not allowed */
-	nb_pkts = RTE_MIN(nb_pkts, txq->tx_rs_thresh);
-
-	if (txq->nb_tx_free < txq->tx_free_thresh)
-		ci_tx_free_bufs_vec(txq, ice_tx_desc_done, false);
-
-	nb_commit = nb_pkts = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts);
-	if (unlikely(nb_pkts == 0))
-		return 0;
-
-	tx_id = txq->tx_tail;
-	txdp = &txq->ci_tx_ring[tx_id];
-	txep = &txq->sw_ring_vec[tx_id];
-
-	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_pkts);
-
-	n = (uint16_t)(txq->nb_tx_desc - tx_id);
-	if (nb_commit >= n) {
-		ci_tx_backlog_entry_vec(txep, tx_pkts, n);
-
-		ci_vtx_avx2(txdp, tx_pkts, n - 1, flags, offload,
-			CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
-		tx_pkts += (n - 1);
-		txdp += (n - 1);
-
-		ci_vtx1(txdp, *tx_pkts++, rs, offload, CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
-
-		nb_commit = (uint16_t)(nb_commit - n);
-
-		tx_id = 0;
-		txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1);
-
-		/* avoid reach the end of ring */
-		txdp = &txq->ci_tx_ring[tx_id];
-		txep = &txq->sw_ring_vec[tx_id];
-	}
-
-	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_commit);
-
-	ci_vtx_avx2(txdp, tx_pkts, nb_commit, flags, offload,
-		CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
-
-	tx_id = (uint16_t)(tx_id + nb_commit);
-	if (tx_id > txq->tx_next_rs) {
-		txq->ci_tx_ring[txq->tx_next_rs].cmd_type_offset_bsz |=
-			rte_cpu_to_le_64(((uint64_t)CI_TX_DESC_CMD_RS) << CI_TXD_QW1_CMD_S);
-		txq->tx_next_rs =
-			(uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh);
-	}
-
-	txq->tx_tail = tx_id;
-
-	ICE_PCI_REG_WC_WRITE(txq->qtx_tail, txq->tx_tail);
-
-	return nb_pkts;
-}
-
 static __rte_always_inline uint16_t
 ice_xmit_pkts_vec_avx2_common(void *tx_queue, struct rte_mbuf **tx_pkts,
 			      uint16_t nb_pkts, bool offload)
@@ -853,8 +785,8 @@ ice_xmit_pkts_vec_avx2_common(void *tx_queue, struct rte_mbuf **tx_pkts,
 		uint16_t ret, num;
 
 		num = (uint16_t)RTE_MIN(nb_pkts, txq->tx_rs_thresh);
-		ret = ice_xmit_fixed_burst_vec_avx2(tx_queue, &tx_pkts[nb_tx],
-						    num, offload);
+		ret = ci_xmit_fixed_burst_vec_avx2(tx_queue, &tx_pkts[nb_tx], num,
+				offload, CI_TAG_IN_DATA_DESC, CI_TAG_IN_DATA_DESC);
 		nb_tx += ret;
 		nb_pkts -= ret;
 		if (ret < num)
drivers/net/intel/ice/ice_rxtx_vec_avx512.c +12 -90

122 lines not on this page · raw message

Signature · 1 line
2.53.0
#62 lore raw

PATCH v3 12/15 net/intel: add common vector Tx fns with context handling

In reply to Bruce Richardson

The iavf vector driver has support for more Tx offloads because it has Tx functions which handle transmit context descriptors. Move those context-handling functions to the common folder for reuse by other drivers.

---
 drivers/net/intel/common/tx_vec_x86.h         | 136 ++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   |  78 +---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c |  89 +-----------
 3 files changed, 147 insertions(+), 156 deletions(-)
drivers/net/intel/common/tx_vec_x86.h +136 -0
index 946dcc1f2e..cbc7855f99 100644
@@ -408,6 +408,74 @@ ci_xmit_fixed_burst_vec_avx2(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkts,
 	return nb_pkts;
 }
 
+static __rte_always_inline uint16_t
+ci_xmit_fixed_burst_vec_ctx_avx2(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkts,
+		uint16_t nb_pkts, bool offload,
+		enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		ci_tx_ctx_lldp_fn lldp_check)
+{
+	volatile struct ci_tx_desc *txdp;
+	struct ci_tx_entry_vec *txep;
+	uint16_t n, nb_commit, nb_mbuf, tx_id;
+	uint64_t flags = CI_TX_DESC_CMD_DEFAULT;
+	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
+
+	if (txq->nb_tx_free < txq->tx_free_thresh)
+		ci_tx_free_bufs_vec(txq, ci_tx_desc_done_simple, true);
+
+	nb_commit = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts << 1);
+	nb_commit &= 0xFFFE;
+	if (unlikely(nb_commit == 0))
+		return 0;
+
+	nb_pkts = nb_commit >> 1;
+	tx_id = txq->tx_tail;
+	txdp = &txq->ci_tx_ring[tx_id];
+	txep = (void *)txq->sw_ring;
+	txep += (tx_id >> 1);
+
+	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_commit);
+	n = (uint16_t)(txq->nb_tx_desc - tx_id);
+
+	if (n != 0 && nb_commit >= n) {
+		nb_mbuf = n >> 1;
+		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+		ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+		tx_pkts += (nb_mbuf - 1);
+		txdp += (n - 2);
+		ci_vtx1_ctx_avx2(txdp, *tx_pkts++, rs, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+
+		nb_commit = (uint16_t)(nb_commit - n);
+
+		txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1);
+		tx_id = 0;
+		/* avoid reach the end of ring */
+		txdp = txq->ci_tx_ring;
+		txep = (void *)txq->sw_ring;
+	}
+
+	nb_mbuf = nb_commit >> 1;
+	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+	ci_vtx_ctx_avx2(txdp, tx_pkts, nb_mbuf, flags, offload,
+			single_vlan_pos, qinq_outer_pos, lldp_check);
+	tx_id = (uint16_t)(tx_id + nb_commit);
+
+	if (tx_id > txq->tx_next_rs) {
+		txq->ci_tx_ring[txq->tx_next_rs].cmd_type_offset_bsz |=
+			rte_cpu_to_le_64(((uint64_t)CI_TX_DESC_CMD_RS) << CI_TXD_QW1_CMD_S);
+		txq->tx_next_rs = (uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh);
+	}
+
+	txq->tx_tail = tx_id;
+
+	ci_tx_qtx_tail_write(txq, tx_id);
+	return nb_pkts;
+}
+
 #endif /* __AVX2__ */
 
 #ifdef __AVX512VL__
@@ -640,6 +708,74 @@ ci_xmit_fixed_burst_vec_avx512(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkt
 	return nb_pkts;
 }
 
+static __rte_always_inline uint16_t
+ci_xmit_fixed_burst_vec_ctx_avx512(struct ci_tx_queue *txq, struct rte_mbuf **tx_pkts,
+		uint16_t nb_pkts, bool offload,
+		enum ci_l2tag_pos single_vlan_pos, enum ci_l2tag_pos qinq_outer_pos,
+		ci_tx_ctx_lldp_fn lldp_check)
+{
+	volatile struct ci_tx_desc *txdp;
+	struct ci_tx_entry_vec *txep;
+	uint16_t n, nb_commit, nb_mbuf, tx_id;
+	uint64_t flags = CI_TX_DESC_CMD_DEFAULT;
+	uint64_t rs = CI_TX_DESC_CMD_RS | flags;
+
+	if (txq->nb_tx_free < txq->tx_free_thresh)
+		ci_tx_free_bufs_vec(txq, ci_tx_desc_done_simple, true);
+
+	nb_commit = (uint16_t)RTE_MIN(txq->nb_tx_free, nb_pkts << 1);
+	nb_commit &= 0xFFFE;
+	if (unlikely(nb_commit == 0))
+		return 0;
+
+	nb_pkts = nb_commit >> 1;
+	tx_id = txq->tx_tail;
+	txdp = &txq->ci_tx_ring[tx_id];
+	txep = (void *)txq->sw_ring;
+	txep += (tx_id >> 1);
+
+	txq->nb_tx_free = (uint16_t)(txq->nb_tx_free - nb_commit);
+	n = (uint16_t)(txq->nb_tx_desc - tx_id);
+
+	if (n != 0 && nb_commit >= n) {
+		nb_mbuf = n >> 1;
+		ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+		ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf - 1, flags, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+		tx_pkts += (nb_mbuf - 1);
+		txdp += (n - 2);
+		ci_vtx1_ctx_avx512(txdp, *tx_pkts++, rs, offload,
+				single_vlan_pos, qinq_outer_pos, lldp_check);
+
+		nb_commit = (uint16_t)(nb_commit - n);
+
+		txq->tx_next_rs = (uint16_t)(txq->tx_rs_thresh - 1);
+		tx_id = 0;
+		/* avoid reach the end of ring */
+		txdp = txq->ci_tx_ring;
+		txep = (void *)txq->sw_ring;
+	}
+
+	nb_mbuf = nb_commit >> 1;
+	ci_tx_backlog_entry_vec(txep, tx_pkts, nb_mbuf);
+
+	ci_vtx_ctx_avx512(txdp, tx_pkts, nb_mbuf, flags, offload,
+			single_vlan_pos, qinq_outer_pos, lldp_check);
+	tx_id = (uint16_t)(tx_id + nb_commit);
+
+	if (tx_id > txq->tx_next_rs) {
+		txq->ci_tx_ring[txq->tx_next_rs].cmd_type_offset_bsz |=
+			rte_cpu_to_le_64(((uint64_t)CI_TX_DESC_CMD_RS) << CI_TXD_QW1_CMD_S);
+		txq->tx_next_rs = (uint16_t)(txq->tx_next_rs + txq->tx_rs_thresh);
+	}
+
+	txq->tx_tail = tx_id;
+
+	ci_tx_qtx_tail_write(txq, tx_id);
+	return nb_pkts;
+}
+
 #endif /* __AVX512VL__ */
 
 #endif /* _COMMON_INTEL_TX_VEC_X86_H_ */
drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c +5 -73

97 lines not on this page · raw message

drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c +6 -83

113 lines not on this page · raw message

Signature · 1 line
2.53.0
#63 lore raw

PATCH v3 13/15 net/intel: improve Tx path selection logic

In reply to Bruce Richardson

Rework the relevant priority of context descriptor vs SIMD width when selecting a Tx path so that presence of context descriptors is only considered when all else is equal.

Normally, path select takes place without having to worry about context descriptors, since offloads requiring context descriptors are specified using the offloads bitmap for each Tx path. However, in some cases, the need to use a context descriptor is not encodable via this offload path, e.g. VLAN offload for iavf can sometimes use the data descriptor and sometimes the context depending on what PF specifies at runtime. To account for those cases, we separate out the use of contexts from the path features, but instead note it as part of the path information, and add an additional parameter to the Tx path selection for drivers to mandate a context descriptor be present. Otherwise, ctx is largely ignored in path selection, except as a last-resort tie-breaker between two paths.

---
 drivers/net/intel/common/tx.h      | 41 +++++++++++++++++---------
 drivers/net/intel/cpfl/cpfl_rxtx.c |  3 +-
 drivers/net/intel/i40e/i40e_rxtx.c |  2 +-
 drivers/net/intel/iavf/iavf_rxtx.c | 46 ++++++++++++++++--------------
 drivers/net/intel/ice/ice_rxtx.c   |  3 +-
 drivers/net/intel/idpf/idpf_rxtx.c |  3 +-
 6 files changed, 58 insertions(+), 40 deletions(-)
drivers/net/intel/common/tx.h +27 -14
index 630df8cb19..0f36989b32 100644
@@ -249,7 +249,6 @@ struct ci_tx_path_features {
 	uint32_t tx_offloads;
 	enum rte_vect_max_simd simd_width;
 	bool simple_tx;
-	bool ctx_desc;
 	bool disabled;
 	bool single_queue;
 };
@@ -259,6 +258,7 @@ struct ci_tx_path_info {
 	const char *info;
 	struct ci_tx_path_features features;
 	eth_tx_prep_t pkt_prep;
+	bool supports_ctx;
 };
 
 static __rte_always_inline void
@@ -411,6 +411,11 @@ ci_txq_release_all_mbufs(struct ci_tx_queue *txq, bool use_ctx)
  *   Number of available paths in the infos array
  * @param default_path
  *   Index of the default path to use if no suitable path is found
+ * @param force_ctx
+ *   If true, only paths that support context descriptors may be selected.
+ *   Use this for offloads that require a context descriptor but cannot be
+ *   discovered purely from req_features->tx_offloads (e.g. a driver-specific
+ *   devarg, or a runtime/hardware-negotiated tag placement).
  *
  * @return
  *   The packet burst function index that best matches the requested features,
@@ -420,10 +425,12 @@ static inline int
 ci_tx_path_select(const struct ci_tx_path_features *req_features,
 			const struct ci_tx_path_info *infos,
 			size_t num_paths,
-			int default_path)
+			int default_path,
+			bool force_ctx)
 {
 	int idx = default_path;
 	const struct ci_tx_path_features *chosen_path_features = NULL;
+	bool chosen_supports_ctx = false;
 
 	for (unsigned int i = 0; i < num_paths; i++) {
 		const struct ci_tx_path_features *path_features = &infos[i].features;
@@ -440,8 +447,8 @@ ci_tx_path_select(const struct ci_tx_path_features *req_features,
 		if (path_features->simple_tx && !req_features->simple_tx)
 			continue;
 
-		/* If a context descriptor is requested, ensure the path supports it. */
-		if (!path_features->ctx_desc && req_features->ctx_desc)
+		/* If a context descriptor is required, ensure the path supports it. */
+		if (!infos[i].supports_ctx && force_ctx)
 			continue;
 
 		/* If requested, ensure the path supports single queue TX. */
@@ -462,22 +469,28 @@ ci_tx_path_select(const struct ci_tx_path_features *req_features,
 			/* Do not select paths with lower SIMD width than the chosen path. */
 			if (path_features->simd_width < chosen_path_features->simd_width)
 				continue;
-			/* Do not select paths with more offloads enabled than the chosen path if
-			 * the SIMD widths are the same.
+			/* The following tie-breaks only matter when SIMD widths are tied;
+			 * a strictly wider path is always preferred regardless of offload
+			 * count or ctx-descriptor use.
 			 */
-			if (path_features->simd_width == chosen_path_features->simd_width &&
-					rte_popcount32(path_features->tx_offloads) >
-					rte_popcount32(chosen_path_features->tx_offloads))
-				continue;
-
-			/* Don't use a context descriptor unless necessary */
-			if (path_features->ctx_desc && !chosen_path_features->ctx_desc)
-				continue;
+			if (path_features->simd_width == chosen_path_features->simd_width) {
+				/* Do not select paths with more offloads enabled than the
+				 * chosen path.
+				 */
+				if (rte_popcount32(path_features->tx_offloads) >
+						rte_popcount32(chosen_path_features->tx_offloads))
+					continue;
+
+				/* Don't use a context descriptor unless necessary */
+				if (infos[i].supports_ctx && !chosen_supports_ctx)
+					continue;
+			}
 		}
 
 		/* Finally, select the path since it has met all the requirements. */
 		idx = i;
 		chosen_path_features = &infos[idx].features;
+		chosen_supports_ctx = infos[idx].supports_ctx;
 	}
 
 	return idx;
drivers/net/intel/cpfl/cpfl_rxtx.c +2 -1
index 2f1641ea76..aba3a5e916 100644
@@ -1542,7 +1542,8 @@ cpfl_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_func_type = ci_tx_path_select(&req_features,
 					&idpf_tx_path_infos[0],
 					IDPF_TX_MAX,
-					IDPF_TX_DEFAULT);
+					IDPF_TX_DEFAULT,
+					false);
 
 	/* Set use_vec_entry for single queue mode - only IDPF_TX_SINGLEQ uses regular entries */
 	if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
drivers/net/intel/i40e/i40e_rxtx.c +1 -1
index e2fffdb70a..f289d26790 100644
@@ -3120,7 +3120,7 @@ i40e_set_tx_function(struct rte_eth_dev *dev)
 	}
 
 	ad->tx_func_type = ci_tx_path_select(&req_features, &i40e_tx_path_infos[0],
-						RTE_DIM(i40e_tx_path_infos), I40E_TX_DEFAULT);
+			RTE_DIM(i40e_tx_path_infos), I40E_TX_DEFAULT, false);
 
 out:
 	dev->tx_pkt_burst = mbuf_check ? i40e_xmit_pkts_check :
drivers/net/intel/iavf/iavf_rxtx.c +24 -22

112 lines not on this page · raw message

drivers/net/intel/ice/ice_rxtx.c +2 -1
index 52d6984214..06920745ed 100644
@@ -3784,7 +3784,8 @@ ice_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_func_type = ci_tx_path_select(&req_features,
 						&ice_tx_path_infos[0],
 						RTE_DIM(ice_tx_path_infos),
-						ICE_TX_DEFAULT);
+						ICE_TX_DEFAULT,
+						false);
 
 out:
 #if defined(RTE_ARCH_X86)
drivers/net/intel/idpf/idpf_rxtx.c +2 -1
index bc3f9a0798..077a92a8a9 100644
@@ -887,7 +887,8 @@ idpf_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_func_type = ci_tx_path_select(&req_features,
 					&idpf_tx_path_infos[0],
 					IDPF_TX_MAX,
-					IDPF_TX_DEFAULT);
+					IDPF_TX_DEFAULT,
+					false);
 
 	/* Set use_vec_entry for single queue mode - only IDPF_TX_SINGLEQ uses regular entries */
 	if (vport->txq_model == VIRTCHNL2_QUEUE_MODEL_SINGLE) {
Signature · 1 line
2.53.0
#64 lore raw

PATCH v3 14/15 net/ice: enable context desc offloads for vector Tx

In reply to Bruce Richardson

Use the context descriptor Tx vector paths from intel/common in ice driver to enable more offloads on the vector path for ice driver.

---
 doc/guides/nics/features/ice.ini            |  8 +++---
 doc/guides/rel_notes/release_26_11.rst      |  6 ++++
 drivers/net/intel/ice/ice_ethdev.h          |  3 ++
 drivers/net/intel/ice/ice_rxtx.c            | 31 ++++++++++++++++++---
 drivers/net/intel/ice/ice_rxtx.h            | 11 ++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 24 ++++++++++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 24 ++++++++++++++++
 7 files changed, 99 insertions(+), 8 deletions(-)
doc/guides/nics/features/ice.ini +4 -4
index 893d09e9ec..8674b588ed 100644
@@ -13,7 +13,7 @@ Link status          = Y
 Link status event    = Y
 FEC                  = Y
 Rx interrupt         = Y
-Fast mbuf free       = P
+Fast mbuf free       = Y
 Free Tx mbuf on demand = Y
 Queue start/stop     = Y
 Burst mode info      = Y
@@ -33,12 +33,12 @@ VLAN filter          = Y
 Traffic manager      = Y
 CRC offload          = Y
 VLAN offload         = Y
-QinQ offload         = P
+QinQ offload         = Y
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 Timestamp offload    = P
-Inner L3 checksum    = P
-Inner L4 checksum    = P
+Inner L3 checksum    = Y
+Inner L4 checksum    = Y
 Packet type parsing  = Y
 Timesync             = Y
 Rx descriptor status = Y
doc/guides/rel_notes/release_26_11.rst +6 -0
index 6c29513041..c1c51c62ec 100644
@@ -69,6 +69,12 @@ New Features
   Added ``fdir_buffer_size`` devarg to select the Flow Director table size
   (``64k``, ``128k`` or ``256k``) at probe time. The default remains ``64k``.
 
+* **Updated Intel ice driver.**
+
+  * Added Tx context descriptor support to the AVX2 and AVX512 vector Tx
+    paths, enabling QinQ tag insertion and outer IPv4/UDP checksum
+    offloads on those paths.
+
 
 Removed Items
 -------------
drivers/net/intel/ice/ice_ethdev.h +3 -0
index 1d038016af..3cfd7afbae 100644
@@ -213,8 +213,10 @@ enum ice_tx_func_type {
 	ICE_TX_SIMPLE,
 	ICE_TX_AVX2,
 	ICE_TX_AVX2_OFFLOAD,
+	ICE_TX_AVX2_CTX_OFFLOAD,
 	ICE_TX_AVX512,
 	ICE_TX_AVX512_OFFLOAD,
+	ICE_TX_AVX512_CTX_OFFLOAD,
 	ICE_TX_NEON,
 };
 
@@ -676,6 +678,7 @@ struct ice_adapter {
 	bool rx_bulk_alloc_allowed;
 	bool tx_vec_allowed;
 	bool tx_simple_allowed;
+	bool use_ctx;
 	enum ice_rx_func_type rx_func_type;
 	enum ice_tx_func_type tx_func_type;
 	/* ptype mapping table */
drivers/net/intel/ice/ice_rxtx.c +27 -4
index 06920745ed..50cacadc44 100644
@@ -890,6 +890,7 @@ ice_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 
 	/* record what kind of descriptor cleanup we need on teardown */
 	txq->use_vec_entry = ad->tx_vec_allowed || ad->tx_simple_allowed;
+	txq->use_ctx = ad->use_ctx;
 
 	if (txq->tsq != NULL && txq->tsq->ts_flag > 0) {
 		struct ice_aqc_set_txtime_qgrp *ts_elem;
@@ -1200,7 +1201,7 @@ ice_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 		return -EINVAL;
 	}
 
-	ci_txq_release_all_mbufs(txq, false);
+	ci_txq_release_all_mbufs(txq, txq->use_ctx);
 	ice_reset_tx_queue(txq);
 	dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
 
@@ -1263,7 +1264,7 @@ ice_fdir_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 		return -EINVAL;
 	}
 
-	ci_txq_release_all_mbufs(txq, false);
+	ci_txq_release_all_mbufs(txq, txq->use_ctx);
 	txq->qtx_tail = NULL;
 
 	return 0;
@@ -1751,7 +1752,7 @@ ice_tx_queue_release(void *txq)
 		return;
 	}
 
-	ci_txq_release_all_mbufs(q, false);
+	ci_txq_release_all_mbufs(q, q->use_ctx);
 	rte_free(q->sw_ring);
 	rte_free(q->rs_last_id);
 	if (q->tsq) {
@@ -3533,7 +3534,8 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.features = {
 			.tx_offloads = ICE_TX_SCALAR_OFFLOADS
 		},
-		.pkt_prep = ice_prep_pkts
+		.pkt_prep = ice_prep_pkts,
+		.supports_ctx = true
 	},
 	[ICE_TX_SIMPLE] = {
 		.pkt_burst = ice_xmit_pkts_simple,
@@ -3563,6 +3565,16 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		},
 		.pkt_prep = ice_prep_pkts
 	},
+	[ICE_TX_AVX2_CTX_OFFLOAD] = {
+		.pkt_burst = ice_xmit_pkts_vec_avx2_ctx_offload,
+		.info = "Offload Vector AVX2 Ctx",
+		.features = {
+			.tx_offloads = ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.simd_width = RTE_VECT_SIMD_256
+		},
+		.pkt_prep = ice_prep_pkts,
+		.supports_ctx = true
+	},
 #ifdef CC_AVX512_SUPPORT
 	[ICE_TX_AVX512] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx512,
@@ -3582,6 +3594,16 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		},
 		.pkt_prep = ice_prep_pkts
 	},
+	[ICE_TX_AVX512_CTX_OFFLOAD] = {
+		.pkt_burst = ice_xmit_pkts_vec_avx512_ctx_offload,
+		.info = "Offload Vector AVX512 Ctx",
+		.features = {
+			.tx_offloads = ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.simd_width = RTE_VECT_SIMD_512
+		},
+		.pkt_prep = ice_prep_pkts,
+		.supports_ctx = true
+	},
 #endif
 #elif defined(RTE_ARCH_ARM64)
 	[ICE_TX_NEON] = {
@@ -3795,6 +3817,7 @@ ice_set_tx_function(struct rte_eth_dev *dev)
 	ad->tx_vec_allowed =
 		(ice_tx_path_infos[ad->tx_func_type].features.simd_width >= RTE_VECT_SIMD_128);
 #endif
+	ad->use_ctx = ice_tx_path_infos[ad->tx_func_type].supports_ctx;
 
 	dev->tx_pkt_burst = mbuf_check ? ice_xmit_pkts_check :
 					 ice_tx_path_infos[ad->tx_func_type].pkt_burst;
drivers/net/intel/ice/ice_rxtx.h +11 -0
index 999b6b30d6..bee8a464f5 100644
@@ -135,6 +135,12 @@
 	RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
 	RTE_ETH_TX_OFFLOAD_TCP_CKSUM |		\
 	RTE_ETH_TX_OFFLOAD_SCTP_CKSUM)
+/* vector ctx offload path: QinQ outer tag + outer/tunnel checksum via ctx desc */
+#define ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS (	\
+	ICE_TX_VECTOR_OFFLOAD_OFFLOADS |	\
+	RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
+	RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
+	RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
 
 /* Max header size can be 2K - 64 bytes */
 #define ICE_RX_HDR_BUF_SIZE    (2048 - 64)
@@ -284,6 +290,8 @@ uint16_t ice_xmit_pkts_vec_avx2(void *tx_queue, struct rte_mbuf **tx_pkts,
 				uint16_t nb_pkts);
 uint16_t ice_xmit_pkts_vec_avx2_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
 					uint16_t nb_pkts);
+uint16_t ice_xmit_pkts_vec_avx2_ctx_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
+					uint16_t nb_pkts);
 uint16_t ice_recv_pkts_vec_avx512(void *rx_queue, struct rte_mbuf **rx_pkts,
 				  uint16_t nb_pkts);
 uint16_t ice_recv_pkts_vec_avx512_offload(void *rx_queue,
@@ -300,6 +308,9 @@ uint16_t ice_xmit_pkts_vec_avx512(void *tx_queue, struct rte_mbuf **tx_pkts,
 uint16_t ice_xmit_pkts_vec_avx512_offload(void *tx_queue,
 					  struct rte_mbuf **tx_pkts,
 					  uint16_t nb_pkts);
+uint16_t ice_xmit_pkts_vec_avx512_ctx_offload(void *tx_queue,
+					  struct rte_mbuf **tx_pkts,
+					  uint16_t nb_pkts);
 int ice_fdir_programming(struct ice_pf *pf, struct ice_fltr_desc *fdir_desc);
 int ice_tx_done_cleanup(void *txq, uint32_t free_cnt);
 int ice_get_monitor_addr(void *rx_queue, struct rte_power_monitor_cond *pmc);
drivers/net/intel/ice/ice_rxtx_vec_avx2.c +24 -0
index 00b5d51aab..056b2dc49b 100644
@@ -810,6 +810,30 @@ ice_xmit_pkts_vec_avx2_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
 	return ice_xmit_pkts_vec_avx2_common(tx_queue, tx_pkts, nb_pkts, true);
 }
 
+uint16_t
+ice_xmit_pkts_vec_avx2_ctx_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
+				   uint16_t nb_pkts)
+{
+	uint16_t nb_tx = 0;
+	struct ci_tx_queue *txq = (struct ci_tx_queue *)tx_queue;
+
+	while (nb_pkts) {
+		uint16_t ret, num;
+
+		/* cross rs_thresh boundary is not allowed */
+		num = (uint16_t)RTE_MIN(nb_pkts << 1, txq->tx_rs_thresh);
+		num = num >> 1;
+		ret = ci_xmit_fixed_burst_vec_ctx_avx2(tx_queue, &tx_pkts[nb_tx], num,
+				true, CI_TAG_IN_DATA_DESC, CI_TAG_IN_CTX_DESC, NULL);
+		nb_tx += ret;
+		nb_pkts -= ret;
+		if (ret < num)
+			break;
+	}
+
+	return nb_tx;
+}
+
 int __rte_cold
 ice_rxq_vec_setup(struct ci_rx_queue *rxq)
 {
drivers/net/intel/ice/ice_rxtx_vec_avx512.c +24 -0
index d8ede5cb42..0548c293bb 100644
@@ -882,3 +882,27 @@ ice_xmit_pkts_vec_avx512_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
 {
 	return ice_xmit_pkts_vec_avx512_common(tx_queue, tx_pkts, nb_pkts, true);
 }
+
+uint16_t
+ice_xmit_pkts_vec_avx512_ctx_offload(void *tx_queue, struct rte_mbuf **tx_pkts,
+				     uint16_t nb_pkts)
+{
+	uint16_t nb_tx = 0;
+	struct ci_tx_queue *txq = (struct ci_tx_queue *)tx_queue;
+
+	while (nb_pkts) {
+		uint16_t ret, num;
+
+		/* cross rs_thresh boundary is not allowed */
+		num = (uint16_t)RTE_MIN(nb_pkts << 1, txq->tx_rs_thresh);
+		num = num >> 1;
+		ret = ci_xmit_fixed_burst_vec_ctx_avx512(tx_queue, &tx_pkts[nb_tx], num,
+				true, CI_TAG_IN_DATA_DESC, CI_TAG_IN_CTX_DESC, NULL);
+		nb_tx += ret;
+		nb_pkts -= ret;
+		if (ret < num)
+			break;
+	}
+
+	return nb_tx;
+}
Signature · 1 line
2.53.0
#65 lore raw

RE: [PATCH v3 14/15] net/ice: enable context desc offloads for vector Tx

Quoted 31 lines

Subject: [PATCH v3 14/15] net/ice: enable context desc offloads for vector Tx

Use the context descriptor Tx vector paths from intel/common in ice driver to enable more offloads on the vector path for ice driver.

---
 doc/guides/nics/features/ice.ini            |  8 +++---
 doc/guides/rel_notes/release_26_11.rst      |  6 ++++
 drivers/net/intel/ice/ice_ethdev.h          |  3 ++
 drivers/net/intel/ice/ice_rxtx.c            | 31 ++++++++++++++++++---
 drivers/net/intel/ice/ice_rxtx.h            | 11 ++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 24 ++++++++++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 24 ++++++++++++++++
 7 files changed, 99 insertions(+), 8 deletions(-)
doc/guides/nics/features/ice.ini +1 -1
index 893d09e9ec..8674b588ed 100644
@@ -13,7 +13,7 @@ Link status          = Y
 Link status event    = Y
 FEC                  = Y
 Rx interrupt         = Y
-Fast mbuf free       = P
+Fast mbuf free       = Y
 Free Tx mbuf on demand = Y
 Queue start/stop     = Y
 Burst mode info      = Y

doc/guides/nics/features/ice.ini VLAN filter = Y · line 36

Quoted 5 lines
doc/guides/nics/features/ice.ini +1 -1
@@ -33,12 +33,12 @@ VLAN filter          = Y
 Traffic manager      = Y
 CRC offload          = Y
 VLAN offload         = Y
-QinQ offload         = P
+QinQ offload         = Y

I think this should stay as P because the vector Rx paths don't support QINQ strip.

doc/guides/nics/features/ice.ini VLAN filter = Y · line 41

Quoted 7 lines
doc/guides/nics/features/ice.ini +2 -2
 L3 checksum offload  = Y
 L4 checksum offload  = Y
 Timestamp offload    = P
-Inner L3 checksum    = P
-Inner L4 checksum    = P
+Inner L3 checksum    = Y
+Inner L4 checksum    = Y

Both of these are OK. Although I've noticed that Inner L4 checksum aka RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM isn't advertised correctly in the path offload masks / rx_offload_capa so I will submit a separate patch to fix that.

Quoted 12 lines
doc/guides/nics/features/ice.ini +0 -0
 Packet type parsing  = Y
 Timesync             = Y
 Rx descriptor status = Y
doc/guides/rel_notes/release_26_11.rst +0 -0
index 6c29513041..c1c51c62ec 100644
@@ -69,6 +69,12 @@ New Features
   Added ``fdir_buffer_size`` devarg to select the Flow Director table size
   (``64k``, ``128k`` or ``256k``) at probe time. The default remains ``64k``.
 
#66 lore raw

Re: [PATCH v3 14/15] net/ice: enable context desc offloads for vector Tx

Quoted 31 lines · Ciara
Quoted 31 lines

Subject: [PATCH v3 14/15] net/ice: enable context desc offloads for vector Tx

Use the context descriptor Tx vector paths from intel/common in ice driver to enable more offloads on the vector path for ice driver.

---
 doc/guides/nics/features/ice.ini            |  8 +++---
 doc/guides/rel_notes/release_26_11.rst      |  6 ++++
 drivers/net/intel/ice/ice_ethdev.h          |  3 ++
 drivers/net/intel/ice/ice_rxtx.c            | 31 ++++++++++++++++++---
 drivers/net/intel/ice/ice_rxtx.h            | 11 ++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 24 ++++++++++++++++
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 24 ++++++++++++++++
 7 files changed, 99 insertions(+), 8 deletions(-)
doc/guides/nics/features/ice.ini +1 -1
index 893d09e9ec..8674b588ed 100644
@@ -13,7 +13,7 @@ Link status          = Y
 Link status event    = Y
 FEC                  = Y
 Rx interrupt         = Y
-Fast mbuf free       = P
+Fast mbuf free       = Y
 Free Tx mbuf on demand = Y
 Queue start/stop     = Y
 Burst mode info      = Y
@@ -33,12 +33,12 @@ VLAN filter          = Y
Quoted 9 lines

doc/guides/nics/features/ice.ini VLAN filter = Y · line 36

Quoted 5 lines
doc/guides/nics/features/ice.ini +1 -1
 Traffic manager      = Y
 CRC offload          = Y
 VLAN offload         = Y
-QinQ offload         = P
+QinQ offload         = Y

I think this should stay as P because the vector Rx paths don't support QINQ strip.

Ok, will revert on apply.
Thanks for flagging.

#67 lore raw

PATCH v3 15/15 net/intel: consolidate Tx vector offload path checks

In reply to Bruce Richardson

Since iavf and ice drivers now have common Tx vector paths, we can consolidate the path decisions a little, including replacing the per-driver offload flags with common ones.

---
 drivers/net/intel/common/tx.h                 | 30 +++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx.c            | 18 +++++------
 drivers/net/intel/iavf/iavf_rxtx.h            | 19 ------------
 drivers/net/intel/iavf/iavf_rxtx_vec_common.h |  3 +-
 drivers/net/intel/ice/ice_rxtx.c              | 14 ++++-----
 drivers/net/intel/ice/ice_rxtx.h              | 18 -----------
 drivers/net/intel/ice/ice_rxtx_vec_common.h   |  3 +-
 7 files changed, 48 insertions(+), 57 deletions(-)
drivers/net/intel/common/tx.h +30 -0
index 0f36989b32..2a63cd4330 100644
@@ -12,6 +12,27 @@
 #include <rte_io.h>
 #include <rte_byteorder.h>
 
+#define CI_VPMD_TX_BURST            32
+#define CI_VPMD_TX_MAX_FREE_BUF     64
+
+/* basic vector path */
+#define CI_TX_VECTOR_OFFLOADS RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
+/* offload vector path */
+#define CI_TX_VEC_OFFLOAD_PATH_OFFLOADS (	\
+		CI_TX_VECTOR_OFFLOADS |		\
+		RTE_ETH_TX_OFFLOAD_VLAN_INSERT |	\
+		RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |		\
+		RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |		\
+		RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
+		RTE_ETH_TX_OFFLOAD_TCP_CKSUM)
+/* offload vector path with context descriptor */
+#define CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS (	\
+		CI_TX_VECTOR_OFFLOADS |		\
+		CI_TX_VEC_OFFLOAD_PATH_OFFLOADS |	\
+		RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
+		RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
+		RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
+
 /* Common TX Descriptor QW1 Field Definitions */
 #define CI_TXD_QW1_DTYPE_S      0
 #define CI_TXD_QW1_DTYPE_M      (0xFUL << CI_TXD_QW1_DTYPE_S)
@@ -261,6 +282,15 @@ struct ci_tx_path_info {
 	bool supports_ctx;
 };
 
+/* basic check for a vector-driver capable Tx queue.
+ * Individual drivers may have other further tests beyond this.
+ */
+static inline bool
+ci_txq_vec_capable(uint16_t rs_thresh)
+{
+	return rs_thresh >= CI_VPMD_TX_BURST && rs_thresh <= CI_VPMD_TX_MAX_FREE_BUF;
+}
+
 static __rte_always_inline void
 ci_tx_backlog_entry(struct ci_tx_entry *txep, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 {
drivers/net/intel/iavf/iavf_rxtx.c +9 -9
index 3be8b00bbd..9b776a6391 100644
@@ -3620,7 +3620,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx2,
 		.info = "Vector AVX2",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		}
 	},
@@ -3628,7 +3628,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx2_offload,
 		.info = "Vector AVX2 Offload",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		}
 	},
@@ -3636,7 +3636,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx2_ctx,
 		.info = "Vector AVX2 Ctx",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		},
 		.supports_ctx = true
@@ -3645,7 +3645,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx2_ctx_offload,
 		.info = "Vector AVX2 Ctx Offload",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		},
 		.supports_ctx = true
@@ -3655,7 +3655,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx512,
 		.info = "Vector AVX512",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		}
 	},
@@ -3663,7 +3663,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx512_offload,
 		.info = "Vector AVX512 Offload",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		}
 	},
@@ -3671,7 +3671,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx512_ctx,
 		.info = "Vector AVX512 Ctx",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		},
 		.supports_ctx = true
@@ -3680,7 +3680,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec_avx512_ctx_offload,
 		.info = "Vector AVX512 Ctx Offload",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		},
 		.supports_ctx = true
@@ -3691,7 +3691,7 @@ static const struct ci_tx_path_info iavf_tx_path_infos[] = {
 		.pkt_burst = iavf_xmit_pkts_vec,
 		.info = "Vector Neon",
 		.features = {
-			.tx_offloads = IAVF_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_128
 		}
 	},
drivers/net/intel/iavf/iavf_rxtx.h +0 -19
index 19931f5f7c..812d7e23ee 100644
@@ -29,11 +29,9 @@
 
 /* used for Vector PMD */
 #define IAVF_VPMD_RX_BURST             CI_VPMD_RX_BURST
-#define IAVF_VPMD_TX_BURST             32
 #define IAVF_VPMD_RXQ_REARM_THRESH     CI_VPMD_RX_REARM_THRESH
 #define IAVF_VPMD_DESCS_PER_LOOP       CI_VPMD_DESCS_PER_LOOP
 #define IAVF_VPMD_DESCS_PER_LOOP_WIDE  CI_VPMD_DESCS_PER_LOOP_WIDE
-#define IAVF_VPMD_TX_MAX_FREE_BUF      64
 
 /* basic scalar path */
 #define IAVF_TX_SCALAR_OFFLOADS (			\
@@ -54,23 +52,6 @@
 		RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE |	\
 		RTE_ETH_TX_OFFLOAD_SECURITY |		\
 		RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM)
-/* basic vector path */
-#define IAVF_TX_VECTOR_OFFLOADS RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
-/* offload vector path */
-#define IAVF_TX_VECTOR_OFFLOAD_OFFLOADS (		\
-		IAVF_TX_VECTOR_OFFLOADS |		\
-		RTE_ETH_TX_OFFLOAD_VLAN_INSERT |	\
-		RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |		\
-		RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |		\
-		RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
-		RTE_ETH_TX_OFFLOAD_TCP_CKSUM)
-/* offload vector path with context descriptor */
-#define IAVF_TX_VECTOR_CTX_OFFLOAD_OFFLOADS (		\
-		IAVF_TX_VECTOR_OFFLOADS |		\
-		IAVF_TX_VECTOR_OFFLOAD_OFFLOADS |	\
-		RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
-		RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
-		RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
 
 /* basic scalar path */
 #define IAVF_RX_SCALAR_OFFLOADS (			\
drivers/net/intel/iavf/iavf_rxtx_vec_common.h +1 -2
index 61478036ec..e0a67fedc6 100644
@@ -80,8 +80,7 @@ iavf_tx_vec_queue_default(struct ci_tx_queue *txq)
 	if (!txq)
 		return -1;
 
-	if (txq->tx_rs_thresh < IAVF_VPMD_TX_BURST ||
-	    txq->tx_rs_thresh > IAVF_VPMD_TX_MAX_FREE_BUF)
+	if (!ci_txq_vec_capable(txq->tx_rs_thresh))
 		return -1;
 
 	return 0;
drivers/net/intel/ice/ice_rxtx.c +7 -7
index 50cacadc44..2db1fe16bf 100644
@@ -3551,7 +3551,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx2,
 		.info = "Vector AVX2",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		},
 		.pkt_prep = rte_eth_tx_pkt_prepare_dummy
@@ -3560,7 +3560,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx2_offload,
 		.info = "Offload Vector AVX2",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		},
 		.pkt_prep = ice_prep_pkts
@@ -3569,7 +3569,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx2_ctx_offload,
 		.info = "Offload Vector AVX2 Ctx",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256
 		},
 		.pkt_prep = ice_prep_pkts,
@@ -3580,7 +3580,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx512,
 		.info = "Vector AVX512",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		},
 		.pkt_prep = rte_eth_tx_pkt_prepare_dummy
@@ -3589,7 +3589,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx512_offload,
 		.info = "Offload Vector AVX512",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		},
 		.pkt_prep = ice_prep_pkts
@@ -3598,7 +3598,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec_avx512_ctx_offload,
 		.info = "Offload Vector AVX512 Ctx",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS,
+			.tx_offloads = CI_TX_VEC_CTX_OFFLOAD_PATH_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512
 		},
 		.pkt_prep = ice_prep_pkts,
@@ -3610,7 +3610,7 @@ static const struct ci_tx_path_info ice_tx_path_infos[] = {
 		.pkt_burst = ice_xmit_pkts_vec,
 		.info = "Vector Neon",
 		.features = {
-			.tx_offloads = ICE_TX_VECTOR_OFFLOADS,
+			.tx_offloads = CI_TX_VECTOR_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_128
 		},
 		.pkt_prep = rte_eth_tx_pkt_prepare_dummy
drivers/net/intel/ice/ice_rxtx.h +0 -18
index bee8a464f5..cd23f7c56f 100644
@@ -47,9 +47,7 @@
 #define ICE_SUPPORT_CHAIN_NUM 5
 
 #define ICE_VPMD_RX_BURST            CI_VPMD_RX_BURST
-#define ICE_VPMD_TX_BURST            32
 #define ICE_VPMD_RXQ_REARM_THRESH    CI_VPMD_RX_REARM_THRESH
-#define ICE_TX_MAX_FREE_BUF_SZ       64
 #define ICE_VPMD_DESCS_PER_LOOP      CI_VPMD_DESCS_PER_LOOP
 #define ICE_VPMD_DESCS_PER_LOOP_WIDE CI_VPMD_DESCS_PER_LOOP_WIDE
 
@@ -125,22 +123,6 @@
 	RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO |	\
 	RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO |	\
 	RTE_ETH_TX_OFFLOAD_SEND_ON_TIMESTAMP)
-/* basic vector path */
-#define ICE_TX_VECTOR_OFFLOADS RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE
-/* vector offload paths */
-#define ICE_TX_VECTOR_OFFLOAD_OFFLOADS (	\
-	ICE_TX_VECTOR_OFFLOADS |		\
-	RTE_ETH_TX_OFFLOAD_VLAN_INSERT |	\
-	RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |		\
-	RTE_ETH_TX_OFFLOAD_UDP_CKSUM |		\
-	RTE_ETH_TX_OFFLOAD_TCP_CKSUM |		\
-	RTE_ETH_TX_OFFLOAD_SCTP_CKSUM)
-/* vector ctx offload path: QinQ outer tag + outer/tunnel checksum via ctx desc */
-#define ICE_TX_VECTOR_CTX_OFFLOAD_OFFLOADS (	\
-	ICE_TX_VECTOR_OFFLOAD_OFFLOADS |	\
-	RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |	\
-	RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM |	\
-	RTE_ETH_TX_OFFLOAD_QINQ_INSERT)
 
 /* Max header size can be 2K - 64 bytes */
 #define ICE_RX_HDR_BUF_SIZE    (2048 - 64)
drivers/net/intel/ice/ice_rxtx_vec_common.h +1 -2
index 53d1eb42a3..d5ef213e08 100644
@@ -72,8 +72,7 @@ ice_tx_vec_queue_default(struct ci_tx_queue *txq)
 	if (!txq)
 		return -1;
 
-	if (txq->tx_rs_thresh < ICE_VPMD_TX_BURST ||
-	    txq->tx_rs_thresh > ICE_TX_MAX_FREE_BUF_SZ)
+	if (!ci_txq_vec_capable(txq->tx_rs_thresh))
 		return -1;
 
 	return 0;
Signature · 1 line
2.53.0
#68 lore raw

Re: [PATCH v3 00/15] consolidate ice and iavf Tx vector paths

In reply to Bruce Richardson
Quoted 15 lines · Bruce Richardson

This patchset consolidates the ice and iavf vector Tx paths, moving the code to net/intel/common. The iavf code is used as the basis for the move, because it has a superset of the features. When the common code is adopted by the ice driver, it then gains features such as QinQ support and tunneling support.

V3:
* fix variable shadowing issue in patch 15 (ci_txq_vec_capable param)
* update ice.ini with new features

V2:
* fix build when iova not in mbuf
* add extra patch to consolidate the offload flags

Quoted 17 lines

Bruce Richardson (15):
net/iavf: remove unnecessary alignment calls net/intel: make Tx context flag common
net/iavf: use separate params for VLAN and QinQ position net/iavf: deduplicate tunnel field fill functions net/intel: define common macros for tunneling bit-shifts net/intel: move iavf descriptor writing functions to common net/intel: use function callback for lldp net/intel: allow building without IOVA in mbuf net/ice: use common descriptor creation functions net/intel: move vector Tx paths to common net/ice: use common AVX Tx functions
net/intel: add common vector Tx fns with context handling net/intel: improve Tx path selection logic net/ice: enable context desc offloads for vector Tx net/intel: consolidate Tx vector offload path checks

Series applied to dpdk-next-net-intel.

/Bruce