get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/77546/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 77546,
    "url": "http://patches.dpdk.org/api/patches/77546/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1600012140-70151-4-git-send-email-bingz@nvidia.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1600012140-70151-4-git-send-email-bingz@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1600012140-70151-4-git-send-email-bingz@nvidia.com",
    "date": "2020-09-13T15:48:59",
    "name": "[RFC,v2,3/4] ethdev: add hairpin bind APIs",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "e71a9da9619a657ffac429389fd9db0fb3a3574e",
    "submitter": {
        "id": 1976,
        "url": "http://patches.dpdk.org/api/people/1976/?format=api",
        "name": "Bing Zhao",
        "email": "bingz@nvidia.com"
    },
    "delegate": {
        "id": 319,
        "url": "http://patches.dpdk.org/api/users/319/?format=api",
        "username": "fyigit",
        "first_name": "Ferruh",
        "last_name": "Yigit",
        "email": "ferruh.yigit@amd.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1600012140-70151-4-git-send-email-bingz@nvidia.com/mbox/",
    "series": [
        {
            "id": 12169,
            "url": "http://patches.dpdk.org/api/series/12169/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=12169",
            "date": "2020-09-13T15:48:56",
            "name": "introduce support for hairpin between two ports",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/12169/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/77546/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/77546/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id B138AA04C9;\n\tSun, 13 Sep 2020 17:49:57 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 976811C0CD;\n\tSun, 13 Sep 2020 17:49:57 +0200 (CEST)",
            "from git-send-mailer.rdmz.labs.mlnx (unknown [37.142.13.130])\n by dpdk.org (Postfix) with ESMTP id B648DE07\n for <dev@dpdk.org>; Sun, 13 Sep 2020 17:49:56 +0200 (CEST)"
        ],
        "From": "Bing Zhao <bingz@nvidia.com>",
        "To": "thomas@monjalon.net, orika@nvidia.com, ferruh.yigit@intel.com,\n arybchenko@solarflare.com",
        "Cc": "dev@dpdk.org",
        "Date": "Sun, 13 Sep 2020 23:48:59 +0800",
        "Message-Id": "<1600012140-70151-4-git-send-email-bingz@nvidia.com>",
        "X-Mailer": "git-send-email 2.5.5",
        "In-Reply-To": "<1600012140-70151-1-git-send-email-bingz@nvidia.com>",
        "References": "\n <CY4PR1201MB0072A4383E611EB8B65D89A6D0240@CY4PR1201MB0072.namprd12.prod.outlook.com>\n <1600012140-70151-1-git-send-email-bingz@nvidia.com>",
        "Subject": "[dpdk-dev] [RFC PATCH v2 3/4] ethdev: add hairpin bind APIs",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "In single port hairpin mode, all the hairpin TX and RX queues belong\nto the same device. After the queues are set up properly, there is\nno other dependency between the TX queue and its RX peer queue. The\nbinding process that connected the TX and RX queues together from\nhardware level will be done automatically during the device start\nprocedure. Everything required for binding will be configured and\ninitialized before.\nBut in two ports hairpin mode, there will be some cross-dependences\nbetween two different ports. Usually, the ports will be initialized\nserially by the master thread but not in parallel. The earlier port\nwill not be able to enable the bind if the following peer port is\nnot configured done with HW resources. What's more, if one port is\ndetached / attached dynamically, it would introduce more trouble\nfor the hairpin binding.\nTo overcome these, new APIs for binding and unbinding are added.\nDuring startup, only the hairpin TX and RX peer queues will be set\nup. Nothing will be done when starting the device if the queues are\nwithout auto bind attribute. Only after the required ports pair\nstarted, the rte_eth_hairpin_bind() API can be called to bind the\nall TX queues of the egress port to the RX queues of the peer port.\nThe connection between the egress and ingress ports pair will be\nestablished.\nrte_eth_hairpin_unbind() API could be used to disconnect the egress\nand the peer ingress ports. This should only be called before the\ndevice is closed if needed.\n\nSigned-off-by: Bing Zhao <bingz@nvidia.com>\n---\n lib/librte_ethdev/rte_ethdev.c        | 100 ++++++++++++++++++++++++++++++++++\n lib/librte_ethdev/rte_ethdev.h        |  51 +++++++++++++++++\n lib/librte_ethdev/rte_ethdev_driver.h |  52 ++++++++++++++++++\n 3 files changed, 203 insertions(+)",
    "diff": "diff --git a/lib/librte_ethdev/rte_ethdev.c b/lib/librte_ethdev/rte_ethdev.c\nindex 066751f..8a3dc73 100644\n--- a/lib/librte_ethdev/rte_ethdev.c\n+++ b/lib/librte_ethdev/rte_ethdev.c\n@@ -2175,6 +2175,106 @@ rte_eth_tx_hairpin_queue_setup(uint16_t port_id, uint16_t tx_queue_id,\n \treturn eth_err(port_id, ret);\n }\n \n+int\n+rte_eth_hairpin_bind(uint16_t tx_port, uint16_t rx_port)\n+{\n+\tstruct rte_eth_dev *dev;\n+\tstruct rte_eth_dev *rdev;\n+\tuint16_t p;\n+\tuint16_t rp;\n+\tint ret = 0;\n+\n+\tRTE_ETH_VALID_PORTID_OR_ERR_RET(tx_port, -EINVAL);\n+\tdev = &rte_eth_devices[tx_port];\n+\tif (!dev->data->dev_started) {\n+\t\tRTE_ETHDEV_LOG(ERR, \"TX port %d is not started\", tx_port);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tif (rx_port == RTE_MAX_ETHPORTS) {\n+\t\tRTE_ETH_FOREACH_DEV(p) {\n+\t\t\trdev = &rte_eth_devices[p];\n+\t\t\tif (!rdev->data->dev_started) {\n+\t\t\t\tRTE_ETHDEV_LOG(ERR,\n+\t\t\t\t\t       \"RX port %d is not started\", p);\n+\t\t\t\tret = -EBUSY;\n+\t\t\t\tgoto error;\n+\t\t\t}\n+\t\t\tret = (*dev->dev_ops->hairpin_bind)(dev, p);\n+\t\t\tif (ret) {\n+\t\t\t\tRTE_ETHDEV_LOG(ERR, \"Failed to bind hairpin TX \"\n+\t\t\t\t\t       \"%d to RX %d\", tx_port, p);\n+\t\t\t\tgoto error;\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\tRTE_ETH_VALID_PORTID_OR_ERR_RET(rx_port, -EINVAL);\n+\t\trdev = &rte_eth_devices[rx_port];\n+\t\tif (!rdev->data->dev_started) {\n+\t\t\tRTE_ETHDEV_LOG(ERR,\n+\t\t\t\t       \"RX port %d is not started\", rx_port);\n+\t\t\treturn -EBUSY;\n+\t\t}\n+\t\tret = (*dev->dev_ops->hairpin_bind)(dev, rx_port);\n+\t\tif (ret)\n+\t\t\tRTE_ETHDEV_LOG(ERR, \"Failed to bind hairpin TX %d \"\n+\t\t\t\t       \"to RX %d\", tx_port, rx_port);\n+\t}\n+\n+\treturn ret;\n+\n+error:\n+\tRTE_ETH_FOREACH_DEV(rp) {\n+\t\tif (rp < p)\n+\t\t\t(*dev->dev_ops->hairpin_unbind)(dev, rp);\n+\t}\n+\treturn ret;\n+}\n+\n+int\n+rte_eth_hairpin_unbind(uint16_t tx_port, uint16_t rx_port)\n+{\n+\tstruct rte_eth_dev *dev;\n+\tstruct rte_eth_dev *rdev;\n+\tuint16_t p;\n+\tuint16_t rp;\n+\tint ret = 0;\n+\n+\tRTE_ETH_VALID_PORTID_OR_ERR_RET(tx_port, -EINVAL);\n+\tdev = &rte_eth_devices[tx_port];\n+\tif (!dev->data->dev_started) {\n+\t\tRTE_ETHDEV_LOG(ERR, \"TX port %d is stopped\", tx_port);\n+\t\treturn -EBUSY;\n+\t}\n+\n+\tif (rx_port == RTE_MAX_ETHPORTS) {\n+\t\tRTE_ETH_FOREACH_DEV(p) {\n+\t\t\trdev = &rte_eth_devices[p];\n+\t\t\tif (!rdev->data->dev_started) {\n+\t\t\t\tRTE_ETHDEV_LOG(ERR, \"RX port %d is stopped\", p);\n+\t\t\t\tret = -EBUSY;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\tret = (*dev->dev_ops->hairpin_unbind)(dev, p);\n+\t\t\tif (ret) {\n+\t\t\t\tRTE_ETHDEV_LOG(ERR, \"Failed to unbind hairpin \"\n+\t\t\t\t\t       \"TX %d from RX %d\", tx_port, p);\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\tRTE_ETH_VALID_PORTID_OR_ERR_RET(rx_port, -EINVAL);\n+\t\trdev = &rte_eth_devices[rx_port];\n+\t\tif (!rdev->data->dev_started) {\n+\t\t\tRTE_ETHDEV_LOG(ERR, \"RX port %d is stopped\", rx_port);\n+\t\t\treturn -EBUSY;\n+\t\t}\n+\t\tret = (*dev->dev_ops->hairpin_unbind)(dev, rx_port);\n+\t}\n+\n+\treturn ret;\n+}\n+\n void\n rte_eth_tx_buffer_drop_callback(struct rte_mbuf **pkts, uint16_t unsent,\n \t\tvoid *userdata __rte_unused)\ndiff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h\nindex e7733d8..fb217b4 100644\n--- a/lib/librte_ethdev/rte_ethdev.h\n+++ b/lib/librte_ethdev/rte_ethdev.h\n@@ -2101,6 +2101,57 @@ int rte_eth_tx_hairpin_queue_setup\n \t const struct rte_eth_hairpin_conf *conf);\n \n /**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice\n+ *\n+ * Bind all hairpin TX queues of one port to the RX queues of the peer port.\n+ * Only allowed after all hairpin queues are configured properly and the\n+ * devices of TX and peer RX are in started state.\n+ *\n+ * @param tx_port\n+ *   The TX port identifier of the Ethernet device.\n+ * @param rx_port\n+ *   The peer RX port identifier of the Ethernet device.\n+ *   RTE_MAX_ETHPORTS is allowed for traversal of all devices.\n+ *   RX port ID could have the same value with TX port ID.\n+ *\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-EINVAL) if bad parameter.\n+ *   - (-EBUSY) if device is not in started state.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - Others detailed errors from PMD drivers.\n+ */\n+__rte_experimental\n+int rte_eth_hairpin_bind(uint16_t tx_port, uint16_t rx_port);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change, or be removed, without prior notice\n+ *\n+ * Unbind all hairpin TX queues of one port from the RX queues of the peer port.\n+ * This should be called before closing the TX or RX devices (optional). After\n+ * unbind the hairpin ports pair, it is allowed to bind them again.\n+ * Changing queues configuration should be after stopping a device.\n+ *\n+ * @param tx_port\n+ *   The TX port identifier of the Ethernet device.\n+ * @param rx_port\n+ *   The peer RX port identifier of the Ethernet device.\n+ *   RTE_MAX_ETHPORTS is allowed for traversal of all devices.\n+ *   RX port ID could have the same value with TX port ID.\n+ *\n+ * @return\n+ *   - (0) if successful.\n+ *   - (-EINVAL) if bad parameter.\n+ *   - (-EBUSY) if device is not in started state.\n+ *   - (-ENOTSUP) if hardware doesn't support.\n+ *   - Others detailed errors from PMD drivers.\n+ */\n+__rte_experimental\n+int rte_eth_hairpin_unbind(uint16_t tx_port, uint16_t rx_port);\n+\n+/**\n  * Return the NUMA socket to which an Ethernet device is connected\n  *\n  * @param port_id\ndiff --git a/lib/librte_ethdev/rte_ethdev_driver.h b/lib/librte_ethdev/rte_ethdev_driver.h\nindex 23cc1e0..b4efad6 100644\n--- a/lib/librte_ethdev/rte_ethdev_driver.h\n+++ b/lib/librte_ethdev/rte_ethdev_driver.h\n@@ -575,6 +575,54 @@ typedef int (*eth_tx_hairpin_queue_setup_t)\n \t const struct rte_eth_hairpin_conf *hairpin_conf);\n \n /**\n+ * @internal\n+ * Bind all hairpin TX queues of one port to the RX queues of the peer port.\n+ *\n+ * @param dev\n+ *   ethdev handle of port.\n+ * @param rx_port\n+ *   the peer RX port.\n+ *\n+ * @return\n+ *   Negative errno value on error, 0 on success.\n+ *\n+ * @retval 0\n+ *   Success, bind successfully.\n+ * @retval -ENOTSUP\n+ *   Bind API is not supported.\n+ * @retval -EINVAL\n+ *   One of the parameters is invalid.\n+ * @retval -EBUSY\n+ *   Device is not started.\n+ */\n+typedef int (*eth_hairpin_bind)(struct rte_eth_dev *dev,\n+\t\t\t\tuint16_t rx_port);\n+\n+/**\n+ * @internal\n+ * Unbind all hairpin TX queues of one port from the RX queues of the peer port.\n+ *\n+ * @param dev\n+ *   ethdev handle of port.\n+ * @param rx_port\n+ *   the peer RX port.\n+ *\n+ * @return\n+ *   Negative errno value on error, 0 on success.\n+ *\n+ * @retval 0\n+ *   Success, bind successfully.\n+ * @retval -ENOTSUP\n+ *   Bind API is not supported.\n+ * @retval -EINVAL\n+ *   One of the parameters is invalid.\n+ * @retval -EBUSY\n+ *   Device is already stopped.\n+ */\n+typedef int (*eth_hairpin_unbind)(struct rte_eth_dev *dev,\n+\t\t\t\t  uint16_t rx_port);\n+\n+/**\n  * @internal A structure containing the functions exported by an Ethernet driver.\n  */\n struct eth_dev_ops {\n@@ -713,6 +761,10 @@ struct eth_dev_ops {\n \t/**< Set up device RX hairpin queue. */\n \teth_tx_hairpin_queue_setup_t tx_hairpin_queue_setup;\n \t/**< Set up device TX hairpin queue. */\n+\teth_hairpin_bind hairpin_bind;\n+\t/**< Bind all hairpin TX queues of device to the peer port RX queues. */\n+\teth_hairpin_unbind hairpin_unbind;\n+\t/**< Unbind all hairpin TX queues from the peer port RX queues. */\n };\n \n /**\n",
    "prefixes": [
        "RFC",
        "v2",
        "3/4"
    ]
}