Skip to contentSkip to conversation

mlx5: external RxQ support

PATCH Superseded Michael Baum 4 participants 26 messages Feb 22, 2022 – Feb 25, 2022

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

cover mlx5: external RxQ support

These patches add support to external Rx queues.
External queue is a queue that is managed by a process external to PMD, but uses PMD process to generate its flow rules.

For the hardware to allow the DPDK process to set rules for it, the process needs to use the same PD of the external process. In addition, the indexes of the queues in hardware are represented by 32-bit compared to the rte_flow indexes represented by 16-bit, so the processes need to share some mapping between the indexes.

These patches allow the external process to provide devargs which enable importing its context and PD, instead of prepare new ones. In addition, an API is provided for mapping for the indexes of the queues.

Depends-on: series-21791 ("refactore mlx5 guides")

Michael Baum (6):
common/mlx5: glue device and PD importation common/mlx5: add remote PD and CTX support net/mlx5: optimize RxQ/TxQ control structure net/mlx5: add external RxQ mapping API net/mlx5: support queue/RSS action for external RxQ app/testpmd: add test for external RxQ

 app/test-pmd/cmdline.c                       | 157 +++++++++++
 app/test-pmd/meson.build                     |   3 +
 doc/guides/nics/mlx5.rst                     |   1 +
 doc/guides/platform/mlx5.rst                 |  37 ++-
 doc/guides/rel_notes/release_22_03.rst       |   6 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst  |  16 ++
 drivers/common/mlx5/linux/meson.build        |   2 +
 drivers/common/mlx5/linux/mlx5_common_os.c   | 227 ++++++++++++++--
 drivers/common/mlx5/linux/mlx5_common_os.h   |   6 -
 drivers/common/mlx5/linux/mlx5_glue.c        |  41 +++
 drivers/common/mlx5/linux/mlx5_glue.h        |   4 +
 drivers/common/mlx5/mlx5_common.c            |  62 ++++-
 drivers/common/mlx5/mlx5_common.h            |  28 +-
 drivers/common/mlx5/version.map              |   4 +
 drivers/common/mlx5/windows/mlx5_common_os.c |  52 +++-
 drivers/common/mlx5/windows/mlx5_common_os.h |   1 -
 drivers/net/mlx5/linux/mlx5_os.c             |  18 ++
 drivers/net/mlx5/mlx5.c                      |   6 +
 drivers/net/mlx5/mlx5.h                      |   1 +
 drivers/net/mlx5/mlx5_defs.h                 |   3 +
 drivers/net/mlx5/mlx5_devx.c                 |  52 ++--
 drivers/net/mlx5/mlx5_ethdev.c               |  18 +-
 drivers/net/mlx5/mlx5_flow.c                 |  43 ++--
 drivers/net/mlx5/mlx5_flow_dv.c              |  14 +-
 drivers/net/mlx5/mlx5_rx.h                   |  49 +++-
 drivers/net/mlx5/mlx5_rxq.c                  | 258 +++++++++++++++++--
 drivers/net/mlx5/mlx5_trigger.c              |  36 +--
 drivers/net/mlx5/mlx5_tx.h                   |   7 +-
 drivers/net/mlx5/mlx5_txq.c                  |  14 +-
 drivers/net/mlx5/rte_pmd_mlx5.h              |  50 +++-
 drivers/net/mlx5/version.map                 |   3 +
 31 files changed, 1047 insertions(+), 172 deletions(-)
Signature · 1 line
2.25.1
#1 lore raw

PATCH 1/6 common/mlx5: glue device and PD importation

Add support for rdma-core API to import device.
The API gets ibv_context file descriptor and returns an ibv_context pointer that is associated with the given file descriptor. Add also support for rdma-core API to import PD.
The API gets ibv_context and PD handle and returns a protection domain (PD) that is associated with the given handle in the given context.

---
 drivers/common/mlx5/linux/meson.build |  2 ++
 drivers/common/mlx5/linux/mlx5_glue.c | 41 +++++++++++++++++++++++++++
 drivers/common/mlx5/linux/mlx5_glue.h |  4 +++
 3 files changed, 47 insertions(+)
drivers/common/mlx5/linux/meson.build +2 -0
index 4c7b53b9bd..ed48245c67 100644
@@ -202,6 +202,8 @@ has_sym_args = [
             'mlx5dv_dr_domain_allow_duplicate_rules' ],
         [ 'HAVE_MLX5_IBV_REG_MR_IOVA', 'infiniband/verbs.h',
             'ibv_reg_mr_iova' ],
+        [ 'HAVE_MLX5_IBV_IMPORT_CTX_PD_AND_MR', 'infiniband/verbs.h',
+            'ibv_import_device' ],
 ]
 config = configuration_data()
 foreach arg:has_sym_args
drivers/common/mlx5/linux/mlx5_glue.c +41 -0

62 lines not on this page · raw message

drivers/common/mlx5/linux/mlx5_glue.h +4 -0
index 4e6d31f263..c4903a6dce 100644
@@ -151,9 +151,13 @@ struct mlx5_glue {
 	int (*fork_init)(void);
 	struct ibv_pd *(*alloc_pd)(struct ibv_context *context);
 	int (*dealloc_pd)(struct ibv_pd *pd);
+	struct ibv_pd *(*import_pd)(struct ibv_context *context,
+				    uint32_t pd_handle);
+	int (*unimport_pd)(struct ibv_pd *pd);
 	struct ibv_device **(*get_device_list)(int *num_devices);
 	void (*free_device_list)(struct ibv_device **list);
 	struct ibv_context *(*open_device)(struct ibv_device *device);
+	struct ibv_context *(*import_device)(int cmd_fd);
 	int (*close_device)(struct ibv_context *context);
 	int (*query_device)(struct ibv_context *context,
 			    struct ibv_device_attr *device_attr);
Signature · 1 line
2.25.1
#2 lore raw

PATCH 2/6 common/mlx5: add remote PD and CTX support

In reply to Michael Baum

Add option to probe common device using import CTX/PD functions instead of create functions.
This option requires accepting the context FD and the PD handle as devargs.

This sharing can be useful for applications that use PMD for only some operations. For example, an app that generates queues itself and uses PMD just to configure flow rules.

---
 doc/guides/platform/mlx5.rst                 |  37 ++-
 drivers/common/mlx5/linux/mlx5_common_os.c   | 227 +++++++++++++++++--
 drivers/common/mlx5/linux/mlx5_common_os.h   |   6 -
 drivers/common/mlx5/mlx5_common.c            |  62 +++--
 drivers/common/mlx5/mlx5_common.h            |  28 ++-
 drivers/common/mlx5/version.map              |   4 +
 drivers/common/mlx5/windows/mlx5_common_os.c |  52 ++++-
 drivers/common/mlx5/windows/mlx5_common_os.h |   1 -
 8 files changed, 366 insertions(+), 51 deletions(-)
doc/guides/platform/mlx5.rst +36 -1
index a8553405ce..c928bf1265 100644
@@ -81,6 +81,12 @@ Limitations
 - On Windows, only ``eth`` and ``crypto`` are supported.
 
 
+Features
+--------
+
+- Remote PD and CTX - Linux only.
+
+
 .. _mlx5_common_compilation:
 
 Compilation Prerequisites
@@ -613,4 +619,33 @@ and below are the arguments supported by the common mlx5 layer.
 
   If ``sq_db_nc`` is omitted, the preset (if any) environment variable
   "MLX5_SHUT_UP_BF" value is used. If there is no "MLX5_SHUT_UP_BF", the
-  default ``sq_db_nc`` value is zero for ARM64 hosts and one for others.
\ No newline at end of file
+  default ``sq_db_nc`` value is zero for ARM64 hosts and one for others.
+
+- ``cmd_fd`` parameter [int]
+
+  File descriptor of ibv_context created outside the PMD.
+  PMD will use this FD to import remote CTX. The ``cmd_fd`` is obtained from
+  the ibv_context cmd_fd member, which must be dup'd before being passed.
+  This parameter is valid only if ``pd_handle`` parameter is specified.
+
+  By default, the PMD will ignore this parameter and create a new ibv_context.
+
+  .. note::
+
+     When FD comes from another process, it is on the user responsibility to
+     share the FD between the processes (e.g. by SCM_RIGHTS).
+
+- ``pd_handle`` parameter [int]
+
+  Protection domain handle of ibv_pd created outside the PMD.
+  PMD will use this handle to import remote PD. The ``pd_handle`` can be
+  achieved from the original PD by getting its ibv_pd->handle member value.
+  This parameter is valid only if ``cmd_fd`` parameter is specified, and its
+  value must be a valid kernel handle for a PD object in the context represented
+  by given ``cmd_fd``.
+
+  By default, the PMD will ignore this parameter and allocate a new PD.
+
+  .. note::
+
+     The ibv_pd->handle member is different then mlx5dv_pd->pdn member.
\ No newline at end of file
drivers/common/mlx5/linux/mlx5_common_os.c +205 -22

304 lines not on this page · raw message

drivers/common/mlx5/linux/mlx5_common_os.h +0 -6
index 83066e752d..246e8b2784 100644
@@ -203,12 +203,6 @@ mlx5_os_get_devx_uar_page_id(void *uar)
 #endif
 }
 
-static inline int
-mlx5_os_dealloc_pd(void *pd)
-{
-	return mlx5_glue->dealloc_pd(pd);
-}
-
 __rte_internal
 static inline void *
 mlx5_os_umem_reg(void *ctx, void *addr, size_t size, uint32_t access)
drivers/common/mlx5/mlx5_common.c +48 -14

112 lines not on this page · raw message

