Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/132195/?format=api
http://patchwork.dpdk.org/api/patches/132195/?format=api", "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20230929095814.692890-6-skori@marvell.com/", "project": { "id": 1, "url": "http://patchwork.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": "<20230929095814.692890-6-skori@marvell.com>", "list_archive_url": "https://inbox.dpdk.org/dev/20230929095814.692890-6-skori@marvell.com", "date": "2023-09-29T09:58:07", "name": "[v8,05/12] app/graph: add ethdev command line interfaces", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": true, "hash": "a375b2a49312aa5eadf38fd198decfe8296bb2be", "submitter": { "id": 1318, "url": "http://patchwork.dpdk.org/api/people/1318/?format=api", "name": "Sunil Kumar Kori", "email": "skori@marvell.com" }, "delegate": { "id": 1, "url": "http://patchwork.dpdk.org/api/users/1/?format=api", "username": "tmonjalo", "first_name": "Thomas", "last_name": "Monjalon", "email": "thomas@monjalon.net" }, "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20230929095814.692890-6-skori@marvell.com/mbox/", "series": [ { "id": 29693, "url": "http://patchwork.dpdk.org/api/series/29693/?format=api", "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=29693", "date": "2023-09-29T09:58:02", "name": "add CLI based graph application", "version": 8, "mbox": "http://patchwork.dpdk.org/series/29693/mbox/" } ], "comments": "http://patchwork.dpdk.org/api/patches/132195/comments/", "check": "warning", "checks": "http://patchwork.dpdk.org/api/patches/132195/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 B291842671;\n\tFri, 29 Sep 2023 11:58:59 +0200 (CEST)", "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id C802540E03;\n\tFri, 29 Sep 2023 11:58:36 +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 D251640A79\n for <dev@dpdk.org>; Fri, 29 Sep 2023 11:58:31 +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 38T27RW2020569 for <dev@dpdk.org>; Fri, 29 Sep 2023 02:58:31 -0700", "from dc5-exch01.marvell.com ([199.233.59.181])\n by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3tcrrs836c-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT)\n for <dev@dpdk.org>; Fri, 29 Sep 2023 02:58:30 -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 Fri, 29 Sep 2023 02:58:28 -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; Fri, 29 Sep 2023 02:58:28 -0700", "from localhost.localdomain (unknown [10.28.34.25])\n by maili.marvell.com (Postfix) with ESMTP id 11F415B6921;\n Fri, 29 Sep 2023 02:58:26 -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=v+U7JW9E1nY+svbyhyYntVK5qnSfrHMTl5/md8SJVNU=;\n b=eMTTaj23hzDQdrIVNJdANrEzliTUVodULcorOX/t+bkip3yZmeAee1lNaXvauLepKtkW\n gU7k4lcGNNDyjBOPYRd1izgTBoKjORRjK4BRG35EaJ96AN4UNIpcb80szHlJWVz+LBmr\n f+p9xBKDRSfJXFTvQpOOJO5xPuxwqRCYrpcxK87eRIsrXP6mLS3ZlGmRwOW9uYjz28hz\n 0ojUm4dmiZwguG9hTXSYMlrP2Tnf8+f8pv3FU+Eu9JKRIEU7JeUVGruopovR+C17/3PL\n ybRSVRojRnR3Cy0k41N6Y74bn2YcKyW40YedABUUATIJ/dmSH8cSbwv586YRXSjQiwaQ /w==", "From": "<skori@marvell.com>", "To": "Sunil Kumar Kori <skori@marvell.com>, Rakesh Kudurumalla\n <rkudurumalla@marvell.com>", "CC": "<dev@dpdk.org>", "Subject": "[PATCH v8 05/12] app/graph: add ethdev command line interfaces", "Date": "Fri, 29 Sep 2023 15:28:07 +0530", "Message-ID": "<20230929095814.692890-6-skori@marvell.com>", "X-Mailer": "git-send-email 2.25.1", "In-Reply-To": "<20230929095814.692890-1-skori@marvell.com>", "References": "<20230927115412.55018-13-skori@marvell.com>\n <20230929095814.692890-1-skori@marvell.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Content-Type": "text/plain", "X-Proofpoint-ORIG-GUID": "3so3nGaSmkktRxFi-l6KHsTPaETHgeh7", "X-Proofpoint-GUID": "3so3nGaSmkktRxFi-l6KHsTPaETHgeh7", "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26\n definitions=2023-09-29_07,2023-09-28_03,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\nIt adds 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>\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 | 47 ++\n 8 files changed, 1092 insertions(+)\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 c9f932517e..c4b5cf3ce1 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 *)ðdev_show_cmd_ctx,\n+\t(cmdline_parse_inst_t *)ðdev_stats_cmd_ctx,\n+\t(cmdline_parse_inst_t *)ðdev_mtu_cmd_ctx,\n+\t(cmdline_parse_inst_t *)ðdev_prom_mode_cmd_ctx,\n+\t(cmdline_parse_inst_t *)ðdev_ip4_cmd_ctx,\n+\t(cmdline_parse_inst_t *)ðdev_ip6_cmd_ctx,\n+\t(cmdline_parse_inst_t *)ðdev_cmd_ctx,\n+\t(cmdline_parse_inst_t *)ðdev_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, ð_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, ð_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, ð_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(ð_node)) {\n+\t\tport = TAILQ_FIRST(ð_node);\n+\t\tTAILQ_REMOVE(ð_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(ðdev_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(ð_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 *)ðdev_stats_cmd,\n+\t\t(void *)ðdev_stats_dev,\n+\t\t(void *)ðdev_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 *)ðdev_show_cmd,\n+\t\t(void *)ðdev_show_dev,\n+\t\t(void *)ðdev_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 *)ðdev_mtu_cmd,\n+\t\t(void *)ðdev_mtu_dev,\n+\t\t(void *)ðdev_mtu_mtu,\n+\t\t(void *)ðdev_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 *)ðdev_prom_mode_cmd,\n+\t\t(void *)ðdev_prom_mode_dev,\n+\t\t(void *)ðdev_prom_mode_prom,\n+\t\t(void *)ðdev_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 *)ðdev_ip4_cmd,\n+\t\t(void *)ðdev_ip4_dev,\n+\t\t(void *)ðdev_ip4_ip4,\n+\t\t(void *)ðdev_ip4_addr,\n+\t\t(void *)ðdev_ip4_add,\n+\t\t(void *)ðdev_ip4_ip,\n+\t\t(void *)ðdev_ip4_netmask,\n+\t\t(void *)ðdev_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 *)ðdev_ip6_cmd,\n+\t\t(void *)ðdev_ip6_dev,\n+\t\t(void *)ðdev_ip6_ip6,\n+\t\t(void *)ðdev_ip6_addr,\n+\t\t(void *)ðdev_ip6_add,\n+\t\t(void *)ðdev_ip6_ip,\n+\t\t(void *)ðdev_ip6_netmask,\n+\t\t(void *)ðdev_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 *)ðdev_cmd,\n+\t\t(void *)ðdev_dev,\n+\t\t(void *)ðdev_rxq,\n+\t\t(void *)ðdev_nb_rxq,\n+\t\t(void *)ðdev_txq,\n+\t\t(void *)ðdev_nb_txq,\n+\t\t(void *)ðdev_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 *)ðdev_help_cmd,\n+\t\t(void *)ðdev_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 2027183050..aaaced4932 100644\n--- a/app/graph/meson.build\n+++ b/app/graph/meson.build\n@@ -12,6 +12,7 @@ deps += ['bus_pci', '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 9f6b83e248..0d810c2389 100644\n--- a/doc/guides/tools/graph.rst\n+++ b/doc/guides/tools/graph.rst\n@@ -88,6 +88,42 @@ file to express the requested use case configuration.\n - Command to dump mempool help message\n - Yes\n - Yes\n+ * - ethdev <ethdev_name> rxq <n_queues> txq <n_queues> <mempool_name>\n+ - Command to create DPDK port with given number of Rx and Tx queues. Also attached\n+ RxQ with given mempool. Each port can have single mempool only i.e. all RxQs will\n+ share the same mempool.\n+ - No\n+ - No\n+ * - ethdev <ethdev_name> mtu <mtu_sz>\n+ - Command to configure MTU of DPDK port\n+ - Yes\n+ - Yes\n+ * - ethdev <ethdev_name> promiscuous <on/off>\n+ - Command to enable/disable promiscuous mode on DPDK port\n+ - Yes\n+ - Yes\n+ * - ethdev <ethdev_name> show\n+ - Command to dump current ethdev configuration\n+ - Yes\n+ - Yes\n+ * - ethdev <ethdev_name> stats\n+ - Command to dump current ethdev statistics\n+ - Yes\n+ - Yes\n+ * - ethdev <ethdev_name> ip4 addr add <ip> netmask <mask>\n+ - Command to configure IPv4 address on given PCI device. It is needed if user\n+ wishes to use ``ipv4_lookup`` node\n+ - Yes\n+ - Yes\n+ * - ethdev <ethdev_name> ip6 addr add <ip> netmask <mask>\n+ - Command to configure IPv6 address on given PCI device. It is needed if user\n+ wishes to use ``ipv6_lookup`` node\n+ - Yes\n+ - Yes\n+ * - help ethdev\n+ - Command to dump ethdev help message\n+ - Yes\n+ - Yes\n \n Runtime configuration\n ---------------------\n@@ -121,6 +157,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": [ "v8", "05/12" ] }{ "id": 132195, "url": "