get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 80831,
    "url": "http://patches.dpdk.org/api/patches/80831/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1602740124-397688-6-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": "<1602740124-397688-6-git-send-email-bingz@nvidia.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1602740124-397688-6-git-send-email-bingz@nvidia.com",
    "date": "2020-10-15T05:35:24",
    "name": "[v5,5/5] app/testpmd: change hairpin queues setup",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "75982e6a3827d706adb579678b9658a4bc9117d1",
    "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/1602740124-397688-6-git-send-email-bingz@nvidia.com/mbox/",
    "series": [
        {
            "id": 12985,
            "url": "http://patches.dpdk.org/api/series/12985/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=12985",
            "date": "2020-10-15T05:35:19",
            "name": "introduce support for hairpin between two ports",
            "version": 5,
            "mbox": "http://patches.dpdk.org/series/12985/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/80831/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/80831/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 27717A04DB;\n\tThu, 15 Oct 2020 07:37:08 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 731661DC6D;\n\tThu, 15 Oct 2020 07:36:01 +0200 (CEST)",
            "from git-send-mailer.rdmz.labs.mlnx (unknown [37.142.13.130])\n by dpdk.org (Postfix) with ESMTP id 4D6BC1DC47\n for <dev@dpdk.org>; Thu, 15 Oct 2020 07:35:50 +0200 (CEST)"
        ],
        "From": "Bing Zhao <bingz@nvidia.com>",
        "To": "thomas@monjalon.net, orika@nvidia.com, ferruh.yigit@intel.com,\n arybchenko@solarflare.com, mdr@ashroe.eu, nhorman@tuxdriver.com,\n bernard.iremonger@intel.com, beilei.xing@intel.com, wenzhuo.lu@intel.com",
        "Cc": "dev@dpdk.org",
        "Date": "Thu, 15 Oct 2020 13:35:24 +0800",
        "Message-Id": "<1602740124-397688-6-git-send-email-bingz@nvidia.com>",
        "X-Mailer": "git-send-email 2.5.5",
        "In-Reply-To": "<1602740124-397688-1-git-send-email-bingz@nvidia.com>",
        "References": "<1601511962-21532-1-git-send-email-bingz@nvidia.com>\n <1602740124-397688-1-git-send-email-bingz@nvidia.com>",
        "Subject": "[dpdk-dev] [PATCH v5 5/5] app/testpmd: change hairpin queues setup",
        "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": "A new parameter `hairpin-mode` is introduced to the testpmd command\nline. Bitmask value is used to provide a more flexible configuration.\nThis parameter should be used when `hairpinq` is specified in the\ncommand line.\n\nBit 0 in the LSB indicates the hairpin will use the loop mode. The\nprevious port RX queue will be connected to the current port TX\nqueue.\nBit 1 in the LSB indicates the hairpin will use pair port mode. The\neven index port will be paired with the next odd index port. If the\ntotal number of the probed ports is odd, then the last one will be\npaired to itself.\nIf this byte is zero, then each port will be paired to itself.\nBit 0 takes a higher priority in the checking.\n\nBit 4 in the second bytes indicate if the hairpin will use explicit\nTX flow mode.\n\ne.g. in the command line, \"--hairpinq=2 --hairpin-mode=0x11\"\n\nIf not set, default value zero will be used and the behavior will\ntry to get aligned with the previous single port mode. If the ports\nbelong to different vendors' NICs, it is suggested to use the `self`\nhairpin mode only.\n\nSince hairpin configures the hardware resources, the port mask of\npackets forwarding engine will not be used here.\n\nSigned-off-by: Bing Zhao <bingz@nvidia.com>\nAcked-by: Ori Kam <orika@nvidia.com>\n---\nv5: add newline character\nv4: squash testpmd guide update\nv2: move the hairpin bind/unbind into start/stop to support hot-plug\n    and hot-unplug\n---\n app/test-pmd/parameters.c             |  15 ++++\n app/test-pmd/testpmd.c                | 125 ++++++++++++++++++++++++++++++++--\n app/test-pmd/testpmd.h                |   2 +\n doc/guides/testpmd_app_ug/run_app.rst |   8 +++\n 4 files changed, 146 insertions(+), 4 deletions(-)",
    "diff": "diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c\nindex 15ce8c1..e231b46 100644\n--- a/app/test-pmd/parameters.c\n+++ b/app/test-pmd/parameters.c\n@@ -222,6 +222,9 @@\n \t       \"enabled\\n\");\n \tprintf(\"  --record-core-cycles: enable measurement of CPU cycles.\\n\");\n \tprintf(\"  --record-burst-stats: enable display of RX and TX bursts.\\n\");\n+\tprintf(\"  --hairpin-mode=0xXX: bitmask set the hairpin port mode.\\n \"\n+\t       \"    0x10 - explicit tx rule, 0x02 - hairpin ports paired\\n\"\n+\t       \"    0x01 - hairpin ports loop, 0x00 - hairpin port self\\n\");\n }\n \n #ifdef RTE_LIBRTE_CMDLINE\n@@ -645,6 +648,7 @@\n \t\t{ \"rxd\",\t\t\t1, 0, 0 },\n \t\t{ \"txd\",\t\t\t1, 0, 0 },\n \t\t{ \"hairpinq\",\t\t\t1, 0, 0 },\n+\t\t{ \"hairpin-mode\",\t\t1, 0, 0 },\n \t\t{ \"burst\",\t\t\t1, 0, 0 },\n \t\t{ \"mbcache\",\t\t\t1, 0, 0 },\n \t\t{ \"txpt\",\t\t\t1, 0, 0 },\n@@ -1113,6 +1117,17 @@\n \t\t\t\trte_exit(EXIT_FAILURE, \"Either rx or tx queues should \"\n \t\t\t\t\t\t\"be non-zero\\n\");\n \t\t\t}\n+\t\t\tif (!strcmp(lgopts[opt_idx].name, \"hairpin-mode\")) {\n+\t\t\t\tchar *end = NULL;\n+\t\t\t\tunsigned int n;\n+\n+\t\t\t\terrno = 0;\n+\t\t\t\tn = strtoul(optarg, &end, 0);\n+\t\t\t\tif (errno != 0 || end == optarg)\n+\t\t\t\t\trte_exit(EXIT_FAILURE, \"hairpin mode invalid\\n\");\n+\t\t\t\telse\n+\t\t\t\t\thairpin_mode = (uint16_t)n;\n+\t\t\t}\n \t\t\tif (!strcmp(lgopts[opt_idx].name, \"burst\")) {\n \t\t\t\tn = atoi(optarg);\n \t\t\t\tif (n == 0) {\ndiff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c\nindex ccba71c..6e07162 100644\n--- a/app/test-pmd/testpmd.c\n+++ b/app/test-pmd/testpmd.c\n@@ -367,6 +367,9 @@ struct fwd_engine * fwd_engines[] = {\n /* Clear ptypes on port initialization. */\n uint8_t clear_ptypes = true;\n \n+/* Hairpin ports configuration mode. */\n+uint16_t hairpin_mode;\n+\n /* Pretty printing of ethdev events */\n static const char * const eth_event_desc[] = {\n \t[RTE_ETH_EVENT_UNKNOWN] = \"unknown\",\n@@ -2345,7 +2348,7 @@ struct extmem_param {\n \n /* Configure the Rx and Tx hairpin queues for the selected port. */\n static int\n-setup_hairpin_queues(portid_t pi)\n+setup_hairpin_queues(portid_t pi, portid_t p_pi, uint16_t cnt_pi)\n {\n \tqueueid_t qi;\n \tstruct rte_eth_hairpin_conf hairpin_conf = {\n@@ -2354,10 +2357,49 @@ struct extmem_param {\n \tint i;\n \tint diag;\n \tstruct rte_port *port = &ports[pi];\n+\tuint16_t peer_rx_port = pi;\n+\tuint16_t peer_tx_port = pi;\n+\tuint32_t manual = 1;\n+\tuint32_t tx_exp = hairpin_mode & 0x10;\n+\n+\tif (!(hairpin_mode & 0xf)) {\n+\t\tpeer_rx_port = pi;\n+\t\tpeer_tx_port = pi;\n+\t\tmanual = 0;\n+\t} else if (hairpin_mode & 0x1) {\n+\t\tpeer_tx_port = rte_eth_find_next_owned_by(pi + 1,\n+\t\t\t\t\t\t       RTE_ETH_DEV_NO_OWNER);\n+\t\tif (peer_tx_port >= RTE_MAX_ETHPORTS)\n+\t\t\tpeer_tx_port = rte_eth_find_next_owned_by(0,\n+\t\t\t\t\t\tRTE_ETH_DEV_NO_OWNER);\n+\t\tif (p_pi != RTE_MAX_ETHPORTS) {\n+\t\t\tpeer_rx_port = p_pi;\n+\t\t} else {\n+\t\t\tuint16_t next_pi;\n+\n+\t\t\t/* Last port will be the peer RX port of the first. */\n+\t\t\tRTE_ETH_FOREACH_DEV(next_pi)\n+\t\t\t\tpeer_rx_port = next_pi;\n+\t\t}\n+\t\tmanual = 1;\n+\t} else if (hairpin_mode & 0x2) {\n+\t\tif (cnt_pi & 0x1) {\n+\t\t\tpeer_rx_port = p_pi;\n+\t\t} else {\n+\t\t\tpeer_rx_port = rte_eth_find_next_owned_by(pi + 1,\n+\t\t\t\t\t\tRTE_ETH_DEV_NO_OWNER);\n+\t\t\tif (peer_rx_port >= RTE_MAX_ETHPORTS)\n+\t\t\t\tpeer_rx_port = pi;\n+\t\t}\n+\t\tpeer_tx_port = peer_rx_port;\n+\t\tmanual = 1;\n+\t}\n \n \tfor (qi = nb_txq, i = 0; qi < nb_hairpinq + nb_txq; qi++) {\n-\t\thairpin_conf.peers[0].port = pi;\n+\t\thairpin_conf.peers[0].port = peer_rx_port;\n \t\thairpin_conf.peers[0].queue = i + nb_rxq;\n+\t\thairpin_conf.manual_bind = !!manual;\n+\t\thairpin_conf.tx_explicit = !!tx_exp;\n \t\tdiag = rte_eth_tx_hairpin_queue_setup\n \t\t\t(pi, qi, nb_txd, &hairpin_conf);\n \t\ti++;\n@@ -2377,8 +2419,10 @@ struct extmem_param {\n \t\treturn -1;\n \t}\n \tfor (qi = nb_rxq, i = 0; qi < nb_hairpinq + nb_rxq; qi++) {\n-\t\thairpin_conf.peers[0].port = pi;\n+\t\thairpin_conf.peers[0].port = peer_tx_port;\n \t\thairpin_conf.peers[0].queue = i + nb_txq;\n+\t\thairpin_conf.manual_bind = !!manual;\n+\t\thairpin_conf.tx_explicit = !!tx_exp;\n \t\tdiag = rte_eth_rx_hairpin_queue_setup\n \t\t\t(pi, qi, nb_rxd, &hairpin_conf);\n \t\ti++;\n@@ -2405,6 +2449,12 @@ struct extmem_param {\n {\n \tint diag, need_check_link_status = -1;\n \tportid_t pi;\n+\tportid_t p_pi = RTE_MAX_ETHPORTS;\n+\tportid_t pl[RTE_MAX_ETHPORTS];\n+\tportid_t peer_pl[RTE_MAX_ETHPORTS];\n+\tuint16_t cnt_pi = 0;\n+\tuint16_t cfg_pi = 0;\n+\tint peer_pi;\n \tqueueid_t qi;\n \tstruct rte_port *port;\n \tstruct rte_ether_addr mac_addr;\n@@ -2544,7 +2594,7 @@ struct extmem_param {\n \t\t\t\treturn -1;\n \t\t\t}\n \t\t\t/* setup hairpin queues */\n-\t\t\tif (setup_hairpin_queues(pi) != 0)\n+\t\t\tif (setup_hairpin_queues(pi, p_pi, cnt_pi) != 0)\n \t\t\t\treturn -1;\n \t\t}\n \t\tconfigure_rxtx_dump_callbacks(verbose_level);\n@@ -2557,6 +2607,9 @@ struct extmem_param {\n \t\t\t\tpi);\n \t\t}\n \n+\t\tp_pi = pi;\n+\t\tcnt_pi++;\n+\n \t\t/* start port */\n \t\tif (rte_eth_dev_start(pi) < 0) {\n \t\t\tprintf(\"Fail to start port %d\\n\", pi);\n@@ -2581,6 +2634,8 @@ struct extmem_param {\n \n \t\t/* at least one port started, need checking link status */\n \t\tneed_check_link_status = 1;\n+\n+\t\tpl[cfg_pi++] = pi;\n \t}\n \n \tif (need_check_link_status == 1 && !no_link_check)\n@@ -2588,6 +2643,50 @@ struct extmem_param {\n \telse if (need_check_link_status == 0)\n \t\tprintf(\"Please stop the ports first\\n\");\n \n+\tif (hairpin_mode & 0xf) {\n+\t\tuint16_t i;\n+\t\tint j;\n+\n+\t\t/* bind all started hairpin ports */\n+\t\tfor (i = 0; i < cfg_pi; i++) {\n+\t\t\tpi = pl[i];\n+\t\t\t/* bind current TX to all peer RX */\n+\t\t\tpeer_pi = rte_eth_hairpin_get_peer_ports(pi, peer_pl,\n+\t\t\t\t\t\t\tRTE_MAX_ETHPORTS, 1);\n+\t\t\tif (peer_pi < 0)\n+\t\t\t\treturn peer_pi;\n+\t\t\tfor (j = 0; j < peer_pi; j++) {\n+\t\t\t\tif (!port_is_started(peer_pl[j]))\n+\t\t\t\t\tcontinue;\n+\t\t\t\tdiag = rte_eth_hairpin_bind(pi, peer_pl[j]);\n+\t\t\t\tif (diag < 0) {\n+\t\t\t\t\tprintf(\"Error during binding \"\n+\t\t\t\t\t       \"hairpin tx port %u to %u: %s\\n\",\n+\t\t\t\t\t       pi, peer_pl[j],\n+\t\t\t\t\t       rte_strerror(-diag));\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t/* bind all peer TX to current RX */\n+\t\t\tpeer_pi = rte_eth_hairpin_get_peer_ports(pi, peer_pl,\n+\t\t\t\t\t\t\tRTE_MAX_ETHPORTS, 0);\n+\t\t\tif (peer_pi < 0)\n+\t\t\t\treturn peer_pi;\n+\t\t\tfor (j = 0; j < peer_pi; j++) {\n+\t\t\t\tif (!port_is_started(peer_pl[j]))\n+\t\t\t\t\tcontinue;\n+\t\t\t\tdiag = rte_eth_hairpin_bind(peer_pl[j], pi);\n+\t\t\t\tif (diag < 0) {\n+\t\t\t\t\tprintf(\"Error during binding \"\n+\t\t\t\t\t       \"hairpin tx port %u to %u: %s\\n\",\n+\t\t\t\t\t       peer_pl[j], pi,\n+\t\t\t\t\t       rte_strerror(-diag));\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n \tprintf(\"Done\\n\");\n \treturn 0;\n }\n@@ -2598,6 +2697,8 @@ struct extmem_param {\n \tportid_t pi;\n \tstruct rte_port *port;\n \tint need_check_link_status = 0;\n+\tportid_t peer_pl[RTE_MAX_ETHPORTS];\n+\tint peer_pi;\n \n \tif (dcb_test) {\n \t\tdcb_test = 0;\n@@ -2628,6 +2729,22 @@ struct extmem_param {\n \t\t\t\t\t\tRTE_PORT_HANDLING) == 0)\n \t\t\tcontinue;\n \n+\t\tif (hairpin_mode & 0xf) {\n+\t\t\tint j;\n+\n+\t\t\trte_eth_hairpin_unbind(pi, RTE_MAX_ETHPORTS);\n+\t\t\t/* unbind all peer TX from current RX */\n+\t\t\tpeer_pi = rte_eth_hairpin_get_peer_ports(pi, peer_pl,\n+\t\t\t\t\t\t\tRTE_MAX_ETHPORTS, 0);\n+\t\t\tif (peer_pi < 0)\n+\t\t\t\tcontinue;\n+\t\t\tfor (j = 0; j < peer_pi; j++) {\n+\t\t\t\tif (!port_is_started(peer_pl[j]))\n+\t\t\t\t\tcontinue;\n+\t\t\t\trte_eth_hairpin_unbind(peer_pl[j], pi);\n+\t\t\t}\n+\t\t}\n+\n \t\trte_eth_dev_stop(pi);\n \n \t\tif (rte_atomic16_cmpset(&(port->port_status),\ndiff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h\nindex 9a29d7a..f2b604c 100644\n--- a/app/test-pmd/testpmd.h\n+++ b/app/test-pmd/testpmd.h\n@@ -398,6 +398,8 @@ struct queue_stats_mappings {\n \n extern uint16_t stats_period;\n \n+extern uint16_t hairpin_mode;\n+\n #ifdef RTE_LIBRTE_LATENCY_STATS\n extern uint8_t latencystats_enabled;\n extern lcoreid_t latencystats_lcore_id;\ndiff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst\nindex ec085c2..b5f5b98 100644\n--- a/doc/guides/testpmd_app_ug/run_app.rst\n+++ b/doc/guides/testpmd_app_ug/run_app.rst\n@@ -503,3 +503,11 @@ The command line options are:\n *   ``--record-burst-stats``\n \n     Enable display of RX and TX burst stats.\n+\n+*   ``--hairpin-mode=0xXX``\n+\n+    Set the hairpin port mode with bitmask, only valid when hairpin queues number is set.\n+    bit 4 - explicit TX flow rule\n+    bit 1 - two hairpin ports paired\n+    bit 0 - two hairpin ports loop\n+    The default value is 0. Hairpin will use single port mode and implicit TX flow mode.\n",
    "prefixes": [
        "v5",
        "5/5"
    ]
}