drivers/common/mlx5/mlx5_common.h +27 -1
index 49bcea1d91..1911d922e8 100644
@@ -446,6 +446,8 @@ void mlx5_common_init(void);
 struct mlx5_common_dev_config {
 	struct mlx5_hca_attr hca_attr; /* HCA attributes. */
 	int dbnc; /* Skip doorbell register write barrier. */
+	int device_fd; /* Device file descriptor for importation. */
+	int pd_handle; /* Protection Domain handle for importation.  */
 	unsigned int devx:1; /* Whether devx interface is available or not. */
 	unsigned int sys_mem_en:1; /* The default memory allocator. */
 	unsigned int mr_mempool_reg_en:1;
@@ -465,6 +467,23 @@ struct mlx5_common_device {
 	struct mlx5_common_dev_config config; /* Device configuration. */
 };
 
+/**
+ * Indicates whether PD and CTX are imported from another process,
+ * or created by this process.
+ *
+ * @param cdev
+ *   Pointer to common device.
+ *
+ * @return
+ *   True if PD and CTX are imported from another process, False otherwise.
+ */
+static inline bool
+mlx5_imported_pd_and_ctx(struct mlx5_common_device *cdev)
+{
+	return (cdev->config.device_fd != MLX5_ARG_UNSET &&
+		cdev->config.pd_handle != MLX5_ARG_UNSET);
+}
+
 /**
  * Initialization function for the driver called during device probing.
  */
@@ -554,7 +573,14 @@ mlx5_devx_uar_release(struct mlx5_uar *uar);
 /* mlx5_common_os.c */
 
 int mlx5_os_open_device(struct mlx5_common_device *cdev, uint32_t classes);
-int mlx5_os_pd_create(struct mlx5_common_device *cdev);
+__rte_internal
+int mlx5_os_pd_prepare(struct mlx5_common_device *cdev);
+__rte_internal
+int mlx5_os_pd_release(struct mlx5_common_device *cdev);
+__rte_internal
+int mlx5_os_remote_pd_and_ctx_validate(struct mlx5_common_dev_config *config);
+__rte_internal
+int mlx5_os_query_hca_attr(struct mlx5_common_device *cdev);
 
 /* mlx5 PMD wrapped MR struct. */
 struct mlx5_pmd_wrapped_mr {
drivers/common/mlx5/version.map +4 -0
index 1c6153c576..be8846f347 100644
@@ -136,6 +136,10 @@ INTERNAL {
 
 	mlx5_os_umem_dereg;
 	mlx5_os_umem_reg;
+	mlx5_os_pd_prepare;
+	mlx5_os_pd_release;
+	mlx5_os_remote_pd_and_ctx_validate;
+	mlx5_os_query_hca_attr;
 
 	mlx5_os_wrapped_mkey_create;
 	mlx5_os_wrapped_mkey_destroy;
drivers/common/mlx5/windows/mlx5_common_os.c +46 -6

81 lines not on this page · raw message

drivers/common/mlx5/windows/mlx5_common_os.h +0 -1
index 61fc8dd761..ee7973f1ec 100644
@@ -248,7 +248,6 @@ mlx5_os_devx_subscribe_devx_event(void *eventc,
 	return -ENOTSUP;
 }
 
-int mlx5_os_dealloc_pd(void *pd);
 __rte_internal
 void *mlx5_os_umem_reg(void *ctx, void *addr, size_t size, uint32_t access);
 __rte_internal
Signature · 1 line
2.25.1
#3 lore raw

PATCH 3/6 net/mlx5: optimize RxQ/TxQ control structure

In reply to Michael Baum

The RxQ/TxQ control structure has a field named type. This type is enum with values for standard and hairpin.
The use of this field is to check whether the queue is of the hairpin type or standard.

This patch replaces it with a boolean variable that saves whether it is a hairpin.

---
 drivers/net/mlx5/mlx5_devx.c    | 26 ++++++++++--------------
 drivers/net/mlx5/mlx5_ethdev.c  |  2 +-
 drivers/net/mlx5/mlx5_flow.c    | 14 ++++++-------
 drivers/net/mlx5/mlx5_flow_dv.c | 14 +++++--------
 drivers/net/mlx5/mlx5_rx.h      | 13 +++---------
 drivers/net/mlx5/mlx5_rxq.c     | 33 +++++++++++-------------------
 drivers/net/mlx5/mlx5_trigger.c | 36 ++++++++++++++++-----------------
 drivers/net/mlx5/mlx5_tx.h      |  7 +------
 drivers/net/mlx5/mlx5_txq.c     | 14 ++++++-------
 9 files changed, 64 insertions(+), 95 deletions(-)
drivers/net/mlx5/mlx5_devx.c +11 -15
index f18b18b1a2..154df99251 100644
@@ -88,7 +88,7 @@ mlx5_devx_modify_rq(struct mlx5_rxq_priv *rxq, uint8_t type)
 	default:
 		break;
 	}
-	if (rxq->ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
+	if (rxq->ctrl->is_hairpin)
 		return mlx5_devx_cmd_modify_rq(rxq->ctrl->obj->rq, &rq_attr);
 	return mlx5_devx_cmd_modify_rq(rxq->devx_rq.rq, &rq_attr);
 }
@@ -162,7 +162,7 @@ mlx5_rxq_devx_obj_release(struct mlx5_rxq_priv *rxq)
 
 	if (rxq_obj == NULL)
 		return;
-	if (rxq_obj->rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN) {
+	if (rxq_obj->rxq_ctrl->is_hairpin) {
 		if (rxq_obj->rq == NULL)
 			return;
 		mlx5_devx_modify_rq(rxq, MLX5_RXQ_MOD_RDY2RST);
@@ -476,7 +476,7 @@ mlx5_rxq_devx_obj_new(struct mlx5_rxq_priv *rxq)
 
 	MLX5_ASSERT(rxq_data);
 	MLX5_ASSERT(tmpl);
-	if (rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
+	if (rxq_ctrl->is_hairpin)
 		return mlx5_rxq_obj_hairpin_new(rxq);
 	tmpl->rxq_ctrl = rxq_ctrl;
 	if (rxq_ctrl->irq && !rxq_ctrl->started) {
@@ -583,7 +583,7 @@ mlx5_devx_ind_table_create_rqt_attr(struct rte_eth_dev *dev,
 		struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, queues[i]);
 
 		MLX5_ASSERT(rxq != NULL);
-		if (rxq->ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
+		if (rxq->ctrl->is_hairpin)
 			rqt_attr->rq_list[i] = rxq->ctrl->obj->rq->id;
 		else
 			rqt_attr->rq_list[i] = rxq->devx_rq.rq->id;
@@ -706,17 +706,13 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 		       int tunnel, struct mlx5_devx_tir_attr *tir_attr)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	enum mlx5_rxq_type rxq_obj_type;
+	bool is_hairpin;
 	bool lro = true;
 	uint32_t i;
 
 	/* NULL queues designate drop queue. */
 	if (ind_tbl->queues != NULL) {
-		struct mlx5_rxq_ctrl *rxq_ctrl =
-				mlx5_rxq_ctrl_get(dev, ind_tbl->queues[0]);
-		rxq_obj_type = rxq_ctrl != NULL ? rxq_ctrl->type :
-						  MLX5_RXQ_TYPE_STANDARD;
-
+		is_hairpin = mlx5_rxq_is_hairpin(dev, ind_tbl->queues[0]);
 		/* Enable TIR LRO only if all the queues were configured for. */
 		for (i = 0; i < ind_tbl->queues_n; ++i) {
 			struct mlx5_rxq_data *rxq_i =
@@ -728,7 +724,7 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			}
 		}
 	} else {
-		rxq_obj_type = priv->drop_queue.rxq->ctrl->type;
+		is_hairpin = priv->drop_queue.rxq->ctrl->is_hairpin;
 	}
 	memset(tir_attr, 0, sizeof(*tir_attr));
 	tir_attr->disp_type = MLX5_TIRC_DISP_TYPE_INDIRECT;
@@ -759,7 +755,7 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			(!!(hash_fields & MLX5_L4_DST_IBV_RX_HASH)) <<
 			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT;
 	}
-	if (rxq_obj_type == MLX5_RXQ_TYPE_HAIRPIN)
+	if (is_hairpin)
 		tir_attr->transport_domain = priv->sh->td->id;
 	else
 		tir_attr->transport_domain = priv->sh->tdn;
@@ -932,7 +928,7 @@ mlx5_rxq_devx_obj_drop_create(struct rte_eth_dev *dev)
 		goto error;
 	}
 	rxq_obj->rxq_ctrl = rxq_ctrl;
-	rxq_ctrl->type = MLX5_RXQ_TYPE_STANDARD;
+	rxq_ctrl->is_hairpin = false;
 	rxq_ctrl->sh = priv->sh;
 	rxq_ctrl->obj = rxq_obj;
 	rxq->ctrl = rxq_ctrl;
@@ -1232,7 +1228,7 @@ mlx5_txq_devx_obj_new(struct rte_eth_dev *dev, uint16_t idx)
 	struct mlx5_txq_ctrl *txq_ctrl =
 			container_of(txq_data, struct mlx5_txq_ctrl, txq);
 
-	if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN)
+	if (txq_ctrl->is_hairpin)
 		return mlx5_txq_obj_hairpin_new(dev, idx);
 #if !defined(HAVE_MLX5DV_DEVX_UAR_OFFSET) && defined(HAVE_INFINIBAND_VERBS_H)
 	DRV_LOG(ERR, "Port %u Tx queue %u cannot create with DevX, no UAR.",
@@ -1369,7 +1365,7 @@ void
 mlx5_txq_devx_obj_release(struct mlx5_txq_obj *txq_obj)
 {
 	MLX5_ASSERT(txq_obj);
-	if (txq_obj->txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) {
+	if (txq_obj->txq_ctrl->is_hairpin) {
 		if (txq_obj->tis)
 			claim_zero(mlx5_devx_cmd_destroy(txq_obj->tis));
 #if defined(HAVE_MLX5DV_DEVX_UAR_OFFSET) || !defined(HAVE_INFINIBAND_VERBS_H)
drivers/net/mlx5/mlx5_ethdev.c +1 -1
index 72bf8ac914..406761ccf8 100644
@@ -173,7 +173,7 @@ mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev)
 	for (i = 0, j = 0; i < rxqs_n; i++) {
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 
-		if (rxq_ctrl && rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl && !rxq_ctrl->is_hairpin)
 			rss_queue_arr[j++] = i;
 	}
 	rss_queue_n = j;
drivers/net/mlx5/mlx5_flow.c +6 -8
index 1c3f648491..5e8454f5f5 100644
@@ -1676,7 +1676,7 @@ mlx5_validate_rss_queues(struct rte_eth_dev *dev,
 			 const char **error, uint32_t *queue_idx)
 {
 	const struct mlx5_priv *priv = dev->data->dev_private;
-	enum mlx5_rxq_type rxq_type = MLX5_RXQ_TYPE_UNDEFINED;
+	bool is_hairpin = false;
 	uint32_t i;
 
 	for (i = 0; i != queues_n; ++i) {
@@ -1693,9 +1693,9 @@ mlx5_validate_rss_queues(struct rte_eth_dev *dev,
 			*queue_idx = i;
 			return -EINVAL;
 		}
-		if (i == 0)
-			rxq_type = rxq_ctrl->type;
-		if (rxq_type != rxq_ctrl->type) {
+		if (i == 0 && rxq_ctrl->is_hairpin)
+			is_hairpin = true;
+		if (is_hairpin != rxq_ctrl->is_hairpin) {
 			*error = "combining hairpin and regular RSS queues is not supported";
 			*queue_idx = i;
 			return -ENOTSUP;
@@ -5767,15 +5767,13 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
 			const struct rte_flow_action_queue *queue;
 
 			queue = qrss->conf;
-			if (mlx5_rxq_get_type(dev, queue->index) ==
-			    MLX5_RXQ_TYPE_HAIRPIN)
+			if (mlx5_rxq_is_hairpin(dev, queue->index))
 				qrss = NULL;
 		} else if (qrss->type == RTE_FLOW_ACTION_TYPE_RSS) {
 			const struct rte_flow_action_rss *rss;
 
 			rss = qrss->conf;
-			if (mlx5_rxq_get_type(dev, rss->queue[0]) ==
-			    MLX5_RXQ_TYPE_HAIRPIN)
+			if (mlx5_rxq_is_hairpin(dev, rss->queue[0]))
 				qrss = NULL;
 		}
 	}
drivers/net/mlx5/mlx5_flow_dv.c +5 -9
index ce69b6ff3a..3034dbd70e 100644
@@ -5767,8 +5767,7 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
 	}
 	/* Continue validation for Xcap actions.*/
 	if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) &&
-	    (queue_index == 0xFFFF ||
-	     mlx5_rxq_get_type(dev, queue_index) != MLX5_RXQ_TYPE_HAIRPIN)) {
+	    (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index))) {
 		if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
 		     MLX5_FLOW_XCAP_ACTIONS)
 			return rte_flow_error_set(error, ENOTSUP,
@@ -7953,8 +7952,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 	 */
 	if ((action_flags & (MLX5_FLOW_XCAP_ACTIONS |
 			     MLX5_FLOW_VLAN_ACTIONS)) &&
-	    (queue_index == 0xFFFF ||
-	     mlx5_rxq_get_type(dev, queue_index) != MLX5_RXQ_TYPE_HAIRPIN ||
+	    (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index) ||
 	     ((conf = mlx5_rxq_get_hairpin_conf(dev, queue_index)) != NULL &&
 	     conf->tx_explicit != 0))) {
 		if ((action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
@@ -10944,10 +10942,8 @@ flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev,
 {
 	const struct mlx5_rte_flow_item_tx_queue *queue_m;
 	const struct mlx5_rte_flow_item_tx_queue *queue_v;
-	void *misc_m =
-		MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
-	void *misc_v =
-		MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+	void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+	void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
 	struct mlx5_txq_ctrl *txq;
 	uint32_t queue, mask;
 
@@ -10958,7 +10954,7 @@ flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev,
 	txq = mlx5_txq_get(dev, queue_v->queue);
 	if (!txq)
 		return;
-	if (txq->type == MLX5_TXQ_TYPE_HAIRPIN)
+	if (txq->is_hairpin)
 		queue = txq->obj->sq->id;
 	else
 		queue = txq->obj->sq_obj.sq->id;
drivers/net/mlx5/mlx5_rx.h +3 -10
index 7e417819f7..2d7c1a983a 100644
@@ -141,12 +141,6 @@ struct mlx5_rxq_data {
 	/* Buffer split segment descriptions - sizes, offsets, pools. */
 } __rte_cache_aligned;
 
-enum mlx5_rxq_type {
-	MLX5_RXQ_TYPE_STANDARD, /* Standard Rx queue. */
-	MLX5_RXQ_TYPE_HAIRPIN, /* Hairpin Rx queue. */
-	MLX5_RXQ_TYPE_UNDEFINED,
-};
-
 /* RX queue control descriptor. */
 struct mlx5_rxq_ctrl {
 	struct mlx5_rxq_data rxq; /* Data path structure. */
@@ -154,7 +148,7 @@ struct mlx5_rxq_ctrl {
 	LIST_HEAD(priv, mlx5_rxq_priv) owners; /* Owner rxq list. */
 	struct mlx5_rxq_obj *obj; /* Verbs/DevX elements. */
 	struct mlx5_dev_ctx_shared *sh; /* Shared context. */
-	enum mlx5_rxq_type type; /* Rxq type. */
+	bool is_hairpin; /* Whether RxQ type is Hairpin. */
 	unsigned int socket; /* CPU socket ID for allocations. */
 	LIST_ENTRY(mlx5_rxq_ctrl) share_entry; /* Entry in shared RXQ list. */
 	uint32_t share_group; /* Group ID of shared RXQ. */
@@ -254,7 +248,7 @@ uint32_t mlx5_hrxq_get(struct rte_eth_dev *dev,
 		       struct mlx5_flow_rss_desc *rss_desc);
 int mlx5_hrxq_release(struct rte_eth_dev *dev, uint32_t hxrq_idx);
 uint32_t mlx5_hrxq_verify(struct rte_eth_dev *dev);
-enum mlx5_rxq_type mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx);
+bool mlx5_rxq_is_hairpin(struct rte_eth_dev *dev, uint16_t idx);
 const struct rte_eth_hairpin_conf *mlx5_rxq_get_hairpin_conf
 	(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_hrxq *mlx5_drop_action_create(struct rte_eth_dev *dev);
@@ -628,8 +622,7 @@ mlx5_mprq_enabled(struct rte_eth_dev *dev)
 	for (i = 0; i < priv->rxqs_n; ++i) {
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 
-		if (rxq_ctrl == NULL ||
-		    rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl == NULL || rxq_ctrl->is_hairpin)
 			continue;
 		n_ibv++;
 		if (mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq))
drivers/net/mlx5/mlx5_rxq.c +12 -21
index 2625fa3308..4d45d494c0 100644
@@ -1393,8 +1393,7 @@ mlx5_mprq_alloc_mp(struct rte_eth_dev *dev)
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 		struct mlx5_rxq_data *rxq;
 
-		if (rxq_ctrl == NULL ||
-		    rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl == NULL || rxq_ctrl->is_hairpin)
 			continue;
 		rxq = &rxq_ctrl->rxq;
 		n_ibv++;
@@ -1482,8 +1481,7 @@ mlx5_mprq_alloc_mp(struct rte_eth_dev *dev)
 	for (i = 0; i != priv->rxqs_n; ++i) {
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 
-		if (rxq_ctrl == NULL ||
-		    rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl == NULL || rxq_ctrl->is_hairpin)
 			continue;
 		rxq_ctrl->rxq.mprq_mp = mp;
 	}
@@ -1810,7 +1808,7 @@ mlx5_rxq_new(struct rte_eth_dev *dev, struct mlx5_rxq_priv *rxq,
 		rte_errno = ENOSPC;
 		goto error;
 	}
-	tmpl->type = MLX5_RXQ_TYPE_STANDARD;
+	tmpl->is_hairpin = false;
 	if (mlx5_mr_ctrl_init(&tmpl->rxq.mr_ctrl,
 			      &priv->sh->cdev->mr_scache.dev_gen, socket)) {
 		/* rte_errno is already set. */
@@ -1975,7 +1973,7 @@ mlx5_rxq_hairpin_new(struct rte_eth_dev *dev, struct mlx5_rxq_priv *rxq,
 	LIST_INIT(&tmpl->owners);
 	rxq->ctrl = tmpl;
 	LIST_INSERT_HEAD(&tmpl->owners, rxq, owner_entry);
-	tmpl->type = MLX5_RXQ_TYPE_HAIRPIN;
+	tmpl->is_hairpin = true;
 	tmpl->socket = SOCKET_ID_ANY;
 	tmpl->rxq.rss_hash = 0;
 	tmpl->rxq.port_id = dev->data->port_id;
@@ -2126,7 +2124,7 @@ mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx)
 			mlx5_free(rxq_ctrl->obj);
 			rxq_ctrl->obj = NULL;
 		}
-		if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) {
+		if (!rxq_ctrl->is_hairpin) {
 			if (!rxq_ctrl->started)
 				rxq_free_elts(rxq_ctrl);
 			dev->data->rx_queue_state[idx] =
@@ -2135,7 +2133,7 @@ mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx)
 	} else { /* Refcnt zero, closing device. */
 		LIST_REMOVE(rxq, owner_entry);
 		if (LIST_EMPTY(&rxq_ctrl->owners)) {
-			if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD)
+			if (!rxq_ctrl->is_hairpin)
 				mlx5_mr_btree_free
 					(&rxq_ctrl->rxq.mr_ctrl.cache_bh);
 			if (rxq_ctrl->rxq.shared)
@@ -2175,7 +2173,7 @@ mlx5_rxq_verify(struct rte_eth_dev *dev)
 }
 
 /**
- * Get a Rx queue type.
+ * Check whether RxQ type is Hairpin.
  *
  * @param dev
  *   Pointer to Ethernet device.
@@ -2183,17 +2181,15 @@ mlx5_rxq_verify(struct rte_eth_dev *dev)
  *   Rx queue index.
  *
  * @return
- *   The Rx queue type.
+ *   True if Rx queue type is Hairpin, otherwise False.
  */
-enum mlx5_rxq_type
-mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx)
+bool
+mlx5_rxq_is_hairpin(struct rte_eth_dev *dev, uint16_t idx)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, idx);
 
-	if (idx < priv->rxqs_n && rxq_ctrl != NULL)
-		return rxq_ctrl->type;
-	return MLX5_RXQ_TYPE_UNDEFINED;
+	return (idx < priv->rxqs_n && rxq_ctrl != NULL && rxq_ctrl->is_hairpin);
 }
 
 /*
@@ -2210,14 +2206,9 @@ mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx)
 const struct rte_eth_hairpin_conf *
 mlx5_rxq_get_hairpin_conf(struct rte_eth_dev *dev, uint16_t idx)
 {
-	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, idx);
 
-	if (idx < priv->rxqs_n && rxq != NULL) {
-		if (rxq->ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
-			return &rxq->hairpin_conf;
-	}
-	return NULL;
+	return mlx5_rxq_is_hairpin(dev, idx) ? &rxq->hairpin_conf : NULL;
 }
 
 /**
drivers/net/mlx5/mlx5_trigger.c +18 -18
index 74c3bc8a13..fe8b42c414 100644
@@ -59,7 +59,7 @@ mlx5_txq_start(struct rte_eth_dev *dev)
 
 		if (!txq_ctrl)
 			continue;
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD)
+		if (!txq_ctrl->is_hairpin)
 			txq_alloc_elts(txq_ctrl);
 		MLX5_ASSERT(!txq_ctrl->obj);
 		txq_ctrl->obj = mlx5_malloc(flags, sizeof(struct mlx5_txq_obj),
@@ -77,7 +77,7 @@ mlx5_txq_start(struct rte_eth_dev *dev)
 			txq_ctrl->obj = NULL;
 			goto error;
 		}
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD) {
+		if (!txq_ctrl->is_hairpin) {
 			size_t size = txq_data->cqe_s * sizeof(*txq_data->fcqs);
 
 			txq_data->fcqs = mlx5_malloc(flags, size,
@@ -167,7 +167,7 @@ mlx5_rxq_ctrl_prepare(struct rte_eth_dev *dev, struct mlx5_rxq_ctrl *rxq_ctrl,
 {
 	int ret = 0;
 
-	if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) {
+	if (!rxq_ctrl->is_hairpin) {
 		/*
 		 * Pre-register the mempools. Regardless of whether
 		 * the implicit registration is enabled or not,
@@ -280,7 +280,7 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (!txq_ctrl)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN ||
+		if (!txq_ctrl->is_hairpin ||
 		    txq_ctrl->hairpin_conf.peers[0].port != self_port) {
 			mlx5_txq_release(dev, i);
 			continue;
@@ -299,7 +299,7 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev)
 		if (!txq_ctrl)
 			continue;
 		/* Skip hairpin queues with other peer ports. */
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN ||
+		if (!txq_ctrl->is_hairpin ||
 		    txq_ctrl->hairpin_conf.peers[0].port != self_port) {
 			mlx5_txq_release(dev, i);
 			continue;
@@ -322,7 +322,7 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev)
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN ||
+		if (!rxq_ctrl->is_hairpin ||
 		    rxq->hairpin_conf.peers[0].queue != i) {
 			rte_errno = ENOMEM;
 			DRV_LOG(ERR, "port %u Tx queue %d can't be binded to "
@@ -412,7 +412,7 @@ mlx5_hairpin_queue_peer_update(struct rte_eth_dev *dev, uint16_t peer_queue,
 				dev->data->port_id, peer_queue);
 			return -rte_errno;
 		}
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d is not a hairpin Txq",
 				dev->data->port_id, peer_queue);
@@ -444,7 +444,7 @@ mlx5_hairpin_queue_peer_update(struct rte_eth_dev *dev, uint16_t peer_queue,
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
+		if (!rxq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d is not a hairpin Rxq",
 				dev->data->port_id, peer_queue);
@@ -510,7 +510,7 @@ mlx5_hairpin_queue_peer_bind(struct rte_eth_dev *dev, uint16_t cur_queue,
 				dev->data->port_id, cur_queue);
 			return -rte_errno;
 		}
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Txq",
 				dev->data->port_id, cur_queue);
@@ -570,7 +570,7 @@ mlx5_hairpin_queue_peer_bind(struct rte_eth_dev *dev, uint16_t cur_queue,
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
+		if (!rxq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Rxq",
 				dev->data->port_id, cur_queue);
@@ -644,7 +644,7 @@ mlx5_hairpin_queue_peer_unbind(struct rte_eth_dev *dev, uint16_t cur_queue,
 				dev->data->port_id, cur_queue);
 			return -rte_errno;
 		}
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Txq",
 				dev->data->port_id, cur_queue);
@@ -683,7 +683,7 @@ mlx5_hairpin_queue_peer_unbind(struct rte_eth_dev *dev, uint16_t cur_queue,
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
+		if (!rxq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Rxq",
 				dev->data->port_id, cur_queue);
@@ -751,7 +751,7 @@ mlx5_hairpin_bind_single_port(struct rte_eth_dev *dev, uint16_t rx_port)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (txq_ctrl == NULL)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			mlx5_txq_release(dev, i);
 			continue;
 		}
@@ -791,7 +791,7 @@ mlx5_hairpin_bind_single_port(struct rte_eth_dev *dev, uint16_t rx_port)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (txq_ctrl == NULL)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			mlx5_txq_release(dev, i);
 			continue;
 		}
@@ -886,7 +886,7 @@ mlx5_hairpin_unbind_single_port(struct rte_eth_dev *dev, uint16_t rx_port)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (txq_ctrl == NULL)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			mlx5_txq_release(dev, i);
 			continue;
 		}
@@ -1016,7 +1016,7 @@ mlx5_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports,
 			txq_ctrl = mlx5_txq_get(dev, i);
 			if (!txq_ctrl)
 				continue;
-			if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+			if (!txq_ctrl->is_hairpin) {
 				mlx5_txq_release(dev, i);
 				continue;
 			}
@@ -1040,7 +1040,7 @@ mlx5_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports,
 			if (rxq == NULL)
 				continue;
 			rxq_ctrl = rxq->ctrl;
-			if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN)
+			if (!rxq_ctrl->is_hairpin)
 				continue;
 			pp = rxq->hairpin_conf.peers[0].port;
 			if (pp >= RTE_MAX_ETHPORTS) {
@@ -1318,7 +1318,7 @@ mlx5_traffic_enable(struct rte_eth_dev *dev)
 		if (!txq_ctrl)
 			continue;
 		/* Only Tx implicit mode requires the default Tx flow. */
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN &&
+		if (txq_ctrl->is_hairpin &&
 		    txq_ctrl->hairpin_conf.tx_explicit == 0 &&
 		    txq_ctrl->hairpin_conf.peers[0].port ==
 		    priv->dev_data->port_id) {
drivers/net/mlx5/mlx5_tx.h +1 -6
index c4b8271f6f..00cc9e19d4 100644
@@ -166,17 +166,12 @@ struct mlx5_txq_data {
 	/* Storage for queued packets, must be the last field. */
 } __rte_cache_aligned;
 
-enum mlx5_txq_type {
-	MLX5_TXQ_TYPE_STANDARD, /* Standard Tx queue. */
-	MLX5_TXQ_TYPE_HAIRPIN, /* Hairpin Tx queue. */
-};
-
 /* TX queue control descriptor. */
 struct mlx5_txq_ctrl {
 	LIST_ENTRY(mlx5_txq_ctrl) next; /* Pointer to the next element. */
 	uint32_t refcnt; /* Reference counter. */
 	unsigned int socket; /* CPU socket ID for allocations. */
-	enum mlx5_txq_type type; /* The txq ctrl type. */
+	bool is_hairpin; /* Whether TxQ type is Hairpin. */
 	unsigned int max_inline_data; /* Max inline data. */
 	unsigned int max_tso_header; /* Max TSO header size. */
 	struct mlx5_txq_obj *obj; /* Verbs/DevX queue object. */
drivers/net/mlx5/mlx5_txq.c +7 -7
index edbaa50692..c2cc0c84ab 100644
@@ -526,7 +526,7 @@ txq_uar_init_secondary(struct mlx5_txq_ctrl *txq_ctrl, int fd)
 		return -rte_errno;
 	}
 
-	if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
+	if (txq_ctrl->is_hairpin)
 		return 0;
 	MLX5_ASSERT(ppriv);
 	/*
@@ -569,7 +569,7 @@ txq_uar_uninit_secondary(struct mlx5_txq_ctrl *txq_ctrl)
 		rte_errno = ENOMEM;
 	}
 
-	if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
+	if (txq_ctrl->is_hairpin)
 		return;
 	addr = ppriv->uar_table[txq_ctrl->txq.idx].db;
 	rte_mem_unmap(RTE_PTR_ALIGN_FLOOR(addr, page_size), page_size);
@@ -630,7 +630,7 @@ mlx5_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd)
 			continue;
 		txq = (*priv->txqs)[i];
 		txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq);
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
+		if (txq_ctrl->is_hairpin)
 			continue;
 		MLX5_ASSERT(txq->idx == (uint16_t)i);
 		ret = txq_uar_init_secondary(txq_ctrl, fd);
@@ -1106,7 +1106,7 @@ mlx5_txq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 		goto error;
 	}
 	__atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED);
-	tmpl->type = MLX5_TXQ_TYPE_STANDARD;
+	tmpl->is_hairpin = false;
 	LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next);
 	return tmpl;
 error:
@@ -1149,7 +1149,7 @@ mlx5_txq_hairpin_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	tmpl->txq.port_id = dev->data->port_id;
 	tmpl->txq.idx = idx;
 	tmpl->hairpin_conf = *hairpin_conf;
-	tmpl->type = MLX5_TXQ_TYPE_HAIRPIN;
+	tmpl->is_hairpin = true;
 	__atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED);
 	LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next);
 	return tmpl;
@@ -1208,7 +1208,7 @@ mlx5_txq_release(struct rte_eth_dev *dev, uint16_t idx)
 		mlx5_free(txq_ctrl->obj);
 		txq_ctrl->obj = NULL;
 	}
-	if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD) {
+	if (!txq_ctrl->is_hairpin) {
 		if (txq_ctrl->txq.fcqs) {
 			mlx5_free(txq_ctrl->txq.fcqs);
 			txq_ctrl->txq.fcqs = NULL;
@@ -1217,7 +1217,7 @@ mlx5_txq_release(struct rte_eth_dev *dev, uint16_t idx)
 		dev->data->tx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED;
 	}
 	if (!__atomic_load_n(&txq_ctrl->refcnt, __ATOMIC_RELAXED)) {
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD)
+		if (!txq_ctrl->is_hairpin)
 			mlx5_mr_btree_free(&txq_ctrl->txq.mr_ctrl.cache_bh);
 		LIST_REMOVE(txq_ctrl, next);
 		mlx5_free(txq_ctrl);
Signature · 1 line
2.25.1
#4 lore raw

PATCH 4/6 net/mlx5: add external RxQ mapping API

In reply to Michael Baum

External queue is a queue that has been created and managed outside the PMD. The queues owner might use PMD to generate flow rules using these external queues.

When the queue is created in hardware it is given an ID represented by 32 bits. In contrast, the index of the queues in PMD is represented by 16 bits. To enable the use of PMD to generate flow rules, the queue owner must provide a mapping between the HW index and a 16-bit index corresponding to the RTE Flow API.

This patch adds an API enabling to insert/cancel a mapping between HW queue id and RTE Flow queue id.

---
 drivers/net/mlx5/linux/mlx5_os.c |  18 +++++
 drivers/net/mlx5/mlx5.c          |   2 +
 drivers/net/mlx5/mlx5.h          |   1 +
 drivers/net/mlx5/mlx5_defs.h     |   3 +
 drivers/net/mlx5/mlx5_ethdev.c   |  16 ++++-
 drivers/net/mlx5/mlx5_rx.h       |   6 ++
 drivers/net/mlx5/mlx5_rxq.c      | 109 +++++++++++++++++++++++++++++++
 drivers/net/mlx5/rte_pmd_mlx5.h  |  50 +++++++++++++-
 drivers/net/mlx5/version.map     |   3 +
 9 files changed, 204 insertions(+), 4 deletions(-)
drivers/net/mlx5/linux/mlx5_os.c +18 -0
index ecf823da56..058c140fe1 100644
@@ -1156,6 +1156,22 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		err = ENOMEM;
 		goto error;
 	}
+	/*
+	 * When user configures remote PD and CTX and device creates RxQ by
+	 * DevX, external RxQ is both supported and requested.
+	 */
+	if (mlx5_imported_pd_and_ctx(sh->cdev) && mlx5_devx_obj_ops_en(sh)) {
+		priv->ext_rxqs = mlx5_malloc(MLX5_MEM_ZERO | MLX5_MEM_RTE,
+					     sizeof(struct mlx5_external_rxq) *
+					     MLX5_MAX_EXT_RX_QUEUES, 0,
+					     SOCKET_ID_ANY);
+		if (priv->ext_rxqs == NULL) {
+			DRV_LOG(ERR, "Fail to allocate external RxQ array.");
+			err = ENOMEM;
+			goto error;
+		}
+		DRV_LOG(DEBUG, "External RxQ is supported.");
+	}
 	priv->sh = sh;
 	priv->dev_port = spawn->phys_port;
 	priv->pci_dev = spawn->pci_dev;
@@ -1613,6 +1629,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 			mlx5_list_destroy(priv->hrxqs);
 		if (eth_dev && priv->flex_item_map)
 			mlx5_flex_item_port_cleanup(eth_dev);
+		if (priv->ext_rxqs)
+			mlx5_free(priv->ext_rxqs);
 		mlx5_free(priv);
 		if (eth_dev != NULL)
 			eth_dev->data->dev_private = NULL;
drivers/net/mlx5/mlx5.c +2 -0
index 9f65a8f901..415e0fe2f2 100644
@@ -1855,6 +1855,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 		close(priv->nl_socket_rdma);
 	if (priv->vmwa_context)
 		mlx5_vlan_vmwa_exit(priv->vmwa_context);
+	if (priv->ext_rxqs)
+		mlx5_free(priv->ext_rxqs);
 	ret = mlx5_hrxq_verify(dev);
 	if (ret)
 		DRV_LOG(WARNING, "port %u some hash Rx queue still remain",
drivers/net/mlx5/mlx5.h +1 -0
index 35ea3fb47c..a316f628ec 100644
@@ -1420,6 +1420,7 @@ struct mlx5_priv {
 	/* RX/TX queues. */
 	unsigned int rxqs_n; /* RX queues array size. */
 	unsigned int txqs_n; /* TX queues array size. */
+	struct mlx5_external_rxq *ext_rxqs; /* External RX queues array. */
 	struct mlx5_rxq_priv *(*rxq_privs)[]; /* RX queue non-shared data. */
 	struct mlx5_txq_data *(*txqs)[]; /* TX queues. */
 	struct rte_mempool *mprq_mp; /* Mempool for Multi-Packet RQ. */
drivers/net/mlx5/mlx5_defs.h +3 -0
index 2d48fde010..15728fb41f 100644
@@ -175,6 +175,9 @@
 /* Maximum number of indirect actions supported by rte_flow */
 #define MLX5_MAX_INDIRECT_ACTIONS 3
 
+/* Maximum number of external Rx queues supported by rte_flow */
+#define MLX5_MAX_EXT_RX_QUEUES (UINT16_MAX - MLX5_EXTERNAL_RX_QUEUE_ID_MIN + 1)
+
 /*
  * Linux definition of static_assert is found in /usr/include/assert.h.
  * Windows does not require a redefinition.
drivers/net/mlx5/mlx5_ethdev.c +13 -3
index 406761ccf8..de0ba2b1ff 100644
@@ -27,6 +27,7 @@
 #include "mlx5_tx.h"
 #include "mlx5_autoconf.h"
 #include "mlx5_devx.h"
+#include "rte_pmd_mlx5.h"
 
 /**
  * Get the interface index from device name.
@@ -81,9 +82,10 @@ mlx5_dev_configure(struct rte_eth_dev *dev)
 		rte_errno = EINVAL;
 		return -rte_errno;
 	}
-	priv->rss_conf.rss_key =
-		mlx5_realloc(priv->rss_conf.rss_key, MLX5_MEM_RTE,
-			    MLX5_RSS_HASH_KEY_LEN, 0, SOCKET_ID_ANY);
+	priv->rss_conf.rss_key = mlx5_realloc(priv->rss_conf.rss_key,
+					      MLX5_MEM_RTE,
+					      MLX5_RSS_HASH_KEY_LEN, 0,
+					      SOCKET_ID_ANY);
 	if (!priv->rss_conf.rss_key) {
 		DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)",
 			dev->data->port_id, rxqs_n);
@@ -127,6 +129,14 @@ mlx5_dev_configure(struct rte_eth_dev *dev)
 		rte_errno = EINVAL;
 		return -rte_errno;
 	}
+	if (priv->ext_rxqs && rxqs_n >= MLX5_EXTERNAL_RX_QUEUE_ID_MIN) {
+		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u), "
+			"the maximal number of internal Rx queues is %u",
+			dev->data->port_id, rxqs_n,
+			MLX5_EXTERNAL_RX_QUEUE_ID_MIN - 1);
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
 	if (rxqs_n != priv->rxqs_n) {
 		DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
 			dev->data->port_id, priv->rxqs_n, rxqs_n);
drivers/net/mlx5/mlx5_rx.h +6 -0
index 2d7c1a983a..1e191a5704 100644
@@ -175,6 +175,12 @@ struct mlx5_rxq_priv {
 	uint32_t hairpin_status; /* Hairpin binding status. */
 };
 
+/* External RX queue descriptor. */
+struct mlx5_external_rxq {
+	uint32_t hw_id; /* Queue index in the Hardware. */
+	uint32_t refcnt; /* Reference counter. */
+};
+
 /* mlx5_rxq.c */
 
 extern uint8_t rss_hash_default_key[];
drivers/net/mlx5/mlx5_rxq.c +109 -0

118 lines not on this page · raw message

drivers/net/mlx5/rte_pmd_mlx5.h +49 -1

57 lines not on this page · raw message

drivers/net/mlx5/version.map +3 -0
index 0af7a12488..79cb79acc6 100644
@@ -9,4 +9,7 @@ EXPERIMENTAL {
 	rte_pmd_mlx5_get_dyn_flag_names;
 	# added in 20.11
 	rte_pmd_mlx5_sync_flow;
+	# added in 22.03
+	rte_pmd_mlx5_external_rx_queue_id_map;
+	rte_pmd_mlx5_external_rx_queue_id_unmap;
 };
Signature · 1 line
2.25.1
#5 lore raw

PATCH 5/6 net/mlx5: support queue/RSS action for external RxQ

In reply to Michael Baum

Add support queue/RSS action for external RxQ.
In indirection table creation, the queue index will be taken from mapping array.

---
 doc/guides/nics/mlx5.rst               |   1 +
 doc/guides/rel_notes/release_22_03.rst |   6 ++
 drivers/net/mlx5/mlx5.c                |   8 +-
 drivers/net/mlx5/mlx5_devx.c           |  30 +++++--
 drivers/net/mlx5/mlx5_flow.c           |  29 +++++--
 drivers/net/mlx5/mlx5_rx.h             |  30 +++++++
 drivers/net/mlx5/mlx5_rxq.c            | 116 +++++++++++++++++++++++--
 7 files changed, 194 insertions(+), 26 deletions(-)
doc/guides/nics/mlx5.rst +1 -0
index 748939527d..724e34d98b 100644
@@ -38,6 +38,7 @@ Features
 - Multiple TX and RX queues.
 - Shared Rx queue.
 - Rx queue delay drop.
+- Support steering for external Rx queue.
 - Support for scattered TX frames.
 - Advanced support for scattered Rx frames with tunable buffer attributes.
 - IPv4, IPv6, TCPv4, TCPv6, UDPv4 and UDPv6 RSS on any number of queues.
doc/guides/rel_notes/release_22_03.rst +6 -0
index 41923f50e6..b5dd5d9913 100644
@@ -118,6 +118,12 @@ New Features
   * Added PPPoL2TPv2oUDP FDIR distribute packets based on inner IP
     src/dst address and UDP/TCP src/dst port.
 
+* **Updated Mellanox mlx5 driver.**
+
+  Updated the Mellanox mlx5 driver with new features and improvements, including:
+
+  * Support steering for external Rx queue.
+
 * **Updated Wangxun ngbe driver.**
 
   * Added support for devices of custom PHY interfaces.
drivers/net/mlx5/mlx5.c +6 -2
index 415e0fe2f2..9760f52b46 100644
@@ -1855,8 +1855,6 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 		close(priv->nl_socket_rdma);
 	if (priv->vmwa_context)
 		mlx5_vlan_vmwa_exit(priv->vmwa_context);
-	if (priv->ext_rxqs)
-		mlx5_free(priv->ext_rxqs);
 	ret = mlx5_hrxq_verify(dev);
 	if (ret)
 		DRV_LOG(WARNING, "port %u some hash Rx queue still remain",
@@ -1869,6 +1867,10 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 	if (ret)
 		DRV_LOG(WARNING, "port %u some Rx queue objects still remain",
 			dev->data->port_id);
+	ret = mlx5_ext_rxq_verify(dev);
+	if (ret)
+		DRV_LOG(WARNING, "Port %u some external RxQ still remain.",
+			dev->data->port_id);
 	ret = mlx5_rxq_verify(dev);
 	if (ret)
 		DRV_LOG(WARNING, "port %u some Rx queues still remain",
@@ -1887,6 +1889,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 			dev->data->port_id);
 	if (priv->hrxqs)
 		mlx5_list_destroy(priv->hrxqs);
+	if (priv->ext_rxqs)
+		mlx5_free(priv->ext_rxqs);
 	/*
 	 * Free the shared context in last turn, because the cleanup
 	 * routines above may use some shared fields, like
drivers/net/mlx5/mlx5_devx.c +21 -9
index 154df99251..19510a540c 100644
@@ -580,13 +580,21 @@ mlx5_devx_ind_table_create_rqt_attr(struct rte_eth_dev *dev,
 		return rqt_attr;
 	}
 	for (i = 0; i != queues_n; ++i) {
-		struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, queues[i]);
+		if (mlx5_is_external_rxq(dev, queues[i])) {
+			struct mlx5_external_rxq *ext_rxq =
+					mlx5_ext_rxq_get(dev, queues[i]);
 
-		MLX5_ASSERT(rxq != NULL);
-		if (rxq->ctrl->is_hairpin)
-			rqt_attr->rq_list[i] = rxq->ctrl->obj->rq->id;
-		else
-			rqt_attr->rq_list[i] = rxq->devx_rq.rq->id;
+			rqt_attr->rq_list[i] = ext_rxq->hw_id;
+		} else {
+			struct mlx5_rxq_priv *rxq =
+					mlx5_rxq_get(dev, queues[i]);
+
+			MLX5_ASSERT(rxq != NULL);
+			if (rxq->ctrl->is_hairpin)
+				rqt_attr->rq_list[i] = rxq->ctrl->obj->rq->id;
+			else
+				rqt_attr->rq_list[i] = rxq->devx_rq.rq->id;
+		}
 	}
 	MLX5_ASSERT(i > 0);
 	for (j = 0; i != rqt_n; ++j, ++i)
@@ -711,7 +719,13 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 	uint32_t i;
 
 	/* NULL queues designate drop queue. */
-	if (ind_tbl->queues != NULL) {
+	if (ind_tbl->queues == NULL) {
+		is_hairpin = priv->drop_queue.rxq->ctrl->is_hairpin;
+	} else if (mlx5_is_external_rxq(dev, ind_tbl->queues[0])) {
+		/* External RxQ supports neither Hairpin nor LRO. */
+		is_hairpin = false;
+		lro = false;
+	} else {
 		is_hairpin = mlx5_rxq_is_hairpin(dev, ind_tbl->queues[0]);
 		/* Enable TIR LRO only if all the queues were configured for. */
 		for (i = 0; i < ind_tbl->queues_n; ++i) {
@@ -723,8 +737,6 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 				break;
 			}
 		}
-	} else {
-		is_hairpin = priv->drop_queue.rxq->ctrl->is_hairpin;
 	}
 	memset(tir_attr, 0, sizeof(*tir_attr));
 	tir_attr->disp_type = MLX5_TIRC_DISP_TYPE_INDIRECT;
drivers/net/mlx5/mlx5_flow.c +20 -9
index 5e8454f5f5..1f81cedecb 100644
@@ -1631,6 +1631,12 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 fate actions in"
 					  " same flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "queue action not supported for egress.");
+	if (mlx5_is_external_rxq(dev, queue->index))
+		return 0;
 	if (!priv->rxqs_n)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
@@ -1645,11 +1651,6 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  &queue->index,
 					  "queue is not configured");
-	if (attr->egress)
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
-					  "queue action not supported for "
-					  "egress");
 	return 0;
 }
 
@@ -1664,7 +1665,7 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
  *   Size of the @p queues array.
  * @param[out] error
  *   On error, filled with a textual error description.
- * @param[out] queue
+ * @param[out] queue_idx
  *   On error, filled with an offending queue index in @p queues array.
  *
  * @return
@@ -1677,17 +1678,27 @@ mlx5_validate_rss_queues(struct rte_eth_dev *dev,
 {
 	const struct mlx5_priv *priv = dev->data->dev_private;
 	bool is_hairpin = false;
+	bool is_ext_rss = false;
 	uint32_t i;
 
 	for (i = 0; i != queues_n; ++i) {
-		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev,
-								   queues[i]);
+		struct mlx5_rxq_ctrl *rxq_ctrl;
 
+		if (mlx5_is_external_rxq(dev, queues[0])) {
+			is_ext_rss = true;
+			continue;
+		}
+		if (is_ext_rss) {
+			*error = "Combining external and regular RSS queues is not supported";
+			*queue_idx = i;
+			return -ENOTSUP;
+		}
 		if (queues[i] >= priv->rxqs_n) {
 			*error = "queue index out of range";
 			*queue_idx = i;
 			return -EINVAL;
 		}
+		rxq_ctrl = mlx5_rxq_ctrl_get(dev, queues[i]);
 		if (rxq_ctrl == NULL) {
 			*error =  "queue is not configured";
 			*queue_idx = i;
@@ -1782,7 +1793,7 @@ mlx5_validate_action_rss(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
 					  "L4 partial RSS requested but L4 RSS"
 					  " type not specified");
-	if (!priv->rxqs_n)
+	if (!priv->rxqs_n && priv->ext_rxqs == NULL)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  NULL, "No Rx queues configured");
drivers/net/mlx5/mlx5_rx.h +30 -0
index 1e191a5704..353c7c05b2 100644
@@ -18,6 +18,7 @@
 
 #include "mlx5.h"
 #include "mlx5_autoconf.h"
+#include "rte_pmd_mlx5.h"
 
 /* Support tunnel matching. */
 #define MLX5_FLOW_TUNNEL 10
@@ -218,8 +219,14 @@ uint32_t mlx5_rxq_deref(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_rxq_priv *mlx5_rxq_get(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_rxq_ctrl *mlx5_rxq_ctrl_get(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_rxq_data *mlx5_rxq_data_get(struct rte_eth_dev *dev, uint16_t idx);
+struct mlx5_external_rxq *mlx5_ext_rxq_ref(struct rte_eth_dev *dev,
+					   uint16_t idx);
+uint32_t mlx5_ext_rxq_deref(struct rte_eth_dev *dev, uint16_t idx);
+struct mlx5_external_rxq *mlx5_ext_rxq_get(struct rte_eth_dev *dev,
+					   uint16_t idx);
 int mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx);
 int mlx5_rxq_verify(struct rte_eth_dev *dev);
+int mlx5_ext_rxq_verify(struct rte_eth_dev *dev);
 int rxq_alloc_elts(struct mlx5_rxq_ctrl *rxq_ctrl);
 int mlx5_ind_table_obj_verify(struct rte_eth_dev *dev);
 struct mlx5_ind_table_obj *mlx5_ind_table_obj_get(struct rte_eth_dev *dev,
@@ -639,4 +646,27 @@ mlx5_mprq_enabled(struct rte_eth_dev *dev)
 	return n == n_ibv;
 }
 
+/**
+ * Check whether given RxQ is external.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ * @param queue_idx
+ *   Rx queue index.
+ *
+ * @return
+ *   True if is external RxQ, otherwise false.
+ */
+static __rte_always_inline bool
+mlx5_is_external_rxq(struct rte_eth_dev *dev, uint16_t queue_idx)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_external_rxq *rxq;
+
+	if (!priv->ext_rxqs || queue_idx < MLX5_EXTERNAL_RX_QUEUE_ID_MIN)
+		return false;
+	rxq = &priv->ext_rxqs[queue_idx - MLX5_EXTERNAL_RX_QUEUE_ID_MIN];
+	return __atomic_load_n(&rxq->refcnt, __ATOMIC_RELAXED);
+}
+
 #endif /* RTE_PMD_MLX5_RX_H_ */
drivers/net/mlx5/mlx5_rxq.c +110 -6

147 lines not on this page · raw message

Signature · 1 line
2.25.1
#6 lore raw

PATCH 6/6 app/testpmd: add test for external RxQ

In reply to Michael Baum

Add test for map and unmap external RxQs.
This patch adds to Testpmd app a runtime function to test the mapping API.

For insert mapping use this command:

testpmd> port (port_id) ext_rxq map (rte_queue_id) (hw_queue_id)

For insert mapping use this command:

testpmd> port (port_id) ext_rxq unmap (rte_queue_id)

---
 app/test-pmd/cmdline.c                      | 157 ++++++++++++++++++++
 app/test-pmd/meson.build                    |   3 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  16 ++
 3 files changed, 176 insertions(+)
app/test-pmd/cmdline.c +157 -0
index b4ba8da2b0..c0899ca6c5 100644
@@ -63,6 +63,9 @@
 #ifdef RTE_NET_BNXT
 #include <rte_pmd_bnxt.h>
 #endif
+#ifdef RTE_NET_MLX5
+#include <rte_pmd_mlx5.h>
+#endif
 #include "testpmd.h"
 #include "cmdline_mtr.h"
 #include "cmdline_tm.h"
@@ -911,6 +914,15 @@ static void cmd_help_long_parsed(void *parsed_result,
 
 			"port cleanup (port_id) txq (queue_id) (free_cnt)\n"
 			"    Cleanup txq mbufs for a specific Tx queue\n\n"
+
+#ifdef RTE_NET_MLX5
+			"port (port_id) ext_rxq map (rte_queue_id) (hw_queue_id)\n"
+			"    Map HW queue index (32 bit) to rte_flow queue"
+			" index (16 bit) for external RxQ\n\n"
+
+			"port (port_id) ext_rxq unmap (rte_queue_id)\n"
+			"    Unmap external Rx queue rte_flow index mapping\n\n"
+#endif
 		);
 	}
 
@@ -17806,6 +17818,147 @@ cmdline_parse_inst_t cmd_show_port_flow_transfer_proxy = {
 	}
 };
 
+#ifdef RTE_NET_MLX5
+
+/* Map HW queue index to rte queue index. */
+struct cmd_map_ext_rxq {
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t ext_rxq;
+	cmdline_fixed_string_t map;
+	uint16_t rte_queue_id;
+	uint32_t hw_queue_id;
+};
+
+cmdline_parse_token_string_t cmd_map_ext_rxq_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_map_ext_rxq, port, "port");
+cmdline_parse_token_num_t cmd_map_ext_rxq_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_map_ext_rxq, port_id, RTE_UINT16);
+cmdline_parse_token_string_t cmd_map_ext_rxq_ext_rxq =
+	TOKEN_STRING_INITIALIZER(struct cmd_map_ext_rxq, ext_rxq, "ext_rxq");
+cmdline_parse_token_string_t cmd_map_ext_rxq_map =
+	TOKEN_STRING_INITIALIZER(struct cmd_map_ext_rxq, map, "map");
+cmdline_parse_token_num_t cmd_map_ext_rxq_rte_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_map_ext_rxq, rte_queue_id, RTE_UINT16);
+cmdline_parse_token_num_t cmd_map_ext_rxq_hw_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_map_ext_rxq, hw_queue_id, RTE_UINT32);
+
+static void
+cmd_map_ext_rxq_parsed(void *parsed_result,
+		       __rte_unused struct cmdline *cl,
+		       __rte_unused void *data)
+{
+	struct cmd_map_ext_rxq *res = parsed_result;
+	int ret;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+	ret = rte_pmd_mlx5_external_rx_queue_id_map(res->port_id,
+						    res->rte_queue_id,
+						    res->hw_queue_id);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		fprintf(stderr, "invalid rte_flow index (%u), out of range\n",
+			res->rte_queue_id);
+		break;
+	case -ENODEV:
+		fprintf(stderr, "invalid port_id %u\n", res->port_id);
+		break;
+	case -ENOTSUP:
+		fprintf(stderr, "function not implemented or supported\n");
+		break;
+	case -EEXIST:
+		fprintf(stderr, "mapping with index %u already exists\n",
+			res->rte_queue_id);
+		break;
+	default:
+		fprintf(stderr, "programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_map_ext_rxq = {
+	.f = cmd_map_ext_rxq_parsed,
+	.data = NULL,
+	.help_str = "port <port_id> ext_rxq map <rte_queue_id> <hw_queue_id>",
+	.tokens = {
+		(void *)&cmd_map_ext_rxq_port,
+		(void *)&cmd_map_ext_rxq_port_id,
+		(void *)&cmd_map_ext_rxq_ext_rxq,
+		(void *)&cmd_map_ext_rxq_map,
+		(void *)&cmd_map_ext_rxq_rte_queue_id,
+		(void *)&cmd_map_ext_rxq_hw_queue_id,
+		NULL,
+	}
+};
+
+/* Unmap HW queue index to rte queue index. */
+struct cmd_unmap_ext_rxq {
+	cmdline_fixed_string_t port;
+	portid_t port_id;
+	cmdline_fixed_string_t ext_rxq;
+	cmdline_fixed_string_t unmap;
+	uint16_t queue_id;
+};
+
+cmdline_parse_token_string_t cmd_unmap_ext_rxq_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_unmap_ext_rxq, port, "port");
+cmdline_parse_token_num_t cmd_unmap_ext_rxq_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_unmap_ext_rxq, port_id, RTE_UINT16);
+cmdline_parse_token_string_t cmd_unmap_ext_rxq_ext_rxq =
+	TOKEN_STRING_INITIALIZER(struct cmd_unmap_ext_rxq, ext_rxq, "ext_rxq");
+cmdline_parse_token_string_t cmd_unmap_ext_rxq_unmap =
+	TOKEN_STRING_INITIALIZER(struct cmd_unmap_ext_rxq, unmap, "unmap");
+cmdline_parse_token_num_t cmd_unmap_ext_rxq_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_unmap_ext_rxq, queue_id, RTE_UINT16);
+
+static void
+cmd_unmap_ext_rxq_parsed(void *parsed_result,
+			 __rte_unused struct cmdline *cl,
+			 __rte_unused void *data)
+{
+	struct cmd_unmap_ext_rxq *res = parsed_result;
+	int ret;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+	ret = rte_pmd_mlx5_external_rx_queue_id_unmap(res->port_id,
+						      res->queue_id);
+	switch (ret) {
+	case 0:
+		break;
+	case -EINVAL:
+		fprintf(stderr, "invalid rte_flow index (%u), "
+			"out of range or doesn't exist\n", res->queue_id);
+		break;
+	case -ENODEV:
+		fprintf(stderr, "invalid port_id %u\n", res->port_id);
+		break;
+	case -ENOTSUP:
+		fprintf(stderr, "function not implemented or supported\n");
+		break;
+	default:
+		fprintf(stderr, "programming error: (%s)\n", strerror(-ret));
+	}
+}
+
+cmdline_parse_inst_t cmd_unmap_ext_rxq = {
+	.f = cmd_unmap_ext_rxq_parsed,
+	.data = NULL,
+	.help_str = "port <port_id> ext_rxq unmap <queue_id>",
+	.tokens = {
+		(void *)&cmd_unmap_ext_rxq_port,
+		(void *)&cmd_unmap_ext_rxq_port_id,
+		(void *)&cmd_unmap_ext_rxq_ext_rxq,
+		(void *)&cmd_unmap_ext_rxq_unmap,
+		(void *)&cmd_unmap_ext_rxq_queue_id,
+		NULL,
+	}
+};
+
+#endif /* RTE_NET_MLX5 */
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -18092,6 +18245,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_show_capability,
 	(cmdline_parse_inst_t *)&cmd_set_flex_is_pattern,
 	(cmdline_parse_inst_t *)&cmd_set_flex_spec_pattern,
