mlx5: external RxQ support
Subsystems (2)
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
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
@@ -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
@@ -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
PATCH 2/6 common/mlx5: add remote PD and CTX support
In reply to Michael BaumAdd 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
@@ -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. + 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.
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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 3/6 net/mlx5: optimize RxQ/TxQ control structure
In reply to Michael BaumThe 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 4/6 net/mlx5: add external RxQ mapping API
In reply to Michael BaumExternal 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 5/6 net/mlx5: support queue/RSS action for external RxQ
In reply to Michael BaumAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 6/6 app/testpmd: add test for external RxQ
In reply to Michael BaumAdd 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
@@ -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
@@ -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
@@ -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
v2 cover mlx5: external RxQ support
In reply to Michael BaumThese 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
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
@@ -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\.
drivers/common/mlx5/linux/mlx5_common_os.h +1 -0
@@ -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 intmlx5_get_device_guid (const struct rte_pci_addr *dev,uint8_t *guid,size_t len);
drivers/common/mlx5/version.map +3 -0
@@ -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
PATCH v2 2/6 common/mlx5: glue device and PD importation
In reply to Michael BaumAdd 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
@@ -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
@@ -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
PATCH v2 3/6 common/mlx5: add remote PD and CTX support
In reply to Michael BaumAdd 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
@@ -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. + 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.
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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v2 4/6 net/mlx5: optimize RxQ/TxQ control structure
In reply to Michael BaumThe 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v2 5/6 net/mlx5: add external RxQ mapping API
In reply to Michael BaumExternal 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v2 6/6 net/mlx5: support queue/RSS action for external RxQ
In reply to Michael BaumAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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_flowindexes 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 RxQdevtools/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
v3 cover mlx5: external RxQ support
In reply to Michael BaumThese 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
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
@@ -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\.
drivers/common/mlx5/linux/mlx5_common_os.h +1 -0
@@ -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 intmlx5_get_device_guid (const struct rte_pci_addr *dev,uint8_t *guid,size_t len);
drivers/common/mlx5/version.map +3 -0
@@ -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
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 functionmlx5_get_device_guidis 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
Signed-off-by Michael Baum <[email protected]>Acked-by Matan Azrad <[email protected]>
<...>
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 functionmlx5_get_device_guidis 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.
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 functionmlx5_get_device_guidis 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
PATCH v3 2/6 common/mlx5: glue device and PD importation
In reply to Michael BaumAdd 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
@@ -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
@@ -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
PATCH v3 3/6 common/mlx5: add remote PD and CTX support
In reply to Michael BaumAdd 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
@@ -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. + 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.
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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v3 4/6 net/mlx5: optimize RxQ/TxQ control structure
In reply to Michael BaumThe 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v3 5/6 net/mlx5: add external RxQ mapping API
In reply to Michael BaumExternal 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v3 6/6 net/mlx5: support queue/RSS action for external RxQ
In reply to Michael BaumAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Thomas Monjalon
AppliedQuoted 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.