From patchwork Thu Oct 22 14:06:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bing Zhao X-Patchwork-Id: 81792 X-Patchwork-Delegate: rasland@nvidia.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id B860DA04DD; Thu, 22 Oct 2020 16:07:58 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id B8A51AA0B; Thu, 22 Oct 2020 16:07:06 +0200 (CEST) Received: from git-send-mailer.rdmz.labs.mlnx (unknown [37.142.13.130]) by dpdk.org (Postfix) with ESMTP id 1B1DBAA01 for ; Thu, 22 Oct 2020 16:06:52 +0200 (CEST) From: Bing Zhao To: viacheslavo@mellanox.com, matan@mellanox.com Cc: dev@dpdk.org, orika@nvidia.com, rasland@nvidia.com Date: Thu, 22 Oct 2020 22:06:34 +0800 Message-Id: <1603375597-430528-4-git-send-email-bingz@nvidia.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1603375597-430528-1-git-send-email-bingz@nvidia.com> References: <1602166620-46303-1-git-send-email-bingz@nvidia.com> <1603375597-430528-1-git-send-email-bingz@nvidia.com> Subject: [dpdk-dev] [PATCH v2 3/6] net/mlx5: add support to get hairpin peer ports X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" In real-life business, one device could be attached and detached dynamically. The hairpin configuration of this port to/from all the other ports should be enabled and disabled accordingly. The RTE ethdev lib and PMD should provide this ability to get the peer ports list in case that the application doesn't save it. It is recommended that the size of the array to save the port IDs is as large as the "RTE_MAX_ETHPORTS" to have the maximal capacity. The order of the peer port IDs may be different from that during hairpin queues set in the initialization stage. The peer port ID could be the same as the current device port ID when the hairpin peer ports contain itself - the single port hairpin. The application should check the ports' status and decide if the peer port should be bound / unbound when starting / stopping the current device. Signed-off-by: Bing Zhao Acked-by: Viacheslav Ovsiienko --- drivers/net/mlx5/linux/mlx5_os.c | 2 + drivers/net/mlx5/mlx5.h | 2 + drivers/net/mlx5/mlx5_trigger.c | 89 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c index 83a8b56..17d3767 100644 --- a/drivers/net/mlx5/linux/mlx5_os.c +++ b/drivers/net/mlx5/linux/mlx5_os.c @@ -2554,6 +2554,7 @@ .mtr_ops_get = mlx5_flow_meter_ops_get, .hairpin_bind = mlx5_hairpin_bind, .hairpin_unbind = mlx5_hairpin_unbind, + .hairpin_get_peer_ports = mlx5_hairpin_get_peer_ports, .hairpin_queue_peer_update = mlx5_hairpin_queue_peer_update, .hairpin_queue_peer_bind = mlx5_hairpin_queue_peer_bind, .hairpin_queue_peer_unbind = mlx5_hairpin_queue_peer_unbind, @@ -2637,6 +2638,7 @@ .mtr_ops_get = mlx5_flow_meter_ops_get, .hairpin_bind = mlx5_hairpin_bind, .hairpin_unbind = mlx5_hairpin_unbind, + .hairpin_get_peer_ports = mlx5_hairpin_get_peer_ports, .hairpin_queue_peer_update = mlx5_hairpin_queue_peer_update, .hairpin_queue_peer_bind = mlx5_hairpin_queue_peer_bind, .hairpin_queue_peer_unbind = mlx5_hairpin_queue_peer_unbind, diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 38d0977..70a0d3d 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -1060,6 +1060,8 @@ int mlx5_hairpin_queue_peer_unbind(struct rte_eth_dev *dev, uint16_t cur_queue, uint32_t direction); int mlx5_hairpin_bind(struct rte_eth_dev *dev, uint16_t rx_port); int mlx5_hairpin_unbind(struct rte_eth_dev *dev, uint16_t rx_port); +int mlx5_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports, + size_t len, uint32_t direction); /* mlx5_flow.c */ diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c index 800645e..497f731 100644 --- a/drivers/net/mlx5/mlx5_trigger.c +++ b/drivers/net/mlx5/mlx5_trigger.c @@ -888,6 +888,95 @@ return ret; } +/* + * DPDK callback to get the hairpin peer ports list. + * This will return the actual number of peer ports and save the identifiers + * into the array (sorted, may be different from that when setting up the + * hairpin peer queues). + * The peer port ID could be the same as the port ID of the current device. + * + * @param dev + * Pointer to Ethernet device structure. + * @param peer_ports + * Pointer to array to save the port identifiers. + * @param len + * The length of the array. + * @param direction + * Current port to peer port direction. + * positive - current used as Tx to get all peer Rx ports. + * zero - current used as Rx to get all peer Tx ports. + * + * @return + * 0 or positive value on success, actual number of peer ports. + * a negative errno value otherwise and rte_errno is set. + */ +int +mlx5_hairpin_get_peer_ports(struct rte_eth_dev *dev, uint16_t *peer_ports, + size_t len, uint32_t direction) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_txq_ctrl *txq_ctrl; + struct mlx5_rxq_ctrl *rxq_ctrl; + uint32_t i; + uint16_t pp; + uint32_t bits[(RTE_MAX_ETHPORTS + 31) / 32] = {0}; + int ret = 0; + + if (direction) { + for (i = 0; i < priv->txqs_n; i++) { + txq_ctrl = mlx5_txq_get(dev, i); + if (!txq_ctrl) + continue; + if (txq_ctrl->type != MLX5_TXQ_TYPE_HAIRPIN) { + mlx5_txq_release(dev, i); + continue; + } + pp = txq_ctrl->hairpin_conf.peers[0].port; + if (pp >= RTE_MAX_ETHPORTS) { + rte_errno = ERANGE; + mlx5_txq_release(dev, i); + DRV_LOG(ERR, "port %hu queue %u peer port " + "out of range %hu", + priv->dev_data->port_id, i, pp); + return -rte_errno; + } + bits[pp / 32] |= 1 << (pp % 32); + mlx5_txq_release(dev, i); + } + } else { + for (i = 0; i < priv->rxqs_n; i++) { + rxq_ctrl = mlx5_rxq_get(dev, i); + if (!rxq_ctrl) + continue; + if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN) { + mlx5_rxq_release(dev, i); + continue; + } + pp = rxq_ctrl->hairpin_conf.peers[0].port; + if (pp >= RTE_MAX_ETHPORTS) { + rte_errno = ERANGE; + mlx5_rxq_release(dev, i); + DRV_LOG(ERR, "port %hu queue %u peer port " + "out of range %hu", + priv->dev_data->port_id, i, pp); + return -rte_errno; + } + bits[pp / 32] |= 1 << (pp % 32); + mlx5_rxq_release(dev, i); + } + } + for (i = 0; i < RTE_MAX_ETHPORTS; i++) { + if (bits[i / 32] & (1 << (i % 32))) { + if ((size_t)ret >= len) { + rte_errno = E2BIG; + return -rte_errno; + } + peer_ports[ret++] = i; + } + } + return ret; +} + /** * DPDK callback to start the device. *