+#ifdef RTE_NET_MLX5
+	(cmdline_parse_inst_t *)&cmd_map_ext_rxq,
+	(cmdline_parse_inst_t *)&cmd_unmap_ext_rxq,
+#endif
 	NULL,
 };
 
app/test-pmd/meson.build +3 -0
index 43130c8856..c4fd379e67 100644
@@ -73,3 +73,6 @@ endif
 if dpdk_conf.has('RTE_NET_DPAA')
     deps += ['bus_dpaa', 'mempool_dpaa', 'net_dpaa']
 endif
+if dpdk_conf.has('RTE_NET_MLX5')
+    deps += 'net_mlx5'
+endif
doc/guides/testpmd_app_ug/testpmd_funcs.rst +16 -0
index 9cc248084f..613d281923 100644
@@ -2462,6 +2462,22 @@ To cleanup txq mbufs currently cached by driver::
 
 If the value of ``free_cnt`` is 0, driver should free all cached mbufs.
 
+port map external RxQ
+~~~~~~~~~~~~~~~~~~~~~
+
+Map HW queue index (32 bit) to rte_flow queue index (16 bit) for external RxQ::
+
+   testpmd> port (port_id) ext_rxq map (rte_queue_id) (hw_queue_id)
+
+Unmap external Rx queue rte_flow index mapping::
+
+   testpmd> port (port_id) ext_rxq unmap (rte_queue_id)
+
+where:
+
+* ``rte_queue_id``: queue index in reage [64536, 65535].
+* ``hw_queue_id``: queue index given by HW in queue creation.
+
 Device Functions
 ----------------
 
Signature · 1 line
2.25.1
#7 lore raw

v2 cover mlx5: external RxQ support

In reply to Michael Baum

These patches add support to external Rx queues.
External queue is a queue that is managed by a process external to PMD, but uses PMD process to generate its flow rules.

For the hardware to allow the DPDK process to set rules for it, the process needs to use the same PD of the external process. In addition, the indexes of the queues in hardware are represented by 32-bit compared to the rte_flow indexes represented by 16-bit, so the processes need to share some mapping between the indexes.

These patches allow the external process to provide devargs which enable importing its context and PD, instead of prepare new ones. In addition, an API is provided for mapping for the indexes of the queues.

v2:
- Rebase.
- Add ABI exception for common/mlx5 library.
- Correct DevX flag updating.
- Improve explanations in doc and comments.
- Remove teatpmd part.

Michael Baum (6):
common/mlx5: consider local functions as internal common/mlx5: glue device and PD importation common/mlx5: add remote PD and CTX support net/mlx5: optimize RxQ/TxQ control structure net/mlx5: add external RxQ mapping API net/mlx5: support queue/RSS action for external RxQ

 devtools/libabigail.abignore                 |   4 +
 doc/guides/nics/mlx5.rst                     |   1 +
 doc/guides/platform/mlx5.rst                 |  37 ++-
 doc/guides/rel_notes/release_22_03.rst       |   1 +
 drivers/common/mlx5/linux/meson.build        |   2 +
 drivers/common/mlx5/linux/mlx5_common_os.c   | 196 ++++++++++++--
 drivers/common/mlx5/linux/mlx5_common_os.h   |   7 +-
 drivers/common/mlx5/linux/mlx5_glue.c        |  41 +++
 drivers/common/mlx5/linux/mlx5_glue.h        |   4 +
 drivers/common/mlx5/mlx5_common.c            |  64 ++++-
 drivers/common/mlx5/mlx5_common.h            |  23 +-
 drivers/common/mlx5/version.map              |   3 +
 drivers/common/mlx5/windows/mlx5_common_os.c |  37 ++-
 drivers/common/mlx5/windows/mlx5_common_os.h |   1 -
 drivers/net/mlx5/linux/mlx5_os.c             |  18 ++
 drivers/net/mlx5/mlx5.c                      |   6 +
 drivers/net/mlx5/mlx5.h                      |   1 +
 drivers/net/mlx5/mlx5_defs.h                 |   3 +
 drivers/net/mlx5/mlx5_devx.c                 |  52 ++--
 drivers/net/mlx5/mlx5_ethdev.c               |  18 +-
 drivers/net/mlx5/mlx5_flow.c                 |  43 ++--
 drivers/net/mlx5/mlx5_flow_dv.c              |  14 +-
 drivers/net/mlx5/mlx5_rx.h                   |  49 +++-
 drivers/net/mlx5/mlx5_rxq.c                  | 258 +++++++++++++++++--
 drivers/net/mlx5/mlx5_trigger.c              |  36 +--
 drivers/net/mlx5/mlx5_tx.h                   |   7 +-
 drivers/net/mlx5/mlx5_txq.c                  |  14 +-
 drivers/net/mlx5/rte_pmd_mlx5.h              |  50 +++-
 drivers/net/mlx5/version.map                 |   3 +
 29 files changed, 821 insertions(+), 172 deletions(-)
Signature · 1 line
2.25.1
#8 lore raw

PATCH v2 1/6 common/mlx5: consider local functions as internal

The functions which are not explicitly marked as internal were exported because the local catch-all rule was missing in the version script.
After adding the missing rule, all local functions are hidden. The function mlx5_get_device_guid is used in another library, so it needs to be exported (as internal).

Because the local functions were exported as non-internal in DPDK 21.11, any change in these functions would break the ABI. An ABI exception is added for this library, considering that all functions are either local or internal.

---
 devtools/libabigail.abignore               | 4 ++++
 drivers/common/mlx5/linux/mlx5_common_os.h | 1 +
 drivers/common/mlx5/version.map            | 3 +++
 3 files changed, 8 insertions(+)
devtools/libabigail.abignore +4 -0
index ef0602975a..78d57497e6 100644
@@ -20,3 +20,7 @@
 ; Ignore changes to rte_crypto_asym_op, asymmetric crypto API is experimental
 [suppress_type]
         name = rte_crypto_asym_op
+
+; Ignore changes in common mlx5 driver, should be all internal
+[suppress_file]
+        soname_regexp = ^librte_common_mlx5\.
\ No newline at end of file
drivers/common/mlx5/linux/mlx5_common_os.h +1 -0
index 83066e752d..edf356a30a 100644
@@ -300,6 +300,7 @@ mlx5_set_context_attr(struct rte_device *dev, struct ibv_context *ctx);
  *  0 if OFED doesn't support.
  *  >0 if success.
  */
+__rte_internal
 int
 mlx5_get_device_guid(const struct rte_pci_addr *dev, uint8_t *guid, size_t len);
 
drivers/common/mlx5/version.map +3 -0
index 1c6153c576..cb20a7d893 100644
@@ -80,6 +80,7 @@ INTERNAL {
 
 	mlx5_free;
 
+	mlx5_get_device_guid; # WINDOWS_NO_EXPORT
 	mlx5_get_ifname_sysfs; # WINDOWS_NO_EXPORT
 	mlx5_get_pci_addr; # WINDOWS_NO_EXPORT
 
@@ -149,4 +150,6 @@ INTERNAL {
 	mlx5_mp_req_mempool_reg;
 	mlx5_mr_mempool2mr_bh;
 	mlx5_mr_mempool_populate_cache;
+
+	local: *;
 };
Signature · 1 line
2.25.1
#9 lore raw

PATCH v2 2/6 common/mlx5: glue device and PD importation

In reply to Michael Baum

Add support for rdma-core API to import device.
The API gets ibv_context file descriptor and returns an ibv_context pointer that is associated with the given file descriptor. Add also support for rdma-core API to import PD.
The API gets ibv_context and PD handle and returns a protection domain (PD) that is associated with the given handle in the given context.

---
 drivers/common/mlx5/linux/meson.build |  2 ++
 drivers/common/mlx5/linux/mlx5_glue.c | 41 +++++++++++++++++++++++++++
 drivers/common/mlx5/linux/mlx5_glue.h |  4 +++
 3 files changed, 47 insertions(+)
drivers/common/mlx5/linux/meson.build +2 -0
index 4c7b53b9bd..ed48245c67 100644
@@ -202,6 +202,8 @@ has_sym_args = [
             'mlx5dv_dr_domain_allow_duplicate_rules' ],
         [ 'HAVE_MLX5_IBV_REG_MR_IOVA', 'infiniband/verbs.h',
             'ibv_reg_mr_iova' ],
+        [ 'HAVE_MLX5_IBV_IMPORT_CTX_PD_AND_MR', 'infiniband/verbs.h',
+            'ibv_import_device' ],
 ]
 config = configuration_data()
 foreach arg:has_sym_args
drivers/common/mlx5/linux/mlx5_glue.c +41 -0

62 lines not on this page · raw message

