From: Tonghao Zhang <xiangxia.m....@gmail.com>

In the dpdk upstream, each hairpin Rxq can be connected
Txq which can belong to a same port. This patch allows
Rxq connected to different port Txq.

rte_eth_hairpin_conf_check will check the hairpin_conf valid
in high level.

Signed-off-by: Tonghao Zhang <xiangxia.m....@gmail.com>
---
 drivers/net/mlx5/mlx5_rxq.c     |  5 ++-
 drivers/net/mlx5/mlx5_trigger.c | 41 ++++++++++++++++-------
 drivers/net/mlx5/mlx5_txq.c     |  4 +--
 lib/librte_ethdev/rte_ethdev.c  | 73 ++++++++++++++++++++++++++++-------------
 4 files changed, 83 insertions(+), 40 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c
index 986ec01..c2daebd 100644
--- a/drivers/net/mlx5/mlx5_rxq.c
+++ b/drivers/net/mlx5/mlx5_rxq.c
@@ -547,9 +547,8 @@
        res = mlx5_rx_queue_pre_setup(dev, idx, desc);
        if (res)
                return res;
-       if (hairpin_conf->peer_count != 1 ||
-           hairpin_conf->peers[0].port != dev->data->port_id ||
-           hairpin_conf->peers[0].queue >= priv->txqs_n) {
+
+       if (hairpin_conf->peer_count != 1) {
                DRV_LOG(ERR, "port %u unable to setup hairpin queue index %u "
                        " invalid hairpind configuration", dev->data->port_id,
                        idx);
diff --git a/drivers/net/mlx5/mlx5_trigger.c b/drivers/net/mlx5/mlx5_trigger.c
index ab6937a..3eb2984 100644
--- a/drivers/net/mlx5/mlx5_trigger.c
+++ b/drivers/net/mlx5/mlx5_trigger.c
@@ -185,6 +185,10 @@
        struct mlx5_rxq_ctrl *rxq_ctrl;
        struct mlx5_devx_obj *sq;
        struct mlx5_devx_obj *rq;
+       struct rte_eth_dev *rxq_dev;
+       struct mlx5_priv *rxq_priv;
+       uint16_t peer_queue_id;
+       uint16_t peer_port_id;
        unsigned int i;
        int ret = 0;
 
@@ -203,37 +207,50 @@
                        mlx5_txq_release(dev, i);
                        return -rte_errno;
                }
-               sq = txq_ctrl->obj->sq;
-               rxq_ctrl = mlx5_rxq_get(dev,
-                                       txq_ctrl->hairpin_conf.peers[0].queue);
+               peer_port_id = txq_ctrl->hairpin_conf.peers[0].port;
+               peer_queue_id = txq_ctrl->hairpin_conf.peers[0].queue;
+               rxq_dev = &rte_eth_devices[peer_port_id];
+               rxq_priv = rxq_dev->data->dev_private;
+
+               rxq_ctrl = mlx5_rxq_get(rxq_dev, peer_queue_id);
                if (!rxq_ctrl) {
                        mlx5_txq_release(dev, i);
                        rte_errno = EINVAL;
                        DRV_LOG(ERR, "port %u no rxq object found: %d",
-                               dev->data->port_id,
-                               txq_ctrl->hairpin_conf.peers[0].queue);
+                               peer_port_id, peer_queue_id);
                        return -rte_errno;
                }
                if (rxq_ctrl->type != MLX5_RXQ_TYPE_HAIRPIN ||
                    rxq_ctrl->hairpin_conf.peers[0].queue != i) {
                        rte_errno = ENOMEM;
                        DRV_LOG(ERR, "port %u Tx queue %d can't be binded to "
-                               "Rx queue %d", dev->data->port_id,
-                               i, txq_ctrl->hairpin_conf.peers[0].queue);
+                               "port %u Rx queue %d",
+                               dev->data->port_id, i,
+                               peer_port_id, peer_queue_id);
                        goto error;
                }
+               if (!rxq_ctrl->obj) {
+                       DRV_LOG(ERR, "port %u rxq obj not created, "
+                               "you may start it firstly.",
+                               peer_port_id);
+                       goto error;
+               }
+
+               sq = txq_ctrl->obj->sq;
                rq = rxq_ctrl->obj->rq;
                if (!rq) {
                        rte_errno = ENOMEM;
-                       DRV_LOG(ERR, "port %u hairpin no matching rxq: %d",
+                       DRV_LOG(ERR, "port %u hairpin no matching port"
+                               " %u rxq %d",
                                dev->data->port_id,
-                               txq_ctrl->hairpin_conf.peers[0].queue);
+                               peer_port_id,
+                               peer_queue_id);
                        goto error;
                }
                sq_attr.state = MLX5_SQC_STATE_RDY;
                sq_attr.sq_state = MLX5_SQC_STATE_RST;
                sq_attr.hairpin_peer_rq = rq->id;
-               sq_attr.hairpin_peer_vhca = priv->config.hca_attr.vhca_id;
+               sq_attr.hairpin_peer_vhca = rxq_priv->config.hca_attr.vhca_id;
                ret = mlx5_devx_cmd_modify_sq(sq, &sq_attr);
                if (ret)
                        goto error;
@@ -245,12 +262,12 @@
                if (ret)
                        goto error;
                mlx5_txq_release(dev, i);
-               mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue);
+               mlx5_rxq_release(rxq_dev, peer_queue_id);
        }
        return 0;
 error:
        mlx5_txq_release(dev, i);
