get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 132977,
    "url": "https://patches.dpdk.org/api/patches/132977/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20231019105000.520914-6-skori@marvell.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<20231019105000.520914-6-skori@marvell.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20231019105000.520914-6-skori@marvell.com",
    "date": "2023-10-19T10:49:53",
    "name": "[v10,05/12] app/graph: support ethdev command line interfaces",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "d6a0cb651199405753aceb42e1d71144486a3a76",
    "submitter": {
        "id": 1318,
        "url": "https://patches.dpdk.org/api/people/1318/?format=api",
        "name": "Sunil Kumar Kori",
        "email": "skori@marvell.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20231019105000.520914-6-skori@marvell.com/mbox/",
    "series": [
        {
            "id": 29919,
            "url": "https://patches.dpdk.org/api/series/29919/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=29919",
            "date": "2023-10-19T10:49:48",
            "name": "add CLI based graph application",
            "version": 10,
            "mbox": "https://patches.dpdk.org/series/29919/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/132977/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/132977/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 mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 82D84431A9;\n\tThu, 19 Oct 2023 12:50:50 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 28D9C410F2;\n\tThu, 19 Oct 2023 12:50:21 +0200 (CEST)",
            "from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com\n [67.231.156.173])\n by mails.dpdk.org (Postfix) with ESMTP id 671B54021F\n for <dev@dpdk.org>; Thu, 19 Oct 2023 12:50:19 +0200 (CEST)",
            "from pps.filterd (m0045851.ppops.net [127.0.0.1])\n by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id\n 39INWtrq018791 for <dev@dpdk.org>; Thu, 19 Oct 2023 03:50:18 -0700",
            "from dc5-exch01.marvell.com ([199.233.59.181])\n by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3tstb41v5n-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT)\n for <dev@dpdk.org>; Thu, 19 Oct 2023 03:50:18 -0700",
            "from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com\n (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48;\n Thu, 19 Oct 2023 03:50:16 -0700",
            "from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com\n (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend\n Transport; Thu, 19 Oct 2023 03:50:16 -0700",
            "from localhost.localdomain (unknown [10.28.34.25])\n by maili.marvell.com (Postfix) with ESMTP id 73A4A5B6953;\n Thu, 19 Oct 2023 03:50:14 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;\n h=from : to : cc :\n subject : date : message-id : in-reply-to : references : mime-version :\n content-transfer-encoding : content-type; s=pfpt0220;\n bh=TQX6bmjhTRYVxe26d9QN083pLVit/Fh8kA7ji7eVVew=;\n b=XzlbTuZh9HdKP0QJwHkZFij1mGB6CtbkkaT5pgFG3I0uDL8YEPRy8NIdBe3QSg0dc5k4\n MfNk3HCblVg7JVT7C5rf0JAvPKEJGiiMy7tqXfjE3NGjvQmBrk9/qwSJkERK53/SPCJu\n bMEyUb3Fy4hpyGqD51fxGBznDdXj+Qh2unuMQ1Oh0+kboLm3HU10RVb4VUAcAhusU8wZ\n CM3U8Yb4hIIUmFQ2tNQ+WzDBSxXI7j8cMhJVXL6eqQWk6A2TGedNJLxzdi51eDEaME4u\n jyNTLwxhrUfnJxOGV5QAbi05Z4tAsnpMH55vZG7h1PRfNyRS6mXQ/S0dS2qKfqHGbZB/ ZQ==",
        "From": "<skori@marvell.com>",
        "To": "Sunil Kumar Kori <skori@marvell.com>, Rakesh Kudurumalla\n <rkudurumalla@marvell.com>",
        "CC": "<dev@dpdk.org>, Jerin Jacob <jerinj@marvell.com>",
        "Subject": "[PATCH v10 05/12] app/graph: support ethdev command line interfaces",
        "Date": "Thu, 19 Oct 2023 16:19:53 +0530",
        "Message-ID": "<20231019105000.520914-6-skori@marvell.com>",
        "X-Mailer": "git-send-email 2.25.1",
        "In-Reply-To": "<20231019105000.520914-1-skori@marvell.com>",
        "References": "<20231018063347.68081-13-skori@marvell.com>\n <20231019105000.520914-1-skori@marvell.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-Proofpoint-ORIG-GUID": "8qaHFZL9Ad4EzhuEffNEgOogieDzjZpD",
        "X-Proofpoint-GUID": "8qaHFZL9Ad4EzhuEffNEgOogieDzjZpD",
        "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26\n definitions=2023-10-19_08,2023-10-19_01,2023-05-22_02",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "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"
    },
    "content": "From: Sunil Kumar Kori <skori@marvell.com>\n\nAdds ethdev module to configure ethernet devices.\n\nFollowing commands are exposed:\n - ethdev <ethdev_name> rxq <n_queues> txq <n_queues> <mempool_name>\n - ethdev <ethdev_name> mtu <mtu_sz>\n - ethdev <ethdev_name> promiscuous <on/off>\n - ethdev <ethdev_name> show\n - ethdev <ethdev_name> stats\n - ethdev <ethdev_name> ip4 addr add <ip> netmask <mask>\n - ethdev <ethdev_name> ip6 addr add <ip> netmask <mask>\n - help ethdev\n\nSigned-off-by: Sunil Kumar Kori <skori@marvell.com>\nSigned-off-by: Rakesh Kudurumalla <rkudurumalla@marvell.com>\nAcked-by: Jerin Jacob <jerinj@marvell.com>\n---\n app/graph/cli.c            |   8 +\n app/graph/ethdev.c         | 882 +++++++++++++++++++++++++++++++++++++\n app/graph/ethdev.h         |  40 ++\n app/graph/ethdev_priv.h    | 112 +++++\n app/graph/main.c           |   1 +\n app/graph/meson.build      |   1 +\n app/graph/module_api.h     |   1 +\n doc/guides/tools/graph.rst |  45 +-\n 8 files changed, 1089 insertions(+), 1 deletion(-)\n create mode 100644 app/graph/ethdev.c\n create mode 100644 app/graph/ethdev.h\n create mode 100644 app/graph/ethdev_priv.h",
    "diff": "diff --git a/app/graph/cli.c b/app/graph/cli.c\nindex cf544d5f8f..fa394fade6 100644\n--- a/app/graph/cli.c\n+++ b/app/graph/cli.c\n@@ -22,6 +22,14 @@\n cmdline_parse_ctx_t modules_ctx[] = {\n \t(cmdline_parse_inst_t *)&mempool_config_cmd_ctx,\n \t(cmdline_parse_inst_t *)&mempool_help_cmd_ctx,\n+\t(cmdline_parse_inst_t *)&ethdev_show_cmd_ctx,\n+\t(cmdline_parse_inst_t *)&ethdev_stats_cmd_ctx,\n+\t(cmdline_parse_inst_t *)&ethdev_mtu_cmd_ctx,\n+\t(cmdline_parse_inst_t *)&ethdev_prom_mode_cmd_ctx,\n+\t(cmdline_parse_inst_t *)&ethdev_ip4_cmd_ctx,\n+\t(cmdline_parse_inst_t *)&ethdev_ip6_cmd_ctx,\n+\t(cmdline_parse_inst_t *)&ethdev_cmd_ctx,\n+\t(cmdline_parse_inst_t *)&ethdev_help_cmd_ctx,\n \tNULL,\n };\n \ndiff --git a/app/graph/ethdev.c b/app/graph/ethdev.c\nnew file mode 100644\nindex 0000000000..74e80679d9\n--- /dev/null\n+++ b/app/graph/ethdev.c\n@@ -0,0 +1,882 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Marvell.\n+ */\n+\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <string.h>\n+\n+#include <cmdline_parse.h>\n+#include <cmdline_parse_num.h>\n+#include <cmdline_parse_string.h>\n+#include <cmdline_socket.h>\n+#include <rte_bitops.h>\n+#include <rte_ethdev.h>\n+#include <rte_mempool.h>\n+\n+#include \"ethdev_priv.h\"\n+#include \"module_api.h\"\n+\n+static const char\n+cmd_ethdev_mtu_help[] = \"ethdev <ethdev_name> mtu <mtu_sz>\";\n+\n+static const char\n+cmd_ethdev_prom_mode_help[] = \"ethdev <ethdev_name> promiscuous <on/off>\";\n+\n+static const char\n+cmd_ethdev_help[] = \"ethdev <ethdev_name> rxq <n_queues> txq <n_queues> <mempool_name>\";\n+static const char\n+cmd_ethdev_show_help[] = \"ethdev <ethdev_name> show\";\n+\n+static const char\n+cmd_ethdev_ip4_addr_help[] = \"ethdev <ethdev_name> ip4 addr add <ip> netmask <mask>\";\n+\n+static const char\n+cmd_ethdev_ip6_addr_help[] = \"ethdev <ethdev_name> ip6 addr add <ip> netmask <mask>\";\n+\n+static struct rte_eth_conf port_conf_default = {\n+\t.link_speeds = 0,\n+\t.rxmode = {\n+\t\t.mq_mode = RTE_ETH_MQ_RX_NONE,\n+\t\t.mtu = 9000 - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN), /* Jumbo frame MTU */\n+\t},\n+\t.rx_adv_conf = {\n+\t\t.rss_conf = {\n+\t\t\t.rss_key = NULL,\n+\t\t\t.rss_key_len = 40,\n+\t\t\t.rss_hf = 0,\n+\t\t},\n+\t},\n+\t.txmode = {\n+\t\t.mq_mode = RTE_ETH_MQ_TX_NONE,\n+\t},\n+\t.lpbk_mode = 0,\n+};\n+\n+uint32_t enabled_port_mask;\n+static struct ethdev_head eth_node = TAILQ_HEAD_INITIALIZER(eth_node);\n+\n+\n+static struct ethdev*\n+ethdev_port_by_id(uint16_t port_id)\n+{\n+\tstruct ethdev *port;\n+\n+\tTAILQ_FOREACH(port, &eth_node, next) {\n+\t\tif (port->config.port_id == port_id)\n+\t\t\treturn port;\n+\t}\n+\treturn NULL;\n+}\n+\n+void *\n+ethdev_mempool_list_by_portid(uint16_t portid)\n+{\n+\tstruct ethdev *port;\n+\n+\tif (portid >= RTE_MAX_ETHPORTS)\n+\t\treturn NULL;\n+\n+\tport = ethdev_port_by_id(portid);\n+\tif (port)\n+\t\treturn &(port->config.rx.mp);\n+\telse\n+\t\treturn NULL;\n+}\n+\n+int16_t\n+ethdev_portid_by_ip4(uint32_t ip, uint32_t mask)\n+{\n+\tint portid = -EINVAL;\n+\tstruct ethdev *port;\n+\n+\tTAILQ_FOREACH(port, &eth_node, next) {\n+\t\tif (mask == 0) {\n+\t\t\tif ((port->ip4_addr.ip & port->ip4_addr.mask) == (ip & port->ip4_addr.mask))\n+\t\t\t\treturn port->config.port_id;\n+\t\t} else {\n+\t\t\tif ((port->ip4_addr.ip & port->ip4_addr.mask) == (ip & mask))\n+\t\t\t\treturn port->config.port_id;\n+\t\t}\n+\t}\n+\n+\treturn portid;\n+}\n+\n+int16_t\n+ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask)\n+{\n+\tint portid = -EINVAL;\n+\tstruct ethdev *port;\n+\tint j;\n+\n+\tTAILQ_FOREACH(port, &eth_node, next) {\n+\t\tfor (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++) {\n+\t\t\tif (mask == NULL) {\n+\t\t\t\tif ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) !=\n+\t\t\t\t    (ip[j] & port->ip6_addr.mask[j]))\n+\t\t\t\t\tbreak;\n+\n+\t\t\t} else {\n+\t\t\t\tif ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) !=\n+\t\t\t\t    (ip[j] & mask[j]))\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\tif (j == ETHDEV_IPV6_ADDR_LEN)\n+\t\t\treturn port->config.port_id;\n+\t}\n+\n+\treturn portid;\n+}\n+\n+void\n+ethdev_list_clean(void)\n+{\n+\tstruct ethdev *port;\n+\n+\twhile (!TAILQ_EMPTY(&eth_node)) {\n+\t\tport = TAILQ_FIRST(&eth_node);\n+\t\tTAILQ_REMOVE(&eth_node, port, next);\n+\t}\n+}\n+\n+void\n+ethdev_stop(void)\n+{\n+\tuint16_t portid;\n+\tint rc;\n+\n+\tRTE_ETH_FOREACH_DEV(portid) {\n+\t\tif ((enabled_port_mask & (1 << portid)) == 0)\n+\t\t\tcontinue;\n+\t\tprintf(\"Closing port %d...\", portid);\n+\t\trc = rte_eth_dev_stop(portid);\n+\t\tif (rc != 0)\n+\t\t\tprintf(\"Failed to stop port %u: %s\\n\",\n+\t\t\t\t\tportid, rte_strerror(-rc));\n+\t\trte_eth_dev_close(portid);\n+\t\tprintf(\" Done\\n\");\n+\t}\n+\n+\tethdev_list_clean();\n+\trte_eal_cleanup();\n+\tprintf(\"Bye...\\n\");\n+}\n+\n+void\n+ethdev_start(void)\n+{\n+\tuint16_t portid;\n+\tint rc;\n+\n+\tRTE_ETH_FOREACH_DEV(portid)\n+\t{\n+\t\tif ((enabled_port_mask & (1 << portid)) == 0)\n+\t\t\tcontinue;\n+\n+\t\trc = rte_eth_dev_start(portid);\n+\t\tif (rc < 0)\n+\t\t\trte_exit(EXIT_FAILURE, \"rte_eth_dev_start: err=%d, port=%d\\n\", rc, portid);\n+\t}\n+}\n+\n+\n+static int\n+ethdev_show(const char *name)\n+{\n+\tuint16_t mtu = 0, port_id = 0;\n+\tstruct rte_eth_dev_info info;\n+\tstruct rte_eth_stats stats;\n+\tstruct rte_ether_addr addr;\n+\tstruct rte_eth_link link;\n+\tuint32_t length;\n+\tint rc;\n+\n+\trc = rte_eth_dev_get_port_by_name(name, &port_id);\n+\tif (rc < 0)\n+\t\treturn rc;\n+\n+\trte_eth_dev_info_get(port_id, &info);\n+\trte_eth_stats_get(port_id, &stats);\n+\trte_eth_macaddr_get(port_id, &addr);\n+\trte_eth_link_get(port_id, &link);\n+\trte_eth_dev_get_mtu(port_id, &mtu);\n+\n+\tlength = strlen(conn->msg_out);\n+\tconn->msg_out += length;\n+\tsnprintf(conn->msg_out, conn->msg_out_len_max,\n+\t\t \"%s: flags=<%s> mtu %u\\n\"\n+\t\t \"\\tether \" RTE_ETHER_ADDR_PRT_FMT \" rxqueues %u txqueues %u\\n\"\n+\t\t \"\\tport# %u  speed %s\\n\"\n+\t\t \"\\tRX packets %\" PRIu64\"  bytes %\" PRIu64\"\\n\"\n+\t\t \"\\tRX errors %\" PRIu64\"  missed %\" PRIu64\"  no-mbuf %\" PRIu64\"\\n\"\n+\t\t \"\\tTX packets %\" PRIu64\"  bytes %\" PRIu64\"\\n\"\n+\t\t \"\\tTX errors %\" PRIu64\"\\n\\n\",\n+\t\t name,\n+\t\t link.link_status ? \"UP\" : \"DOWN\",\n+\t\t mtu,\n+\t\t RTE_ETHER_ADDR_BYTES(&addr),\n+\t\t info.nb_rx_queues,\n+\t\t info.nb_tx_queues,\n+\t\t port_id,\n+\t\t rte_eth_link_speed_to_str(link.link_speed),\n+\t\t stats.ipackets,\n+\t\t stats.ibytes,\n+\t\t stats.ierrors,\n+\t\t stats.imissed,\n+\t\t stats.rx_nombuf,\n+\t\t stats.opackets,\n+\t\t stats.obytes,\n+\t\t stats.oerrors);\n+\n+\tlength = strlen(conn->msg_out);\n+\tconn->msg_out_len_max -= length;\n+\treturn 0;\n+}\n+\n+static int\n+ethdev_ip4_addr_add(const char *name, struct ipv4_addr_config *config)\n+{\n+\tstruct ethdev *eth_hdl;\n+\tuint16_t portid = 0;\n+\tint rc;\n+\n+\trc = rte_eth_dev_get_port_by_name(name, &portid);\n+\tif (rc < 0)\n+\t\treturn rc;\n+\n+\teth_hdl = ethdev_port_by_id(portid);\n+\n+\tif (eth_hdl) {\n+\t\teth_hdl->ip4_addr.ip = config->ip;\n+\t\teth_hdl->ip4_addr.mask = config->mask;\n+\t\treturn 0;\n+\t}\n+\n+\trc = -EINVAL;\n+\treturn rc;\n+}\n+\n+static int\n+ethdev_ip6_addr_add(const char *name, struct ipv6_addr_config *config)\n+{\n+\tstruct ethdev *eth_hdl;\n+\tuint16_t portid = 0;\n+\tint rc, i;\n+\n+\trc = rte_eth_dev_get_port_by_name(name, &portid);\n+\tif (rc < 0)\n+\t\treturn rc;\n+\n+\teth_hdl = ethdev_port_by_id(portid);\n+\n+\tif (eth_hdl) {\n+\t\tfor (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++) {\n+\t\t\teth_hdl->ip6_addr.ip[i] = config->ip[i];\n+\t\t\teth_hdl->ip6_addr.mask[i] = config->mask[i];\n+\t\t}\n+\t\treturn 0;\n+\t}\n+\trc = -EINVAL;\n+\treturn rc;\n+}\n+\n+static int\n+ethdev_prom_mode_config(const char *name, bool enable)\n+{\n+\tstruct ethdev *eth_hdl;\n+\tuint16_t portid = 0;\n+\tint rc;\n+\n+\trc = rte_eth_dev_get_port_by_name(name, &portid);\n+\tif (rc < 0)\n+\t\treturn rc;\n+\n+\teth_hdl = ethdev_port_by_id(portid);\n+\n+\tif (eth_hdl) {\n+\t\tif (enable)\n+\t\t\trc = rte_eth_promiscuous_enable(portid);\n+\t\telse\n+\t\t\trc = rte_eth_promiscuous_disable(portid);\n+\t\tif (rc < 0)\n+\t\t\treturn rc;\n+\n+\t\teth_hdl->config.promiscuous = enable;\n+\t\treturn 0;\n+\t}\n+\n+\trc = -EINVAL;\n+\treturn rc;\n+}\n+\n+static int\n+ethdev_mtu_config(const char *name, uint32_t mtu)\n+{\n+\tstruct ethdev *eth_hdl;\n+\tuint16_t portid = 0;\n+\tint rc;\n+\n+\trc = rte_eth_dev_get_port_by_name(name, &portid);\n+\tif (rc < 0)\n+\t\treturn rc;\n+\n+\teth_hdl = ethdev_port_by_id(portid);\n+\n+\tif (eth_hdl) {\n+\t\trc = rte_eth_dev_set_mtu(portid, mtu);\n+\t\tif (rc < 0)\n+\t\t\treturn rc;\n+\n+\t\teth_hdl->config.mtu = mtu;\n+\t\treturn 0;\n+\t}\n+\n+\trc = -EINVAL;\n+\treturn rc;\n+}\n+\n+\n+static int\n+ethdev_process(const char *name, struct ethdev_config *params)\n+{\n+\tstruct rte_eth_dev_info port_info;\n+\tstruct rte_eth_conf port_conf;\n+\tstruct ethdev_rss_config *rss;\n+\tstruct rte_mempool *mempool;\n+\tstruct ethdev *ethdev_port;\n+\tstruct rte_ether_addr smac;\n+\tuint16_t port_id = 0;\n+\tint numa_node, rc;\n+\tuint32_t i;\n+\n+\t/* Check input params */\n+\tif (!name || !name[0] || !params || !params->rx.n_queues || !params->rx.queue_size ||\n+\t    !params->tx.n_queues || !params->tx.queue_size)\n+\t\treturn -EINVAL;\n+\n+\trc = rte_eth_dev_get_port_by_name(name, &port_id);\n+\tif (rc)\n+\t\treturn -EINVAL;\n+\n+\tif (!ethdev_port_by_id(port_id)) {\n+\t\tethdev_port = malloc(sizeof(struct ethdev));\n+\t\tif (!ethdev_port)\n+\t\t\treturn -EINVAL;\n+\t} else {\n+\t\treturn 0;\n+\t}\n+\n+\trc = rte_eth_dev_info_get(port_id, &port_info);\n+\tif (rc) {\n+\t\trc = -EINVAL;\n+\t\tgoto exit;\n+\t}\n+\n+\tmempool = rte_mempool_lookup(params->rx.mempool_name);\n+\tif (!mempool) {\n+\t\trc =  -EINVAL;\n+\t\tgoto exit;\n+\t}\n+\n+\tparams->rx.mp = mempool;\n+\n+\trss = params->rx.rss;\n+\tif (rss) {\n+\t\tif (!port_info.reta_size || port_info.reta_size > RTE_ETH_RSS_RETA_SIZE_512) {\n+\t\t\trc = -EINVAL;\n+\t\t\tgoto exit;\n+\t\t}\n+\n+\t\tif (!rss->n_queues || rss->n_queues >= ETHDEV_RXQ_RSS_MAX) {\n+\t\t\trc = -EINVAL;\n+\t\t\tgoto exit;\n+\t\t}\n+\n+\t\tfor (i = 0; i < rss->n_queues; i++)\n+\t\t\tif (rss->queue_id[i] >= port_info.max_rx_queues) {\n+\t\t\t\trc = -EINVAL;\n+\t\t\t\tgoto exit;\n+\t\t\t}\n+\t}\n+\n+\t/* Port */\n+\tmemcpy(&port_conf, &port_conf_default, sizeof(struct rte_eth_conf));\n+\tif (rss) {\n+\t\tuint64_t rss_hf = RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP;\n+\n+\t\tport_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS;\n+\t\tport_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf & port_info.flow_type_rss_offloads;\n+\t}\n+\n+\tnuma_node = rte_eth_dev_socket_id(port_id);\n+\tif (numa_node == SOCKET_ID_ANY)\n+\t\tnuma_node = 0;\n+\n+\tif (params->mtu)\n+\t\tport_conf.rxmode.mtu = params->mtu;\n+\n+\trc = rte_eth_dev_configure(port_id, params->rx.n_queues, params->tx.n_queues,\n+\t\t\t\t       &port_conf);\n+\tif (rc < 0) {\n+\t\trc = -EINVAL;\n+\t\tgoto exit;\n+\t}\n+\n+\trc = rte_eth_macaddr_get(port_id, &smac);\n+\tif (rc < 0) {\n+\t\trc = -EINVAL;\n+\t\tgoto exit;\n+\t}\n+\n+\tprintf(\"Port_id = %d srcmac = %x:%x:%x:%x:%x:%x\\n\", port_id,\n+\t\tsmac.addr_bytes[0], smac.addr_bytes[1],\n+\t\tsmac.addr_bytes[2], smac.addr_bytes[3],\n+\t\tsmac.addr_bytes[4], smac.addr_bytes[5]);\n+\n+\t/* Port RX */\n+\tfor (i = 0; i < params->rx.n_queues; i++) {\n+\t\trc = rte_eth_rx_queue_setup(port_id, i, params->rx.queue_size, numa_node, NULL,\n+\t\t\tmempool);\n+\t\tif (rc < 0) {\n+\t\t\trc = -EINVAL;\n+\t\t\tgoto exit;\n+\t\t}\n+\t}\n+\n+\t/* Port TX */\n+\tfor (i = 0; i < params->tx.n_queues; i++) {\n+\t\trc = rte_eth_tx_queue_setup(port_id, i, params->tx.queue_size, numa_node, NULL);\n+\t\tif (rc < 0) {\n+\t\t\trc = -EINVAL;\n+\t\t\tgoto exit;\n+\t\t}\n+\t}\n+\n+\tmemcpy(&ethdev_port->config, params, sizeof(struct ethdev_config));\n+\tmemcpy(ethdev_port->config.dev_name, name, strlen(name));\n+\tethdev_port->config.port_id = port_id;\n+\tenabled_port_mask |= RTE_BIT32(port_id);\n+\n+\tTAILQ_INSERT_TAIL(&eth_node, ethdev_port, next);\n+\treturn 0;\n+exit:\n+\tfree(ethdev_port);\n+\treturn rc;\n+\n+}\n+\n+static int\n+ethdev_stats_show(const char *name)\n+{\n+\tuint64_t diff_pkts_rx, diff_pkts_tx, diff_bytes_rx, diff_bytes_tx;\n+\tstatic uint64_t prev_pkts_rx[RTE_MAX_ETHPORTS];\n+\tstatic uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS];\n+\tstatic uint64_t prev_bytes_rx[RTE_MAX_ETHPORTS];\n+\tstatic uint64_t prev_bytes_tx[RTE_MAX_ETHPORTS];\n+\tstatic uint64_t prev_cycles[RTE_MAX_ETHPORTS];\n+\tuint64_t mpps_rx, mpps_tx, mbps_rx, mbps_tx;\n+\tuint64_t diff_ns, diff_cycles, curr_cycles;\n+\tstruct rte_eth_stats stats;\n+\tstatic const char *nic_stats_border = \"########################\";\n+\tuint16_t port_id, len;\n+\tint rc;\n+\n+\trc = rte_eth_dev_get_port_by_name(name, &port_id);\n+\tif (rc < 0)\n+\t\treturn rc;\n+\n+\trc = rte_eth_stats_get(port_id, &stats);\n+\tif (rc != 0) {\n+\t\tfprintf(stderr,\n+\t\t\t\"%s: Error: failed to get stats (port %u): %d\",\n+\t\t\t__func__, port_id, rc);\n+\t\treturn rc;\n+\t}\n+\n+\tlen = strlen(conn->msg_out);\n+\tconn->msg_out += len;\n+\tsnprintf(conn->msg_out, conn->msg_out_len_max,\n+\t\t \"\\n  %s NIC statistics for port %-2d %s\\n\"\n+\t\t \"  RX-packets: %-10\"PRIu64\" RX-missed: %-10\"PRIu64\" RX-bytes:  \"\"%-\"PRIu64\"\\n\"\n+\t\t \"  RX-errors: %-\"PRIu64\"\\n\"\n+\t\t \"  RX-nombuf:  %-10\"PRIu64\"\\n\"\n+\t\t \"  TX-packets: %-10\"PRIu64\" TX-errors: %-10\"PRIu64\" TX-bytes:  \"\"%-\"PRIu64\"\\n\",\n+\t\t nic_stats_border, port_id, nic_stats_border, stats.ipackets, stats.imissed,\n+\t\t stats.ibytes, stats.ierrors, stats.rx_nombuf, stats.opackets, stats.oerrors,\n+\t\t stats.obytes);\n+\n+\tlen = strlen(conn->msg_out) - len;\n+\tconn->msg_out_len_max -= len;\n+\n+\tdiff_ns = 0;\n+\tdiff_cycles = 0;\n+\n+\tcurr_cycles = rte_rdtsc();\n+\tif (prev_cycles[port_id] != 0)\n+\t\tdiff_cycles = curr_cycles - prev_cycles[port_id];\n+\n+\tprev_cycles[port_id] = curr_cycles;\n+\tdiff_ns = diff_cycles > 0 ?\n+\t\tdiff_cycles * (1 / (double)rte_get_tsc_hz()) * NS_PER_SEC : 0;\n+\n+\tdiff_pkts_rx = (stats.ipackets > prev_pkts_rx[port_id]) ?\n+\t\t(stats.ipackets - prev_pkts_rx[port_id]) : 0;\n+\tdiff_pkts_tx = (stats.opackets > prev_pkts_tx[port_id]) ?\n+\t\t(stats.opackets - prev_pkts_tx[port_id]) : 0;\n+\tprev_pkts_rx[port_id] = stats.ipackets;\n+\tprev_pkts_tx[port_id] = stats.opackets;\n+\tmpps_rx = diff_ns > 0 ?\n+\t\t(double)diff_pkts_rx / diff_ns * NS_PER_SEC : 0;\n+\tmpps_tx = diff_ns > 0 ?\n+\t\t(double)diff_pkts_tx / diff_ns * NS_PER_SEC : 0;\n+\n+\tdiff_bytes_rx = (stats.ibytes > prev_bytes_rx[port_id]) ?\n+\t\t(stats.ibytes - prev_bytes_rx[port_id]) : 0;\n+\tdiff_bytes_tx = (stats.obytes > prev_bytes_tx[port_id]) ?\n+\t\t(stats.obytes - prev_bytes_tx[port_id]) : 0;\n+\tprev_bytes_rx[port_id] = stats.ibytes;\n+\tprev_bytes_tx[port_id] = stats.obytes;\n+\tmbps_rx = diff_ns > 0 ?\n+\t\t(double)diff_bytes_rx / diff_ns * NS_PER_SEC : 0;\n+\tmbps_tx = diff_ns > 0 ?\n+\t\t(double)diff_bytes_tx / diff_ns * NS_PER_SEC : 0;\n+\n+\tlen = strlen(conn->msg_out);\n+\tsnprintf(conn->msg_out + len, conn->msg_out_len_max,\n+\t\t \"\\n  Throughput (since last show)\\n\"\n+\t\t \"  Rx-pps: %12\"PRIu64\"          Rx-bps: %12\"PRIu64\"\\n  Tx-pps: %12\"\n+\t\t PRIu64\"          Tx-bps: %12\"PRIu64\"\\n\"\n+\t\t \"  %s############################%s\\n\",\n+\t\t mpps_rx, mbps_rx * 8, mpps_tx, mbps_tx * 8, nic_stats_border, nic_stats_border);\n+\treturn 0;\n+}\n+\n+static void\n+cli_ethdev_mtu(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)\n+{\n+\tstruct ethdev_mtu_cmd_tokens *res = parsed_result;\n+\tint rc = -EINVAL;\n+\n+\trc = ethdev_mtu_config(res->dev, res->size);\n+\tif (rc < 0)\n+\t\tprintf(MSG_CMD_FAIL, res->cmd);\n+}\n+\n+static void\n+cli_ethdev_prom_mode(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)\n+{\n+\tstruct ethdev_prom_mode_cmd_tokens *res = parsed_result;\n+\tbool enable = false;\n+\tint rc = -EINVAL;\n+\n+\tif (!strcmp(res->enable, \"on\"))\n+\t\tenable = true;\n+\n+\trc = ethdev_prom_mode_config(res->dev, enable);\n+\tif (rc < 0)\n+\t\tprintf(MSG_CMD_FAIL, res->cmd);\n+}\n+\n+static void\n+cli_ip4_addr(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)\n+{\n+\tstruct ethdev_ip4_cmd_tokens *res = parsed_result;\n+\tstruct ipv4_addr_config config;\n+\tint rc = -EINVAL;\n+\n+\tif (parser_ip4_read(&config.ip, res->ip)) {\n+\t\tprintf(MSG_ARG_INVALID, \"ip\");\n+\t\treturn;\n+\t}\n+\n+\tif (parser_ip4_read(&config.mask, res->mask)) {\n+\t\tprintf(MSG_ARG_INVALID, \"netmask\");\n+\t\treturn;\n+\t}\n+\n+\trc = ethdev_ip4_addr_add(res->dev, &config);\n+\tif (rc < 0)\n+\t\tprintf(MSG_CMD_FAIL, res->cmd);\n+}\n+\n+static void\n+cli_ip6_addr(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)\n+{\n+\tstruct ethdev_ip6_cmd_tokens *res = parsed_result;\n+\tstruct ipv6_addr_config config;\n+\tint rc = -EINVAL;\n+\n+\tif (parser_ip6_read(config.ip, res->ip)) {\n+\t\tprintf(MSG_ARG_INVALID, \"ip\");\n+\t\treturn;\n+\t}\n+\n+\tif (parser_ip6_read(config.mask, res->mask)) {\n+\t\tprintf(MSG_ARG_INVALID, \"netmask\");\n+\t\treturn;\n+\t}\n+\n+\trc = ethdev_ip6_addr_add(res->dev, &config);\n+\tif (rc < 0)\n+\t\tprintf(MSG_CMD_FAIL, res->cmd);\n+}\n+\n+static void\n+cli_ethdev_show(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)\n+{\n+\tstruct ethdev_show_cmd_tokens *res = parsed_result;\n+\tint rc = -EINVAL;\n+\n+\trc = ethdev_show(res->dev);\n+\tif (rc < 0)\n+\t\tprintf(MSG_ARG_INVALID, res->dev);\n+}\n+\n+static void\n+cli_ethdev_stats(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)\n+{\n+\tstruct ethdev_stats_cmd_tokens *res = parsed_result;\n+\tint rc = -EINVAL;\n+\n+\trc = ethdev_stats_show(res->dev);\n+\tif (rc < 0)\n+\t\tprintf(MSG_ARG_INVALID, res->dev);\n+}\n+\n+static void\n+cli_ethdev(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused)\n+{\n+\tstruct ethdev_cmd_tokens *res = parsed_result;\n+\tstruct ethdev_config config;\n+\tint rc;\n+\n+\tmemset(&config, 0, sizeof(struct ethdev_config));\n+\tconfig.rx.n_queues = res->nb_rxq;\n+\tconfig.rx.queue_size = ETHDEV_RX_DESC_DEFAULT;\n+\tmemcpy(config.rx.mempool_name, res->mempool, strlen(res->mempool));\n+\n+\tconfig.tx.n_queues = res->nb_txq;\n+\tconfig.tx.queue_size = ETHDEV_TX_DESC_DEFAULT;\n+\n+\tconfig.mtu = port_conf_default.rxmode.mtu;\n+\n+\trc = ethdev_process(res->dev, &config);\n+\tif (rc < 0)\n+\t\tprintf(MSG_CMD_FAIL, res->cmd);\n+}\n+\n+static void\n+cli_ethdev_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl,\n+\t\t__rte_unused void *data)\n+{\n+\tsize_t len;\n+\n+\tlen = strlen(conn->msg_out);\n+\tconn->msg_out += len;\n+\tsnprintf(conn->msg_out, conn->msg_out_len_max, \"\\n%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n%s\\n\",\n+\t\t \"----------------------------- ethdev command help -----------------------------\",\n+\t\t cmd_ethdev_help, cmd_ethdev_ip4_addr_help, cmd_ethdev_ip6_addr_help,\n+\t\t cmd_ethdev_prom_mode_help, cmd_ethdev_mtu_help, cmd_ethdev_show_help);\n+\n+\tlen = strlen(conn->msg_out);\n+\tconn->msg_out_len_max -= len;\n+}\n+\n+cmdline_parse_token_string_t ethdev_stats_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, cmd, \"ethdev\");\n+cmdline_parse_token_string_t ethdev_stats_dev =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, dev, NULL);\n+cmdline_parse_token_string_t ethdev_stats_stats =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, stats, \"stats\");\n+\n+cmdline_parse_inst_t ethdev_stats_cmd_ctx = {\n+\t.f = cli_ethdev_stats,\n+\t.data = NULL,\n+\t.help_str = \"\",\n+\t.tokens = {\n+\t\t(void *)&ethdev_stats_cmd,\n+\t\t(void *)&ethdev_stats_dev,\n+\t\t(void *)&ethdev_stats_stats,\n+\t\tNULL,\n+\t},\n+};\n+\n+cmdline_parse_token_string_t ethdev_show_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, cmd, \"ethdev\");\n+cmdline_parse_token_string_t ethdev_show_dev =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, dev, NULL);\n+cmdline_parse_token_string_t ethdev_show_show =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, show, \"show\");\n+\n+cmdline_parse_inst_t ethdev_show_cmd_ctx = {\n+\t.f = cli_ethdev_show,\n+\t.data = NULL,\n+\t.help_str = cmd_ethdev_show_help,\n+\t.tokens = {\n+\t\t(void *)&ethdev_show_cmd,\n+\t\t(void *)&ethdev_show_dev,\n+\t\t(void *)&ethdev_show_show,\n+\t\tNULL,\n+\t},\n+};\n+\n+cmdline_parse_token_string_t ethdev_mtu_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, cmd, \"ethdev\");\n+cmdline_parse_token_string_t ethdev_mtu_dev =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, dev, NULL);\n+cmdline_parse_token_string_t ethdev_mtu_mtu =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, mtu, \"mtu\");\n+cmdline_parse_token_num_t ethdev_mtu_size =\n+\tTOKEN_NUM_INITIALIZER(struct ethdev_mtu_cmd_tokens, size, RTE_UINT16);\n+\n+cmdline_parse_inst_t ethdev_mtu_cmd_ctx = {\n+\t.f = cli_ethdev_mtu,\n+\t.data = NULL,\n+\t.help_str = cmd_ethdev_mtu_help,\n+\t.tokens = {\n+\t\t(void *)&ethdev_mtu_cmd,\n+\t\t(void *)&ethdev_mtu_dev,\n+\t\t(void *)&ethdev_mtu_mtu,\n+\t\t(void *)&ethdev_mtu_size,\n+\t\tNULL,\n+\t},\n+};\n+\n+cmdline_parse_token_string_t ethdev_prom_mode_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, cmd, \"ethdev\");\n+cmdline_parse_token_string_t ethdev_prom_mode_dev =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, dev, NULL);\n+cmdline_parse_token_string_t ethdev_prom_mode_prom =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, prom, \"promiscuous\");\n+cmdline_parse_token_string_t ethdev_prom_mode_enable =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, enable, \"on#off\");\n+\n+cmdline_parse_inst_t ethdev_prom_mode_cmd_ctx = {\n+\t.f = cli_ethdev_prom_mode,\n+\t.data = NULL,\n+\t.help_str = cmd_ethdev_prom_mode_help,\n+\t.tokens = {\n+\t\t(void *)&ethdev_prom_mode_cmd,\n+\t\t(void *)&ethdev_prom_mode_dev,\n+\t\t(void *)&ethdev_prom_mode_prom,\n+\t\t(void *)&ethdev_prom_mode_enable,\n+\t\tNULL,\n+\t},\n+};\n+\n+cmdline_parse_token_string_t ethdev_ip4_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, cmd, \"ethdev\");\n+cmdline_parse_token_string_t ethdev_ip4_dev =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, dev, NULL);\n+cmdline_parse_token_string_t ethdev_ip4_ip4 =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, ip4, \"ip4\");\n+cmdline_parse_token_string_t ethdev_ip4_addr =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, addr, \"addr\");\n+cmdline_parse_token_string_t ethdev_ip4_add =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, add, \"add\");\n+cmdline_parse_token_string_t ethdev_ip4_ip =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, ip, NULL);\n+cmdline_parse_token_string_t ethdev_ip4_netmask =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, netmask, \"netmask\");\n+cmdline_parse_token_string_t ethdev_ip4_mask =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, mask, NULL);\n+\n+cmdline_parse_inst_t ethdev_ip4_cmd_ctx = {\n+\t.f = cli_ip4_addr,\n+\t.data = NULL,\n+\t.help_str = cmd_ethdev_ip4_addr_help,\n+\t.tokens = {\n+\t\t(void *)&ethdev_ip4_cmd,\n+\t\t(void *)&ethdev_ip4_dev,\n+\t\t(void *)&ethdev_ip4_ip4,\n+\t\t(void *)&ethdev_ip4_addr,\n+\t\t(void *)&ethdev_ip4_add,\n+\t\t(void *)&ethdev_ip4_ip,\n+\t\t(void *)&ethdev_ip4_netmask,\n+\t\t(void *)&ethdev_ip4_mask,\n+\t\tNULL,\n+\t},\n+};\n+\n+cmdline_parse_token_string_t ethdev_ip6_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, cmd, \"ethdev\");\n+cmdline_parse_token_string_t ethdev_ip6_dev =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, dev, NULL);\n+cmdline_parse_token_string_t ethdev_ip6_ip6 =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, ip6, \"ip6\");\n+cmdline_parse_token_string_t ethdev_ip6_addr =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, addr, \"addr\");\n+cmdline_parse_token_string_t ethdev_ip6_add =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, add, \"add\");\n+cmdline_parse_token_string_t ethdev_ip6_ip =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, ip, NULL);\n+cmdline_parse_token_string_t ethdev_ip6_netmask =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, netmask, \"netmask\");\n+cmdline_parse_token_string_t ethdev_ip6_mask =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, mask, NULL);\n+\n+cmdline_parse_inst_t ethdev_ip6_cmd_ctx = {\n+\t.f = cli_ip6_addr,\n+\t.data = NULL,\n+\t.help_str = cmd_ethdev_ip6_addr_help,\n+\t.tokens = {\n+\t\t(void *)&ethdev_ip6_cmd,\n+\t\t(void *)&ethdev_ip6_dev,\n+\t\t(void *)&ethdev_ip6_ip6,\n+\t\t(void *)&ethdev_ip6_addr,\n+\t\t(void *)&ethdev_ip6_add,\n+\t\t(void *)&ethdev_ip6_ip,\n+\t\t(void *)&ethdev_ip6_netmask,\n+\t\t(void *)&ethdev_ip6_mask,\n+\t\tNULL,\n+\t},\n+};\n+\n+cmdline_parse_token_string_t ethdev_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, cmd, \"ethdev\");\n+cmdline_parse_token_string_t ethdev_dev =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, dev, NULL);\n+cmdline_parse_token_string_t ethdev_rxq =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, rxq, \"rxq\");\n+cmdline_parse_token_num_t ethdev_nb_rxq =\n+\tTOKEN_NUM_INITIALIZER(struct ethdev_cmd_tokens, nb_rxq, RTE_UINT16);\n+cmdline_parse_token_string_t ethdev_txq =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, txq, \"txq\");\n+cmdline_parse_token_num_t ethdev_nb_txq =\n+\tTOKEN_NUM_INITIALIZER(struct ethdev_cmd_tokens, nb_txq, RTE_UINT16);\n+cmdline_parse_token_string_t ethdev_mempool =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, mempool, NULL);\n+\n+cmdline_parse_inst_t ethdev_cmd_ctx = {\n+\t.f = cli_ethdev,\n+\t.data = NULL,\n+\t.help_str = cmd_ethdev_help,\n+\t.tokens = {\n+\t\t(void *)&ethdev_cmd,\n+\t\t(void *)&ethdev_dev,\n+\t\t(void *)&ethdev_rxq,\n+\t\t(void *)&ethdev_nb_rxq,\n+\t\t(void *)&ethdev_txq,\n+\t\t(void *)&ethdev_nb_txq,\n+\t\t(void *)&ethdev_mempool,\n+\t\tNULL,\n+\t},\n+};\n+\n+cmdline_parse_token_string_t ethdev_help_cmd =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_help_cmd_tokens, help, \"help\");\n+cmdline_parse_token_string_t ethdev_help_ethdev =\n+\tTOKEN_STRING_INITIALIZER(struct ethdev_help_cmd_tokens, ethdev, \"ethdev\");\n+\n+cmdline_parse_inst_t ethdev_help_cmd_ctx = {\n+\t.f = cli_ethdev_help,\n+\t.data = NULL,\n+\t.help_str = \"\",\n+\t.tokens = {\n+\t\t(void *)&ethdev_help_cmd,\n+\t\t(void *)&ethdev_help_ethdev,\n+\t\tNULL,\n+\t},\n+};\ndiff --git a/app/graph/ethdev.h b/app/graph/ethdev.h\nnew file mode 100644\nindex 0000000000..94d3247a2c\n--- /dev/null\n+++ b/app/graph/ethdev.h\n@@ -0,0 +1,40 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Marvell.\n+ */\n+\n+#ifndef APP_GRAPH_ETHDEV_H\n+#define APP_GRAPH_ETHDEV_H\n+\n+#include <cmdline_parse.h>\n+\n+#define ETHDEV_IPV6_ADDR_LEN\t16\n+\n+extern cmdline_parse_inst_t ethdev_show_cmd_ctx;\n+extern cmdline_parse_inst_t ethdev_stats_cmd_ctx;\n+extern cmdline_parse_inst_t ethdev_mtu_cmd_ctx;\n+extern cmdline_parse_inst_t ethdev_prom_mode_cmd_ctx;\n+extern cmdline_parse_inst_t ethdev_ip4_cmd_ctx;\n+extern cmdline_parse_inst_t ethdev_ip6_cmd_ctx;\n+extern cmdline_parse_inst_t ethdev_cmd_ctx;\n+extern cmdline_parse_inst_t ethdev_help_cmd_ctx;\n+\n+struct ipv4_addr_config {\n+\tuint32_t ip;\n+\tuint32_t mask;\n+};\n+\n+struct ipv6_addr_config {\n+\tuint8_t ip[ETHDEV_IPV6_ADDR_LEN];\n+\tuint8_t mask[ETHDEV_IPV6_ADDR_LEN];\n+};\n+\n+extern uint32_t enabled_port_mask;\n+\n+void ethdev_start(void);\n+void ethdev_stop(void);\n+void *ethdev_mempool_list_by_portid(uint16_t portid);\n+int16_t ethdev_portid_by_ip4(uint32_t ip, uint32_t mask);\n+int16_t ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask);\n+void ethdev_list_clean(void);\n+\n+#endif\ndiff --git a/app/graph/ethdev_priv.h b/app/graph/ethdev_priv.h\nnew file mode 100644\nindex 0000000000..f231f3f3e1\n--- /dev/null\n+++ b/app/graph/ethdev_priv.h\n@@ -0,0 +1,112 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2023 Marvell.\n+ */\n+\n+#ifndef APP_GRAPH_ETHDEV_PRIV_H\n+#define APP_GRAPH_ETHDEV_PRIV_H\n+\n+#include \"ethdev.h\"\n+\n+#define NS_PER_SEC 1E9\n+\n+#define ETHDEV_RXQ_RSS_MAX\t16\n+#define ETHDEV_RX_DESC_DEFAULT 1024\n+#define ETHDEV_TX_DESC_DEFAULT 1024\n+\n+struct ethdev_show_cmd_tokens {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t dev;\n+\tcmdline_fixed_string_t show;\n+};\n+\n+struct ethdev_stats_cmd_tokens {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t dev;\n+\tcmdline_fixed_string_t stats;\n+};\n+\n+struct ethdev_mtu_cmd_tokens {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t dev;\n+\tcmdline_fixed_string_t mtu;\n+\tuint16_t size;\n+};\n+\n+struct ethdev_prom_mode_cmd_tokens {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t dev;\n+\tcmdline_fixed_string_t prom;\n+\tcmdline_fixed_string_t enable;\n+};\n+\n+struct ethdev_ip4_cmd_tokens {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t dev;\n+\tcmdline_fixed_string_t ip4;\n+\tcmdline_fixed_string_t addr;\n+\tcmdline_fixed_string_t add;\n+\tcmdline_fixed_string_t ip;\n+\tcmdline_fixed_string_t netmask;\n+\tcmdline_fixed_string_t mask;\n+};\n+\n+struct ethdev_ip6_cmd_tokens {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t dev;\n+\tcmdline_fixed_string_t ip6;\n+\tcmdline_fixed_string_t addr;\n+\tcmdline_fixed_string_t add;\n+\tcmdline_fixed_string_t ip;\n+\tcmdline_fixed_string_t netmask;\n+\tcmdline_fixed_string_t mask;\n+};\n+\n+struct ethdev_cmd_tokens {\n+\tcmdline_fixed_string_t cmd;\n+\tcmdline_fixed_string_t dev;\n+\tcmdline_fixed_string_t rxq;\n+\tcmdline_fixed_string_t txq;\n+\tcmdline_fixed_string_t mempool;\n+\tuint16_t nb_rxq;\n+\tuint16_t nb_txq;\n+};\n+\n+struct ethdev_help_cmd_tokens {\n+\tcmdline_fixed_string_t help;\n+\tcmdline_fixed_string_t ethdev;\n+};\n+\n+struct ethdev_rss_config {\n+\tuint32_t queue_id[ETHDEV_RXQ_RSS_MAX];\n+\tuint32_t n_queues;\n+};\n+\n+struct ethdev_config {\n+\tchar dev_name[RTE_ETH_NAME_MAX_LEN];\n+\tuint16_t port_id;\n+\n+\tstruct {\n+\t\tuint32_t n_queues;\n+\t\tuint32_t queue_size;\n+\t\tchar mempool_name[RTE_MEMPOOL_NAMESIZE];\n+\t\tstruct rte_mempool *mp;\n+\t\tstruct ethdev_rss_config *rss;\n+\t} rx;\n+\n+\tstruct {\n+\t\tuint32_t n_queues;\n+\t\tuint32_t queue_size;\n+\t} tx;\n+\n+\tint promiscuous;\n+\tuint32_t mtu;\n+};\n+\n+struct ethdev {\n+\tTAILQ_ENTRY(ethdev) next;\n+\tstruct ethdev_config config;\n+\tstruct ipv4_addr_config ip4_addr;\n+\tstruct ipv6_addr_config ip6_addr;\n+};\n+TAILQ_HEAD(ethdev_head, ethdev);\n+#endif\ndiff --git a/app/graph/main.c b/app/graph/main.c\nindex 96548f49e7..c1cb435588 100644\n--- a/app/graph/main.c\n+++ b/app/graph/main.c\n@@ -215,6 +215,7 @@ main(int argc, char **argv)\n \n exit:\n \tconn_free(conn);\n+\tethdev_stop();\n \tcli_exit();\n \trte_eal_cleanup();\n \treturn 0;\ndiff --git a/app/graph/meson.build b/app/graph/meson.build\nindex 5dc23c875b..c17e0cc63e 100644\n--- a/app/graph/meson.build\n+++ b/app/graph/meson.build\n@@ -12,6 +12,7 @@ deps += ['graph', 'eal', 'lpm', 'ethdev', 'node', 'cmdline']\n sources = files(\n         'cli.c',\n         'conn.c',\n+        'ethdev.c',\n         'main.c',\n         'mempool.c',\n         'utils.c',\ndiff --git a/app/graph/module_api.h b/app/graph/module_api.h\nindex b45419811b..e8a6ccb562 100644\n--- a/app/graph/module_api.h\n+++ b/app/graph/module_api.h\n@@ -10,6 +10,7 @@\n \n #include \"cli.h\"\n #include \"conn.h\"\n+#include \"ethdev.h\"\n #include \"mempool.h\"\n #include \"utils.h\"\n /*\ndiff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst\nindex 6009b0c291..124c16e546 100644\n--- a/doc/guides/tools/graph.rst\n+++ b/doc/guides/tools/graph.rst\n@@ -78,7 +78,39 @@ file to express the requested use case configuration.\n    +--------------------------------------+-----------------------------------+---------+----------+\n    | help mempool                         | | Command to dump mempool help    |   Yes   |    Yes   |\n    |                                      | | message.                        |         |          |\n-   |                                      |                                   |         |          |\n+   +--------------------------------------+-----------------------------------+---------+----------+\n+   | | ethdev <ethdev_name> rxq <n_queues>| | Command to create DPDK port with|   No    |    No    |\n+   | | txq <n_queues> <mempool_name>      | | given number of Rx and Tx queues|         |          |\n+   |                                      | | . Also attach RxQ with given    |         |          |\n+   |                                      | | mempool. Each port can have     |         |          |\n+   |                                      | | single mempool only i.e. all    |         |          |\n+   |                                      | | RxQs will share the same mempool|         |          |\n+   |                                      | | .                               |         |          |\n+   +--------------------------------------+-----------------------------------+---------+----------+\n+   | ethdev <ethdev_name> mtu <mtu_sz>    | | Command to configure MTU of DPDK|   Yes   |    Yes   |\n+   |                                      | | port.                           |         |          |\n+   +--------------------------------------+-----------------------------------+---------+----------+\n+   |  | ethdev <ethdev_name> promiscuous  | | Command to enable/disable       |   Yes   |    Yes   |\n+   |  | <on/off>                          | | promiscuous mode on DPDK port.  |         |          |\n+   +--------------------------------------+-----------------------------------+---------+----------+\n+   | ethdev <ethdev_name> show            | | Command to dump current ethdev  |   Yes   |    Yes   |\n+   |                                      | | configuration.                  |         |          |\n+   +--------------------------------------+-----------------------------------+---------+----------+\n+   | ethdev <ethdev_name> stats           | | Command to dump current ethdev  |   Yes   |    Yes   |\n+   |                                      | | statistics.                     |         |          |\n+   +--------------------------------------+-----------------------------------+---------+----------+\n+   | | ethdev <ethdev_name> ip4 addr add  | | Command to configure IPv4       |   Yes   |    Yes   |\n+   | | <ip> netmask <mask>                | | address on given PCI device. It |         |          |\n+   |                                      | | is needed if user wishes to use |         |          |\n+   |                                      | | ``ipv4_lookup`` node.           |         |          |\n+   +--------------------------------------+-----------------------------------+---------+----------+\n+   | | ethdev <ethdev_name> ip6 addr add  | | Command to configure IPv6       |   Yes   |    Yes   |\n+   | | <ip> netmask <mask>                | | address on given PCI device. It |         |          |\n+   |                                      | | is needed if user wishes to use |         |          |\n+   |                                      | | ``ipv6_lookup`` node.           |         |          |\n+   +--------------------------------------+-----------------------------------+---------+----------+\n+   | help ethdev                          | | Command to dump ethdev help     |   Yes   |    Yes   |\n+   |                                      | | message.                        |         |          |\n    +--------------------------------------+-----------------------------------+---------+----------+\n \n Runtime configuration\n@@ -113,6 +145,17 @@ Example: ``dpdk-graph`` is started with -h 10.28.35.207 and -p 50000 then\n \n    graph>\n    graph>\n+   graph> help ethdev\n+\n+   ----------------------------- ethdev command help -----------------------------\n+   ethdev <ethdev_name> rxq <n_queues> txq <n_queues> <mempool_name>\n+   ethdev <ethdev_name> ip4 addr add <ip> netmask <mask>\n+   ethdev <ethdev_name> ip6 addr add <ip> netmask <mask>\n+   ethdev <ethdev_name> promiscuous <on/off>\n+   ethdev <ethdev_name> mtu <mtu_sz>\n+   ethdev <ethdev_name> show\n+   graph>\n+\n Created graph for use case\n --------------------------\n \n",
    "prefixes": [
        "v10",
        "05/12"
    ]
}