drivers/common/mlx5/linux/mlx5_glue.h +4 -0
index 4e6d31f263..c4903a6dce 100644
@@ -151,9 +151,13 @@ struct mlx5_glue {
 	int (*fork_init)(void);
 	struct ibv_pd *(*alloc_pd)(struct ibv_context *context);
 	int (*dealloc_pd)(struct ibv_pd *pd);
+	struct ibv_pd *(*import_pd)(struct ibv_context *context,
+				    uint32_t pd_handle);
+	int (*unimport_pd)(struct ibv_pd *pd);
 	struct ibv_device **(*get_device_list)(int *num_devices);
 	void (*free_device_list)(struct ibv_device **list);
 	struct ibv_context *(*open_device)(struct ibv_device *device);
+	struct ibv_context *(*import_device)(int cmd_fd);
 	int (*close_device)(struct ibv_context *context);
 	int (*query_device)(struct ibv_context *context,
 			    struct ibv_device_attr *device_attr);
Signature · 1 line
2.25.1
#10 lore raw

PATCH v2 3/6 common/mlx5: add remote PD and CTX support

In reply to Michael Baum

Add option to probe common device using import CTX/PD functions instead of create functions.
This option requires accepting the context FD and the PD handle as devargs.

This sharing can be useful for applications that use PMD for only some operations. For example, an app that generates queues itself and uses PMD just to configure flow rules.

---
 doc/guides/platform/mlx5.rst                 |  37 +++-
 drivers/common/mlx5/linux/mlx5_common_os.c   | 196 ++++++++++++++++---
 drivers/common/mlx5/linux/mlx5_common_os.h   |   6 -
 drivers/common/mlx5/mlx5_common.c            |  64 ++++--
 drivers/common/mlx5/mlx5_common.h            |  23 ++-
 drivers/common/mlx5/windows/mlx5_common_os.c |  37 +++-
 drivers/common/mlx5/windows/mlx5_common_os.h |   1 -
 7 files changed, 313 insertions(+), 51 deletions(-)
doc/guides/platform/mlx5.rst +36 -1
index d073c213ca..d2ed094357 100644
@@ -81,6 +81,12 @@ Limitations
 - On Windows, only ``eth`` and ``crypto`` are supported.
 
 
+Features
+--------
+
+- Remote PD and CTX - Linux only.
+
+
 .. _mlx5_common_compilation:
 
 Compilation Prerequisites
@@ -638,4 +644,33 @@ and below are the arguments supported by the common mlx5 layer.
 
   If ``sq_db_nc`` is omitted, the preset (if any) environment variable
   "MLX5_SHUT_UP_BF" value is used. If there is no "MLX5_SHUT_UP_BF", the
-  default ``sq_db_nc`` value is zero for ARM64 hosts and one for others.
\ No newline at end of file
+  default ``sq_db_nc`` value is zero for ARM64 hosts and one for others.
+
+- ``cmd_fd`` parameter [int]
+
+  File descriptor of ibv_context created outside the PMD.
+  PMD will use this FD to import remote CTX. The ``cmd_fd`` is obtained from
+  the ibv_context cmd_fd member, which must be dup'd before being passed.
+  This parameter is valid only if ``pd_handle`` parameter is specified.
+
+  By default, the PMD will ignore this parameter and create a new ibv_context.
+
+  .. note::
+
+     When FD comes from another process, it is on the user responsibility to
+     share the FD between the processes (e.g. by SCM_RIGHTS).
+
+- ``pd_handle`` parameter [int]
+
+  Protection domain handle of ibv_pd created outside the PMD.
+  PMD will use this handle to import remote PD. The ``pd_handle`` can be
+  achieved from the original PD by getting its ibv_pd->handle member value.
+  This parameter is valid only if ``cmd_fd`` parameter is specified, and its
+  value must be a valid kernel handle for a PD object in the context represented
+  by given ``cmd_fd``.
+
+  By default, the PMD will ignore this parameter and allocate a new PD.
+
+  .. note::
+
+     The ibv_pd->handle member is different then mlx5dv_pd->pdn member.
\ No newline at end of file
drivers/common/mlx5/linux/mlx5_common_os.c +174 -22

273 lines not on this page · raw message

drivers/common/mlx5/linux/mlx5_common_os.h +0 -6
index edf356a30a..a85f3b5f3c 100644
@@ -203,12 +203,6 @@ mlx5_os_get_devx_uar_page_id(void *uar)
 #endif
 }
 
-static inline int
-mlx5_os_dealloc_pd(void *pd)
-{
-	return mlx5_glue->dealloc_pd(pd);
-}
-
 __rte_internal
 static inline void *
 mlx5_os_umem_reg(void *ctx, void *addr, size_t size, uint32_t access)
drivers/common/mlx5/mlx5_common.c +50 -14

114 lines not on this page · raw message