-       mlx5_rxq_release(dev, txq_ctrl->hairpin_conf.peers[0].queue);
+       mlx5_rxq_release(dev, peer_queue_id);
        return -rte_errno;
 }
 
diff --git a/drivers/net/mlx5/mlx5_txq.c b/drivers/net/mlx5/mlx5_txq.c
index bac4f71..98ee35e 100644
--- a/drivers/net/mlx5/mlx5_txq.c
+++ b/drivers/net/mlx5/mlx5_txq.c
@@ -254,9 +254,7 @@
        res = mlx5_tx_queue_pre_setup(dev, idx, desc);
        if (res)
                return res;
-       if (hairpin_conf->peer_count != 1 ||
-           hairpin_conf->peers[0].port != dev->data->port_id ||
-           hairpin_conf->peers[0].queue >= priv->rxqs_n) {
+       if (hairpin_conf->peer_count != 1) {
                DRV_LOG(ERR, "port %u unable to setup hairpin queue index %u "
                        " invalid hairpind configuration", dev->data->port_id,
                        idx);
diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c
index 8d2ce31..0bd6d87 100644
--- a/lib/librte_ethdev/rte_ethdev.c
+++ b/lib/librte_ethdev/rte_ethdev.c
@@ -1923,6 +1923,53 @@ struct rte_eth_dev *
        return eth_err(port_id, ret);
 }
 
+static int
+rte_eth_hairpin_conf_check(const struct rte_eth_hairpin_conf *conf,
+                             const struct rte_eth_hairpin_cap *cap,
+                             bool is_rx_hairpin)
+{
+       uint16_t max_queues_mapping = is_rx_hairpin ?
+                                     cap->max_rx_2_tx : cap->max_tx_2_rx;
+       struct rte_eth_dev *dev;
+       uint16_t nb_queues;
+       uint16_t port_id;
+       int i;
+
+       if (conf->peer_count == 0) {
+               RTE_ETHDEV_LOG(ERR, "Invalid value for number of peers(=%hu),"
+                               " should be: > 0",
+                              conf->peer_count);
+               return -EINVAL;
+       }
+       if (conf->peer_count > max_queues_mapping) {
+               RTE_ETHDEV_LOG(ERR, "Invalid value for number of peers(=%hu),"
+                              " should be: <= %hu",
+                              conf->peer_count, max_queues_mapping);
+               return -EINVAL;
+       }
+       for (i = 0; i < conf->peer_count; i++) {
+               port_id = conf->peers[i].port;
+
+               if (!rte_eth_dev_is_valid_port(port_id)) {
+                       RTE_ETHDEV_LOG(ERR, "Invalid port_id(=%hu) for"
+                                      " hairpin peers", conf->peer_count);
+                       return -EINVAL;
+               }
+
+               dev = &rte_eth_devices[port_id];
+               nb_queues = is_rx_hairpin ?
+                           dev->data->nb_tx_queues : dev->data->nb_rx_queues;
+               if (conf->peers[i].queue >= nb_queues) {
+                       RTE_ETHDEV_LOG(ERR, "Invalid queue_id(=%hu) for"
+                                      " hairpin peers, shoud be < %hu",
+                                      conf->peer_count, nb_queues);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
 int
 rte_eth_rx_hairpin_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
                               uint16_t nb_rx_desc,
@@ -1956,18 +2003,9 @@ struct rte_eth_dev *
                        nb_rx_desc, cap.max_nb_desc);
                return -EINVAL;
        }
-       if (conf->peer_count > cap.max_rx_2_tx) {
-               RTE_ETHDEV_LOG(ERR,
-                       "Invalid value for number of peers for Rx queue(=%hu), 
should be: <= %hu",
-                       conf->peer_count, cap.max_rx_2_tx);
-               return -EINVAL;
-       }
-       if (conf->peer_count == 0) {
-               RTE_ETHDEV_LOG(ERR,
-                       "Invalid value for number of peers for Rx queue(=%hu), 
should be: > 0",
-                       conf->peer_count);
+       if (rte_eth_hairpin_conf_check(conf, &cap, true))
                return -EINVAL;
-       }
+
        for (i = 0, count = 0; i < dev->data->nb_rx_queues &&
             cap.max_nb_queues != UINT16_MAX; i++) {
                if (i == rx_queue_id || rte_eth_dev_is_rx_hairpin_queue(dev, i))
@@ -2126,18 +2164,9 @@ struct rte_eth_dev *
                        nb_tx_desc, cap.max_nb_desc);
                return -EINVAL;
        }
-       if (conf->peer_count > cap.max_tx_2_rx) {
-               RTE_ETHDEV_LOG(ERR,
-                       "Invalid value for number of peers for Tx queue(=%hu), 
should be: <= %hu",
-                       conf->peer_count, cap.max_tx_2_rx);
+       if (rte_eth_hairpin_conf_check(conf, &cap, false))
                return -EINVAL;
-       }
-       if (conf->peer_count == 0) {
-               RTE_ETHDEV_LOG(ERR,
-                       "Invalid value for number of peers for Tx queue(=%hu), 
should be: > 0",
-                       conf->peer_count);
-               return -EINVAL;
-       }
+
        for (i = 0, count = 0; i < dev->data->nb_tx_queues &&
             cap.max_nb_queues != UINT16_MAX; i++) {
                if (i == tx_queue_id || rte_eth_dev_is_tx_hairpin_queue(dev, i))
-- 
1.8.3.1

Reply via email to