drivers/common/mlx5/mlx5_common.h +22 -1
index 49bcea1d91..451cdb4fad 100644
@@ -446,6 +446,8 @@ void mlx5_common_init(void);
 struct mlx5_common_dev_config {
 	struct mlx5_hca_attr hca_attr; /* HCA attributes. */
 	int dbnc; /* Skip doorbell register write barrier. */
+	int device_fd; /* Device file descriptor for importation. */
+	int pd_handle; /* Protection Domain handle for importation.  */
 	unsigned int devx:1; /* Whether devx interface is available or not. */
 	unsigned int sys_mem_en:1; /* The default memory allocator. */
 	unsigned int mr_mempool_reg_en:1;
@@ -465,6 +467,23 @@ struct mlx5_common_device {
 	struct mlx5_common_dev_config config; /* Device configuration. */
 };
 
+/**
+ * Indicates whether PD and CTX are imported from another process,
+ * or created by this process.
+ *
+ * @param cdev
+ *   Pointer to common device.
+ *
+ * @return
+ *   True if PD and CTX are imported from another process, False otherwise.
+ */
+static inline bool
+mlx5_imported_pd_and_ctx(struct mlx5_common_device *cdev)
+{
+	return (cdev->config.device_fd != MLX5_ARG_UNSET &&
+		cdev->config.pd_handle != MLX5_ARG_UNSET);
+}
+
 /**
  * Initialization function for the driver called during device probing.
  */
@@ -554,7 +573,9 @@ mlx5_devx_uar_release(struct mlx5_uar *uar);
 /* mlx5_common_os.c */
 
 int mlx5_os_open_device(struct mlx5_common_device *cdev, uint32_t classes);
-int mlx5_os_pd_create(struct mlx5_common_device *cdev);
+int mlx5_os_pd_prepare(struct mlx5_common_device *cdev);
+int mlx5_os_pd_release(struct mlx5_common_device *cdev);
+int mlx5_os_remote_pd_and_ctx_validate(struct mlx5_common_dev_config *config);
 
 /* mlx5 PMD wrapped MR struct. */
 struct mlx5_pmd_wrapped_mr {
drivers/common/mlx5/windows/mlx5_common_os.c +31 -6
index c3cfc315f2..f2fc7cd494 100644
@@ -25,21 +25,46 @@ mlx5_glue_constructor(void)
 {
 }
 
+/**
+ * Validate user arguments for remote PD and CTX.
+ *
+ * @param config
+ *   Pointer to device configuration structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_os_remote_pd_and_ctx_validate(struct mlx5_common_dev_config *config)
+{
+	int device_fd = config->device_fd;
+	int pd_handle = config->pd_handle;
+
+	if (pd_handle != MLX5_ARG_UNSET || device_fd != MLX5_ARG_UNSET) {
+		DRV_LOG(ERR, "Remote PD and CTX is not supported on Windows.");
+		rte_errno = ENOTSUP;
+		return -rte_errno;
+	}
+	return 0;
+}
+
 /**
  * Release PD. Releases a given mlx5_pd object
  *
- * @param[in] pd
- *   Pointer to mlx5_pd.
+ * @param[in] cdev
+ *   Pointer to the mlx5 device.
  *
  * @return
  *   Zero if pd is released successfully, negative number otherwise.
  */
 int
-mlx5_os_dealloc_pd(void *pd)
+mlx5_os_pd_release(struct mlx5_common_device *cdev)
 {
+	struct mlx5_pd *pd = cdev->pd;
+
 	if (!pd)
 		return -EINVAL;
-	mlx5_devx_cmd_destroy(((struct mlx5_pd *)pd)->obj);
+	mlx5_devx_cmd_destroy(pd->obj);
 	mlx5_free(pd);
 	return 0;
 }
@@ -47,14 +72,14 @@ mlx5_os_dealloc_pd(void *pd)
 /**
  * Allocate Protection Domain object and extract its pdn using DV API.
  *
- * @param[out] dev
+ * @param[out] cdev
  *   Pointer to the mlx5 device.
  *
  * @return
  *   0 on success, a negative value otherwise.
  */
 int
-mlx5_os_pd_create(struct mlx5_common_device *cdev)
+mlx5_os_pd_prepare(struct mlx5_common_device *cdev)
 {
 	struct mlx5_pd *pd;
 
drivers/common/mlx5/windows/mlx5_common_os.h +0 -1
index 61fc8dd761..ee7973f1ec 100644
@@ -248,7 +248,6 @@ mlx5_os_devx_subscribe_devx_event(void *eventc,
 	return -ENOTSUP;
 }
 
-int mlx5_os_dealloc_pd(void *pd);
 __rte_internal
 void *mlx5_os_umem_reg(void *ctx, void *addr, size_t size, uint32_t access);
 __rte_internal
Signature · 1 line
2.25.1
#11 lore raw

PATCH v2 4/6 net/mlx5: optimize RxQ/TxQ control structure

In reply to Michael Baum

The RxQ/TxQ control structure has a field named type. This type is enum with values for standard and hairpin.
The use of this field is to check whether the queue is of the hairpin type or standard.

This patch replaces it with a boolean variable that saves whether it is a hairpin.

---
 drivers/net/mlx5/mlx5_devx.c    | 26 ++++++++++--------------
 drivers/net/mlx5/mlx5_ethdev.c  |  2 +-
 drivers/net/mlx5/mlx5_flow.c    | 14 ++++++-------
 drivers/net/mlx5/mlx5_flow_dv.c | 14 +++++--------
 drivers/net/mlx5/mlx5_rx.h      | 13 +++---------
 drivers/net/mlx5/mlx5_rxq.c     | 33 +++++++++++-------------------
 drivers/net/mlx5/mlx5_trigger.c | 36 ++++++++++++++++-----------------
 drivers/net/mlx5/mlx5_tx.h      |  7 +------
 drivers/net/mlx5/mlx5_txq.c     | 14 ++++++-------
 9 files changed, 64 insertions(+), 95 deletions(-)
drivers/net/mlx5/mlx5_devx.c +11 -15
index a9b8c2a1b7..e4bc90a30e 100644
@@ -88,7 +88,7 @@ mlx5_devx_modify_rq(struct mlx5_rxq_priv *rxq, uint8_t type)
 	default:
 		break;
 	}
-	if (rxq->ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
+	if (rxq->ctrl->is_hairpin)
 		return mlx5_devx_cmd_modify_rq(rxq->ctrl->obj->rq, &rq_attr);
 	return mlx5_devx_cmd_modify_rq(rxq->devx_rq.rq, &rq_attr);
 }
@@ -162,7 +162,7 @@ mlx5_rxq_devx_obj_release(struct mlx5_rxq_priv *rxq)
 
 	if (rxq_obj == NULL)
 		return;
-	if (rxq_obj->rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN) {
+	if (rxq_obj->rxq_ctrl->is_hairpin) {
 		if (rxq_obj->rq == NULL)
 			return;
 		mlx5_devx_modify_rq(rxq, MLX5_RXQ_MOD_RDY2RST);
@@ -476,7 +476,7 @@ mlx5_rxq_devx_obj_new(struct mlx5_rxq_priv *rxq)
 
 	MLX5_ASSERT(rxq_data);
 	MLX5_ASSERT(tmpl);
-	if (rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
+	if (rxq_ctrl->is_hairpin)
 		return mlx5_rxq_obj_hairpin_new(rxq);
 	tmpl->rxq_ctrl = rxq_ctrl;
 	if (rxq_ctrl->irq && !rxq_ctrl->started) {
@@ -583,7 +583,7 @@ mlx5_devx_ind_table_create_rqt_attr(struct rte_eth_dev *dev,
 		struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, queues[i]);
 
 		MLX5_ASSERT(rxq != NULL);
-		if (rxq->ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
+		if (rxq->ctrl->is_hairpin)
 			rqt_attr->rq_list[i] = rxq->ctrl->obj->rq->id;
 		else
 			rqt_attr->rq_list[i] = rxq->devx_rq.rq->id;
@@ -706,17 +706,13 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 		       int tunnel, struct mlx5_devx_tir_attr *tir_attr)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	enum mlx5_rxq_type rxq_obj_type;
+	bool is_hairpin;
 	bool lro = true;
 	uint32_t i;
 
 	/* NULL queues designate drop queue. */
 	if (ind_tbl->queues != NULL) {
-		struct mlx5_rxq_ctrl *rxq_ctrl =
-				mlx5_rxq_ctrl_get(dev, ind_tbl->queues[0]);
-		rxq_obj_type = rxq_ctrl != NULL ? rxq_ctrl->type :
-						  MLX5_RXQ_TYPE_STANDARD;
-
+		is_hairpin = mlx5_rxq_is_hairpin(dev, ind_tbl->queues[0]);
 		/* Enable TIR LRO only if all the queues were configured for. */
 		for (i = 0; i < ind_tbl->queues_n; ++i) {
 			struct mlx5_rxq_data *rxq_i =
@@ -728,7 +724,7 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			}
 		}
 	} else {
-		rxq_obj_type = priv->drop_queue.rxq->ctrl->type;
+		is_hairpin = priv->drop_queue.rxq->ctrl->is_hairpin;
 	}
 	memset(tir_attr, 0, sizeof(*tir_attr));
 	tir_attr->disp_type = MLX5_TIRC_DISP_TYPE_INDIRECT;
@@ -759,7 +755,7 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			(!!(hash_fields & MLX5_L4_DST_IBV_RX_HASH)) <<
 			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT;
 	}
-	if (rxq_obj_type == MLX5_RXQ_TYPE_HAIRPIN)
+	if (is_hairpin)
 		tir_attr->transport_domain = priv->sh->td->id;
 	else
 		tir_attr->transport_domain = priv->sh->tdn;
@@ -932,7 +928,7 @@ mlx5_rxq_devx_obj_drop_create(struct rte_eth_dev *dev)
 		goto error;
 	}
 	rxq_obj->rxq_ctrl = rxq_ctrl;
-	rxq_ctrl->type = MLX5_RXQ_TYPE_STANDARD;
+	rxq_ctrl->is_hairpin = false;
 	rxq_ctrl->sh = priv->sh;
 	rxq_ctrl->obj = rxq_obj;
 	rxq->ctrl = rxq_ctrl;
@@ -1232,7 +1228,7 @@ mlx5_txq_devx_obj_new(struct rte_eth_dev *dev, uint16_t idx)
 	struct mlx5_txq_ctrl *txq_ctrl =
 			container_of(txq_data, struct mlx5_txq_ctrl, txq);
 
-	if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN)
+	if (txq_ctrl->is_hairpin)
 		return mlx5_txq_obj_hairpin_new(dev, idx);
 #if !defined(HAVE_MLX5DV_DEVX_UAR_OFFSET) && defined(HAVE_INFINIBAND_VERBS_H)
 	DRV_LOG(ERR, "Port %u Tx queue %u cannot create with DevX, no UAR.",
@@ -1371,7 +1367,7 @@ void
 mlx5_txq_devx_obj_release(struct mlx5_txq_obj *txq_obj)
 {
 	MLX5_ASSERT(txq_obj);
-	if (txq_obj->txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) {
+	if (txq_obj->txq_ctrl->is_hairpin) {
 		if (txq_obj->tis)
 			claim_zero(mlx5_devx_cmd_destroy(txq_obj->tis));
 #if defined(HAVE_MLX5DV_DEVX_UAR_OFFSET) || !defined(HAVE_INFINIBAND_VERBS_H)
drivers/net/mlx5/mlx5_ethdev.c +1 -1
index 72bf8ac914..406761ccf8 100644
@@ -173,7 +173,7 @@ mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev)
 	for (i = 0, j = 0; i < rxqs_n; i++) {
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 
-		if (rxq_ctrl && rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl && !rxq_ctrl->is_hairpin)
 			rss_queue_arr[j++] = i;
 	}
 	rss_queue_n = j;
drivers/net/mlx5/mlx5_flow.c +6 -8
index a87ac8e6d7..58f0aba294 100644
@@ -1676,7 +1676,7 @@ mlx5_validate_rss_queues(struct rte_eth_dev *dev,
 			 const char **error, uint32_t *queue_idx)
 {
 	const struct mlx5_priv *priv = dev->data->dev_private;
-	enum mlx5_rxq_type rxq_type = MLX5_RXQ_TYPE_UNDEFINED;
+	bool is_hairpin = false;
 	uint32_t i;
 
 	for (i = 0; i != queues_n; ++i) {
@@ -1693,9 +1693,9 @@ mlx5_validate_rss_queues(struct rte_eth_dev *dev,
 			*queue_idx = i;
 			return -EINVAL;
 		}
-		if (i == 0)
-			rxq_type = rxq_ctrl->type;
-		if (rxq_type != rxq_ctrl->type) {
+		if (i == 0 && rxq_ctrl->is_hairpin)
+			is_hairpin = true;
+		if (is_hairpin != rxq_ctrl->is_hairpin) {
 			*error = "combining hairpin and regular RSS queues is not supported";
 			*queue_idx = i;
 			return -ENOTSUP;
@@ -5767,15 +5767,13 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
 			const struct rte_flow_action_queue *queue;
 
 			queue = qrss->conf;
-			if (mlx5_rxq_get_type(dev, queue->index) ==
-			    MLX5_RXQ_TYPE_HAIRPIN)
+			if (mlx5_rxq_is_hairpin(dev, queue->index))
 				qrss = NULL;
 		} else if (qrss->type == RTE_FLOW_ACTION_TYPE_RSS) {
 			const struct rte_flow_action_rss *rss;
 
 			rss = qrss->conf;
-			if (mlx5_rxq_get_type(dev, rss->queue[0]) ==
-			    MLX5_RXQ_TYPE_HAIRPIN)
+			if (mlx5_rxq_is_hairpin(dev, rss->queue[0]))
 				qrss = NULL;
 		}
 	}
drivers/net/mlx5/mlx5_flow_dv.c +5 -9
index abd1c27538..c4cd5c894b 100644
@@ -5771,8 +5771,7 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
 	}
 	/* Continue validation for Xcap actions.*/
 	if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) &&
-	    (queue_index == 0xFFFF ||
-	     mlx5_rxq_get_type(dev, queue_index) != MLX5_RXQ_TYPE_HAIRPIN)) {
+	    (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index))) {
 		if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
 		     MLX5_FLOW_XCAP_ACTIONS)
 			return rte_flow_error_set(error, ENOTSUP,
@@ -7957,8 +7956,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 	 */
 	if ((action_flags & (MLX5_FLOW_XCAP_ACTIONS |
 			     MLX5_FLOW_VLAN_ACTIONS)) &&
-	    (queue_index == 0xFFFF ||
-	     mlx5_rxq_get_type(dev, queue_index) != MLX5_RXQ_TYPE_HAIRPIN ||
+	    (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index) ||
 	     ((conf = mlx5_rxq_get_hairpin_conf(dev, queue_index)) != NULL &&
 	     conf->tx_explicit != 0))) {
 		if ((action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
@@ -10948,10 +10946,8 @@ flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev,
 {
 	const struct mlx5_rte_flow_item_tx_queue *queue_m;
 	const struct mlx5_rte_flow_item_tx_queue *queue_v;
-	void *misc_m =
-		MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
-	void *misc_v =
-		MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+	void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+	void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
 	struct mlx5_txq_ctrl *txq;
 	uint32_t queue, mask;
 
@@ -10962,7 +10958,7 @@ flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev,
 	txq = mlx5_txq_get(dev, queue_v->queue);
 	if (!txq)
 		return;
-	if (txq->type == MLX5_TXQ_TYPE_HAIRPIN)
+	if (txq->is_hairpin)
 		queue = txq->obj->sq->id;
 	else
 		queue = txq->obj->sq_obj.sq->id;
drivers/net/mlx5/mlx5_rx.h +3 -10
index 38335fd744..1fdf4ff161 100644
@@ -141,12 +141,6 @@ struct mlx5_rxq_data {
 	/* Buffer split segment descriptions - sizes, offsets, pools. */
 } __rte_cache_aligned;
 
-enum mlx5_rxq_type {
-	MLX5_RXQ_TYPE_STANDARD, /* Standard Rx queue. */
-	MLX5_RXQ_TYPE_HAIRPIN, /* Hairpin Rx queue. */
-	MLX5_RXQ_TYPE_UNDEFINED,
-};
-
 /* RX queue control descriptor. */
 struct mlx5_rxq_ctrl {
 	struct mlx5_rxq_data rxq; /* Data path structure. */
@@ -154,7 +148,7 @@ struct mlx5_rxq_ctrl {
 	LIST_HEAD(priv, mlx5_rxq_priv) owners; /* Owner rxq list. */
 	struct mlx5_rxq_obj *obj; /* Verbs/DevX elements. */
 	struct mlx5_dev_ctx_shared *sh; /* Shared context. */
-	enum mlx5_rxq_type type; /* Rxq type. */
+	bool is_hairpin; /* Whether RxQ type is Hairpin. */
 	unsigned int socket; /* CPU socket ID for allocations. */
 	LIST_ENTRY(mlx5_rxq_ctrl) share_entry; /* Entry in shared RXQ list. */
 	uint32_t share_group; /* Group ID of shared RXQ. */
@@ -253,7 +247,7 @@ uint32_t mlx5_hrxq_get(struct rte_eth_dev *dev,
 		       struct mlx5_flow_rss_desc *rss_desc);
 int mlx5_hrxq_release(struct rte_eth_dev *dev, uint32_t hxrq_idx);
 uint32_t mlx5_hrxq_verify(struct rte_eth_dev *dev);
-enum mlx5_rxq_type mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx);
+bool mlx5_rxq_is_hairpin(struct rte_eth_dev *dev, uint16_t idx);
 const struct rte_eth_hairpin_conf *mlx5_rxq_get_hairpin_conf
 	(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_hrxq *mlx5_drop_action_create(struct rte_eth_dev *dev);
@@ -627,8 +621,7 @@ mlx5_mprq_enabled(struct rte_eth_dev *dev)
 	for (i = 0; i < priv->rxqs_n; ++i) {
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 
-		if (rxq_ctrl == NULL ||
-		    rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl == NULL || rxq_ctrl->is_hairpin)
 			continue;
 		n_ibv++;
 		if (mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq))
drivers/net/mlx5/mlx5_rxq.c +12 -21
index 809006f66a..796497ab1a 100644
@@ -1391,8 +1391,7 @@ mlx5_mprq_alloc_mp(struct rte_eth_dev *dev)
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 		struct mlx5_rxq_data *rxq;
 
-		if (rxq_ctrl == NULL ||
-		    rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl == NULL || rxq_ctrl->is_hairpin)
 			continue;
 		rxq = &rxq_ctrl->rxq;
 		n_ibv++;
@@ -1480,8 +1479,7 @@ mlx5_mprq_alloc_mp(struct rte_eth_dev *dev)
 	for (i = 0; i != priv->rxqs_n; ++i) {
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 
-		if (rxq_ctrl == NULL ||
-		    rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl == NULL || rxq_ctrl->is_hairpin)
 			continue;
 		rxq_ctrl->rxq.mprq_mp = mp;
 	}
@@ -1798,7 +1796,7 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 		rte_errno = ENOSPC;
 		goto error;
 	}
-	tmpl->type = MLX5_RXQ_TYPE_STANDARD;
+	tmpl->is_hairpin = false;
 	if (mlx5_mr_ctrl_init(&tmpl->rxq.mr_ctrl,
 			      &priv->sh->cdev->mr_scache.dev_gen, socket)) {
 		/* rte_errno is already set. */
@@ -1969,7 +1967,7 @@ mlx5_rxq_hairpin_new(struct rte_eth_dev *dev, struct mlx5_rxq_priv *rxq,
 	LIST_INIT(&tmpl->owners);
 	rxq->ctrl = tmpl;
 	LIST_INSERT_HEAD(&tmpl->owners, rxq, owner_entry);
-	tmpl->type = MLX5_RXQ_TYPE_HAIRPIN;
+	tmpl->is_hairpin = true;
 	tmpl->socket = SOCKET_ID_ANY;
 	tmpl->rxq.rss_hash = 0;
 	tmpl->rxq.port_id = dev->data->port_id;
@@ -2120,7 +2118,7 @@ mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx)
 			mlx5_free(rxq_ctrl->obj);
 			rxq_ctrl->obj = NULL;
 		}
-		if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) {
+		if (!rxq_ctrl->is_hairpin) {
 			if (!rxq_ctrl->started)
 				rxq_free_elts(rxq_ctrl);
 			dev->data->rx_queue_state[idx] =
@@ -2129,7 +2127,7 @@ mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx)
 	} else { /* Refcnt zero, closing device. */
 		LIST_REMOVE(rxq, owner_entry);
 		if (LIST_EMPTY(&rxq_ctrl->owners)) {
-			if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD)
+			if (!rxq_ctrl->is_hairpin)
 				mlx5_mr_btree_free
 					(&rxq_ctrl->rxq.mr_ctrl.cache_bh);
 			if (rxq_ctrl->rxq.shared)
@@ -2169,7 +2167,7 @@ mlx5_rxq_verify(struct rte_eth_dev *dev)
 }
 
 /**
- * Get a Rx queue type.
+ * Check whether RxQ type is Hairpin.
  *
  * @param dev
  *   Pointer to Ethernet device.
@@ -2177,17 +2175,15 @@ mlx5_rxq_verify(struct rte_eth_dev *dev)
  *   Rx queue index.
  *
  * @return
- *   The Rx queue type.
+ *   True if Rx queue type is Hairpin, otherwise False.
  */
-enum mlx5_rxq_type
-mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx)
+bool
+mlx5_rxq_is_hairpin(struct rte_eth_dev *dev, uint16_t idx)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, idx);
 
-	if (idx < priv->rxqs_n && rxq_ctrl != NULL)
-		return rxq_ctrl->type;
-	return MLX5_RXQ_TYPE_UNDEFINED;
+	return (idx < priv->rxqs_n && rxq_ctrl != NULL && rxq_ctrl->is_hairpin);
 }
 
 /*
@@ -2204,14 +2200,9 @@ mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx)
 const struct rte_eth_hairpin_conf *
 mlx5_rxq_get_hairpin_conf(struct rte_eth_dev *dev, uint16_t idx)
 {
-	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, idx);
 
-	if (idx < priv->rxqs_n && rxq != NULL) {
-		if (rxq->ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
-			return &rxq->hairpin_conf;
-	}
-	return NULL;
+	return mlx5_rxq_is_hairpin(dev, idx) ? &rxq->hairpin_conf : NULL;
 }
 
 /**
drivers/net/mlx5/mlx5_trigger.c +18 -18
index 74c3bc8a13..fe8b42c414 100644
@@ -59,7 +59,7 @@ mlx5_txq_start(struct rte_eth_dev *dev)
 
 		if (!txq_ctrl)
 			continue;
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD)
+		if (!txq_ctrl->is_hairpin)
 			txq_alloc_elts(txq_ctrl);
 		MLX5_ASSERT(!txq_ctrl->obj);
 		txq_ctrl->obj = mlx5_malloc(flags, sizeof(struct mlx5_txq_obj),
@@ -77,7 +77,7 @@ mlx5_txq_start(struct rte_eth_dev *dev)
 			txq_ctrl->obj = NULL;
 			goto error;
 		}
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD) {
+		if (!txq_ctrl->is_hairpin) {
 			size_t size = txq_data->cqe_s * sizeof(*txq_data->fcqs);
 
 			txq_data->fcqs = mlx5_malloc(flags, size,
@@ -167,7 +167,7 @@ mlx5_rxq_ctrl_prepare(struct rte_eth_dev *dev, struct mlx5_rxq_ctrl *rxq_ctrl,
 {
 	int ret = 0;
 
-	if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) {
+	if (!rxq_ctrl->is_hairpin) {
 		/*
 		 * Pre-register the mempools. Regardless of whether
 		 * the implicit registration is enabled or not,
@@ -280,7 +280,7 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (!txq_ctrl)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN ||
+		if (!txq_ctrl->is_hairpin ||
 		    txq_ctrl->hairpin_conf.peers[0].port != self_port) {
 			mlx5_txq_release(dev, i);
 			continue;
@@ -299,7 +299,7 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev)
 		if (!txq_ctrl)
 			continue;
 		/* Skip hairpin queues with other peer ports. */
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN ||
+		if (!txq_ctrl->is_hairpin ||
 		    txq_ctrl->hairpin_conf.peers[0].port != self_port) {
 			mlx5_txq_release(dev, i);
 			continue;
@@ -322,7 +322,7 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev)
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN ||
+		if (!rxq_ctrl->is_hairpin ||
 		    rxq->hairpin_conf.peers[0].queue != i) {
 			rte_errno = ENOMEM;
 			DRV_LOG(ERR, "port %u Tx queue %d can't be binded to "
@@ -412,7 +412,7 @@ mlx5_hairpin_queue_peer_update(struct rte_eth_dev *dev, uint16_t peer_queue,
 				dev->data->port_id, peer_queue);
 			return -rte_errno;
 		}
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d is not a hairpin Txq",
 				dev->data->port_id, peer_queue);
@@ -444,7 +444,7 @@ mlx5_hairpin_queue_peer_update(struct rte_eth_dev *dev, uint16_t peer_queue,
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
+		if (!rxq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d is not a hairpin Rxq",
 				dev->data->port_id, peer_queue);
@@ -510,7 +510,7 @@ mlx5_hairpin_queue_peer_bind(struct rte_eth_dev *dev, uint16_t cur_queue,
 				dev->data->port_id, cur_queue);
 			return -rte_errno;
 		}
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Txq",
 				dev->data->port_id, cur_queue);
@@ -570,7 +570,7 @@ mlx5_hairpin_queue_peer_bind(struct rte_eth_dev *dev, uint16_t cur_queue,
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
+		if (!rxq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Rxq",
 				dev->data->port_id, cur_queue);
@@ -644,7 +644,7 @@ mlx5_hairpin_queue_peer_unbind(struct rte_eth_dev *dev, uint16_t cur_queue,
 				dev->data->port_id, cur_queue);
 			return -rte_errno;
 		}
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Txq",
 				dev->data->port_id, cur_queue);
@@ -683,7 +683,7 @@ mlx5_hairpin_queue_peer_unbind(struct rte_eth_dev *dev, uint16_t cur_queue,
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
+		if (!rxq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Rxq",
 				dev->data->port_id, cur_queue);
@@ -751,7 +751,7 @@ mlx5_hairpin_bind_single_port(struct rte_eth_dev *dev, uint16_t rx_port)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (txq_ctrl == NULL)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			mlx5_txq_release(dev, i);
 			continue;
 		}
@@ -791,7 +791,7 @@ mlx5_hairpin_bind_single_port(struct rte_eth_dev *dev, uint16_t rx_port)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (txq_ctrl == NULL)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			mlx5_txq_release(dev, i);
 			continue;
 		}
@@ -886,7 +886,7 @@ mlx5_hairpin_unbind_single_port(struct rte_eth_dev *dev, uint16_t rx_port)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (txq_ctrl == NULL)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			mlx5_txq_release(dev, i);
 			continue;
 		}
@@ -1016,7 +1016,7 @@ mlx5_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports,
 			txq_ctrl = mlx5_txq_get(dev, i);
 			if (!txq_ctrl)
 				continue;
-			if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+			if (!txq_ctrl->is_hairpin) {
 				mlx5_txq_release(dev, i);
 				continue;
 			}
@@ -1040,7 +1040,7 @@ mlx5_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports,
 			if (rxq == NULL)
 				continue;
 			rxq_ctrl = rxq->ctrl;
-			if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN)
+			if (!rxq_ctrl->is_hairpin)
 				continue;
 			pp = rxq->hairpin_conf.peers[0].port;
 			if (pp >= RTE_MAX_ETHPORTS) {
@@ -1318,7 +1318,7 @@ mlx5_traffic_enable(struct rte_eth_dev *dev)
 		if (!txq_ctrl)
 			continue;
 		/* Only Tx implicit mode requires the default Tx flow. */
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN &&
+		if (txq_ctrl->is_hairpin &&
 		    txq_ctrl->hairpin_conf.tx_explicit == 0 &&
 		    txq_ctrl->hairpin_conf.peers[0].port ==
 		    priv->dev_data->port_id) {
drivers/net/mlx5/mlx5_tx.h +1 -6
index 0adc3f4839..89dac0c65a 100644
@@ -169,17 +169,12 @@ struct mlx5_txq_data {
 	/* Storage for queued packets, must be the last field. */
 } __rte_cache_aligned;
 
-enum mlx5_txq_type {
-	MLX5_TXQ_TYPE_STANDARD, /* Standard Tx queue. */
-	MLX5_TXQ_TYPE_HAIRPIN, /* Hairpin Tx queue. */
-};
-
 /* TX queue control descriptor. */
 struct mlx5_txq_ctrl {
 	LIST_ENTRY(mlx5_txq_ctrl) next; /* Pointer to the next element. */
 	uint32_t refcnt; /* Reference counter. */
 	unsigned int socket; /* CPU socket ID for allocations. */
-	enum mlx5_txq_type type; /* The txq ctrl type. */
+	bool is_hairpin; /* Whether TxQ type is Hairpin. */
 	unsigned int max_inline_data; /* Max inline data. */
 	unsigned int max_tso_header; /* Max TSO header size. */
 	struct mlx5_txq_obj *obj; /* Verbs/DevX queue object. */
drivers/net/mlx5/mlx5_txq.c +7 -7
index f128c3d1a5..0140f8b3b2 100644
@@ -527,7 +527,7 @@ txq_uar_init_secondary(struct mlx5_txq_ctrl *txq_ctrl, int fd)
 		return -rte_errno;
 	}
 
-	if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
+	if (txq_ctrl->is_hairpin)
 		return 0;
 	MLX5_ASSERT(ppriv);
 	/*
@@ -570,7 +570,7 @@ txq_uar_uninit_secondary(struct mlx5_txq_ctrl *txq_ctrl)
 		rte_errno = ENOMEM;
 	}
 
-	if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
+	if (txq_ctrl->is_hairpin)
 		return;
 	addr = ppriv->uar_table[txq_ctrl->txq.idx].db;
 	rte_mem_unmap(RTE_PTR_ALIGN_FLOOR(addr, page_size), page_size);
@@ -631,7 +631,7 @@ mlx5_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd)
 			continue;
 		txq = (*priv->txqs)[i];
 		txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq);
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
+		if (txq_ctrl->is_hairpin)
 			continue;
 		MLX5_ASSERT(txq->idx == (uint16_t)i);
 		ret = txq_uar_init_secondary(txq_ctrl, fd);
@@ -1107,7 +1107,7 @@ mlx5_txq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 		goto error;
 	}
 	__atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED);
-	tmpl->type = MLX5_TXQ_TYPE_STANDARD;
+	tmpl->is_hairpin = false;
 	LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next);
 	return tmpl;
 error:
@@ -1150,7 +1150,7 @@ mlx5_txq_hairpin_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	tmpl->txq.port_id = dev->data->port_id;
 	tmpl->txq.idx = idx;
 	tmpl->hairpin_conf = *hairpin_conf;
-	tmpl->type = MLX5_TXQ_TYPE_HAIRPIN;
+	tmpl->is_hairpin = true;
 	__atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED);
 	LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next);
 	return tmpl;
@@ -1209,7 +1209,7 @@ mlx5_txq_release(struct rte_eth_dev *dev, uint16_t idx)
 		mlx5_free(txq_ctrl->obj);
 		txq_ctrl->obj = NULL;
 	}
-	if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD) {
+	if (!txq_ctrl->is_hairpin) {
 		if (txq_ctrl->txq.fcqs) {
 			mlx5_free(txq_ctrl->txq.fcqs);
 			txq_ctrl->txq.fcqs = NULL;
@@ -1218,7 +1218,7 @@ mlx5_txq_release(struct rte_eth_dev *dev, uint16_t idx)
 		dev->data->tx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED;
 	}
 	if (!__atomic_load_n(&txq_ctrl->refcnt, __ATOMIC_RELAXED)) {
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD)
+		if (!txq_ctrl->is_hairpin)
 			mlx5_mr_btree_free(&txq_ctrl->txq.mr_ctrl.cache_bh);
 		LIST_REMOVE(txq_ctrl, next);
 		mlx5_free(txq_ctrl);
Signature · 1 line
2.25.1
#12 lore raw

PATCH v2 5/6 net/mlx5: add external RxQ mapping API

In reply to Michael Baum

External queue is a queue that has been created and managed outside the PMD. The queues owner might use PMD to generate flow rules using these external queues.

When the queue is created in hardware it is given an ID represented by 32 bits. In contrast, the index of the queues in PMD is represented by 16 bits. To enable the use of PMD to generate flow rules, the queue owner must provide a mapping between the HW index and a 16-bit index corresponding to the RTE Flow API.

This patch adds an API enabling to insert/cancel a mapping between HW queue id and RTE Flow queue id.

---
 drivers/net/mlx5/linux/mlx5_os.c |  18 +++++
 drivers/net/mlx5/mlx5.c          |   2 +
 drivers/net/mlx5/mlx5.h          |   1 +
 drivers/net/mlx5/mlx5_defs.h     |   3 +
 drivers/net/mlx5/mlx5_ethdev.c   |  16 ++++-
 drivers/net/mlx5/mlx5_rx.h       |   6 ++
 drivers/net/mlx5/mlx5_rxq.c      | 109 +++++++++++++++++++++++++++++++
 drivers/net/mlx5/rte_pmd_mlx5.h  |  50 +++++++++++++-
 drivers/net/mlx5/version.map     |   3 +
 9 files changed, 204 insertions(+), 4 deletions(-)
drivers/net/mlx5/linux/mlx5_os.c +18 -0
index ecf823da56..058c140fe1 100644
@@ -1156,6 +1156,22 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		err = ENOMEM;
 		goto error;
 	}
+	/*
+	 * When user configures remote PD and CTX and device creates RxQ by
+	 * DevX, external RxQ is both supported and requested.
+	 */
+	if (mlx5_imported_pd_and_ctx(sh->cdev) && mlx5_devx_obj_ops_en(sh)) {
+		priv->ext_rxqs = mlx5_malloc(MLX5_MEM_ZERO | MLX5_MEM_RTE,
+					     sizeof(struct mlx5_external_rxq) *
+					     MLX5_MAX_EXT_RX_QUEUES, 0,
+					     SOCKET_ID_ANY);
+		if (priv->ext_rxqs == NULL) {
+			DRV_LOG(ERR, "Fail to allocate external RxQ array.");
+			err = ENOMEM;
+			goto error;
+		}
+		DRV_LOG(DEBUG, "External RxQ is supported.");
+	}
 	priv->sh = sh;
 	priv->dev_port = spawn->phys_port;
 	priv->pci_dev = spawn->pci_dev;
@@ -1613,6 +1629,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 			mlx5_list_destroy(priv->hrxqs);
 		if (eth_dev && priv->flex_item_map)
 			mlx5_flex_item_port_cleanup(eth_dev);
+		if (priv->ext_rxqs)
+			mlx5_free(priv->ext_rxqs);
 		mlx5_free(priv);
 		if (eth_dev != NULL)
 			eth_dev->data->dev_private = NULL;
drivers/net/mlx5/mlx5.c +2 -0
index 9f65a8f901..415e0fe2f2 100644
@@ -1855,6 +1855,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 		close(priv->nl_socket_rdma);
 	if (priv->vmwa_context)
 		mlx5_vlan_vmwa_exit(priv->vmwa_context);
+	if (priv->ext_rxqs)
+		mlx5_free(priv->ext_rxqs);
 	ret = mlx5_hrxq_verify(dev);
 	if (ret)
 		DRV_LOG(WARNING, "port %u some hash Rx queue still remain",
drivers/net/mlx5/mlx5.h +1 -0
index 0f465d0e9e..fa27f65a36 100644
@@ -1423,6 +1423,7 @@ struct mlx5_priv {
 	/* RX/TX queues. */
 	unsigned int rxqs_n; /* RX queues array size. */
 	unsigned int txqs_n; /* TX queues array size. */
+	struct mlx5_external_rxq *ext_rxqs; /* External RX queues array. */
 	struct mlx5_rxq_priv *(*rxq_privs)[]; /* RX queue non-shared data. */
 	struct mlx5_txq_data *(*txqs)[]; /* TX queues. */
 	struct rte_mempool *mprq_mp; /* Mempool for Multi-Packet RQ. */
drivers/net/mlx5/mlx5_defs.h +3 -0
index 2d48fde010..15728fb41f 100644
@@ -175,6 +175,9 @@
 /* Maximum number of indirect actions supported by rte_flow */
 #define MLX5_MAX_INDIRECT_ACTIONS 3
 
+/* Maximum number of external Rx queues supported by rte_flow */
+#define MLX5_MAX_EXT_RX_QUEUES (UINT16_MAX - MLX5_EXTERNAL_RX_QUEUE_ID_MIN + 1)
+
 /*
  * Linux definition of static_assert is found in /usr/include/assert.h.
  * Windows does not require a redefinition.
drivers/net/mlx5/mlx5_ethdev.c +13 -3
index 406761ccf8..de0ba2b1ff 100644
@@ -27,6 +27,7 @@
 #include "mlx5_tx.h"
 #include "mlx5_autoconf.h"
 #include "mlx5_devx.h"
+#include "rte_pmd_mlx5.h"
 
 /**
  * Get the interface index from device name.
@@ -81,9 +82,10 @@ mlx5_dev_configure(struct rte_eth_dev *dev)
 		rte_errno = EINVAL;
 		return -rte_errno;
 	}
-	priv->rss_conf.rss_key =
-		mlx5_realloc(priv->rss_conf.rss_key, MLX5_MEM_RTE,
-			    MLX5_RSS_HASH_KEY_LEN, 0, SOCKET_ID_ANY);
+	priv->rss_conf.rss_key = mlx5_realloc(priv->rss_conf.rss_key,
+					      MLX5_MEM_RTE,
+					      MLX5_RSS_HASH_KEY_LEN, 0,
+					      SOCKET_ID_ANY);
 	if (!priv->rss_conf.rss_key) {
 		DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)",
 			dev->data->port_id, rxqs_n);
@@ -127,6 +129,14 @@ mlx5_dev_configure(struct rte_eth_dev *dev)
 		rte_errno = EINVAL;
 		return -rte_errno;
 	}
+	if (priv->ext_rxqs && rxqs_n >= MLX5_EXTERNAL_RX_QUEUE_ID_MIN) {
+		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u), "
+			"the maximal number of internal Rx queues is %u",
+			dev->data->port_id, rxqs_n,
+			MLX5_EXTERNAL_RX_QUEUE_ID_MIN - 1);
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
 	if (rxqs_n != priv->rxqs_n) {
 		DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
 			dev->data->port_id, priv->rxqs_n, rxqs_n);
drivers/net/mlx5/mlx5_rx.h +6 -0
index 1fdf4ff161..754c526464 100644
@@ -175,6 +175,12 @@ struct mlx5_rxq_priv {
 	uint32_t hairpin_status; /* Hairpin binding status. */
 };
 
+/* External RX queue descriptor. */
+struct mlx5_external_rxq {
+	uint32_t hw_id; /* Queue index in the Hardware. */
+	uint32_t refcnt; /* Reference counter. */
+};
+
 /* mlx5_rxq.c */
 
 extern uint8_t rss_hash_default_key[];
drivers/net/mlx5/mlx5_rxq.c +109 -0

118 lines not on this page · raw message

drivers/net/mlx5/rte_pmd_mlx5.h +49 -1

57 lines not on this page · raw message

drivers/net/mlx5/version.map +3 -0
index 0af7a12488..79cb79acc6 100644
@@ -9,4 +9,7 @@ EXPERIMENTAL {
 	rte_pmd_mlx5_get_dyn_flag_names;
 	# added in 20.11
 	rte_pmd_mlx5_sync_flow;
+	# added in 22.03
+	rte_pmd_mlx5_external_rx_queue_id_map;
+	rte_pmd_mlx5_external_rx_queue_id_unmap;
 };
Signature · 1 line
2.25.1
#13 lore raw

PATCH v2 6/6 net/mlx5: support queue/RSS action for external RxQ

In reply to Michael Baum

Add support queue/RSS action for external RxQ.
In indirection table creation, the queue index will be taken from mapping array.

This feature supports neither LRO nor Hairpin.

---
 doc/guides/nics/mlx5.rst               |   1 +
 doc/guides/rel_notes/release_22_03.rst |   1 +
 drivers/net/mlx5/mlx5.c                |   8 +-
 drivers/net/mlx5/mlx5_devx.c           |  30 +++++--
 drivers/net/mlx5/mlx5_flow.c           |  29 +++++--
 drivers/net/mlx5/mlx5_rx.h             |  30 +++++++
 drivers/net/mlx5/mlx5_rxq.c            | 116 +++++++++++++++++++++++--
 7 files changed, 189 insertions(+), 26 deletions(-)
doc/guides/nics/mlx5.rst +1 -0
index 8956cd1dd8..34be031360 100644
@@ -38,6 +38,7 @@ Features
 - Multiple TX and RX queues.
 - Shared Rx queue.
 - Rx queue delay drop.
+- Support steering for external Rx queue created outside the PMD.
 - Support for scattered TX frames.
 - Advanced support for scattered Rx frames with tunable buffer attributes.
 - IPv4, IPv6, TCPv4, TCPv6, UDPv4 and UDPv6 RSS on any number of queues.
doc/guides/rel_notes/release_22_03.rst +1 -0
index acd56e0a80..c093616d7f 100644
@@ -123,6 +123,7 @@ New Features
   Updated the Mellanox mlx5 driver with new features and improvements, including:
 
   * Support ConnectX-7 capability to schedule traffic sending on timestamp
+  * Support steering for external Rx queue created outside the PMD.
 
 * **Updated Wangxun ngbe driver.**
 
drivers/net/mlx5/mlx5.c +6 -2
index 415e0fe2f2..9760f52b46 100644
@@ -1855,8 +1855,6 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 		close(priv->nl_socket_rdma);
 	if (priv->vmwa_context)
 		mlx5_vlan_vmwa_exit(priv->vmwa_context);
-	if (priv->ext_rxqs)
-		mlx5_free(priv->ext_rxqs);
 	ret = mlx5_hrxq_verify(dev);
 	if (ret)
 		DRV_LOG(WARNING, "port %u some hash Rx queue still remain",
@@ -1869,6 +1867,10 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 	if (ret)
 		DRV_LOG(WARNING, "port %u some Rx queue objects still remain",
 			dev->data->port_id);
+	ret = mlx5_ext_rxq_verify(dev);
+	if (ret)
+		DRV_LOG(WARNING, "Port %u some external RxQ still remain.",
+			dev->data->port_id);
 	ret = mlx5_rxq_verify(dev);
 	if (ret)
 		DRV_LOG(WARNING, "port %u some Rx queues still remain",
@@ -1887,6 +1889,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 			dev->data->port_id);
 	if (priv->hrxqs)
 		mlx5_list_destroy(priv->hrxqs);
+	if (priv->ext_rxqs)
+		mlx5_free(priv->ext_rxqs);
 	/*
 	 * Free the shared context in last turn, because the cleanup
 	 * routines above may use some shared fields, like
drivers/net/mlx5/mlx5_devx.c +21 -9
index e4bc90a30e..8aa68d9658 100644
@@ -580,13 +580,21 @@ mlx5_devx_ind_table_create_rqt_attr(struct rte_eth_dev *dev,
 		return rqt_attr;
 	}
 	for (i = 0; i != queues_n; ++i) {
-		struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, queues[i]);
+		if (mlx5_is_external_rxq(dev, queues[i])) {
+			struct mlx5_external_rxq *ext_rxq =
+					mlx5_ext_rxq_get(dev, queues[i]);
 
-		MLX5_ASSERT(rxq != NULL);
-		if (rxq->ctrl->is_hairpin)
-			rqt_attr->rq_list[i] = rxq->ctrl->obj->rq->id;
-		else
-			rqt_attr->rq_list[i] = rxq->devx_rq.rq->id;
+			rqt_attr->rq_list[i] = ext_rxq->hw_id;
+		} else {
+			struct mlx5_rxq_priv *rxq =
+					mlx5_rxq_get(dev, queues[i]);
+
+			MLX5_ASSERT(rxq != NULL);
+			if (rxq->ctrl->is_hairpin)
+				rqt_attr->rq_list[i] = rxq->ctrl->obj->rq->id;
+			else
+				rqt_attr->rq_list[i] = rxq->devx_rq.rq->id;
+		}
 	}
 	MLX5_ASSERT(i > 0);
 	for (j = 0; i != rqt_n; ++j, ++i)
@@ -711,7 +719,13 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 	uint32_t i;
 
 	/* NULL queues designate drop queue. */
-	if (ind_tbl->queues != NULL) {
+	if (ind_tbl->queues == NULL) {
+		is_hairpin = priv->drop_queue.rxq->ctrl->is_hairpin;
+	} else if (mlx5_is_external_rxq(dev, ind_tbl->queues[0])) {
+		/* External RxQ supports neither Hairpin nor LRO. */
+		is_hairpin = false;
+		lro = false;
+	} else {
 		is_hairpin = mlx5_rxq_is_hairpin(dev, ind_tbl->queues[0]);
 		/* Enable TIR LRO only if all the queues were configured for. */
 		for (i = 0; i < ind_tbl->queues_n; ++i) {
@@ -723,8 +737,6 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 				break;
 			}
 		}
-	} else {
-		is_hairpin = priv->drop_queue.rxq->ctrl->is_hairpin;
 	}
 	memset(tir_attr, 0, sizeof(*tir_attr));
 	tir_attr->disp_type = MLX5_TIRC_DISP_TYPE_INDIRECT;
drivers/net/mlx5/mlx5_flow.c +20 -9
index 58f0aba294..96f3402418 100644
@@ -1631,6 +1631,12 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 fate actions in"
 					  " same flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "queue action not supported for egress.");
+	if (mlx5_is_external_rxq(dev, queue->index))
+		return 0;
 	if (!priv->rxqs_n)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
@@ -1645,11 +1651,6 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  &queue->index,
 					  "queue is not configured");
-	if (attr->egress)
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
-					  "queue action not supported for "
-					  "egress");
 	return 0;
 }
 
@@ -1664,7 +1665,7 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
  *   Size of the @p queues array.
  * @param[out] error
  *   On error, filled with a textual error description.
- * @param[out] queue
+ * @param[out] queue_idx
  *   On error, filled with an offending queue index in @p queues array.
  *
  * @return
@@ -1677,17 +1678,27 @@ mlx5_validate_rss_queues(struct rte_eth_dev *dev,
 {
 	const struct mlx5_priv *priv = dev->data->dev_private;
 	bool is_hairpin = false;
+	bool is_ext_rss = false;
 	uint32_t i;
 
 	for (i = 0; i != queues_n; ++i) {
-		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev,
-								   queues[i]);
+		struct mlx5_rxq_ctrl *rxq_ctrl;
 
+		if (mlx5_is_external_rxq(dev, queues[0])) {
+			is_ext_rss = true;
+			continue;
+		}
+		if (is_ext_rss) {
+			*error = "Combining external and regular RSS queues is not supported";
+			*queue_idx = i;
+			return -ENOTSUP;
+		}
 		if (queues[i] >= priv->rxqs_n) {
 			*error = "queue index out of range";
 			*queue_idx = i;
 			return -EINVAL;
 		}
+		rxq_ctrl = mlx5_rxq_ctrl_get(dev, queues[i]);
 		if (rxq_ctrl == NULL) {
 			*error =  "queue is not configured";
 			*queue_idx = i;
@@ -1782,7 +1793,7 @@ mlx5_validate_action_rss(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
 					  "L4 partial RSS requested but L4 RSS"
 					  " type not specified");
-	if (!priv->rxqs_n)
+	if (!priv->rxqs_n && priv->ext_rxqs == NULL)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  NULL, "No Rx queues configured");
drivers/net/mlx5/mlx5_rx.h +30 -0
index 754c526464..29652a8c9f 100644
@@ -18,6 +18,7 @@
 
 #include "mlx5.h"
 #include "mlx5_autoconf.h"
+#include "rte_pmd_mlx5.h"
 
 /* Support tunnel matching. */
 #define MLX5_FLOW_TUNNEL 10
@@ -217,8 +218,14 @@ uint32_t mlx5_rxq_deref(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_rxq_priv *mlx5_rxq_get(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_rxq_ctrl *mlx5_rxq_ctrl_get(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_rxq_data *mlx5_rxq_data_get(struct rte_eth_dev *dev, uint16_t idx);
+struct mlx5_external_rxq *mlx5_ext_rxq_ref(struct rte_eth_dev *dev,
+					   uint16_t idx);
+uint32_t mlx5_ext_rxq_deref(struct rte_eth_dev *dev, uint16_t idx);
+struct mlx5_external_rxq *mlx5_ext_rxq_get(struct rte_eth_dev *dev,
+					   uint16_t idx);
 int mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx);
 int mlx5_rxq_verify(struct rte_eth_dev *dev);
+int mlx5_ext_rxq_verify(struct rte_eth_dev *dev);
 int rxq_alloc_elts(struct mlx5_rxq_ctrl *rxq_ctrl);
 int mlx5_ind_table_obj_verify(struct rte_eth_dev *dev);
 struct mlx5_ind_table_obj *mlx5_ind_table_obj_get(struct rte_eth_dev *dev,
@@ -638,4 +645,27 @@ mlx5_mprq_enabled(struct rte_eth_dev *dev)
 	return n == n_ibv;
 }
 
+/**
+ * Check whether given RxQ is external.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ * @param queue_idx
+ *   Rx queue index.
+ *
+ * @return
+ *   True if is external RxQ, otherwise false.
+ */
+static __rte_always_inline bool
+mlx5_is_external_rxq(struct rte_eth_dev *dev, uint16_t queue_idx)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_external_rxq *rxq;
+
+	if (!priv->ext_rxqs || queue_idx < MLX5_EXTERNAL_RX_QUEUE_ID_MIN)
+		return false;
+	rxq = &priv->ext_rxqs[queue_idx - MLX5_EXTERNAL_RX_QUEUE_ID_MIN];
+	return !!__atomic_load_n(&rxq->refcnt, __ATOMIC_RELAXED);
+}
+
 #endif /* RTE_PMD_MLX5_RX_H_ */
drivers/net/mlx5/mlx5_rxq.c +110 -6

147 lines not on this page · raw message

Signature · 1 line
2.25.1
#14 lore raw
In reply to Michael Baum

From: Michael Baum

Quoted 14 lines

These patches add support to external Rx queues.
External queue is a queue that is managed by a process external to PMD, but uses PMD process to generate its flow rules.

For the hardware to allow the DPDK process to set rules for it, the process needs to use the same PD of the external process. In addition, the indexes of the queues in hardware are represented by 32-bit compared to the rte_flow indexes represented by 16-bit, so the processes need to share some mapping between the indexes.

These patches allow the external process to provide devargs which enable importing its context and PD, instead of prepare new ones. In addition, an API is provided for mapping for the indexes of the queues.

Quoted 7 lines

v2:
- Rebase.
- Add ABI exception for common/mlx5 library.
- Correct DevX flag updating.
- Improve explanations in doc and comments.
- Remove teatpmd part.

Quoted 41 lines

Michael Baum (6):
common/mlx5: consider local functions as internal common/mlx5: glue device and PD importation common/mlx5: add remote PD and CTX support net/mlx5: optimize RxQ/TxQ control structure net/mlx5: add external RxQ mapping API net/mlx5: support queue/RSS action for external RxQ

 devtools/libabigail.abignore                 |   4 +
 doc/guides/nics/mlx5.rst                     |   1 +
 doc/guides/platform/mlx5.rst                 |  37 ++-
 doc/guides/rel_notes/release_22_03.rst       |   1 +
 drivers/common/mlx5/linux/meson.build        |   2 +
 drivers/common/mlx5/linux/mlx5_common_os.c   | 196 ++++++++++++--
 drivers/common/mlx5/linux/mlx5_common_os.h   |   7 +-
 drivers/common/mlx5/linux/mlx5_glue.c        |  41 +++
 drivers/common/mlx5/linux/mlx5_glue.h        |   4 +
 drivers/common/mlx5/mlx5_common.c            |  64 ++++-
 drivers/common/mlx5/mlx5_common.h            |  23 +-
 drivers/common/mlx5/version.map              |   3 +
 drivers/common/mlx5/windows/mlx5_common_os.c |  37 ++-
 drivers/common/mlx5/windows/mlx5_common_os.h |   1 -
 drivers/net/mlx5/linux/mlx5_os.c             |  18 ++
 drivers/net/mlx5/mlx5.c                      |   6 +
 drivers/net/mlx5/mlx5.h                      |   1 +
 drivers/net/mlx5/mlx5_defs.h                 |   3 +
 drivers/net/mlx5/mlx5_devx.c                 |  52 ++--
 drivers/net/mlx5/mlx5_ethdev.c               |  18 +-
 drivers/net/mlx5/mlx5_flow.c                 |  43 ++--
 drivers/net/mlx5/mlx5_flow_dv.c              |  14 +-
 drivers/net/mlx5/mlx5_rx.h                   |  49 +++-
 drivers/net/mlx5/mlx5_rxq.c                  | 258 +++++++++++++++++--
 drivers/net/mlx5/mlx5_trigger.c              |  36 +--
 drivers/net/mlx5/mlx5_tx.h                   |   7 +-
 drivers/net/mlx5/mlx5_txq.c                  |  14 +-
 drivers/net/mlx5/rte_pmd_mlx5.h              |  50 +++-
 drivers/net/mlx5/version.map                 |   3 +
 29 files changed, 821 insertions(+), 172 deletions(-)

--
2.25.1

#15 lore raw

v3 cover mlx5: external RxQ support

In reply to Michael Baum

These patches add support to external Rx queues.
External queue is a queue that is managed by a process external to PMD, but uses PMD process to generate its flow rules.

For the hardware to allow the DPDK process to set rules for it, the process needs to use the same PD of the external process. In addition, the indexes of the queues in hardware are represented by 32-bit compared to the rte_flow indexes represented by 16-bit, so the processes need to share some mapping between the indexes.

These patches allow the external process to provide devargs which enable importing its context and PD, instead of prepare new ones. In addition, an API is provided for mapping for the indexes of the queues.

v1:
- initial commits.

v2:
- Rebase.
- Add ABI exception for common/mlx5 library.
- Correct DevX flag updating.
- Improve explanations in doc and comments.
- Remove teatpmd part.

v3:
- Rebase.
- Fix compilation error.
- Avoide TOCTOU issue in external RxQ map/unmap functions.
- Add check it the queue still referenced in unmapping function.
- Improve guide explanations for the new devargs.

Michael Baum (6):
common/mlx5: consider local functions as internal common/mlx5: glue device and PD importation common/mlx5: add remote PD and CTX support net/mlx5: optimize RxQ/TxQ control structure net/mlx5: add external RxQ mapping API net/mlx5: support queue/RSS action for external RxQ

 devtools/libabigail.abignore                 |   4 +
 doc/guides/nics/mlx5.rst                     |   1 +
 doc/guides/platform/mlx5.rst                 |  37 ++-
 doc/guides/rel_notes/release_22_03.rst       |   1 +
 drivers/common/mlx5/linux/meson.build        |   2 +
 drivers/common/mlx5/linux/mlx5_common_os.c   | 196 ++++++++++++--
 drivers/common/mlx5/linux/mlx5_common_os.h   |   7 +-
 drivers/common/mlx5/linux/mlx5_glue.c        |  41 +++
 drivers/common/mlx5/linux/mlx5_glue.h        |   4 +
 drivers/common/mlx5/mlx5_common.c            |  84 ++++--
 drivers/common/mlx5/mlx5_common.h            |  23 +-
 drivers/common/mlx5/version.map              |   3 +
 drivers/common/mlx5/windows/mlx5_common_os.c |  37 ++-
 drivers/common/mlx5/windows/mlx5_common_os.h |   1 -
 drivers/net/mlx5/linux/mlx5_os.c             |  17 ++
 drivers/net/mlx5/mlx5.c                      |   5 +
 drivers/net/mlx5/mlx5.h                      |   1 +
 drivers/net/mlx5/mlx5_defs.h                 |   3 +
 drivers/net/mlx5/mlx5_devx.c                 |  52 ++--
 drivers/net/mlx5/mlx5_ethdev.c               |  18 +-
 drivers/net/mlx5/mlx5_flow.c                 |  43 +--
 drivers/net/mlx5/mlx5_flow_dv.c              |  14 +-
 drivers/net/mlx5/mlx5_rx.h                   |  49 +++-
 drivers/net/mlx5/mlx5_rxq.c                  | 266 +++++++++++++++++--
 drivers/net/mlx5/mlx5_trigger.c              |  36 +--
 drivers/net/mlx5/mlx5_tx.h                   |   7 +-
 drivers/net/mlx5/mlx5_txq.c                  |  14 +-
 drivers/net/mlx5/rte_pmd_mlx5.h              |  50 +++-
 drivers/net/mlx5/version.map                 |   3 +
 29 files changed, 838 insertions(+), 181 deletions(-)
Signature · 1 line
2.25.1
#16 lore raw

PATCH v3 1/6 common/mlx5: consider local functions as internal

The functions which are not explicitly marked as internal were exported because the local catch-all rule was missing in the version script.
After adding the missing rule, all local functions are hidden. The function mlx5_get_device_guid is used in another library, so it needs to be exported (as internal).

Because the local functions were exported as non-internal in DPDK 21.11, any change in these functions would break the ABI. An ABI exception is added for this library, considering that all functions are either local or internal.

---
 devtools/libabigail.abignore               | 4 ++++
 drivers/common/mlx5/linux/mlx5_common_os.h | 1 +
 drivers/common/mlx5/version.map            | 3 +++
 3 files changed, 8 insertions(+)
devtools/libabigail.abignore +4 -0
index ef0602975a..78d57497e6 100644
@@ -20,3 +20,7 @@
 ; Ignore changes to rte_crypto_asym_op, asymmetric crypto API is experimental
 [suppress_type]
         name = rte_crypto_asym_op
+
+; Ignore changes in common mlx5 driver, should be all internal
+[suppress_file]
+        soname_regexp = ^librte_common_mlx5\.
\ No newline at end of file
drivers/common/mlx5/linux/mlx5_common_os.h +1 -0
index 83066e752d..edf356a30a 100644
@@ -300,6 +300,7 @@ mlx5_set_context_attr(struct rte_device *dev, struct ibv_context *ctx);
  *  0 if OFED doesn't support.
  *  >0 if success.
  */
+__rte_internal
 int
 mlx5_get_device_guid(const struct rte_pci_addr *dev, uint8_t *guid, size_t len);
 
drivers/common/mlx5/version.map +3 -0
index 1c6153c576..cb20a7d893 100644
@@ -80,6 +80,7 @@ INTERNAL {
 
 	mlx5_free;
 
+	mlx5_get_device_guid; # WINDOWS_NO_EXPORT
 	mlx5_get_ifname_sysfs; # WINDOWS_NO_EXPORT
 	mlx5_get_pci_addr; # WINDOWS_NO_EXPORT
 
@@ -149,4 +150,6 @@ INTERNAL {
 	mlx5_mp_req_mempool_reg;
 	mlx5_mr_mempool2mr_bh;
 	mlx5_mr_mempool_populate_cache;
+
+	local: *;
 };
Signature · 1 line
2.25.1
#17 lore raw

Re: [PATCH v3 1/6] common/mlx5: consider local functions as internal

Quoted 7 lines · Michael Baum

The functions which are not explicitly marked as internal were exported because the local catch-all rule was missing in the version script.
After adding the missing rule, all local functions are hidden. The function mlx5_get_device_guid is used in another library, so it needs to be exported (as internal).

Quoted 5 lines

Because the local functions were exported as non-internal in DPDK 21.11, any change in these functions would break the ABI. An ABI exception is added for this library, considering that all functions are either local or internal.

When a function is not listed explicitly in .map file, it shouldn't be exported at all.

So I am not sure if this exception is required, did you get warning for tool, or is this theoretical?

cc'ed David and Ray for comment.

Quoted 2 lines

<...>

#18 lore raw

Re: [PATCH v3 1/6] common/mlx5: consider local functions as internal

25/02/2022 19:01, Ferruh Yigit:

Quoted 8 lines · Michael Baum
Quoted 7 lines

The functions which are not explicitly marked as internal were exported because the local catch-all rule was missing in the version script.
After adding the missing rule, all local functions are hidden. The function mlx5_get_device_guid is used in another library, so it needs to be exported (as internal).

Quoted 8 lines
Quoted 5 lines

Because the local functions were exported as non-internal in DPDK 21.11, any change in these functions would break the ABI. An ABI exception is added for this library, considering that all functions are either local or internal.

When a function is not listed explicitly in .map file, it shouldn't be exported at all.

It seems we need local:* to achieve this behaviour. Few other libs are missing it. I plan to send a patch for them.

Quoted 2 lines

So I am not sure if this exception is required, did you get warning for tool, or is this theoretical?

It is not theoritical, you can check with objdump:
objdump -T build/lib/librte_common_mlx5.so | sed -rn 's,^[[:xdigit:]]* g *(D[^0]*)[^ ]* *,\1,p'

I did not check the ABI tool without the exception.

#19 lore raw

Re: [PATCH v3 1/6] common/mlx5: consider local functions as internal

Quoted 15 lines · Thomas Monjalon

25/02/2022 19:01, Ferruh Yigit:

Quoted 14 lines · Michael Baum
Quoted 12 lines

The functions which are not explicitly marked as internal were exported because the local catch-all rule was missing in the version script.
After adding the missing rule, all local functions are hidden. The function mlx5_get_device_guid is used in another library, so it needs to be exported (as internal).

Because the local functions were exported as non-internal in DPDK 21.11, any change in these functions would break the ABI. An ABI exception is added for this library, considering that all functions are either local or internal.

Quoted 6 lines
Quoted 2 lines

When a function is not listed explicitly in .map file, it shouldn't be exported at all.

It seems we need local:* to achieve this behaviour. Few other libs are missing it. I plan to send a patch for them.

+1 for this patch, thanks.

Quoted 8 lines
Quoted 2 lines

So I am not sure if this exception is required, did you get warning for tool, or is this theoretical?

It is not theoritical, you can check with objdump:
objdump -T build/lib/librte_common_mlx5.so | sed -rn 's,^[[:xdigit:]]* g *(D[^0]*)[^ ]* *,\1,p'

I did not check the ABI tool without the exception.

Yes tool complains with change [1], I will proceed with original patch.

[1]
29 Removed functions:

[D] 'function int mlx5_auxiliary_get_pci_str(const rte_auxiliary_device*, char*, size_t)' {mlx5_auxiliary_get_pci_str}
[D] 'function void mlx5_common_auxiliary_init()' {mlx5_common_auxiliary_init}
[D] 'function int mlx5_common_dev_dma_map(rte_device*, void*, uint64_t, size_t)' {mlx5_common_dev_dma_map}
[D] 'function int mlx5_common_dev_dma_unmap(rte_device*, void*, uint64_t, size_t)' {mlx5_common_dev_dma_unmap}
[D] 'function int mlx5_common_dev_probe(rte_device*)' {mlx5_common_dev_probe}
[D] 'function int mlx5_common_dev_remove(rte_device*)' {mlx5_common_dev_remove}
[D] 'function void mlx5_common_driver_on_register_pci(mlx5_class_driver*)' {mlx5_common_driver_on_register_pci}
[D] 'function void mlx5_common_pci_init()' {mlx5_common_pci_init}
[D] 'function mlx5_mr* mlx5_create_mr_ext(void*, uintptr_t, size_t, int, mlx5_reg_mr_t)' {mlx5_create_mr_ext}
[D] 'function bool mlx5_dev_pci_match(const mlx5_class_driver*, const rte_device*)' {mlx5_dev_pci_match}
[D] 'function int mlx5_dev_to_pci_str(const rte_device*, char*, size_t)' {mlx5_dev_to_pci_str}
[D] 'function void mlx5_free_mr_by_addr(mlx5_mr_share_cache*, const char*, void*, size_t)' {mlx5_free_mr_by_addr}
[D] 'function ibv_device* mlx5_get_aux_ibv_device(const rte_auxiliary_device*)' {mlx5_get_aux_ibv_device}
[D] 'function void mlx5_glue_constructor()' {mlx5_glue_constructor}
[D] 'function void mlx5_malloc_mem_select(uint32_t)' {mlx5_malloc_mem_select}
[D] 'function void mlx5_mr_btree_dump(mlx5_mr_btree*)' {mlx5_mr_btree_dump}
[D] 'function int mlx5_mr_create_cache(mlx5_mr_share_cache*, int)' {mlx5_mr_create_cache}
[D] 'function void mlx5_mr_free(mlx5_mr*, mlx5_dereg_mr_t)' {mlx5_mr_free}
[D] 'function int mlx5_mr_insert_cache(mlx5_mr_share_cache*, mlx5_mr*)' {mlx5_mr_insert_cache}
[D] 'function mlx5_mr* mlx5_mr_lookup_list(mlx5_mr_share_cache*, mr_cache_entry*, uintptr_t)' {mlx5_mr_lookup_list}
[D] 'function void mlx5_mr_rebuild_cache(mlx5_mr_share_cache*)' {mlx5_mr_rebuild_cache}
[D] 'function void mlx5_mr_release_cache(mlx5_mr_share_cache*)' {mlx5_mr_release_cache}
[D] 'function int mlx5_nl_devlink_family_id_get(int)' {mlx5_nl_devlink_family_id_get}
[D] 'function int mlx5_nl_enable_roce_get(int, int, const char*, int*)' {mlx5_nl_enable_roce_get}
[D] 'function int mlx5_nl_enable_roce_set(int, int, const char*, int)' {mlx5_nl_enable_roce_set}
[D] 'function int mlx5_os_open_device(mlx5_common_device*, uint32_t)' {mlx5_os_open_device}
[D] 'function int mlx5_os_pd_create(mlx5_common_device*)' {mlx5_os_pd_create}
[D] 'function void mlx5_os_set_reg_mr_cb(mlx5_reg_mr_t*, mlx5_dereg_mr_t*)' {mlx5_os_set_reg_mr_cb}
[D] 'function void mlx5_set_context_attr(rte_device*, ibv_context*)' {mlx5_set_context_attr}

2 Removed variables:

[D] 'uint32_t atomic_sn' {atomic_sn}
[D] 'int mlx5_common_logtype' {mlx5_common_logtype}

1 Removed function symbol not referenced by debug info:

[D] mlx5_mr_dump_cache

#20 lore raw

PATCH v3 2/6 common/mlx5: glue device and PD importation

In reply to Michael Baum

Add support for rdma-core API to import device.
The API gets ibv_context file descriptor and returns an ibv_context pointer that is associated with the given file descriptor. Add also support for rdma-core API to import PD.
The API gets ibv_context and PD handle and returns a protection domain (PD) that is associated with the given handle in the given context.

---
 drivers/common/mlx5/linux/meson.build |  2 ++
 drivers/common/mlx5/linux/mlx5_glue.c | 41 +++++++++++++++++++++++++++
 drivers/common/mlx5/linux/mlx5_glue.h |  4 +++
 3 files changed, 47 insertions(+)
drivers/common/mlx5/linux/meson.build +2 -0
index 4c7b53b9bd..ed48245c67 100644
@@ -202,6 +202,8 @@ has_sym_args = [
             'mlx5dv_dr_domain_allow_duplicate_rules' ],
         [ 'HAVE_MLX5_IBV_REG_MR_IOVA', 'infiniband/verbs.h',
             'ibv_reg_mr_iova' ],
+        [ 'HAVE_MLX5_IBV_IMPORT_CTX_PD_AND_MR', 'infiniband/verbs.h',
+            'ibv_import_device' ],
 ]
 config = configuration_data()
 foreach arg:has_sym_args
drivers/common/mlx5/linux/mlx5_glue.c +41 -0

62 lines not on this page · raw message

drivers/common/mlx5/linux/mlx5_glue.h +4 -0
index 4e6d31f263..c4903a6dce 100644
@@ -151,9 +151,13 @@ struct mlx5_glue {
 	int (*fork_init)(void);
 	struct ibv_pd *(*alloc_pd)(struct ibv_context *context);
 	int (*dealloc_pd)(struct ibv_pd *pd);
+	struct ibv_pd *(*import_pd)(struct ibv_context *context,
+				    uint32_t pd_handle);
+	int (*unimport_pd)(struct ibv_pd *pd);
 	struct ibv_device **(*get_device_list)(int *num_devices);
 	void (*free_device_list)(struct ibv_device **list);
 	struct ibv_context *(*open_device)(struct ibv_device *device);
+	struct ibv_context *(*import_device)(int cmd_fd);
 	int (*close_device)(struct ibv_context *context);
 	int (*query_device)(struct ibv_context *context,
 			    struct ibv_device_attr *device_attr);
Signature · 1 line
2.25.1
#21 lore raw

PATCH v3 3/6 common/mlx5: add remote PD and CTX support

In reply to Michael Baum

Add option to probe common device using import CTX/PD functions instead of create functions.
This option requires accepting the context FD and the PD handle as devargs.

This sharing can be useful for applications that use PMD for only some operations. For example, an app that generates queues itself and uses PMD just to configure flow rules.

---
 doc/guides/platform/mlx5.rst                 |  37 +++-
 drivers/common/mlx5/linux/mlx5_common_os.c   | 196 ++++++++++++++++---
 drivers/common/mlx5/linux/mlx5_common_os.h   |   6 -
 drivers/common/mlx5/mlx5_common.c            |  84 +++++---
 drivers/common/mlx5/mlx5_common.h            |  23 ++-
 drivers/common/mlx5/windows/mlx5_common_os.c |  37 +++-
 drivers/common/mlx5/windows/mlx5_common_os.h |   1 -
 7 files changed, 324 insertions(+), 60 deletions(-)
doc/guides/platform/mlx5.rst +36 -1
index d073c213ca..76b3f80315 100644
@@ -81,6 +81,12 @@ Limitations
 - On Windows, only ``eth`` and ``crypto`` are supported.
 
 
+Features
+--------
+
+- Remote PD and CTX - Linux only.
+
+
 .. _mlx5_common_compilation:
 
 Compilation Prerequisites
@@ -638,4 +644,33 @@ and below are the arguments supported by the common mlx5 layer.
 
   If ``sq_db_nc`` is omitted, the preset (if any) environment variable
   "MLX5_SHUT_UP_BF" value is used. If there is no "MLX5_SHUT_UP_BF", the
-  default ``sq_db_nc`` value is zero for ARM64 hosts and one for others.
\ No newline at end of file
+  default ``sq_db_nc`` value is zero for ARM64 hosts and one for others.
+
+- ``cmd_fd`` parameter [int]
+
+  File descriptor of ``ibv_context`` created outside the PMD.
+  PMD will use this FD to import remote CTX. The ``cmd_fd`` is obtained from
+  the ``ibv_context->cmd_fd`` member, which must be dup'd before being passed.
+  This parameter is valid only if ``pd_handle`` parameter is specified.
+
+  By default, the PMD will create a new ``ibv_context``.
+
+  .. note::
+
+     When FD comes from another process, it is the user responsibility to
+     share the FD between the processes (e.g. by SCM_RIGHTS).
+
+- ``pd_handle`` parameter [int]
+
+  Protection domain handle of ``ibv_pd`` created outside the PMD.
+  PMD will use this handle to import remote PD. The ``pd_handle`` can be
+  achieved from the original PD by getting its ``ibv_pd->handle`` member value.
+  This parameter is valid only if ``cmd_fd`` parameter is specified, and its
+  value must be a valid kernel handle for a PD object in the context represented
+  by given ``cmd_fd``.
+
+  By default, the PMD will allocate a new PD.
+
+  .. note::
+
+     The ``ibv_pd->handle`` member is different then ``mlx5dv_pd->pdn`` member.
\ No newline at end of file
drivers/common/mlx5/linux/mlx5_common_os.c +174 -22

273 lines not on this page · raw message

drivers/common/mlx5/linux/mlx5_common_os.h +0 -6
index edf356a30a..a85f3b5f3c 100644
@@ -203,12 +203,6 @@ mlx5_os_get_devx_uar_page_id(void *uar)
 #endif
 }
 
-static inline int
-mlx5_os_dealloc_pd(void *pd)
-{
-	return mlx5_glue->dealloc_pd(pd);
-}
-
 __rte_internal
 static inline void *
 mlx5_os_umem_reg(void *ctx, void *addr, size_t size, uint32_t access)
drivers/common/mlx5/mlx5_common.c +61 -23

145 lines not on this page · raw message

drivers/common/mlx5/mlx5_common.h +22 -1
index 49bcea1d91..63f31437da 100644
@@ -446,6 +446,8 @@ void mlx5_common_init(void);
 struct mlx5_common_dev_config {
 	struct mlx5_hca_attr hca_attr; /* HCA attributes. */
 	int dbnc; /* Skip doorbell register write barrier. */
+	int device_fd; /* Device file descriptor for importation. */
+	int pd_handle; /* Protection Domain handle for importation.  */
 	unsigned int devx:1; /* Whether devx interface is available or not. */
 	unsigned int sys_mem_en:1; /* The default memory allocator. */
 	unsigned int mr_mempool_reg_en:1;
@@ -465,6 +467,23 @@ struct mlx5_common_device {
 	struct mlx5_common_dev_config config; /* Device configuration. */
 };
 
+/**
+ * Indicates whether PD and CTX are imported from another process,
+ * or created by this process.
+ *
+ * @param cdev
+ *   Pointer to common device.
+ *
+ * @return
+ *   True if PD and CTX are imported from another process, False otherwise.
+ */
+static inline bool
+mlx5_imported_pd_and_ctx(struct mlx5_common_device *cdev)
+{
+	return cdev->config.device_fd != MLX5_ARG_UNSET &&
+	       cdev->config.pd_handle != MLX5_ARG_UNSET;
+}
+
 /**
  * Initialization function for the driver called during device probing.
  */
@@ -554,7 +573,9 @@ mlx5_devx_uar_release(struct mlx5_uar *uar);
 /* mlx5_common_os.c */
 
 int mlx5_os_open_device(struct mlx5_common_device *cdev, uint32_t classes);
-int mlx5_os_pd_create(struct mlx5_common_device *cdev);
+int mlx5_os_pd_prepare(struct mlx5_common_device *cdev);
+int mlx5_os_pd_release(struct mlx5_common_device *cdev);
+int mlx5_os_remote_pd_and_ctx_validate(struct mlx5_common_dev_config *config);
 
 /* mlx5 PMD wrapped MR struct. */
 struct mlx5_pmd_wrapped_mr {
drivers/common/mlx5/windows/mlx5_common_os.c +31 -6
index c3cfc315f2..f2fc7cd494 100644
@@ -25,21 +25,46 @@ mlx5_glue_constructor(void)
 {
 }
 
+/**
+ * Validate user arguments for remote PD and CTX.
+ *
+ * @param config
+ *   Pointer to device configuration structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+int
+mlx5_os_remote_pd_and_ctx_validate(struct mlx5_common_dev_config *config)
+{
+	int device_fd = config->device_fd;
+	int pd_handle = config->pd_handle;
+
+	if (pd_handle != MLX5_ARG_UNSET || device_fd != MLX5_ARG_UNSET) {
+		DRV_LOG(ERR, "Remote PD and CTX is not supported on Windows.");
+		rte_errno = ENOTSUP;
+		return -rte_errno;
+	}
+	return 0;
+}
+
 /**
  * Release PD. Releases a given mlx5_pd object
  *
- * @param[in] pd
- *   Pointer to mlx5_pd.
+ * @param[in] cdev
+ *   Pointer to the mlx5 device.
  *
  * @return
  *   Zero if pd is released successfully, negative number otherwise.
  */
 int
-mlx5_os_dealloc_pd(void *pd)
+mlx5_os_pd_release(struct mlx5_common_device *cdev)
 {
+	struct mlx5_pd *pd = cdev->pd;
+
 	if (!pd)
 		return -EINVAL;
-	mlx5_devx_cmd_destroy(((struct mlx5_pd *)pd)->obj);
+	mlx5_devx_cmd_destroy(pd->obj);
 	mlx5_free(pd);
 	return 0;
 }
@@ -47,14 +72,14 @@ mlx5_os_dealloc_pd(void *pd)
 /**
  * Allocate Protection Domain object and extract its pdn using DV API.
  *
- * @param[out] dev
+ * @param[out] cdev
  *   Pointer to the mlx5 device.
  *
  * @return
  *   0 on success, a negative value otherwise.
  */
 int
-mlx5_os_pd_create(struct mlx5_common_device *cdev)
+mlx5_os_pd_prepare(struct mlx5_common_device *cdev)
 {
 	struct mlx5_pd *pd;
 
drivers/common/mlx5/windows/mlx5_common_os.h +0 -1
index 61fc8dd761..ee7973f1ec 100644
@@ -248,7 +248,6 @@ mlx5_os_devx_subscribe_devx_event(void *eventc,
 	return -ENOTSUP;
 }
 
-int mlx5_os_dealloc_pd(void *pd);
 __rte_internal
 void *mlx5_os_umem_reg(void *ctx, void *addr, size_t size, uint32_t access);
 __rte_internal
Signature · 1 line
2.25.1
#22 lore raw

PATCH v3 4/6 net/mlx5: optimize RxQ/TxQ control structure

In reply to Michael Baum

The RxQ/TxQ control structure has a field named type. This type is enum with values for standard and hairpin.
The use of this field is to check whether the queue is of the hairpin type or standard.

This patch replaces it with a boolean variable that saves whether it is a hairpin.

---
 drivers/net/mlx5/mlx5_devx.c    | 26 ++++++++++--------------
 drivers/net/mlx5/mlx5_ethdev.c  |  2 +-
 drivers/net/mlx5/mlx5_flow.c    | 14 ++++++-------
 drivers/net/mlx5/mlx5_flow_dv.c | 14 +++++--------
 drivers/net/mlx5/mlx5_rx.h      | 13 +++---------
 drivers/net/mlx5/mlx5_rxq.c     | 33 +++++++++++-------------------
 drivers/net/mlx5/mlx5_trigger.c | 36 ++++++++++++++++-----------------
 drivers/net/mlx5/mlx5_tx.h      |  7 +------
 drivers/net/mlx5/mlx5_txq.c     | 14 ++++++-------
 9 files changed, 64 insertions(+), 95 deletions(-)
drivers/net/mlx5/mlx5_devx.c +11 -15
index 8d151fa4ab..bcd2358165 100644
@@ -88,7 +88,7 @@ mlx5_devx_modify_rq(struct mlx5_rxq_priv *rxq, uint8_t type)
 	default:
 		break;
 	}
-	if (rxq->ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
+	if (rxq->ctrl->is_hairpin)
 		return mlx5_devx_cmd_modify_rq(rxq->ctrl->obj->rq, &rq_attr);
 	return mlx5_devx_cmd_modify_rq(rxq->devx_rq.rq, &rq_attr);
 }
@@ -162,7 +162,7 @@ mlx5_rxq_devx_obj_release(struct mlx5_rxq_priv *rxq)
 
 	if (rxq_obj == NULL)
 		return;
-	if (rxq_obj->rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN) {
+	if (rxq_obj->rxq_ctrl->is_hairpin) {
 		if (rxq_obj->rq == NULL)
 			return;
 		mlx5_devx_modify_rq(rxq, MLX5_RXQ_MOD_RDY2RST);
@@ -476,7 +476,7 @@ mlx5_rxq_devx_obj_new(struct mlx5_rxq_priv *rxq)
 
 	MLX5_ASSERT(rxq_data);
 	MLX5_ASSERT(tmpl);
-	if (rxq_ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
+	if (rxq_ctrl->is_hairpin)
 		return mlx5_rxq_obj_hairpin_new(rxq);
 	tmpl->rxq_ctrl = rxq_ctrl;
 	if (rxq_ctrl->irq && !rxq_ctrl->started) {
@@ -583,7 +583,7 @@ mlx5_devx_ind_table_create_rqt_attr(struct rte_eth_dev *dev,
 		struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, queues[i]);
 
 		MLX5_ASSERT(rxq != NULL);
-		if (rxq->ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
+		if (rxq->ctrl->is_hairpin)
 			rqt_attr->rq_list[i] = rxq->ctrl->obj->rq->id;
 		else
 			rqt_attr->rq_list[i] = rxq->devx_rq.rq->id;
@@ -706,17 +706,13 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 		       int tunnel, struct mlx5_devx_tir_attr *tir_attr)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	enum mlx5_rxq_type rxq_obj_type;
+	bool is_hairpin;
 	bool lro = true;
 	uint32_t i;
 
 	/* NULL queues designate drop queue. */
 	if (ind_tbl->queues != NULL) {
-		struct mlx5_rxq_ctrl *rxq_ctrl =
-				mlx5_rxq_ctrl_get(dev, ind_tbl->queues[0]);
-		rxq_obj_type = rxq_ctrl != NULL ? rxq_ctrl->type :
-						  MLX5_RXQ_TYPE_STANDARD;
-
+		is_hairpin = mlx5_rxq_is_hairpin(dev, ind_tbl->queues[0]);
 		/* Enable TIR LRO only if all the queues were configured for. */
 		for (i = 0; i < ind_tbl->queues_n; ++i) {
 			struct mlx5_rxq_data *rxq_i =
@@ -728,7 +724,7 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			}
 		}
 	} else {
-		rxq_obj_type = priv->drop_queue.rxq->ctrl->type;
+		is_hairpin = priv->drop_queue.rxq->ctrl->is_hairpin;
 	}
 	memset(tir_attr, 0, sizeof(*tir_attr));
 	tir_attr->disp_type = MLX5_TIRC_DISP_TYPE_INDIRECT;
@@ -759,7 +755,7 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 			(!!(hash_fields & MLX5_L4_DST_IBV_RX_HASH)) <<
 			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT;
 	}
-	if (rxq_obj_type == MLX5_RXQ_TYPE_HAIRPIN)
+	if (is_hairpin)
 		tir_attr->transport_domain = priv->sh->td->id;
 	else
 		tir_attr->transport_domain = priv->sh->tdn;
@@ -940,7 +936,7 @@ mlx5_rxq_devx_obj_drop_create(struct rte_eth_dev *dev)
 		goto error;
 	}
 	rxq_obj->rxq_ctrl = rxq_ctrl;
-	rxq_ctrl->type = MLX5_RXQ_TYPE_STANDARD;
+	rxq_ctrl->is_hairpin = false;
 	rxq_ctrl->sh = priv->sh;
 	rxq_ctrl->obj = rxq_obj;
 	rxq->ctrl = rxq_ctrl;
@@ -1242,7 +1238,7 @@ mlx5_txq_devx_obj_new(struct rte_eth_dev *dev, uint16_t idx)
 	struct mlx5_txq_ctrl *txq_ctrl =
 			container_of(txq_data, struct mlx5_txq_ctrl, txq);
 
-	if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN)
+	if (txq_ctrl->is_hairpin)
 		return mlx5_txq_obj_hairpin_new(dev, idx);
 #if !defined(HAVE_MLX5DV_DEVX_UAR_OFFSET) && defined(HAVE_INFINIBAND_VERBS_H)
 	DRV_LOG(ERR, "Port %u Tx queue %u cannot create with DevX, no UAR.",
@@ -1381,7 +1377,7 @@ void
 mlx5_txq_devx_obj_release(struct mlx5_txq_obj *txq_obj)
 {
 	MLX5_ASSERT(txq_obj);
-	if (txq_obj->txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN) {
+	if (txq_obj->txq_ctrl->is_hairpin) {
 		if (txq_obj->tis)
 			claim_zero(mlx5_devx_cmd_destroy(txq_obj->tis));
 #if defined(HAVE_MLX5DV_DEVX_UAR_OFFSET) || !defined(HAVE_INFINIBAND_VERBS_H)
drivers/net/mlx5/mlx5_ethdev.c +1 -1
index 72bf8ac914..406761ccf8 100644
@@ -173,7 +173,7 @@ mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev)
 	for (i = 0, j = 0; i < rxqs_n; i++) {
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 
-		if (rxq_ctrl && rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl && !rxq_ctrl->is_hairpin)
 			rss_queue_arr[j++] = i;
 	}
 	rss_queue_n = j;
drivers/net/mlx5/mlx5_flow.c +6 -8
index 5a4e000c12..09701a73c1 100644
@@ -1788,7 +1788,7 @@ mlx5_validate_rss_queues(struct rte_eth_dev *dev,
 			 const char **error, uint32_t *queue_idx)
 {
 	const struct mlx5_priv *priv = dev->data->dev_private;
-	enum mlx5_rxq_type rxq_type = MLX5_RXQ_TYPE_UNDEFINED;
+	bool is_hairpin = false;
 	uint32_t i;
 
 	for (i = 0; i != queues_n; ++i) {
@@ -1805,9 +1805,9 @@ mlx5_validate_rss_queues(struct rte_eth_dev *dev,
 			*queue_idx = i;
 			return -EINVAL;
 		}
-		if (i == 0)
-			rxq_type = rxq_ctrl->type;
-		if (rxq_type != rxq_ctrl->type) {
+		if (i == 0 && rxq_ctrl->is_hairpin)
+			is_hairpin = true;
+		if (is_hairpin != rxq_ctrl->is_hairpin) {
 			*error = "combining hairpin and regular RSS queues is not supported";
 			*queue_idx = i;
 			return -ENOTSUP;
@@ -5885,15 +5885,13 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
 			const struct rte_flow_action_queue *queue;
 
 			queue = qrss->conf;
-			if (mlx5_rxq_get_type(dev, queue->index) ==
-			    MLX5_RXQ_TYPE_HAIRPIN)
+			if (mlx5_rxq_is_hairpin(dev, queue->index))
 				qrss = NULL;
 		} else if (qrss->type == RTE_FLOW_ACTION_TYPE_RSS) {
 			const struct rte_flow_action_rss *rss;
 
 			rss = qrss->conf;
-			if (mlx5_rxq_get_type(dev, rss->queue[0]) ==
-			    MLX5_RXQ_TYPE_HAIRPIN)
+			if (mlx5_rxq_is_hairpin(dev, rss->queue[0]))
 				qrss = NULL;
 		}
 	}
drivers/net/mlx5/mlx5_flow_dv.c +5 -9
index 7a012f7bb9..313dc64604 100644
@@ -5771,8 +5771,7 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
 	}
 	/* Continue validation for Xcap actions.*/
 	if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) &&
-	    (queue_index == 0xFFFF ||
-	     mlx5_rxq_get_type(dev, queue_index) != MLX5_RXQ_TYPE_HAIRPIN)) {
+	    (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index))) {
 		if ((sub_action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
 		     MLX5_FLOW_XCAP_ACTIONS)
 			return rte_flow_error_set(error, ENOTSUP,
@@ -7957,8 +7956,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 	 */
 	if ((action_flags & (MLX5_FLOW_XCAP_ACTIONS |
 			     MLX5_FLOW_VLAN_ACTIONS)) &&
-	    (queue_index == 0xFFFF ||
-	     mlx5_rxq_get_type(dev, queue_index) != MLX5_RXQ_TYPE_HAIRPIN ||
+	    (queue_index == 0xFFFF || !mlx5_rxq_is_hairpin(dev, queue_index) ||
 	     ((conf = mlx5_rxq_get_hairpin_conf(dev, queue_index)) != NULL &&
 	     conf->tx_explicit != 0))) {
 		if ((action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
@@ -10948,10 +10946,8 @@ flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev,
 {
 	const struct mlx5_rte_flow_item_tx_queue *queue_m;
 	const struct mlx5_rte_flow_item_tx_queue *queue_v;
-	void *misc_m =
-		MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
-	void *misc_v =
-		MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+	void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+	void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
 	struct mlx5_txq_ctrl *txq;
 	uint32_t queue, mask;
 
@@ -10962,7 +10958,7 @@ flow_dv_translate_item_tx_queue(struct rte_eth_dev *dev,
 	txq = mlx5_txq_get(dev, queue_v->queue);
 	if (!txq)
 		return;
-	if (txq->type == MLX5_TXQ_TYPE_HAIRPIN)
+	if (txq->is_hairpin)
 		queue = txq->obj->sq->id;
 	else
 		queue = txq->obj->sq_obj.sq->id;
drivers/net/mlx5/mlx5_rx.h +3 -10
index 295dba063b..fbc86dcef2 100644
@@ -141,12 +141,6 @@ struct mlx5_rxq_data {
 	/* Buffer split segment descriptions - sizes, offsets, pools. */
 } __rte_cache_aligned;
 
-enum mlx5_rxq_type {
-	MLX5_RXQ_TYPE_STANDARD, /* Standard Rx queue. */
-	MLX5_RXQ_TYPE_HAIRPIN, /* Hairpin Rx queue. */
-	MLX5_RXQ_TYPE_UNDEFINED,
-};
-
 /* RX queue control descriptor. */
 struct mlx5_rxq_ctrl {
 	struct mlx5_rxq_data rxq; /* Data path structure. */
@@ -154,7 +148,7 @@ struct mlx5_rxq_ctrl {
 	LIST_HEAD(priv, mlx5_rxq_priv) owners; /* Owner rxq list. */
 	struct mlx5_rxq_obj *obj; /* Verbs/DevX elements. */
 	struct mlx5_dev_ctx_shared *sh; /* Shared context. */
-	enum mlx5_rxq_type type; /* Rxq type. */
+	bool is_hairpin; /* Whether RxQ type is Hairpin. */
 	unsigned int socket; /* CPU socket ID for allocations. */
 	LIST_ENTRY(mlx5_rxq_ctrl) share_entry; /* Entry in shared RXQ list. */
 	uint32_t share_group; /* Group ID of shared RXQ. */
@@ -258,7 +252,7 @@ struct mlx5_hrxq *mlx5_hrxq_get(struct rte_eth_dev *dev,
 int mlx5_hrxq_obj_release(struct rte_eth_dev *dev, struct mlx5_hrxq *hrxq);
 int mlx5_hrxq_release(struct rte_eth_dev *dev, uint32_t hxrq_idx);
 uint32_t mlx5_hrxq_verify(struct rte_eth_dev *dev);
-enum mlx5_rxq_type mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx);
+bool mlx5_rxq_is_hairpin(struct rte_eth_dev *dev, uint16_t idx);
 const struct rte_eth_hairpin_conf *mlx5_rxq_get_hairpin_conf
 	(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_hrxq *mlx5_drop_action_create(struct rte_eth_dev *dev);
@@ -632,8 +626,7 @@ mlx5_mprq_enabled(struct rte_eth_dev *dev)
 	for (i = 0; i < priv->rxqs_n; ++i) {
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 
-		if (rxq_ctrl == NULL ||
-		    rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl == NULL || rxq_ctrl->is_hairpin)
 			continue;
 		n_ibv++;
 		if (mlx5_rxq_mprq_enabled(&rxq_ctrl->rxq))
drivers/net/mlx5/mlx5_rxq.c +12 -21
index e7284f9da9..e96584d55d 100644
@@ -1391,8 +1391,7 @@ mlx5_mprq_alloc_mp(struct rte_eth_dev *dev)
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 		struct mlx5_rxq_data *rxq;
 
-		if (rxq_ctrl == NULL ||
-		    rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl == NULL || rxq_ctrl->is_hairpin)
 			continue;
 		rxq = &rxq_ctrl->rxq;
 		n_ibv++;
@@ -1480,8 +1479,7 @@ mlx5_mprq_alloc_mp(struct rte_eth_dev *dev)
 	for (i = 0; i != priv->rxqs_n; ++i) {
 		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, i);
 
-		if (rxq_ctrl == NULL ||
-		    rxq_ctrl->type != MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl == NULL || rxq_ctrl->is_hairpin)
 			continue;
 		rxq_ctrl->rxq.mprq_mp = mp;
 	}
@@ -1798,7 +1796,7 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 		rte_errno = ENOSPC;
 		goto error;
 	}
-	tmpl->type = MLX5_RXQ_TYPE_STANDARD;
+	tmpl->is_hairpin = false;
 	if (mlx5_mr_ctrl_init(&tmpl->rxq.mr_ctrl,
 			      &priv->sh->cdev->mr_scache.dev_gen, socket)) {
 		/* rte_errno is already set. */
@@ -1969,7 +1967,7 @@ mlx5_rxq_hairpin_new(struct rte_eth_dev *dev, struct mlx5_rxq_priv *rxq,
 	LIST_INIT(&tmpl->owners);
 	rxq->ctrl = tmpl;
 	LIST_INSERT_HEAD(&tmpl->owners, rxq, owner_entry);
-	tmpl->type = MLX5_RXQ_TYPE_HAIRPIN;
+	tmpl->is_hairpin = true;
 	tmpl->socket = SOCKET_ID_ANY;
 	tmpl->rxq.rss_hash = 0;
 	tmpl->rxq.port_id = dev->data->port_id;
@@ -2120,7 +2118,7 @@ mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx)
 			mlx5_free(rxq_ctrl->obj);
 			rxq_ctrl->obj = NULL;
 		}
-		if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) {
+		if (!rxq_ctrl->is_hairpin) {
 			if (!rxq_ctrl->started)
 				rxq_free_elts(rxq_ctrl);
 			dev->data->rx_queue_state[idx] =
@@ -2129,7 +2127,7 @@ mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx)
 	} else { /* Refcnt zero, closing device. */
 		LIST_REMOVE(rxq, owner_entry);
 		if (LIST_EMPTY(&rxq_ctrl->owners)) {
-			if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD)
+			if (!rxq_ctrl->is_hairpin)
 				mlx5_mr_btree_free
 					(&rxq_ctrl->rxq.mr_ctrl.cache_bh);
 			if (rxq_ctrl->rxq.shared)
@@ -2169,7 +2167,7 @@ mlx5_rxq_verify(struct rte_eth_dev *dev)
 }
 
 /**
- * Get a Rx queue type.
+ * Check whether RxQ type is Hairpin.
  *
  * @param dev
  *   Pointer to Ethernet device.
@@ -2177,17 +2175,15 @@ mlx5_rxq_verify(struct rte_eth_dev *dev)
  *   Rx queue index.
  *
  * @return
- *   The Rx queue type.
+ *   True if Rx queue type is Hairpin, otherwise False.
  */
-enum mlx5_rxq_type
-mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx)
+bool
+mlx5_rxq_is_hairpin(struct rte_eth_dev *dev, uint16_t idx)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev, idx);
 
-	if (idx < priv->rxqs_n && rxq_ctrl != NULL)
-		return rxq_ctrl->type;
-	return MLX5_RXQ_TYPE_UNDEFINED;
+	return (idx < priv->rxqs_n && rxq_ctrl != NULL && rxq_ctrl->is_hairpin);
 }
 
 /*
@@ -2204,14 +2200,9 @@ mlx5_rxq_get_type(struct rte_eth_dev *dev, uint16_t idx)
 const struct rte_eth_hairpin_conf *
 mlx5_rxq_get_hairpin_conf(struct rte_eth_dev *dev, uint16_t idx)
 {
-	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, idx);
 
-	if (idx < priv->rxqs_n && rxq != NULL) {
-		if (rxq->ctrl->type == MLX5_RXQ_TYPE_HAIRPIN)
-			return &rxq->hairpin_conf;
-	}
-	return NULL;
+	return mlx5_rxq_is_hairpin(dev, idx) ? &rxq->hairpin_conf : NULL;
 }
 
 /**
drivers/net/mlx5/mlx5_trigger.c +18 -18
index 74c3bc8a13..fe8b42c414 100644
@@ -59,7 +59,7 @@ mlx5_txq_start(struct rte_eth_dev *dev)
 
 		if (!txq_ctrl)
 			continue;
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD)
+		if (!txq_ctrl->is_hairpin)
 			txq_alloc_elts(txq_ctrl);
 		MLX5_ASSERT(!txq_ctrl->obj);
 		txq_ctrl->obj = mlx5_malloc(flags, sizeof(struct mlx5_txq_obj),
@@ -77,7 +77,7 @@ mlx5_txq_start(struct rte_eth_dev *dev)
 			txq_ctrl->obj = NULL;
 			goto error;
 		}
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD) {
+		if (!txq_ctrl->is_hairpin) {
 			size_t size = txq_data->cqe_s * sizeof(*txq_data->fcqs);
 
 			txq_data->fcqs = mlx5_malloc(flags, size,
@@ -167,7 +167,7 @@ mlx5_rxq_ctrl_prepare(struct rte_eth_dev *dev, struct mlx5_rxq_ctrl *rxq_ctrl,
 {
 	int ret = 0;
 
-	if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD) {
+	if (!rxq_ctrl->is_hairpin) {
 		/*
 		 * Pre-register the mempools. Regardless of whether
 		 * the implicit registration is enabled or not,
@@ -280,7 +280,7 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (!txq_ctrl)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN ||
+		if (!txq_ctrl->is_hairpin ||
 		    txq_ctrl->hairpin_conf.peers[0].port != self_port) {
 			mlx5_txq_release(dev, i);
 			continue;
@@ -299,7 +299,7 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev)
 		if (!txq_ctrl)
 			continue;
 		/* Skip hairpin queues with other peer ports. */
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN ||
+		if (!txq_ctrl->is_hairpin ||
 		    txq_ctrl->hairpin_conf.peers[0].port != self_port) {
 			mlx5_txq_release(dev, i);
 			continue;
@@ -322,7 +322,7 @@ mlx5_hairpin_auto_bind(struct rte_eth_dev *dev)
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN ||
+		if (!rxq_ctrl->is_hairpin ||
 		    rxq->hairpin_conf.peers[0].queue != i) {
 			rte_errno = ENOMEM;
 			DRV_LOG(ERR, "port %u Tx queue %d can't be binded to "
@@ -412,7 +412,7 @@ mlx5_hairpin_queue_peer_update(struct rte_eth_dev *dev, uint16_t peer_queue,
 				dev->data->port_id, peer_queue);
 			return -rte_errno;
 		}
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d is not a hairpin Txq",
 				dev->data->port_id, peer_queue);
@@ -444,7 +444,7 @@ mlx5_hairpin_queue_peer_update(struct rte_eth_dev *dev, uint16_t peer_queue,
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
+		if (!rxq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d is not a hairpin Rxq",
 				dev->data->port_id, peer_queue);
@@ -510,7 +510,7 @@ mlx5_hairpin_queue_peer_bind(struct rte_eth_dev *dev, uint16_t cur_queue,
 				dev->data->port_id, cur_queue);
 			return -rte_errno;
 		}
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Txq",
 				dev->data->port_id, cur_queue);
@@ -570,7 +570,7 @@ mlx5_hairpin_queue_peer_bind(struct rte_eth_dev *dev, uint16_t cur_queue,
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
+		if (!rxq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Rxq",
 				dev->data->port_id, cur_queue);
@@ -644,7 +644,7 @@ mlx5_hairpin_queue_peer_unbind(struct rte_eth_dev *dev, uint16_t cur_queue,
 				dev->data->port_id, cur_queue);
 			return -rte_errno;
 		}
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Txq",
 				dev->data->port_id, cur_queue);
@@ -683,7 +683,7 @@ mlx5_hairpin_queue_peer_unbind(struct rte_eth_dev *dev, uint16_t cur_queue,
 			return -rte_errno;
 		}
 		rxq_ctrl = rxq->ctrl;
-		if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) {
+		if (!rxq_ctrl->is_hairpin) {
 			rte_errno = EINVAL;
 			DRV_LOG(ERR, "port %u queue %d not a hairpin Rxq",
 				dev->data->port_id, cur_queue);
@@ -751,7 +751,7 @@ mlx5_hairpin_bind_single_port(struct rte_eth_dev *dev, uint16_t rx_port)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (txq_ctrl == NULL)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			mlx5_txq_release(dev, i);
 			continue;
 		}
@@ -791,7 +791,7 @@ mlx5_hairpin_bind_single_port(struct rte_eth_dev *dev, uint16_t rx_port)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (txq_ctrl == NULL)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			mlx5_txq_release(dev, i);
 			continue;
 		}
@@ -886,7 +886,7 @@ mlx5_hairpin_unbind_single_port(struct rte_eth_dev *dev, uint16_t rx_port)
 		txq_ctrl = mlx5_txq_get(dev, i);
 		if (txq_ctrl == NULL)
 			continue;
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+		if (!txq_ctrl->is_hairpin) {
 			mlx5_txq_release(dev, i);
 			continue;
 		}
@@ -1016,7 +1016,7 @@ mlx5_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports,
 			txq_ctrl = mlx5_txq_get(dev, i);
 			if (!txq_ctrl)
 				continue;
-			if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) {
+			if (!txq_ctrl->is_hairpin) {
 				mlx5_txq_release(dev, i);
 				continue;
 			}
@@ -1040,7 +1040,7 @@ mlx5_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports,
 			if (rxq == NULL)
 				continue;
 			rxq_ctrl = rxq->ctrl;
-			if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN)
+			if (!rxq_ctrl->is_hairpin)
 				continue;
 			pp = rxq->hairpin_conf.peers[0].port;
 			if (pp >= RTE_MAX_ETHPORTS) {
@@ -1318,7 +1318,7 @@ mlx5_traffic_enable(struct rte_eth_dev *dev)
 		if (!txq_ctrl)
 			continue;
 		/* Only Tx implicit mode requires the default Tx flow. */
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_HAIRPIN &&
+		if (txq_ctrl->is_hairpin &&
 		    txq_ctrl->hairpin_conf.tx_explicit == 0 &&
 		    txq_ctrl->hairpin_conf.peers[0].port ==
 		    priv->dev_data->port_id) {
drivers/net/mlx5/mlx5_tx.h +1 -6
index 0adc3f4839..89dac0c65a 100644
@@ -169,17 +169,12 @@ struct mlx5_txq_data {
 	/* Storage for queued packets, must be the last field. */
 } __rte_cache_aligned;
 
-enum mlx5_txq_type {
-	MLX5_TXQ_TYPE_STANDARD, /* Standard Tx queue. */
-	MLX5_TXQ_TYPE_HAIRPIN, /* Hairpin Tx queue. */
-};
-
 /* TX queue control descriptor. */
 struct mlx5_txq_ctrl {
 	LIST_ENTRY(mlx5_txq_ctrl) next; /* Pointer to the next element. */
 	uint32_t refcnt; /* Reference counter. */
 	unsigned int socket; /* CPU socket ID for allocations. */
-	enum mlx5_txq_type type; /* The txq ctrl type. */
+	bool is_hairpin; /* Whether TxQ type is Hairpin. */
 	unsigned int max_inline_data; /* Max inline data. */
 	unsigned int max_tso_header; /* Max TSO header size. */
 	struct mlx5_txq_obj *obj; /* Verbs/DevX queue object. */
drivers/net/mlx5/mlx5_txq.c +7 -7
index f128c3d1a5..0140f8b3b2 100644
@@ -527,7 +527,7 @@ txq_uar_init_secondary(struct mlx5_txq_ctrl *txq_ctrl, int fd)
 		return -rte_errno;
 	}
 
-	if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
+	if (txq_ctrl->is_hairpin)
 		return 0;
 	MLX5_ASSERT(ppriv);
 	/*
@@ -570,7 +570,7 @@ txq_uar_uninit_secondary(struct mlx5_txq_ctrl *txq_ctrl)
 		rte_errno = ENOMEM;
 	}
 
-	if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
+	if (txq_ctrl->is_hairpin)
 		return;
 	addr = ppriv->uar_table[txq_ctrl->txq.idx].db;
 	rte_mem_unmap(RTE_PTR_ALIGN_FLOOR(addr, page_size), page_size);
@@ -631,7 +631,7 @@ mlx5_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd)
 			continue;
 		txq = (*priv->txqs)[i];
 		txq_ctrl = container_of(txq, struct mlx5_txq_ctrl, txq);
-		if (txq_ctrl->type != MLX5_TXQ_TYPE_STANDARD)
+		if (txq_ctrl->is_hairpin)
 			continue;
 		MLX5_ASSERT(txq->idx == (uint16_t)i);
 		ret = txq_uar_init_secondary(txq_ctrl, fd);
@@ -1107,7 +1107,7 @@ mlx5_txq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 		goto error;
 	}
 	__atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED);
-	tmpl->type = MLX5_TXQ_TYPE_STANDARD;
+	tmpl->is_hairpin = false;
 	LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next);
 	return tmpl;
 error:
@@ -1150,7 +1150,7 @@ mlx5_txq_hairpin_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	tmpl->txq.port_id = dev->data->port_id;
 	tmpl->txq.idx = idx;
 	tmpl->hairpin_conf = *hairpin_conf;
-	tmpl->type = MLX5_TXQ_TYPE_HAIRPIN;
+	tmpl->is_hairpin = true;
 	__atomic_fetch_add(&tmpl->refcnt, 1, __ATOMIC_RELAXED);
 	LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next);
 	return tmpl;
@@ -1209,7 +1209,7 @@ mlx5_txq_release(struct rte_eth_dev *dev, uint16_t idx)
 		mlx5_free(txq_ctrl->obj);
 		txq_ctrl->obj = NULL;
 	}
-	if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD) {
+	if (!txq_ctrl->is_hairpin) {
 		if (txq_ctrl->txq.fcqs) {
 			mlx5_free(txq_ctrl->txq.fcqs);
 			txq_ctrl->txq.fcqs = NULL;
@@ -1218,7 +1218,7 @@ mlx5_txq_release(struct rte_eth_dev *dev, uint16_t idx)
 		dev->data->tx_queue_state[idx] = RTE_ETH_QUEUE_STATE_STOPPED;
 	}
 	if (!__atomic_load_n(&txq_ctrl->refcnt, __ATOMIC_RELAXED)) {
-		if (txq_ctrl->type == MLX5_TXQ_TYPE_STANDARD)
+		if (!txq_ctrl->is_hairpin)
 			mlx5_mr_btree_free(&txq_ctrl->txq.mr_ctrl.cache_bh);
 		LIST_REMOVE(txq_ctrl, next);
 		mlx5_free(txq_ctrl);
Signature · 1 line
2.25.1
#23 lore raw

PATCH v3 5/6 net/mlx5: add external RxQ mapping API

In reply to Michael Baum

External queue is a queue that has been created and managed outside the PMD. The queues owner might use PMD to generate flow rules using these external queues.

When the queue is created in hardware it is given an ID represented by 32 bits. In contrast, the index of the queues in PMD is represented by 16 bits. To enable the use of PMD to generate flow rules, the queue owner must provide a mapping between the HW index and a 16-bit index corresponding to the RTE Flow API.

This patch adds an API enabling to insert/cancel a mapping between HW queue id and RTE Flow queue id.

---
 drivers/net/mlx5/linux/mlx5_os.c |  17 +++++
 drivers/net/mlx5/mlx5.c          |   1 +
 drivers/net/mlx5/mlx5.h          |   1 +
 drivers/net/mlx5/mlx5_defs.h     |   3 +
 drivers/net/mlx5/mlx5_ethdev.c   |  16 ++++-
 drivers/net/mlx5/mlx5_rx.h       |   6 ++
 drivers/net/mlx5/mlx5_rxq.c      | 117 +++++++++++++++++++++++++++++++
 drivers/net/mlx5/rte_pmd_mlx5.h  |  50 ++++++++++++-
 drivers/net/mlx5/version.map     |   3 +
 9 files changed, 210 insertions(+), 4 deletions(-)
drivers/net/mlx5/linux/mlx5_os.c +17 -0
index 2e1606a733..a847ed13cc 100644
@@ -1158,6 +1158,22 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		err = ENOMEM;
 		goto error;
 	}
+	/*
+	 * When user configures remote PD and CTX and device creates RxQ by
+	 * DevX, external RxQ is both supported and requested.
+	 */
+	if (mlx5_imported_pd_and_ctx(sh->cdev) && mlx5_devx_obj_ops_en(sh)) {
+		priv->ext_rxqs = mlx5_malloc(MLX5_MEM_ZERO | MLX5_MEM_RTE,
+					     sizeof(struct mlx5_external_rxq) *
+					     MLX5_MAX_EXT_RX_QUEUES, 0,
+					     SOCKET_ID_ANY);
+		if (priv->ext_rxqs == NULL) {
+			DRV_LOG(ERR, "Fail to allocate external RxQ array.");
+			err = ENOMEM;
+			goto error;
+		}
+		DRV_LOG(DEBUG, "External RxQ is supported.");
+	}
 	priv->sh = sh;
 	priv->dev_port = spawn->phys_port;
 	priv->pci_dev = spawn->pci_dev;
@@ -1617,6 +1633,7 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 			mlx5_list_destroy(priv->hrxqs);
 		if (eth_dev && priv->flex_item_map)
 			mlx5_flex_item_port_cleanup(eth_dev);
+		mlx5_free(priv->ext_rxqs);
 		mlx5_free(priv);
 		if (eth_dev != NULL)
 			eth_dev->data->dev_private = NULL;
drivers/net/mlx5/mlx5.c +1 -0
index 7611fdd62b..5ecca2dd1b 100644
@@ -1930,6 +1930,7 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 			dev->data->port_id);
 	if (priv->hrxqs)
 		mlx5_list_destroy(priv->hrxqs);
+	mlx5_free(priv->ext_rxqs);
 	/*
 	 * Free the shared context in last turn, because the cleanup
 	 * routines above may use some shared fields, like
drivers/net/mlx5/mlx5.h +1 -0
index bd69aa2334..0f825396a2 100644
@@ -1461,6 +1461,7 @@ struct mlx5_priv {
 	/* RX/TX queues. */
 	unsigned int rxqs_n; /* RX queues array size. */
 	unsigned int txqs_n; /* TX queues array size. */
+	struct mlx5_external_rxq *ext_rxqs; /* External RX queues array. */
 	struct mlx5_rxq_priv *(*rxq_privs)[]; /* RX queue non-shared data. */
 	struct mlx5_txq_data *(*txqs)[]; /* TX queues. */
 	struct rte_mempool *mprq_mp; /* Mempool for Multi-Packet RQ. */
drivers/net/mlx5/mlx5_defs.h +3 -0
index 2d48fde010..15728fb41f 100644
@@ -175,6 +175,9 @@
 /* Maximum number of indirect actions supported by rte_flow */
 #define MLX5_MAX_INDIRECT_ACTIONS 3
 
+/* Maximum number of external Rx queues supported by rte_flow */
+#define MLX5_MAX_EXT_RX_QUEUES (UINT16_MAX - MLX5_EXTERNAL_RX_QUEUE_ID_MIN + 1)
+
 /*
  * Linux definition of static_assert is found in /usr/include/assert.h.
  * Windows does not require a redefinition.
drivers/net/mlx5/mlx5_ethdev.c +13 -3
index 406761ccf8..de0ba2b1ff 100644
@@ -27,6 +27,7 @@
 #include "mlx5_tx.h"
 #include "mlx5_autoconf.h"
 #include "mlx5_devx.h"
+#include "rte_pmd_mlx5.h"
 
 /**
  * Get the interface index from device name.
@@ -81,9 +82,10 @@ mlx5_dev_configure(struct rte_eth_dev *dev)
 		rte_errno = EINVAL;
 		return -rte_errno;
 	}
-	priv->rss_conf.rss_key =
-		mlx5_realloc(priv->rss_conf.rss_key, MLX5_MEM_RTE,
-			    MLX5_RSS_HASH_KEY_LEN, 0, SOCKET_ID_ANY);
+	priv->rss_conf.rss_key = mlx5_realloc(priv->rss_conf.rss_key,
+					      MLX5_MEM_RTE,
+					      MLX5_RSS_HASH_KEY_LEN, 0,
+					      SOCKET_ID_ANY);
 	if (!priv->rss_conf.rss_key) {
 		DRV_LOG(ERR, "port %u cannot allocate RSS hash key memory (%u)",
 			dev->data->port_id, rxqs_n);
@@ -127,6 +129,14 @@ mlx5_dev_configure(struct rte_eth_dev *dev)
 		rte_errno = EINVAL;
 		return -rte_errno;
 	}
+	if (priv->ext_rxqs && rxqs_n >= MLX5_EXTERNAL_RX_QUEUE_ID_MIN) {
+		DRV_LOG(ERR, "port %u cannot handle this many Rx queues (%u), "
+			"the maximal number of internal Rx queues is %u",
+			dev->data->port_id, rxqs_n,
+			MLX5_EXTERNAL_RX_QUEUE_ID_MIN - 1);
+		rte_errno = EINVAL;
+		return -rte_errno;
+	}
 	if (rxqs_n != priv->rxqs_n) {
 		DRV_LOG(INFO, "port %u Rx queues number update: %u -> %u",
 			dev->data->port_id, priv->rxqs_n, rxqs_n);
drivers/net/mlx5/mlx5_rx.h +6 -0
index fbc86dcef2..aba05dffa7 100644
@@ -175,6 +175,12 @@ struct mlx5_rxq_priv {
 	uint32_t hairpin_status; /* Hairpin binding status. */
 };
 
+/* External RX queue descriptor. */
+struct mlx5_external_rxq {
+	uint32_t hw_id; /* Queue index in the Hardware. */
+	uint32_t refcnt; /* Reference counter. */
+};
+
 /* mlx5_rxq.c */
 
 extern uint8_t rss_hash_default_key[];
drivers/net/mlx5/mlx5_rxq.c +117 -0

126 lines not on this page · raw message

drivers/net/mlx5/rte_pmd_mlx5.h +49 -1

57 lines not on this page · raw message

drivers/net/mlx5/version.map +3 -0
index 0af7a12488..79cb79acc6 100644
@@ -9,4 +9,7 @@ EXPERIMENTAL {
 	rte_pmd_mlx5_get_dyn_flag_names;
 	# added in 20.11
 	rte_pmd_mlx5_sync_flow;
+	# added in 22.03
+	rte_pmd_mlx5_external_rx_queue_id_map;
+	rte_pmd_mlx5_external_rx_queue_id_unmap;
 };
Signature · 1 line
2.25.1
#24 lore raw

PATCH v3 6/6 net/mlx5: support queue/RSS action for external RxQ

In reply to Michael Baum

Add support queue/RSS action for external RxQ.
In indirection table creation, the queue index will be taken from mapping array.

This feature supports neither LRO nor Hairpin.

---
 doc/guides/nics/mlx5.rst               |   1 +
 doc/guides/rel_notes/release_22_03.rst |   1 +
 drivers/net/mlx5/mlx5.c                |   4 +
 drivers/net/mlx5/mlx5_devx.c           |  30 +++++--
 drivers/net/mlx5/mlx5_flow.c           |  29 +++++--
 drivers/net/mlx5/mlx5_rx.h             |  30 +++++++
 drivers/net/mlx5/mlx5_rxq.c            | 116 +++++++++++++++++++++++--
 7 files changed, 187 insertions(+), 24 deletions(-)
doc/guides/nics/mlx5.rst +1 -0
index 7b04e9bac5..a5b3298f0c 100644
@@ -38,6 +38,7 @@ Features
 - Multiple TX and RX queues.
 - Shared Rx queue.
 - Rx queue delay drop.
+- Support steering for external Rx queue created outside the PMD.
 - Support for scattered TX frames.
 - Advanced support for scattered Rx frames with tunable buffer attributes.
 - IPv4, IPv6, TCPv4, TCPv6, UDPv4 and UDPv6 RSS on any number of queues.
doc/guides/rel_notes/release_22_03.rst +1 -0
index e66548558c..a29e96c37c 100644
@@ -164,6 +164,7 @@ New Features
 
   * Support ConnectX-7 capability to schedule traffic sending on timestamp
   * Added WQE based hardware steering support with ``rte_flow_async`` API.
+  * Support steering for external Rx queue created outside the PMD.
 
 * **Updated Wangxun ngbe driver.**
 
drivers/net/mlx5/mlx5.c +4 -0
index 5ecca2dd1b..74841caaf9 100644
@@ -1912,6 +1912,10 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 	if (ret)
 		DRV_LOG(WARNING, "port %u some Rx queue objects still remain",
 			dev->data->port_id);
+	ret = mlx5_ext_rxq_verify(dev);
+	if (ret)
+		DRV_LOG(WARNING, "Port %u some external RxQ still remain.",
+			dev->data->port_id);
 	ret = mlx5_rxq_verify(dev);
 	if (ret)
 		DRV_LOG(WARNING, "port %u some Rx queues still remain",
drivers/net/mlx5/mlx5_devx.c +21 -9
index bcd2358165..af106bda50 100644
@@ -580,13 +580,21 @@ mlx5_devx_ind_table_create_rqt_attr(struct rte_eth_dev *dev,
 		return rqt_attr;
 	}
 	for (i = 0; i != queues_n; ++i) {
-		struct mlx5_rxq_priv *rxq = mlx5_rxq_get(dev, queues[i]);
+		if (mlx5_is_external_rxq(dev, queues[i])) {
+			struct mlx5_external_rxq *ext_rxq =
+					mlx5_ext_rxq_get(dev, queues[i]);
 
-		MLX5_ASSERT(rxq != NULL);
-		if (rxq->ctrl->is_hairpin)
-			rqt_attr->rq_list[i] = rxq->ctrl->obj->rq->id;
-		else
-			rqt_attr->rq_list[i] = rxq->devx_rq.rq->id;
+			rqt_attr->rq_list[i] = ext_rxq->hw_id;
+		} else {
+			struct mlx5_rxq_priv *rxq =
+					mlx5_rxq_get(dev, queues[i]);
+
+			MLX5_ASSERT(rxq != NULL);
+			if (rxq->ctrl->is_hairpin)
+				rqt_attr->rq_list[i] = rxq->ctrl->obj->rq->id;
+			else
+				rqt_attr->rq_list[i] = rxq->devx_rq.rq->id;
+		}
 	}
 	MLX5_ASSERT(i > 0);
 	for (j = 0; i != rqt_n; ++j, ++i)
@@ -711,7 +719,13 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 	uint32_t i;
 
 	/* NULL queues designate drop queue. */
-	if (ind_tbl->queues != NULL) {
+	if (ind_tbl->queues == NULL) {
+		is_hairpin = priv->drop_queue.rxq->ctrl->is_hairpin;
+	} else if (mlx5_is_external_rxq(dev, ind_tbl->queues[0])) {
+		/* External RxQ supports neither Hairpin nor LRO. */
+		is_hairpin = false;
+		lro = false;
+	} else {
 		is_hairpin = mlx5_rxq_is_hairpin(dev, ind_tbl->queues[0]);
 		/* Enable TIR LRO only if all the queues were configured for. */
 		for (i = 0; i < ind_tbl->queues_n; ++i) {
@@ -723,8 +737,6 @@ mlx5_devx_tir_attr_set(struct rte_eth_dev *dev, const uint8_t *rss_key,
 				break;
 			}
 		}
-	} else {
-		is_hairpin = priv->drop_queue.rxq->ctrl->is_hairpin;
 	}
 	memset(tir_attr, 0, sizeof(*tir_attr));
 	tir_attr->disp_type = MLX5_TIRC_DISP_TYPE_INDIRECT;
drivers/net/mlx5/mlx5_flow.c +20 -9
index 09701a73c1..3875160708 100644
@@ -1743,6 +1743,12 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have 2 fate actions in"
 					  " same flow");
+	if (attr->egress)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+					  "queue action not supported for egress.");
+	if (mlx5_is_external_rxq(dev, queue->index))
+		return 0;
 	if (!priv->rxqs_n)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
@@ -1757,11 +1763,6 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  &queue->index,
 					  "queue is not configured");
-	if (attr->egress)
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
-					  "queue action not supported for "
-					  "egress");
 	return 0;
 }
 
@@ -1776,7 +1777,7 @@ mlx5_flow_validate_action_queue(const struct rte_flow_action *action,
  *   Size of the @p queues array.
  * @param[out] error
  *   On error, filled with a textual error description.
- * @param[out] queue
+ * @param[out] queue_idx
  *   On error, filled with an offending queue index in @p queues array.
  *
  * @return
@@ -1789,17 +1790,27 @@ mlx5_validate_rss_queues(struct rte_eth_dev *dev,
 {
 	const struct mlx5_priv *priv = dev->data->dev_private;
 	bool is_hairpin = false;
+	bool is_ext_rss = false;
 	uint32_t i;
 
 	for (i = 0; i != queues_n; ++i) {
-		struct mlx5_rxq_ctrl *rxq_ctrl = mlx5_rxq_ctrl_get(dev,
-								   queues[i]);
+		struct mlx5_rxq_ctrl *rxq_ctrl;
 
+		if (mlx5_is_external_rxq(dev, queues[0])) {
+			is_ext_rss = true;
+			continue;
+		}
+		if (is_ext_rss) {
+			*error = "Combining external and regular RSS queues is not supported";
+			*queue_idx = i;
+			return -ENOTSUP;
+		}
 		if (queues[i] >= priv->rxqs_n) {
 			*error = "queue index out of range";
 			*queue_idx = i;
 			return -EINVAL;
 		}
+		rxq_ctrl = mlx5_rxq_ctrl_get(dev, queues[i]);
 		if (rxq_ctrl == NULL) {
 			*error =  "queue is not configured";
 			*queue_idx = i;
@@ -1894,7 +1905,7 @@ mlx5_validate_action_rss(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
 					  "L4 partial RSS requested but L4 RSS"
 					  " type not specified");
-	if (!priv->rxqs_n)
+	if (!priv->rxqs_n && priv->ext_rxqs == NULL)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  NULL, "No Rx queues configured");
drivers/net/mlx5/mlx5_rx.h +30 -0
index aba05dffa7..acebe3348c 100644
@@ -18,6 +18,7 @@
 
 #include "mlx5.h"
 #include "mlx5_autoconf.h"
+#include "rte_pmd_mlx5.h"
 
 /* Support tunnel matching. */
 #define MLX5_FLOW_TUNNEL 10
@@ -217,8 +218,14 @@ uint32_t mlx5_rxq_deref(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_rxq_priv *mlx5_rxq_get(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_rxq_ctrl *mlx5_rxq_ctrl_get(struct rte_eth_dev *dev, uint16_t idx);
 struct mlx5_rxq_data *mlx5_rxq_data_get(struct rte_eth_dev *dev, uint16_t idx);
+struct mlx5_external_rxq *mlx5_ext_rxq_ref(struct rte_eth_dev *dev,
+					   uint16_t idx);
+uint32_t mlx5_ext_rxq_deref(struct rte_eth_dev *dev, uint16_t idx);
+struct mlx5_external_rxq *mlx5_ext_rxq_get(struct rte_eth_dev *dev,
+					   uint16_t idx);
 int mlx5_rxq_release(struct rte_eth_dev *dev, uint16_t idx);
 int mlx5_rxq_verify(struct rte_eth_dev *dev);
+int mlx5_ext_rxq_verify(struct rte_eth_dev *dev);
 int rxq_alloc_elts(struct mlx5_rxq_ctrl *rxq_ctrl);
 int mlx5_ind_table_obj_verify(struct rte_eth_dev *dev);
 struct mlx5_ind_table_obj *mlx5_ind_table_obj_get(struct rte_eth_dev *dev,
@@ -643,4 +650,27 @@ mlx5_mprq_enabled(struct rte_eth_dev *dev)
 	return n == n_ibv;
 }
 
+/**
+ * Check whether given RxQ is external.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ * @param queue_idx
+ *   Rx queue index.
+ *
+ * @return
+ *   True if is external RxQ, otherwise false.
+ */
+static __rte_always_inline bool
+mlx5_is_external_rxq(struct rte_eth_dev *dev, uint16_t queue_idx)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_external_rxq *rxq;
+
+	if (!priv->ext_rxqs || queue_idx < MLX5_EXTERNAL_RX_QUEUE_ID_MIN)
+		return false;
+	rxq = &priv->ext_rxqs[queue_idx - MLX5_EXTERNAL_RX_QUEUE_ID_MIN];
+	return !!__atomic_load_n(&rxq->refcnt, __ATOMIC_RELAXED);
+}
+
 #endif /* RTE_PMD_MLX5_RX_H_ */
drivers/net/mlx5/mlx5_rxq.c +110 -6

147 lines not on this page · raw message

Signature · 1 line
2.25.1
#25 lore raw
In reply to Michael Baum
Quoted 7 lines

Michael Baum (6):
common/mlx5: consider local functions as internal common/mlx5: glue device and PD importation common/mlx5: add remote PD and CTX support net/mlx5: optimize RxQ/TxQ control structure net/mlx5: add external RxQ mapping API net/mlx5: support queue/RSS action for external RxQ

Applied in next-net-mlx, thanks.