From patchwork Tue Sep 26 10:57:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131951 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 73FE442642; Tue, 26 Sep 2023 12:57:56 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id AF78B402E2; Tue, 26 Sep 2023 12:57:54 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 4D515402E0 for ; Tue, 26 Sep 2023 12:57:52 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38PNkg1w032220; Tue, 26 Sep 2023 03:57:51 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=66HheXHs3P+7dls2Og1DwfuEpWgUyd+HsJvuVJQfFIA=; b=Ni1Wi3Brnq8EFa50nLmsHWb1c6jTAfLz6Sq67K1Ha4sK8KuLDWEcPvUJ30xUb1k4zRy2 gFeEEgcTY513o0E1SAuBUuH5SUm5iMO8VuBJpf8aRASTS9SVhqXo9LMGF7DcR0EaXFdy yerZdZ1fpeNR/GDHN0nT48wdMtNmAF0CwRDiooWjxe6xTiklr3J1Dl/ttPHUf7fKr1vR 09L5zimycRy99Li5hNtga5hv1CVWPTD1FHBahKRILcJjdrQNGXO+ULcEVZG6p6QSRnp0 tsZY27uN8sl+pCwfllZOMS1Cb1KxbEAlv4BZQFait6rwDstwUHLgvywZx+kn1Kk3ASsd yQ== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3t9yhm0kfn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Tue, 26 Sep 2023 03:57:51 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:57:48 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:57:48 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 926F03F70A9; Tue, 26 Sep 2023 03:57:47 -0700 (PDT) From: To: Thomas Monjalon , Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 01/12] app/graph: add application framework to read CLI Date: Tue, 26 Sep 2023 16:27:31 +0530 Message-ID: <20230926105742.2638594-2-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: xJ6I9jT5TKNH0aZQz0oeyvHsGOgCuqq2 X-Proofpoint-ORIG-GUID: xJ6I9jT5TKNH0aZQz0oeyvHsGOgCuqq2 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori It adds base framework to read a given .cli file as a command line parameter "-s". Example: # ./dpdk-graph -c 0xff -- -s ./app/graph/examples/dummy.cli Each .cli file will contain commands to configure different module like mempool, ethdev, lookup tables, graph etc. Command parsing is backed by commandline library. Each module needs to expose its supported commands & corresponding callback functions to commandline library to get them parsed. Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- v5..v6: - Fix build errors. - Fix checkpatch errors. - Fix individual patch build errors. v4..v5: - Fix application exit issue. - Enable graph packet capture feature. - Fix graph coremask synchronization with eal coremask. - Update user guide. https://patches.dpdk.org/project/dpdk/patch/20230919160455.1678716-1-skori@marvell.com/ v3..v4: - Use commandline library to parse command tokens. - Split to multiple smaller patches. - Make neigh and route as dynamic database. - add ethdev and graph stats command via telnet. - Update user guide. https://patches.dpdk.org/project/dpdk/patch/20230908104907.4060511-1-skori@marvell.com/ MAINTAINERS | 7 ++ app/graph/cli.c | 113 ++++++++++++++++++++++++++++++++ app/graph/cli.h | 32 ++++++++++ app/graph/main.c | 128 +++++++++++++++++++++++++++++++++++++ app/graph/meson.build | 14 ++++ app/graph/module_api.h | 16 +++++ app/meson.build | 1 + doc/guides/tools/graph.rst | 82 ++++++++++++++++++++++++ doc/guides/tools/index.rst | 1 + 9 files changed, 394 insertions(+) create mode 100644 app/graph/cli.c create mode 100644 app/graph/cli.h create mode 100644 app/graph/main.c create mode 100644 app/graph/meson.build create mode 100644 app/graph/module_api.h create mode 100644 doc/guides/tools/graph.rst diff --git a/MAINTAINERS b/MAINTAINERS index 00f5a5f9e6..7998be98f1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1811,6 +1811,13 @@ F: dts/ F: devtools/dts-check-format.sh F: doc/guides/tools/dts.rst +Graph application +M: Sunil Kumar Kori +M: Rakesh Kudurumalla +F: app/graph/ +F: doc/guides/tools/graph.rst +F: doc/guides/tools/img/graph-usecase-l3fwd.svg + Other Example Applications -------------------------- diff --git a/app/graph/cli.c b/app/graph/cli.c new file mode 100644 index 0000000000..473fa1635a --- /dev/null +++ b/app/graph/cli.c @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "module_api.h" + +#define CMD_MAX_TOKENS 256 +#define MAX_LINE_SIZE 2048 + +cmdline_parse_ctx_t modules_ctx[] = { + NULL, +}; + +static struct cmdline *cl; + +static int +is_comment(char *in) +{ + if ((strlen(in) && index("!#%;", in[0])) || + (strncmp(in, "//", 2) == 0) || + (strncmp(in, "--", 2) == 0)) + return 1; + + return 0; +} + +void +cli_init(void) +{ + cl = cmdline_stdin_new(modules_ctx, ""); +} + +void +cli_exit(void) +{ + cmdline_stdin_exit(cl); +} + +void +cli_process(char *in, char *out, size_t out_size, __rte_unused void *obj) +{ + int rc; + + if (is_comment(in)) + return; + + rc = cmdline_parse(cl, in); + if (rc == CMDLINE_PARSE_AMBIGUOUS) + snprintf(out, out_size, MSG_CMD_FAIL, "Ambiguous command"); + else if (rc == CMDLINE_PARSE_NOMATCH) + snprintf(out, out_size, MSG_CMD_FAIL, "Command mismatch"); + else if (rc == CMDLINE_PARSE_BAD_ARGS) + snprintf(out, out_size, MSG_CMD_FAIL, "Bad arguments"); + + return; + +} + +int +cli_script_process(const char *file_name, size_t msg_in_len_max, size_t msg_out_len_max, void *obj) +{ + char *msg_in = NULL, *msg_out = NULL; + FILE *f = NULL; + + /* Check input arguments */ + if ((file_name == NULL) || (strlen(file_name) == 0) || (msg_in_len_max == 0) || + (msg_out_len_max == 0)) + return -EINVAL; + + msg_in = malloc(msg_in_len_max + 1); + msg_out = malloc(msg_out_len_max + 1); + if ((msg_in == NULL) || (msg_out == NULL)) { + free(msg_out); + free(msg_in); + return -ENOMEM; + } + + /* Open input file */ + f = fopen(file_name, "r"); + if (f == NULL) { + free(msg_out); + free(msg_in); + return -EIO; + } + + /* Read file */ + while (fgets(msg_in, msg_in_len_max, f) != NULL) { + msg_out[0] = 0; + + cli_process(msg_in, msg_out, msg_out_len_max, obj); + + if (strlen(msg_out)) + printf("%s", msg_out); + } + + /* Close file */ + fclose(f); + free(msg_out); + free(msg_in); + return 0; +} diff --git a/app/graph/cli.h b/app/graph/cli.h new file mode 100644 index 0000000000..652f948352 --- /dev/null +++ b/app/graph/cli.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_CLI_H +#define APP_GRAPH_CLI_H + +/* Macros */ +#define MSG_OUT_OF_MEMORY "Not enough memory.\n" +#define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" +#define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" +#define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" +#define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" +#define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" +#define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" +#define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" +#define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" +#define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" +#define MSG_CMD_FAIL "Command \"%s\" failed.\n" + +#define APP_CLI_CMD_NAME_SIZE 64 + +void cli_init(void); + +void cli_exit(void); + +void cli_process(char *in, char *out, size_t out_size, void *arg); + +int cli_script_process(const char *file_name, size_t msg_in_len_max, size_t msg_out_len_max, + void *arg); + +#endif diff --git a/app/graph/main.c b/app/graph/main.c new file mode 100644 index 0000000000..734a94444e --- /dev/null +++ b/app/graph/main.c @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "module_api.h" + +volatile bool force_quit; + +static const char usage[] = "%s EAL_ARGS -- -s SCRIPT " + "[--help]\n"; + +static struct app_params { + char *script_name; +} app = { + .script_name = NULL, +}; + +static void +signal_handler(int signum) +{ + if (signum == SIGINT || signum == SIGTERM) { + printf("\n\nSignal %d received, preparing to exit...\n", signum); + force_quit = true; + } +} + +static int +app_args_parse(int argc, char **argv) +{ + struct option lgopts[] = { + {"help", 0, 0, 'H'}, + }; + int s_present, n_args, i; + char *app_name = argv[0]; + int opt, option_index; + + /* Skip EAL input args */ + n_args = argc; + for (i = 0; i < n_args; i++) + if (strcmp(argv[i], "--") == 0) { + argc -= i; + argv += i; + break; + } + + if (i == n_args) + return 0; + + /* Parse args */ + s_present = 0; + + while ((opt = getopt_long(argc, argv, "s:", lgopts, &option_index)) != EOF) { + switch (opt) { + case 's': + if (s_present) { + printf("Error: Multiple -s arguments\n"); + return -1; + } + s_present = 1; + + if (!strlen(optarg)) { + printf("Error: Argument for -s not provided\n"); + return -1; + } + + app.script_name = strdup(optarg); + if (app.script_name == NULL) { + printf("Error: Not enough memory\n"); + return -1; + } + break; + + case 'H': + default: + printf(usage, app_name); + return -1; + } + } + optind = 1; /* reset getopt lib */ + + return 0; +} + +int +main(int argc, char **argv) +{ + int rc; + + /* Parse application arguments */ + rc = app_args_parse(argc, argv); + if (rc < 0) + return rc; + + /* EAL */ + rc = rte_eal_init(argc, argv); + if (rc < 0) { + printf("Error: EAL initialization failed (%d)\n", rc); + return rc; + }; + + force_quit = false; + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + cli_init(); + + /* Script */ + if (app.script_name) { + cli_script_process(app.script_name, 0, + 0, NULL); + } + + cli_exit(); + rte_eal_cleanup(); + return 0; +} diff --git a/app/graph/meson.build b/app/graph/meson.build new file mode 100644 index 0000000000..87c4ce30a8 --- /dev/null +++ b/app/graph/meson.build @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Marvell. + +# override default name to drop the hyphen +name = 'graph' +if not build + subdir_done() +endif + +deps += ['bus_pci', 'graph', 'eal', 'lpm', 'ethdev', 'node', 'cmdline'] +sources = files( + 'cli.c', + 'main.c', +) diff --git a/app/graph/module_api.h b/app/graph/module_api.h new file mode 100644 index 0000000000..372aeae7e3 --- /dev/null +++ b/app/graph/module_api.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_MODULE_API_H +#define APP_GRAPH_MODULE_API_H + +#include +#include +#include "cli.h" +/* + * Externs + */ +extern volatile bool force_quit; + +#endif diff --git a/app/meson.build b/app/meson.build index e4bf5c531c..728c936383 100644 --- a/app/meson.build +++ b/app/meson.build @@ -17,6 +17,7 @@ endif apps = [ 'dumpcap', 'pdump', + 'graph', 'proc-info', 'test-acl', 'test-bbdev', diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst new file mode 100644 index 0000000000..271a85896d --- /dev/null +++ b/doc/guides/tools/graph.rst @@ -0,0 +1,82 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright(c) 2023 Marvell. + +dpdk-graph Application +====================== + +The ``dpdk-graph`` tool is a Data Plane Development Kit (DPDK) +application that allows exercising various graph use cases. +This application has a generic framework to add new graph based use cases to +verify functionality. Each use case is defined as a ``.cli`` file. +Based on the input file, application creates a graph to cater the use case. + +Supported Use cases +------------------- + * + +Running the Application +----------------------- + +The application has a number of command line options which can be provided in +following syntax + +.. code-block:: console + + dpdk-graph [EAL Options] -- [application options] + +EAL Options +~~~~~~~~~~~ + +Following are the EAL command-line options that can be used in conjunction +with the ``dpdk-graph`` application. +See the DPDK Getting Started Guides for more information on these options. + +* ``-c `` or ``-l `` + + Set the hexadecimal bit mask of the cores to run on. The CORELIST is a + list of cores to be used. + +Application Options +~~~~~~~~~~~~~~~~~~~ + +Following are the application command-line options: + +* ``-s`` + + Script name with absolute path which specifies the use case. It is + a mandatory parameter which will be used to create desired graph + for a given use case. + +* ``--help`` + + Dumps application usage + +Supported CLI commands +---------------------- + +This section provides details on commands which can be used in ``.cli`` +file to express the requested use case configuration. + +.. list-table:: Exposed CLIs + :widths: 40 40 10 10 + :header-rows: 1 + :class: longtable + + * - Command + - Description + - Dynamic + - Optional + * - Dummy command + - Dummy command description + - No + - No + +Runtime configuration +--------------------- + + +Created graph for use case +-------------------------- + +On the successful execution of ``.cli`` file, corresponding graph will be created. +This section mentions the created graph for each use case. diff --git a/doc/guides/tools/index.rst b/doc/guides/tools/index.rst index f2afb1fcc5..4f4dc8b518 100644 --- a/doc/guides/tools/index.rst +++ b/doc/guides/tools/index.rst @@ -23,4 +23,5 @@ DPDK Tools User Guides testeventdev testregex testmldev + graph dts From patchwork Tue Sep 26 10:57:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131952 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 0D55842642; Tue, 26 Sep 2023 12:58:03 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E7409402F2; Tue, 26 Sep 2023 12:57:56 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 5A98940269 for ; Tue, 26 Sep 2023 12:57:54 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38QAIp4l025962 for ; Tue, 26 Sep 2023 03:57:53 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=JuQJtv+hWg/WDAtk4fo6LpeYm2p88B3Jl60kIW6Ppbw=; b=a99emhf+j3vvy5OUKH4LKwmve9BRROSW5ULvhJgCQr9dxBVZXhZO5wG8IW0VeBiM3cG/ wbHN45QRWynPU3QaC1Z5oHUACVau+dHQewzUBT8GzuvpdZOzOPAKtab+zKuovDw9ImcX EAA157qsGN86sQCSsTX8bTYMdX9aD2ay4BnqNMs05owXrPY9XAKexFZZ6sTquaeQckkV +yAWWLGMPUQ70o2tIF7VSFaHjDXIG7T+NN2IEvHFbbDUJg9lhWFYrcCIocNIxLWWjS+O ExH21bdQMR7bUat4eoU6wys5CByqpTyl5G7WHd9N09FTBLJEqGG1mo7yHeWqMxYBVr1n QQ== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3t9yhm0kfr-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:57:53 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:57:51 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:57:50 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id CC77D3F70A6; Tue, 26 Sep 2023 03:57:49 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 02/12] app/graph: add telnet connectivity framework Date: Tue, 26 Sep 2023 16:27:32 +0530 Message-ID: <20230926105742.2638594-3-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: M00hIaykTt-_je6qrlgKuyh1hTbmYL2H X-Proofpoint-ORIG-GUID: M00hIaykTt-_je6qrlgKuyh1hTbmYL2H X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori It adds framework to initiate a telnet session with application. Some configurations and debug commands are exposed as runtime APIs. Those commands can be invoked using telnet session. Application initiates a telnet server with host address 0.0.0.0 and port number 8086 by default. To make it configurable, "-h" and "-p" options are provided. Using them user can pass host address and port number on which application will start telnet server. Using same host address and port number, telnet client can connect to application. Syntax to connect with application: # telnet Once session is connected, "graph> " prompt will be available. Example: # telnet 10.28.35.207 50000 Trying 10.28.35.207... Connected to 10.28.35.207. Escape character is '^]'. Welcome! graph> Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/conn.c | 282 +++++++++++++++++++++++++++++++++++++ app/graph/conn.h | 46 ++++++ app/graph/main.c | 103 +++++++++++++- app/graph/meson.build | 1 + app/graph/module_api.h | 3 + doc/guides/tools/graph.rst | 38 +++++ 6 files changed, 468 insertions(+), 5 deletions(-) create mode 100644 app/graph/conn.c create mode 100644 app/graph/conn.h diff --git a/app/graph/conn.c b/app/graph/conn.c new file mode 100644 index 0000000000..8c88500605 --- /dev/null +++ b/app/graph/conn.c @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "module_api.h" + +#define MSG_CMD_TOO_LONG "Command too long." + +static int +data_event_handle(struct conn *conn, int fd_client) +{ + ssize_t len, i, rc = 0; + + /* Read input message */ + len = read(fd_client, conn->buf, conn->buf_size); + if (len == -1) { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + return 0; + + return -1; + } + + if (len == 0) + return rc; + + /* Handle input messages */ + for (i = 0; i < len; i++) { + if (conn->buf[i] == '\n') { + size_t n; + + conn->msg_in[conn->msg_in_len] = 0; + conn->msg_out[0] = 0; + + conn->msg_handle(conn->msg_in, conn->msg_out, conn->msg_out_len_max, + conn->msg_handle_arg); + + n = strlen(conn->msg_out); + if (n) { + rc = write(fd_client, conn->msg_out, n); + if (rc == -1) + goto exit; + } + + conn->msg_in_len = 0; + } else if (conn->msg_in_len < conn->msg_in_len_max) { + conn->msg_in[conn->msg_in_len] = conn->buf[i]; + conn->msg_in_len++; + } else { + rc = write(fd_client, MSG_CMD_TOO_LONG, strlen(MSG_CMD_TOO_LONG)); + if (rc == -1) + goto exit; + + conn->msg_in_len = 0; + } + } + + /* Write prompt */ + rc = write(fd_client, conn->prompt, strlen(conn->prompt)); + rc = (rc == -1) ? -1 : 0; + +exit: + return rc; +} + +static int +control_event_handle(struct conn *conn, int fd_client) +{ + int rc; + + rc = epoll_ctl(conn->fd_client_group, EPOLL_CTL_DEL, fd_client, NULL); + if (rc == -1) + goto exit; + + rc = close(fd_client); + if (rc == -1) + goto exit; + + rc = 0; + +exit: + return rc; +} + +struct conn * +conn_init(struct conn_params *p) +{ + int fd_server, fd_client_group, rc; + struct sockaddr_in server_address; + struct conn *conn = NULL; + int reuse = 1; + + memset(&server_address, 0, sizeof(server_address)); + + /* Check input arguments */ + if ((p == NULL) || (p->welcome == NULL) || (p->prompt == NULL) || (p->addr == NULL) || + (p->buf_size == 0) || (p->msg_in_len_max == 0) || (p->msg_out_len_max == 0) || + (p->msg_handle == NULL)) + goto exit; + + rc = inet_aton(p->addr, &server_address.sin_addr); + if (rc == 0) + goto exit; + + /* Memory allocation */ + conn = calloc(1, sizeof(struct conn)); + if (conn == NULL) + goto exit; + + conn->welcome = calloc(1, CONN_WELCOME_LEN_MAX + 1); + conn->prompt = calloc(1, CONN_PROMPT_LEN_MAX + 1); + conn->buf = calloc(1, p->buf_size); + conn->msg_in = calloc(1, p->msg_in_len_max + 1); + conn->msg_out = calloc(1, p->msg_out_len_max + 1); + + if ((conn->welcome == NULL) || (conn->prompt == NULL) || (conn->buf == NULL) || + (conn->msg_in == NULL) || (conn->msg_out == NULL)) { + conn_free(conn); + conn = NULL; + goto exit; + } + + /* Server socket */ + server_address.sin_family = AF_INET; + server_address.sin_port = htons(p->port); + + fd_server = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + if (fd_server == -1) { + conn_free(conn); + conn = NULL; + goto exit; + } + + if (setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse, + sizeof(reuse)) < 0) + goto free; + + rc = bind(fd_server, (struct sockaddr *)&server_address, sizeof(server_address)); + if (rc == -1) + goto free; + + rc = listen(fd_server, 16); + if (rc == -1) + goto free; + + /* Client group */ + fd_client_group = epoll_create(1); + if (fd_client_group == -1) + goto free; + + /* Fill in */ + strncpy(conn->welcome, p->welcome, CONN_WELCOME_LEN_MAX); + strncpy(conn->prompt, p->prompt, CONN_PROMPT_LEN_MAX); + conn->buf_size = p->buf_size; + conn->msg_in_len_max = p->msg_in_len_max; + conn->msg_out_len_max = p->msg_out_len_max; + conn->msg_in_len = 0; + conn->fd_server = fd_server; + conn->fd_client_group = fd_client_group; + conn->msg_handle = p->msg_handle; + conn->msg_handle_arg = p->msg_handle_arg; + +exit: + return conn; +free: + conn_free(conn); + close(fd_server); + conn = NULL; + return conn; +} + +void +conn_free(struct conn *conn) +{ + if (conn == NULL) + return; + + if (conn->fd_client_group) + close(conn->fd_client_group); + + if (conn->fd_server) + close(conn->fd_server); + + free(conn->msg_out); + free(conn->msg_in); + free(conn->prompt); + free(conn->welcome); + free(conn); +} + +int +conn_req_poll(struct conn *conn) +{ + struct sockaddr_in client_address; + socklen_t client_address_length; + struct epoll_event event; + int fd_client, rc; + + /* Check input arguments */ + if (conn == NULL) + return -1; + + /* Server socket */ + client_address_length = sizeof(client_address); + fd_client = accept4(conn->fd_server, (struct sockaddr *)&client_address, + &client_address_length, SOCK_NONBLOCK); + if (fd_client == -1) { + if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) + return 0; + + return -1; + } + + /* Client group */ + event.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP; + event.data.fd = fd_client; + + rc = epoll_ctl(conn->fd_client_group, EPOLL_CTL_ADD, fd_client, &event); + if (rc == -1) { + close(fd_client); + goto exit; + } + + /* Client */ + rc = write(fd_client, conn->welcome, strlen(conn->welcome)); + if (rc == -1) { + close(fd_client); + goto exit; + } + + rc = write(fd_client, conn->prompt, strlen(conn->prompt)); + if (rc == -1) { + close(fd_client); + goto exit; + } + + rc = 0; + +exit: + return rc; +} + +int +conn_msg_poll(struct conn *conn) +{ + int fd_client, rc, rc_data = 0, rc_control = 0; + struct epoll_event event; + + /* Check input arguments */ + if (conn == NULL) + return -1; + + /* Client group */ + rc = epoll_wait(conn->fd_client_group, &event, 1, 0); + if ((rc == -1) || rc == 0) + return rc; + + fd_client = event.data.fd; + + /* Data available */ + if (event.events & EPOLLIN) + rc_data = data_event_handle(conn, fd_client); + + /* Control events */ + if (event.events & (EPOLLRDHUP | EPOLLERR | EPOLLHUP)) + rc_control = control_event_handle(conn, fd_client); + + if (rc_data || rc_control) + return -1; + + return 0; +} diff --git a/app/graph/conn.h b/app/graph/conn.h new file mode 100644 index 0000000000..770964cf4c --- /dev/null +++ b/app/graph/conn.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_CONN_H +#define APP_GRAPH_CONN_H + +#define CONN_WELCOME_LEN_MAX 1024 +#define CONN_PROMPT_LEN_MAX 16 + +typedef void (*conn_msg_handle_t)(char *msg_in, char *msg_out, size_t msg_out_len_max, void *arg); + +struct conn { + char *welcome; + char *prompt; + char *buf; + char *msg_in; + char *msg_out; + size_t buf_size; + size_t msg_in_len_max; + size_t msg_out_len_max; + size_t msg_in_len; + int fd_server; + int fd_client_group; + conn_msg_handle_t msg_handle; + void *msg_handle_arg; +}; + +struct conn_params { + const char *welcome; + const char *prompt; + const char *addr; + uint16_t port; + size_t buf_size; + size_t msg_in_len_max; + size_t msg_out_len_max; + conn_msg_handle_t msg_handle; + void *msg_handle_arg; +}; + +struct conn *conn_init(struct conn_params *p); +void conn_free(struct conn *conn); +int conn_req_poll(struct conn *conn); +int conn_msg_poll(struct conn *conn); + +#endif diff --git a/app/graph/main.c b/app/graph/main.c index 734a94444e..96548f49e7 100644 --- a/app/graph/main.c +++ b/app/graph/main.c @@ -2,6 +2,7 @@ * Copyright(c) 2023 Marvell. */ +#include #include #include #include @@ -11,19 +12,33 @@ #include #include +#include #include #include #include "module_api.h" volatile bool force_quit; +struct conn *conn; -static const char usage[] = "%s EAL_ARGS -- -s SCRIPT " +static const char usage[] = "%s EAL_ARGS -- -s SCRIPT [-h HOST] [-p PORT] " "[--help]\n"; static struct app_params { + struct conn_params conn; char *script_name; } app = { + .conn = { + .welcome = "\nWelcome!\n\n", + .prompt = "graph> ", + .addr = "0.0.0.0", + .port = 8086, + .buf_size = 1024 * 1024, + .msg_in_len_max = 1024, + .msg_out_len_max = 1024 * 1024, + .msg_handle = cli_process, + .msg_handle_arg = NULL, /* set later. */ + }, .script_name = NULL, }; @@ -42,7 +57,7 @@ app_args_parse(int argc, char **argv) struct option lgopts[] = { {"help", 0, 0, 'H'}, }; - int s_present, n_args, i; + int h_present, p_present, s_present, n_args, i; char *app_name = argv[0]; int opt, option_index; @@ -59,10 +74,46 @@ app_args_parse(int argc, char **argv) return 0; /* Parse args */ + h_present = 0; + p_present = 0; s_present = 0; - while ((opt = getopt_long(argc, argv, "s:", lgopts, &option_index)) != EOF) { + while ((opt = getopt_long(argc, argv, "h:p:s:", lgopts, &option_index)) != EOF) { switch (opt) { + case 'h': + if (h_present) { + printf("Error: Multiple -h arguments\n"); + return -1; + } + h_present = 1; + + if (!strlen(optarg)) { + printf("Error: Argument for -h not provided\n"); + return -1; + } + + app.conn.addr = strdup(optarg); + if (app.conn.addr == NULL) { + printf("Error: Not enough memory\n"); + return -1; + } + break; + + case 'p': + if (p_present) { + printf("Error: Multiple -p arguments\n"); + return -1; + } + p_present = 1; + + if (!strlen(optarg)) { + printf("Error: Argument for -p not provided\n"); + return -1; + } + + app.conn.port = (uint16_t)strtoul(optarg, NULL, 10); + break; + case 's': if (s_present) { printf("Error: Multiple -s arguments\n"); @@ -93,6 +144,26 @@ app_args_parse(int argc, char **argv) return 0; } +bool +app_graph_exit(void) +{ + struct timeval tv; + fd_set fds; + int ret; + char c; + + FD_ZERO(&fds); + FD_SET(0, &fds); + tv.tv_sec = 0; + tv.tv_usec = 100; + ret = select(1, &fds, NULL, NULL, &tv); + if ((ret < 0 && errno == EINTR) || (ret == 1 && read(0, &c, 1) > 0)) + return true; + else + return false; + +} + int main(int argc, char **argv) { @@ -118,10 +189,32 @@ main(int argc, char **argv) /* Script */ if (app.script_name) { - cli_script_process(app.script_name, 0, - 0, NULL); + cli_script_process(app.script_name, app.conn.msg_in_len_max, + app.conn.msg_out_len_max, NULL); + } + + /* Connectivity */ + app.conn.msg_handle_arg = NULL; + conn = conn_init(&app.conn); + if (!conn) { + printf("Error: Connectivity initialization failed\n"); + goto exit; + }; + + rte_delay_ms(1); + printf("Press enter to exit\n"); + + /* Dispatch loop */ + while (!force_quit) { + conn_req_poll(conn); + + conn_msg_poll(conn); + if (app_graph_exit()) + force_quit = true; } +exit: + conn_free(conn); cli_exit(); rte_eal_cleanup(); return 0; diff --git a/app/graph/meson.build b/app/graph/meson.build index 87c4ce30a8..7e1ab0a214 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -10,5 +10,6 @@ endif deps += ['bus_pci', 'graph', 'eal', 'lpm', 'ethdev', 'node', 'cmdline'] sources = files( 'cli.c', + 'conn.c', 'main.c', ) diff --git a/app/graph/module_api.h b/app/graph/module_api.h index 372aeae7e3..9826303f0c 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -7,10 +7,13 @@ #include #include + #include "cli.h" +#include "conn.h" /* * Externs */ extern volatile bool force_quit; +bool app_graph_exit(void); #endif diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 271a85896d..26a7982722 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -41,6 +41,16 @@ Application Options Following are the application command-line options: +* ``-h`` + + Set the host IPv4 address over which telnet session can be opened. + It is an optional parameter. Default host address is 0.0.0.0. + +* ``-p`` + + Set the L4 port number over which telnet session can be opened. + It is an optional parameter. Default port is 8086. + * ``-s`` Script name with absolute path which specifies the use case. It is @@ -74,7 +84,35 @@ file to express the requested use case configuration. Runtime configuration --------------------- +Application allows some configuration to be modified at runtime using a telnet session. +Application initiates a telnet server with host address ``0.0.0.0`` and port number ``8086`` +by default. + +if user passes ``-h`` and ``-p`` options while running application then corresponding +IPv4 address and port number will be used for telnet session. + +After successful launch of application, client can connect to application using given +host & port and console will be accessed with prompt ``graph>``. + +Command to access a telnet session + +.. code-block:: console + + telnet + +Example: ``dpdk-graph`` is started with -h 10.28.35.207 and -p 50000 then + +.. code-block:: console + + $ telnet 10.28.35.207 50000 + Trying 10.28.35.207... + Connected to 10.28.35.207. + Escape character is '^]'. + + Welcome! + graph> + graph> Created graph for use case -------------------------- From patchwork Tue Sep 26 10:57:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131953 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 78BCF42642; Tue, 26 Sep 2023 12:58:12 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7A63140A7D; Tue, 26 Sep 2023 12:58:00 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id B8CA0402EE for ; Tue, 26 Sep 2023 12:57:55 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38Q6gkaA032209 for ; Tue, 26 Sep 2023 03:57:55 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=ViKqMMHJ8NUlDp1bCpiXKVyJcoqFvgHdmaVMPoMOBZ8=; b=Vdl19nxg8f3TsUDNRkx1s4MKjj0uo1C20mPcUoDVXX9SnjeB3yc7DFa0sTkwq93isIcl 07b6M8ixM1CdahwUKQxKMSTOrdiOEFnoFdDl/27fIvthrZh+eRs+xflS2I4arHdzxX31 7DieggO8ssH4HkAFX8/Xb5Y6sHpEFXQaH2ZeLDw+02B+jB4dipd69aP7qoULwieV18GP MW/9Pi58cH9akTARlTnOotVHR8ztMJwlw8vOreqKclbdxOlLkD1f6nQKRrtnpyCwLEQs zbSbsG4qSXlTOFD2B21aH6UGz3E9SgP4AZtO81O3vu8y/PUKmtPAqUmtYOyynlz2NFCS bg== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3t9yhm0kfv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:57:55 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:57:52 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:57:53 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id C3DC53F70A9; Tue, 26 Sep 2023 03:57:51 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 03/12] app/graph: add parser utility APIs Date: Tue, 26 Sep 2023 16:27:33 +0530 Message-ID: <20230926105742.2638594-4-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: ZD4kXXMCGJ407QHYAKs2g4dDonfwOuJG X-Proofpoint-ORIG-GUID: ZD4kXXMCGJ407QHYAKs2g4dDonfwOuJG X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori It adds some helper functions to parse IPv4, IPv6 and MAC addresses string into respective datatype. Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/meson.build | 1 + app/graph/module_api.h | 1 + app/graph/utils.c | 156 +++++++++++++++++++++++++++++++++++++++++ app/graph/utils.h | 14 ++++ 4 files changed, 172 insertions(+) create mode 100644 app/graph/utils.c create mode 100644 app/graph/utils.h diff --git a/app/graph/meson.build b/app/graph/meson.build index 7e1ab0a214..ed3bcb1567 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -12,4 +12,5 @@ sources = files( 'cli.c', 'conn.c', 'main.c', + 'utils.c', ) diff --git a/app/graph/module_api.h b/app/graph/module_api.h index 9826303f0c..ad4fb50989 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -10,6 +10,7 @@ #include "cli.h" #include "conn.h" +#include "utils.h" /* * Externs */ diff --git a/app/graph/utils.c b/app/graph/utils.c new file mode 100644 index 0000000000..c7b6ae83cf --- /dev/null +++ b/app/graph/utils.c @@ -0,0 +1,156 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include +#include +#include + +#include + +#include "module_api.h" + +#define white_spaces_skip(pos) \ +({ \ + __typeof__(pos) _p = (pos); \ + for ( ; isspace(*_p); _p++) \ + ; \ + _p; \ +}) + +static void +hex_string_to_uint64(uint64_t *dst, const char *hexs) +{ + char buf[2] = {0}; + uint8_t shift = 4; + int iter = 0; + char c; + + while ((c = *hexs++)) { + buf[0] = c; + *dst |= (strtol(buf, NULL, 16) << shift); + shift -= 4; + iter++; + if (iter == 2) { + iter = 0; + shift = 4; + dst++; + } + } +} + +int +parser_uint64_read(uint64_t *value, const char *p) +{ + char *next; + uint64_t val; + + p = white_spaces_skip(p); + if (!isdigit(*p)) + return -EINVAL; + + val = strtoul(p, &next, 0); + if (p == next) + return -EINVAL; + + p = next; + switch (*p) { + case 'T': + val *= 1024ULL; + /* fall through */ + case 'G': + val *= 1024ULL; + /* fall through */ + case 'M': + val *= 1024ULL; + /* fall through */ + case 'k': + case 'K': + val *= 1024ULL; + p++; + break; + } + + p = white_spaces_skip(p); + if (*p != '\0') + return -EINVAL; + + *value = val; + return 0; +} + +int +parser_uint32_read(uint32_t *value, const char *p) +{ + uint64_t val = 0; + int rc = parser_uint64_read(&val, p); + + if (rc < 0) + return rc; + + if (val > UINT32_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +parser_ip4_read(uint32_t *value, char *p) +{ + uint8_t shift = 24; + uint32_t ip = 0; + char *token; + + token = strtok(p, "."); + while (token != NULL) { + ip |= (((uint32_t)strtoul(token, NULL, 10)) << shift); + token = strtok(NULL, "."); + shift -= 8; + } + + *value = ip; + + return 0; +} + +int +parser_ip6_read(uint8_t *value, char *p) +{ + uint64_t val = 0; + char *token; + + token = strtok(p, ":"); + while (token != NULL) { + hex_string_to_uint64(&val, token); + *value = val; + token = strtok(NULL, ":"); + value++; + val = 0; + } + + return 0; +} + +int +parser_mac_read(uint64_t *value, char *p) +{ + uint64_t mac = 0, val = 0; + uint8_t shift = 40; + char *token; + + token = strtok(p, ":"); + while (token != NULL) { + hex_string_to_uint64(&val, token); + mac |= val << shift; + token = strtok(NULL, ":"); + shift -= 8; + val = 0; + } + + *value = mac; + + return 0; +} diff --git a/app/graph/utils.h b/app/graph/utils.h new file mode 100644 index 0000000000..0ebb5de55a --- /dev/null +++ b/app/graph/utils.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_UTILS_H +#define APP_GRAPH_UTILS_H + +int parser_uint64_read(uint64_t *value, const char *p); +int parser_uint32_read(uint32_t *value, const char *p); +int parser_ip4_read(uint32_t *value, char *p); +int parser_ip6_read(uint8_t *value, char *p); +int parser_mac_read(uint64_t *value, char *p); + +#endif From patchwork Tue Sep 26 10:57:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131954 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 03D4742642; Tue, 26 Sep 2023 12:58:19 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B7D9D40A8B; Tue, 26 Sep 2023 12:58:01 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 12EDC40698 for ; Tue, 26 Sep 2023 12:57:57 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38QATmf0010403 for ; Tue, 26 Sep 2023 03:57:57 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=DrXpA9GYXdlsyQs/1jI+I+XJfuH8enAP6TYHmFvmULQ=; b=gUKvEP0TSp3wLcWuJ4PM19fXvQR5WVGJs9MZ2HWROnFxktMmF2I+qXcGf+y0Pq43lNAr SpXNSZKG5zJwsl2L6eSreMp4LmDv9uOWfs7p4GF3ttw5NHztkZQ4lvmSsThQeQW13atC JbtlqMKTxXbImEtfwAOfYKSLDufYen2JvrD3GfG4jMaszIzE5grUWJquGsVxjWU51Vb8 wLEyG5oDNIsV6cxHDDd4UZ2Dhq6MmtspsJO7PXHsQhuqTxTN33cUhIUBo98Cbp7c3j7M 6oR5HPKnvkZrV2zjCDizNeBOEqm/WYXEzuKvG0bEF4Zl0wACBc2sewMqqwdVUrsj071t lw== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3t9yhm0kfy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:57:57 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:57:54 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:57:55 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id BE0863F70A6; Tue, 26 Sep 2023 03:57:53 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 04/12] app/graph: add mempool command line interfaces Date: Tue, 26 Sep 2023 16:27:34 +0530 Message-ID: <20230926105742.2638594-5-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: G36EJz6scJd1xLpmyxjJyX-67rzw--mB X-Proofpoint-ORIG-GUID: G36EJz6scJd1xLpmyxjJyX-67rzw--mB X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla It adds mempool module which will be creating mempools. Following commands are exposed: - mempool size buffers \ cache numa - help mempool User will add this command in .cli file according to its need. Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/cli.c | 2 + app/graph/mempool.c | 140 +++++++++++++++++++++++++++++++++++++ app/graph/mempool.h | 24 +++++++ app/graph/mempool_priv.h | 34 +++++++++ app/graph/meson.build | 1 + app/graph/module_api.h | 2 + doc/guides/tools/graph.rst | 8 +++ 7 files changed, 211 insertions(+) create mode 100644 app/graph/mempool.c create mode 100644 app/graph/mempool.h create mode 100644 app/graph/mempool_priv.h diff --git a/app/graph/cli.c b/app/graph/cli.c index 473fa1635a..c9f932517e 100644 --- a/app/graph/cli.c +++ b/app/graph/cli.c @@ -20,6 +20,8 @@ #define MAX_LINE_SIZE 2048 cmdline_parse_ctx_t modules_ctx[] = { + (cmdline_parse_inst_t *)&mempool_config_cmd_ctx, + (cmdline_parse_inst_t *)&mempool_help_cmd_ctx, NULL, }; diff --git a/app/graph/mempool.c b/app/graph/mempool.c new file mode 100644 index 0000000000..901f07f461 --- /dev/null +++ b/app/graph/mempool.c @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "mempool_priv.h" +#include "module_api.h" + +static const char +cmd_mempool_help[] = "mempool size buffers " + "cache numa "; + +struct mempools mpconfig; + +int +mempool_process(struct mempool_config *config) +{ + struct rte_mempool *mp; + uint8_t nb_pools; + + nb_pools = mpconfig.nb_pools; + strcpy(mpconfig.config[nb_pools].name, config->name); + mpconfig.config[nb_pools].pool_size = config->pool_size; + mpconfig.config[nb_pools].buffer_size = config->buffer_size; + mpconfig.config[nb_pools].cache_size = config->cache_size; + mpconfig.config[nb_pools].numa_node = config->numa_node; + + mp = rte_pktmbuf_pool_create(config->name, config->pool_size, config->cache_size, + 64, config->buffer_size, config->numa_node); + if (!mp) + return -EINVAL; + + mpconfig.mp[nb_pools] = mp; + nb_pools++; + mpconfig.nb_pools = nb_pools; + + return 0; +} + +static void +cli_mempool_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + size_t len; + + len = strlen(conn->msg_out); + conn->msg_out += len; + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n", + "----------------------------- mempool command help -----------------------------", + cmd_mempool_help); + + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; +} + +static void +cli_mempool(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) +{ + struct mempool_config_cmd_tokens *res = parsed_result; + struct mempool_config config; + int rc = -EINVAL; + + + strcpy(config.name, res->name); + config.name[strlen(res->name)] = '\0'; + config.pool_size = res->nb_bufs; + config.buffer_size = res->buf_sz; + config.cache_size = res->cache_size; + config.numa_node = res->node; + + rc = mempool_process(&config); + if (rc < 0) + printf(MSG_CMD_FAIL, "mempool"); +} + +cmdline_parse_token_string_t mempool_config_add_mempool = + TOKEN_STRING_INITIALIZER(struct mempool_config_cmd_tokens, mempool, "mempool"); +cmdline_parse_token_string_t mempool_config_add_name = + TOKEN_STRING_INITIALIZER(struct mempool_config_cmd_tokens, name, NULL); +cmdline_parse_token_string_t mempool_config_add_size = + TOKEN_STRING_INITIALIZER(struct mempool_config_cmd_tokens, size, "size"); +cmdline_parse_token_num_t mempool_config_add_buf_sz = + TOKEN_NUM_INITIALIZER(struct mempool_config_cmd_tokens, buf_sz, RTE_UINT16); +cmdline_parse_token_string_t mempool_config_add_buffers = + TOKEN_STRING_INITIALIZER(struct mempool_config_cmd_tokens, buffers, "buffers"); +cmdline_parse_token_num_t mempool_config_add_nb_bufs = + TOKEN_NUM_INITIALIZER(struct mempool_config_cmd_tokens, nb_bufs, RTE_UINT16); +cmdline_parse_token_string_t mempool_config_add_cache = + TOKEN_STRING_INITIALIZER(struct mempool_config_cmd_tokens, cache, "cache"); +cmdline_parse_token_num_t mempool_config_add_cache_size = + TOKEN_NUM_INITIALIZER(struct mempool_config_cmd_tokens, cache_size, RTE_UINT16); +cmdline_parse_token_string_t mempool_config_add_numa = + TOKEN_STRING_INITIALIZER(struct mempool_config_cmd_tokens, numa, "numa"); +cmdline_parse_token_num_t mempool_config_add_node = + TOKEN_NUM_INITIALIZER(struct mempool_config_cmd_tokens, node, RTE_UINT16); + +cmdline_parse_inst_t mempool_config_cmd_ctx = { + .f = cli_mempool, + .data = NULL, + .help_str = cmd_mempool_help, + .tokens = { + (void *)&mempool_config_add_mempool, + (void *)&mempool_config_add_name, + (void *)&mempool_config_add_size, + (void *)&mempool_config_add_buf_sz, + (void *)&mempool_config_add_buffers, + (void *)&mempool_config_add_nb_bufs, + (void *)&mempool_config_add_cache, + (void *)&mempool_config_add_cache_size, + (void *)&mempool_config_add_numa, + (void *)&mempool_config_add_node, + NULL, + }, +}; + +cmdline_parse_token_string_t mempool_help_cmd = + TOKEN_STRING_INITIALIZER(struct mempool_help_cmd_tokens, help, "help"); +cmdline_parse_token_string_t mempool_help_mempool = + TOKEN_STRING_INITIALIZER(struct mempool_help_cmd_tokens, mempool, "mempool"); + +cmdline_parse_inst_t mempool_help_cmd_ctx = { + .f = cli_mempool_help, + .data = NULL, + .help_str = "", + .tokens = { + (void *)&mempool_help_cmd, + (void *)&mempool_help_mempool, + NULL, + }, +}; diff --git a/app/graph/mempool.h b/app/graph/mempool.h new file mode 100644 index 0000000000..0808c4259e --- /dev/null +++ b/app/graph/mempool.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_MEMPOOL_H +#define APP_GRAPH_MEMPOOL_H + +#include +#include + +struct mempool_config { + char name[RTE_MEMPOOL_NAMESIZE]; + int pool_size; + int cache_size; + int buffer_size; + int numa_node; +}; + +extern cmdline_parse_inst_t mempool_config_cmd_ctx; +extern cmdline_parse_inst_t mempool_help_cmd_ctx; + +int mempool_process(struct mempool_config *config); + +#endif diff --git a/app/graph/mempool_priv.h b/app/graph/mempool_priv.h new file mode 100644 index 0000000000..3ce64702a9 --- /dev/null +++ b/app/graph/mempool_priv.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_MEMPOOL_PRIV_H +#define APP_GRAPH_MEMPOOL_PRIV_H + +#include "mempool.h" + +struct mempool_config_cmd_tokens { + cmdline_fixed_string_t mempool; + cmdline_fixed_string_t size; + cmdline_fixed_string_t buffers; + cmdline_fixed_string_t cache; + cmdline_fixed_string_t numa; + cmdline_fixed_string_t name; + uint16_t buf_sz; + uint16_t nb_bufs; + uint16_t cache_size; + uint16_t node; +}; + +struct mempool_help_cmd_tokens { + cmdline_fixed_string_t help; + cmdline_fixed_string_t mempool; +}; + +struct mempools { + struct mempool_config config[RTE_MAX_ETHPORTS]; + struct rte_mempool *mp[RTE_MAX_ETHPORTS]; + uint8_t nb_pools; +}; + +#endif diff --git a/app/graph/meson.build b/app/graph/meson.build index ed3bcb1567..d35287be14 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -12,5 +12,6 @@ sources = files( 'cli.c', 'conn.c', 'main.c', + 'mempool.c', 'utils.c', ) diff --git a/app/graph/module_api.h b/app/graph/module_api.h index ad4fb50989..b45419811b 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -10,11 +10,13 @@ #include "cli.h" #include "conn.h" +#include "mempool.h" #include "utils.h" /* * Externs */ extern volatile bool force_quit; +extern struct conn *conn; bool app_graph_exit(void); #endif diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 26a7982722..9f6b83e248 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -80,6 +80,14 @@ file to express the requested use case configuration. - Dummy command description - No - No + * - mempool size buffers cache numa + - Command to create mempool which will be further associated to RxQ to dequeue the packets + - No + - No + * - help mempool + - Command to dump mempool help message + - Yes + - Yes Runtime configuration --------------------- From patchwork Tue Sep 26 10:57:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131955 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id D2C1142642; Tue, 26 Sep 2023 12:58:26 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1BAB040A76; Tue, 26 Sep 2023 12:58:06 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 286A3409FA for ; Tue, 26 Sep 2023 12:58:00 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38Q9xg9p012813 for ; Tue, 26 Sep 2023 03:57:59 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=jXaksB3xPHTZO1Jm+yvNYFIWTmDkFCsn1cI5TX/ZgqA=; b=lKaK4yXzFojeli4f1WyKntvpRungRh4mNCv4TjWRYUatWMAjz8nnChhh6JevOs6zJMgs 9mU3+03ZA8mCBjVphGr7tXrhJcJy5R2gPzQbHMlp4AoRTyg4DnFOuMVj6TXlIkJN2Lsm 5xp0oWPYuT1z+1O27llhDjO2x7UpW+eImg7BOJt8JMwH4T0tacnDCZhjCLGcKBxdvE6q e+u5SRrXbkfTQdljlTDo8WiZSZEfTcnnX/lcV/pcJtcIlDn4n+HeerdqYiBOTy0t+x+s THWj95w7FxoBa8KHVz+aRPKTCs9679K+LLPf89gnsUMovOxAVORsUs+opU3i8KvgTtUM pA== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3tbw5gg5fw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:57:59 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:57:57 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:57:57 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id B982B3F70AA; Tue, 26 Sep 2023 03:57:55 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 05/12] app/graph: add ethdev command line interfaces Date: Tue, 26 Sep 2023 16:27:35 +0530 Message-ID: <20230926105742.2638594-6-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: VB1RkJp2FHuHsRaiPZH-TsWTGITQ8heO X-Proofpoint-ORIG-GUID: VB1RkJp2FHuHsRaiPZH-TsWTGITQ8heO X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori It adds ethdev module to configure ethernet devices. Following commands are exposed: - ethdev rxq txq - ethdev mtu - ethdev promiscuous - ethdev show - ethdev stats - ethdev ip4 addr add netmask - ethdev ip6 addr add netmask - help ethdev Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/cli.c | 8 + app/graph/ethdev.c | 882 +++++++++++++++++++++++++++++++++++++ app/graph/ethdev.h | 40 ++ app/graph/ethdev_priv.h | 112 +++++ app/graph/main.c | 1 + app/graph/meson.build | 1 + app/graph/module_api.h | 1 + doc/guides/tools/graph.rst | 47 ++ 8 files changed, 1092 insertions(+) create mode 100644 app/graph/ethdev.c create mode 100644 app/graph/ethdev.h create mode 100644 app/graph/ethdev_priv.h diff --git a/app/graph/cli.c b/app/graph/cli.c index c9f932517e..c4b5cf3ce1 100644 --- a/app/graph/cli.c +++ b/app/graph/cli.c @@ -22,6 +22,14 @@ cmdline_parse_ctx_t modules_ctx[] = { (cmdline_parse_inst_t *)&mempool_config_cmd_ctx, (cmdline_parse_inst_t *)&mempool_help_cmd_ctx, + (cmdline_parse_inst_t *)ðdev_show_cmd_ctx, + (cmdline_parse_inst_t *)ðdev_stats_cmd_ctx, + (cmdline_parse_inst_t *)ðdev_mtu_cmd_ctx, + (cmdline_parse_inst_t *)ðdev_prom_mode_cmd_ctx, + (cmdline_parse_inst_t *)ðdev_ip4_cmd_ctx, + (cmdline_parse_inst_t *)ðdev_ip6_cmd_ctx, + (cmdline_parse_inst_t *)ðdev_cmd_ctx, + (cmdline_parse_inst_t *)ðdev_help_cmd_ctx, NULL, }; diff --git a/app/graph/ethdev.c b/app/graph/ethdev.c new file mode 100644 index 0000000000..81ad8c4757 --- /dev/null +++ b/app/graph/ethdev.c @@ -0,0 +1,882 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ethdev_priv.h" +#include "module_api.h" + +static const char +cmd_ethdev_mtu_help[] = "ethdev mtu "; + +static const char +cmd_ethdev_prom_mode_help[] = "ethdev promiscuous "; + +static const char +cmd_ethdev_help[] = "ethdev rxq txq "; +static const char +cmd_ethdev_show_help[] = "ethdev show"; + +static const char +cmd_ethdev_ip4_addr_help[] = "ethdev ip4 addr add netmask "; + +static const char +cmd_ethdev_ip6_addr_help[] = "ethdev ip6 addr add netmask "; + +static struct rte_eth_conf port_conf_default = { + .link_speeds = 0, + .rxmode = { + .mq_mode = RTE_ETH_MQ_RX_NONE, + .mtu = 9000 - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN), /* Jumbo frame MTU */ + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_key_len = 40, + .rss_hf = 0, + }, + }, + .txmode = { + .mq_mode = RTE_ETH_MQ_TX_NONE, + }, + .lpbk_mode = 0, +}; + +uint32_t enabled_port_mask; +static struct ethdev_head eth_node = TAILQ_HEAD_INITIALIZER(eth_node); + + +static struct ethdev* +ethdev_port_by_id(uint16_t port_id) +{ + struct ethdev *port; + + TAILQ_FOREACH(port, ð_node, next) { + if (port->config.port_id == port_id) + return port; + } + return NULL; +} + +void * +ethdev_mempool_list_by_portid(uint16_t portid) +{ + struct ethdev *port; + + if (portid >= RTE_MAX_ETHPORTS) + return NULL; + + port = ethdev_port_by_id(portid); + if (port) + return &(port->config.rx.mp); + else + return NULL; +} + +int16_t +ethdev_portid_by_ip4(uint32_t ip, uint32_t mask) +{ + int portid = -EINVAL; + struct ethdev *port; + + TAILQ_FOREACH(port, ð_node, next) { + if (mask == 0) { + if ((port->ip4_addr.ip & port->ip4_addr.mask) == (ip & port->ip4_addr.mask)) + return port->config.port_id; + } else { + if ((port->ip4_addr.ip & port->ip4_addr.mask) == (ip & mask)) + return port->config.port_id; + } + } + + return portid; +} + +int16_t +ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask) +{ + int portid = -EINVAL; + struct ethdev *port; + int j; + + TAILQ_FOREACH(port, ð_node, next) { + for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++) { + if (mask == NULL) { + if ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) != + (ip[j] & port->ip6_addr.mask[j])) + break; + + } else { + if ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) != + (ip[j] & mask[j])) + break; + } + } + if (j == ETHDEV_IPV6_ADDR_LEN) + return port->config.port_id; + } + + return portid; +} + +void +ethdev_list_clean(void) +{ + struct ethdev *port; + + while (!TAILQ_EMPTY(ð_node)) { + port = TAILQ_FIRST(ð_node); + TAILQ_REMOVE(ð_node, port, next); + } +} + +void +ethdev_stop(void) +{ + uint16_t portid; + int rc; + + RTE_ETH_FOREACH_DEV(portid) { + if ((enabled_port_mask & (1 << portid)) == 0) + continue; + printf("Closing port %d...", portid); + rc = rte_eth_dev_stop(portid); + if (rc != 0) + printf("Failed to stop port %u: %s\n", + portid, rte_strerror(-rc)); + rte_eth_dev_close(portid); + printf(" Done\n"); + } + + ethdev_list_clean(); + rte_eal_cleanup(); + printf("Bye...\n"); +} + +void +ethdev_start(void) +{ + uint16_t portid; + int rc; + + RTE_ETH_FOREACH_DEV(portid) + { + if ((enabled_port_mask & (1 << portid)) == 0) + continue; + + rc = rte_eth_dev_start(portid); + if (rc < 0) + rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", rc, portid); + } +} + + +static int +ethdev_show(const char *name) +{ + uint16_t mtu = 0, port_id = 0; + struct rte_eth_dev_info info; + struct rte_eth_stats stats; + struct rte_ether_addr addr; + struct rte_eth_link link; + uint32_t length; + int rc; + + rc = rte_eth_dev_get_port_by_name(name, &port_id); + if (rc < 0) + return rc; + + rte_eth_dev_info_get(port_id, &info); + rte_eth_stats_get(port_id, &stats); + rte_eth_macaddr_get(port_id, &addr); + rte_eth_link_get(port_id, &link); + rte_eth_dev_get_mtu(port_id, &mtu); + + length = strlen(conn->msg_out); + conn->msg_out += length; + snprintf(conn->msg_out, conn->msg_out_len_max, + "%s: flags=<%s> mtu %u\n" + "\tether " RTE_ETHER_ADDR_PRT_FMT " rxqueues %u txqueues %u\n" + "\tport# %u speed %s\n" + "\tRX packets %" PRIu64" bytes %" PRIu64"\n" + "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n" + "\tTX packets %" PRIu64" bytes %" PRIu64"\n" + "\tTX errors %" PRIu64"\n\n", + name, + link.link_status ? "UP" : "DOWN", + mtu, + RTE_ETHER_ADDR_BYTES(&addr), + info.nb_rx_queues, + info.nb_tx_queues, + port_id, + rte_eth_link_speed_to_str(link.link_speed), + stats.ipackets, + stats.ibytes, + stats.ierrors, + stats.imissed, + stats.rx_nombuf, + stats.opackets, + stats.obytes, + stats.oerrors); + + length = strlen(conn->msg_out); + conn->msg_out_len_max -= length; + return 0; +} + +static int +ethdev_ip4_addr_add(const char *name, struct ipv4_addr_config *config) +{ + struct ethdev *eth_hdl; + uint16_t portid = 0; + int rc; + + rc = rte_eth_dev_get_port_by_name(name, &portid); + if (rc < 0) + return rc; + + eth_hdl = ethdev_port_by_id(portid); + + if (eth_hdl) { + eth_hdl->ip4_addr.ip = config->ip; + eth_hdl->ip4_addr.mask = config->mask; + return 0; + } + + rc = -EINVAL; + return rc; +} + +static int +ethdev_ip6_addr_add(const char *name, struct ipv6_addr_config *config) +{ + struct ethdev *eth_hdl; + uint16_t portid = 0; + int rc, i; + + rc = rte_eth_dev_get_port_by_name(name, &portid); + if (rc < 0) + return rc; + + eth_hdl = ethdev_port_by_id(portid); + + if (eth_hdl) { + for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++) { + eth_hdl->ip6_addr.ip[i] = config->ip[i]; + eth_hdl->ip6_addr.mask[i] = config->mask[i]; + } + return 0; + } + rc = -EINVAL; + return rc; +} + +static int +ethdev_prom_mode_config(const char *name, bool enable) +{ + struct ethdev *eth_hdl; + uint16_t portid = 0; + int rc; + + rc = rte_eth_dev_get_port_by_name(name, &portid); + if (rc < 0) + return rc; + + eth_hdl = ethdev_port_by_id(portid); + + if (eth_hdl) { + if (enable) + rc = rte_eth_promiscuous_enable(portid); + else + rc = rte_eth_promiscuous_disable(portid); + if (rc < 0) + return rc; + + eth_hdl->config.promiscuous = enable; + return 0; + } + + rc = -EINVAL; + return rc; +} + +static int +ethdev_mtu_config(const char *name, uint32_t mtu) +{ + struct ethdev *eth_hdl; + uint16_t portid = 0; + int rc; + + rc = rte_eth_dev_get_port_by_name(name, &portid); + if (rc < 0) + return rc; + + eth_hdl = ethdev_port_by_id(portid); + + if (eth_hdl) { + rc = rte_eth_dev_set_mtu(portid, mtu); + if (rc < 0) + return rc; + + eth_hdl->config.mtu = mtu; + return 0; + } + + rc = -EINVAL; + return rc; +} + + +static int +ethdev_process(const char *name, struct ethdev_config *params) +{ + struct rte_eth_dev_info port_info; + struct rte_eth_conf port_conf; + struct ethdev_rss_config *rss; + struct rte_mempool *mempool; + struct ethdev *ethdev_port; + struct rte_ether_addr smac; + int numa_node, rc; + uint16_t port_id = 0; + uint32_t i; + + /* Check input params */ + if (!name || !name[0] || !params || !params->rx.n_queues || !params->rx.queue_size || + !params->tx.n_queues || !params->tx.queue_size) + return -EINVAL; + + rc = rte_eth_dev_get_port_by_name(name, &port_id); + if (rc) + return -EINVAL; + + if (!ethdev_port_by_id(port_id)) { + ethdev_port = malloc(sizeof(struct ethdev)); + if (!ethdev_port) + return -EINVAL; + } else { + return 0; + } + + rc = rte_eth_dev_info_get(port_id, &port_info); + if (rc) { + rc = -EINVAL; + goto exit; + } + + mempool = rte_mempool_lookup(params->rx.mempool_name); + if (!mempool) { + rc = -EINVAL; + goto exit; + } + + params->rx.mp = mempool; + + rss = params->rx.rss; + if (rss) { + if (!port_info.reta_size || port_info.reta_size > RTE_ETH_RSS_RETA_SIZE_512) { + rc = -EINVAL; + goto exit; + } + + if (!rss->n_queues || rss->n_queues >= ETHDEV_RXQ_RSS_MAX) { + rc = -EINVAL; + goto exit; + } + + for (i = 0; i < rss->n_queues; i++) + if (rss->queue_id[i] >= port_info.max_rx_queues) { + rc = -EINVAL; + goto exit; + } + } + + /* Port */ + memcpy(&port_conf, &port_conf_default, sizeof(struct rte_eth_conf)); + if (rss) { + uint64_t rss_hf = RTE_ETH_RSS_IP | RTE_ETH_RSS_TCP | RTE_ETH_RSS_UDP; + + port_conf.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS; + port_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf & port_info.flow_type_rss_offloads; + } + + numa_node = rte_eth_dev_socket_id(port_id); + if (numa_node == SOCKET_ID_ANY) + numa_node = 0; + + if (params->mtu) + port_conf.rxmode.mtu = params->mtu; + + rc = rte_eth_dev_configure(port_id, params->rx.n_queues, params->tx.n_queues, + &port_conf); + if (rc < 0) { + rc = -EINVAL; + goto exit; + } + + rc = rte_eth_macaddr_get(port_id, &smac); + if (rc < 0) { + rc = -EINVAL; + goto exit; + } + + printf("Port_id = %d srcmac = %x:%x:%x:%x:%x:%x\n", port_id, + smac.addr_bytes[0], smac.addr_bytes[1], + smac.addr_bytes[2], smac.addr_bytes[3], + smac.addr_bytes[4], smac.addr_bytes[5]); + + /* Port RX */ + for (i = 0; i < params->rx.n_queues; i++) { + rc = rte_eth_rx_queue_setup(port_id, i, params->rx.queue_size, numa_node, NULL, + mempool); + if (rc < 0) { + rc = -EINVAL; + goto exit; + } + } + + /* Port TX */ + for (i = 0; i < params->tx.n_queues; i++) { + rc = rte_eth_tx_queue_setup(port_id, i, params->tx.queue_size, numa_node, NULL); + if (rc < 0) { + rc = -EINVAL; + goto exit; + } + } + + memcpy(ðdev_port->config, params, sizeof(struct ethdev_config)); + memcpy(ethdev_port->config.dev_name, name, strlen(name)); + ethdev_port->config.port_id = port_id; + enabled_port_mask |= RTE_BIT32(port_id); + + TAILQ_INSERT_TAIL(ð_node, ethdev_port, next); + return 0; +exit: + free(ethdev_port); + return rc; + +} + +static int +ethdev_stats_show(const char *name) +{ + uint64_t diff_pkts_rx, diff_pkts_tx, diff_bytes_rx, diff_bytes_tx; + static uint64_t prev_pkts_rx[RTE_MAX_ETHPORTS]; + static uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS]; + static uint64_t prev_bytes_rx[RTE_MAX_ETHPORTS]; + static uint64_t prev_bytes_tx[RTE_MAX_ETHPORTS]; + static uint64_t prev_cycles[RTE_MAX_ETHPORTS]; + uint64_t mpps_rx, mpps_tx, mbps_rx, mbps_tx; + uint64_t diff_ns, diff_cycles, curr_cycles; + struct rte_eth_stats stats; + static const char *nic_stats_border = "########################"; + uint16_t port_id, len; + int rc; + + rc = rte_eth_dev_get_port_by_name(name, &port_id); + if (rc < 0) + return rc; + + rc = rte_eth_stats_get(port_id, &stats); + if (rc != 0) { + fprintf(stderr, + "%s: Error: failed to get stats (port %u): %d", + __func__, port_id, rc); + return rc; + } + + len = strlen(conn->msg_out); + conn->msg_out += len; + snprintf(conn->msg_out, conn->msg_out_len_max, + "\n %s NIC statistics for port %-2d %s\n" + " RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes: ""%-"PRIu64"\n" + " RX-errors: %-"PRIu64"\n" + " RX-nombuf: %-10"PRIu64"\n" + " TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes: ""%-"PRIu64"\n", + nic_stats_border, port_id, nic_stats_border, stats.ipackets, stats.imissed, + stats.ibytes, stats.ierrors, stats.rx_nombuf, stats.opackets, stats.oerrors, + stats.obytes); + + len = strlen(conn->msg_out) - len; + conn->msg_out_len_max -= len; + + diff_ns = 0; + diff_cycles = 0; + + curr_cycles = rte_rdtsc(); + if (prev_cycles[port_id] != 0) + diff_cycles = curr_cycles - prev_cycles[port_id]; + + prev_cycles[port_id] = curr_cycles; + diff_ns = diff_cycles > 0 ? + diff_cycles * (1 / (double)rte_get_tsc_hz()) * NS_PER_SEC : 0; + + diff_pkts_rx = (stats.ipackets > prev_pkts_rx[port_id]) ? + (stats.ipackets - prev_pkts_rx[port_id]) : 0; + diff_pkts_tx = (stats.opackets > prev_pkts_tx[port_id]) ? + (stats.opackets - prev_pkts_tx[port_id]) : 0; + prev_pkts_rx[port_id] = stats.ipackets; + prev_pkts_tx[port_id] = stats.opackets; + mpps_rx = diff_ns > 0 ? + (double)diff_pkts_rx / diff_ns * NS_PER_SEC : 0; + mpps_tx = diff_ns > 0 ? + (double)diff_pkts_tx / diff_ns * NS_PER_SEC : 0; + + diff_bytes_rx = (stats.ibytes > prev_bytes_rx[port_id]) ? + (stats.ibytes - prev_bytes_rx[port_id]) : 0; + diff_bytes_tx = (stats.obytes > prev_bytes_tx[port_id]) ? + (stats.obytes - prev_bytes_tx[port_id]) : 0; + prev_bytes_rx[port_id] = stats.ibytes; + prev_bytes_tx[port_id] = stats.obytes; + mbps_rx = diff_ns > 0 ? + (double)diff_bytes_rx / diff_ns * NS_PER_SEC : 0; + mbps_tx = diff_ns > 0 ? + (double)diff_bytes_tx / diff_ns * NS_PER_SEC : 0; + + len = strlen(conn->msg_out); + snprintf(conn->msg_out + len, conn->msg_out_len_max, + "\n Throughput (since last show)\n" + " Rx-pps: %12"PRIu64" Rx-bps: %12"PRIu64"\n Tx-pps: %12" + PRIu64" Tx-bps: %12"PRIu64"\n" + " %s############################%s\n", + mpps_rx, mbps_rx * 8, mpps_tx, mbps_tx * 8, nic_stats_border, nic_stats_border); + return 0; +} + +static void +cli_ethdev_mtu(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct ethdev_mtu_cmd_tokens *res = parsed_result; + int rc = -EINVAL; + + rc = ethdev_mtu_config(res->dev, res->size); + if (rc < 0) + printf(MSG_CMD_FAIL, res->cmd); +} + +static void +cli_ethdev_prom_mode(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct ethdev_prom_mode_cmd_tokens *res = parsed_result; + bool enable = false; + int rc = -EINVAL; + + if (!strcmp(res->enable, "on")) + enable = true; + + rc = ethdev_prom_mode_config(res->dev, enable); + if (rc < 0) + printf(MSG_CMD_FAIL, res->cmd); +} + +static void +cli_ip4_addr(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct ethdev_ip4_cmd_tokens *res = parsed_result; + struct ipv4_addr_config config; + int rc = -EINVAL; + + if (parser_ip4_read(&config.ip, res->ip)) { + printf(MSG_ARG_INVALID, "ip"); + return; + } + + if (parser_ip4_read(&config.mask, res->mask)) { + printf(MSG_ARG_INVALID, "netmask"); + return; + } + + rc = ethdev_ip4_addr_add(res->dev, &config); + if (rc < 0) + printf(MSG_CMD_FAIL, res->cmd); +} + +static void +cli_ip6_addr(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct ethdev_ip6_cmd_tokens *res = parsed_result; + struct ipv6_addr_config config; + int rc = -EINVAL; + + if (parser_ip6_read(config.ip, res->ip)) { + printf(MSG_ARG_INVALID, "ip"); + return; + } + + if (parser_ip6_read(config.mask, res->mask)) { + printf(MSG_ARG_INVALID, "netmask"); + return; + } + + rc = ethdev_ip6_addr_add(res->dev, &config); + if (rc < 0) + printf(MSG_CMD_FAIL, res->cmd); +} + +static void +cli_ethdev_show(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct ethdev_show_cmd_tokens *res = parsed_result; + int rc = -EINVAL; + + rc = ethdev_show(res->dev); + if (rc < 0) + printf(MSG_ARG_INVALID, res->dev); +} + +static void +cli_ethdev_stats(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct ethdev_stats_cmd_tokens *res = parsed_result; + int rc = -EINVAL; + + rc = ethdev_stats_show(res->dev); + if (rc < 0) + printf(MSG_ARG_INVALID, res->dev); +} + +static void +cli_ethdev(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct ethdev_cmd_tokens *res = parsed_result; + struct ethdev_config config; + int rc; + + memset(&config, 0, sizeof(struct ethdev_config)); + config.rx.n_queues = res->nb_rxq; + config.rx.queue_size = ETHDEV_RX_DESC_DEFAULT; + memcpy(config.rx.mempool_name, res->mempool, strlen(res->mempool)); + + config.tx.n_queues = res->nb_txq; + config.tx.queue_size = ETHDEV_TX_DESC_DEFAULT; + + config.mtu = port_conf_default.rxmode.mtu; + + rc = ethdev_process(res->dev, &config); + if (rc < 0) + printf(MSG_CMD_FAIL, res->cmd); +} + +static void +cli_ethdev_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + size_t len; + + len = strlen(conn->msg_out); + conn->msg_out += len; + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", + "----------------------------- ethdev command help -----------------------------", + cmd_ethdev_help, cmd_ethdev_ip4_addr_help, cmd_ethdev_ip6_addr_help, + cmd_ethdev_prom_mode_help, cmd_ethdev_mtu_help, cmd_ethdev_show_help); + + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; +} + +cmdline_parse_token_string_t ethdev_stats_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_stats_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_stats_stats = + TOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, stats, "stats"); + +cmdline_parse_inst_t ethdev_stats_cmd_ctx = { + .f = cli_ethdev_stats, + .data = NULL, + .help_str = "", + .tokens = { + (void *)ðdev_stats_cmd, + (void *)ðdev_stats_dev, + (void *)ðdev_stats_stats, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_show_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_show_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_show_show = + TOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, show, "show"); + +cmdline_parse_inst_t ethdev_show_cmd_ctx = { + .f = cli_ethdev_show, + .data = NULL, + .help_str = cmd_ethdev_show_help, + .tokens = { + (void *)ðdev_show_cmd, + (void *)ðdev_show_dev, + (void *)ðdev_show_show, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_mtu_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_mtu_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_mtu_mtu = + TOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, mtu, "mtu"); +cmdline_parse_token_num_t ethdev_mtu_size = + TOKEN_NUM_INITIALIZER(struct ethdev_mtu_cmd_tokens, size, RTE_UINT16); + +cmdline_parse_inst_t ethdev_mtu_cmd_ctx = { + .f = cli_ethdev_mtu, + .data = NULL, + .help_str = cmd_ethdev_mtu_help, + .tokens = { + (void *)ðdev_mtu_cmd, + (void *)ðdev_mtu_dev, + (void *)ðdev_mtu_mtu, + (void *)ðdev_mtu_size, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_prom_mode_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_prom_mode_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_prom_mode_prom = + TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, prom, "promiscuous"); +cmdline_parse_token_string_t ethdev_prom_mode_enable = + TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, enable, "on#off"); + +cmdline_parse_inst_t ethdev_prom_mode_cmd_ctx = { + .f = cli_ethdev_prom_mode, + .data = NULL, + .help_str = cmd_ethdev_prom_mode_help, + .tokens = { + (void *)ðdev_prom_mode_cmd, + (void *)ðdev_prom_mode_dev, + (void *)ðdev_prom_mode_prom, + (void *)ðdev_prom_mode_enable, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_ip4_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_ip4_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_ip4_ip4 = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, ip4, "ip4"); +cmdline_parse_token_string_t ethdev_ip4_addr = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, addr, "addr"); +cmdline_parse_token_string_t ethdev_ip4_add = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, add, "add"); +cmdline_parse_token_string_t ethdev_ip4_ip = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, ip, NULL); +cmdline_parse_token_string_t ethdev_ip4_netmask = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, netmask, "netmask"); +cmdline_parse_token_string_t ethdev_ip4_mask = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, mask, NULL); + +cmdline_parse_inst_t ethdev_ip4_cmd_ctx = { + .f = cli_ip4_addr, + .data = NULL, + .help_str = cmd_ethdev_ip4_addr_help, + .tokens = { + (void *)ðdev_ip4_cmd, + (void *)ðdev_ip4_dev, + (void *)ðdev_ip4_ip4, + (void *)ðdev_ip4_addr, + (void *)ðdev_ip4_add, + (void *)ðdev_ip4_ip, + (void *)ðdev_ip4_netmask, + (void *)ðdev_ip4_mask, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_ip6_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_ip6_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_ip6_ip6 = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, ip6, "ip6"); +cmdline_parse_token_string_t ethdev_ip6_addr = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, addr, "addr"); +cmdline_parse_token_string_t ethdev_ip6_add = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, add, "add"); +cmdline_parse_token_string_t ethdev_ip6_ip = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, ip, NULL); +cmdline_parse_token_string_t ethdev_ip6_netmask = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, netmask, "netmask"); +cmdline_parse_token_string_t ethdev_ip6_mask = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, mask, NULL); + +cmdline_parse_inst_t ethdev_ip6_cmd_ctx = { + .f = cli_ip6_addr, + .data = NULL, + .help_str = cmd_ethdev_ip6_addr_help, + .tokens = { + (void *)ðdev_ip6_cmd, + (void *)ðdev_ip6_dev, + (void *)ðdev_ip6_ip6, + (void *)ðdev_ip6_addr, + (void *)ðdev_ip6_add, + (void *)ðdev_ip6_ip, + (void *)ðdev_ip6_netmask, + (void *)ðdev_ip6_mask, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_rxq = + TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, rxq, "rxq"); +cmdline_parse_token_num_t ethdev_nb_rxq = + TOKEN_NUM_INITIALIZER(struct ethdev_cmd_tokens, nb_rxq, RTE_UINT16); +cmdline_parse_token_string_t ethdev_txq = + TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, txq, "txq"); +cmdline_parse_token_num_t ethdev_nb_txq = + TOKEN_NUM_INITIALIZER(struct ethdev_cmd_tokens, nb_txq, RTE_UINT16); +cmdline_parse_token_string_t ethdev_mempool = + TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, mempool, NULL); + +cmdline_parse_inst_t ethdev_cmd_ctx = { + .f = cli_ethdev, + .data = NULL, + .help_str = cmd_ethdev_help, + .tokens = { + (void *)ðdev_cmd, + (void *)ðdev_dev, + (void *)ðdev_rxq, + (void *)ðdev_nb_rxq, + (void *)ðdev_txq, + (void *)ðdev_nb_txq, + (void *)ðdev_mempool, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_help_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_help_cmd_tokens, help, "help"); +cmdline_parse_token_string_t ethdev_help_ethdev = + TOKEN_STRING_INITIALIZER(struct ethdev_help_cmd_tokens, ethdev, "ethdev"); + +cmdline_parse_inst_t ethdev_help_cmd_ctx = { + .f = cli_ethdev_help, + .data = NULL, + .help_str = "", + .tokens = { + (void *)ðdev_help_cmd, + (void *)ðdev_help_ethdev, + NULL, + }, +}; diff --git a/app/graph/ethdev.h b/app/graph/ethdev.h new file mode 100644 index 0000000000..94d3247a2c --- /dev/null +++ b/app/graph/ethdev.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_ETHDEV_H +#define APP_GRAPH_ETHDEV_H + +#include + +#define ETHDEV_IPV6_ADDR_LEN 16 + +extern cmdline_parse_inst_t ethdev_show_cmd_ctx; +extern cmdline_parse_inst_t ethdev_stats_cmd_ctx; +extern cmdline_parse_inst_t ethdev_mtu_cmd_ctx; +extern cmdline_parse_inst_t ethdev_prom_mode_cmd_ctx; +extern cmdline_parse_inst_t ethdev_ip4_cmd_ctx; +extern cmdline_parse_inst_t ethdev_ip6_cmd_ctx; +extern cmdline_parse_inst_t ethdev_cmd_ctx; +extern cmdline_parse_inst_t ethdev_help_cmd_ctx; + +struct ipv4_addr_config { + uint32_t ip; + uint32_t mask; +}; + +struct ipv6_addr_config { + uint8_t ip[ETHDEV_IPV6_ADDR_LEN]; + uint8_t mask[ETHDEV_IPV6_ADDR_LEN]; +}; + +extern uint32_t enabled_port_mask; + +void ethdev_start(void); +void ethdev_stop(void); +void *ethdev_mempool_list_by_portid(uint16_t portid); +int16_t ethdev_portid_by_ip4(uint32_t ip, uint32_t mask); +int16_t ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask); +void ethdev_list_clean(void); + +#endif diff --git a/app/graph/ethdev_priv.h b/app/graph/ethdev_priv.h new file mode 100644 index 0000000000..f231f3f3e1 --- /dev/null +++ b/app/graph/ethdev_priv.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_ETHDEV_PRIV_H +#define APP_GRAPH_ETHDEV_PRIV_H + +#include "ethdev.h" + +#define NS_PER_SEC 1E9 + +#define ETHDEV_RXQ_RSS_MAX 16 +#define ETHDEV_RX_DESC_DEFAULT 1024 +#define ETHDEV_TX_DESC_DEFAULT 1024 + +struct ethdev_show_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t show; +}; + +struct ethdev_stats_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t stats; +}; + +struct ethdev_mtu_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t mtu; + uint16_t size; +}; + +struct ethdev_prom_mode_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t prom; + cmdline_fixed_string_t enable; +}; + +struct ethdev_ip4_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t ip4; + cmdline_fixed_string_t addr; + cmdline_fixed_string_t add; + cmdline_fixed_string_t ip; + cmdline_fixed_string_t netmask; + cmdline_fixed_string_t mask; +}; + +struct ethdev_ip6_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t ip6; + cmdline_fixed_string_t addr; + cmdline_fixed_string_t add; + cmdline_fixed_string_t ip; + cmdline_fixed_string_t netmask; + cmdline_fixed_string_t mask; +}; + +struct ethdev_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t rxq; + cmdline_fixed_string_t txq; + cmdline_fixed_string_t mempool; + uint16_t nb_rxq; + uint16_t nb_txq; +}; + +struct ethdev_help_cmd_tokens { + cmdline_fixed_string_t help; + cmdline_fixed_string_t ethdev; +}; + +struct ethdev_rss_config { + uint32_t queue_id[ETHDEV_RXQ_RSS_MAX]; + uint32_t n_queues; +}; + +struct ethdev_config { + char dev_name[RTE_ETH_NAME_MAX_LEN]; + uint16_t port_id; + + struct { + uint32_t n_queues; + uint32_t queue_size; + char mempool_name[RTE_MEMPOOL_NAMESIZE]; + struct rte_mempool *mp; + struct ethdev_rss_config *rss; + } rx; + + struct { + uint32_t n_queues; + uint32_t queue_size; + } tx; + + int promiscuous; + uint32_t mtu; +}; + +struct ethdev { + TAILQ_ENTRY(ethdev) next; + struct ethdev_config config; + struct ipv4_addr_config ip4_addr; + struct ipv6_addr_config ip6_addr; +}; +TAILQ_HEAD(ethdev_head, ethdev); +#endif diff --git a/app/graph/main.c b/app/graph/main.c index 96548f49e7..c1cb435588 100644 --- a/app/graph/main.c +++ b/app/graph/main.c @@ -215,6 +215,7 @@ main(int argc, char **argv) exit: conn_free(conn); + ethdev_stop(); cli_exit(); rte_eal_cleanup(); return 0; diff --git a/app/graph/meson.build b/app/graph/meson.build index d35287be14..d0369f1c09 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -11,6 +11,7 @@ deps += ['bus_pci', 'graph', 'eal', 'lpm', 'ethdev', 'node', 'cmdline'] sources = files( 'cli.c', 'conn.c', + 'ethdev.c', 'main.c', 'mempool.c', 'utils.c', diff --git a/app/graph/module_api.h b/app/graph/module_api.h index b45419811b..e8a6ccb562 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -10,6 +10,7 @@ #include "cli.h" #include "conn.h" +#include "ethdev.h" #include "mempool.h" #include "utils.h" /* diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 9f6b83e248..09416a32ce 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -88,6 +88,42 @@ file to express the requested use case configuration. - Command to dump mempool help message - Yes - Yes + * - ethdev rxq txq + - Command to create DPDK port with given number of Rx and Tx queues. Also attached + RxQ with given mempool. Each port can have single mempool only i.e. all RxQs will + share the same mempool. + - No + - No + * - ethdev mtu + - Command to configure MTU of DPDK port + - Yes + - Yes + * - ethdev promiscuous + - Command to enable/disable promiscuous mode on DPDK port + - Yes + - Yes + * - ethdev show + - Command to dump current ethdev configuration + - Yes + - Yes + * - ethdev stats + - Command to dump current ethdev statistics + - Yes + - Yes + * - ethdev ip4 addr add netmask + - Command to configure IPv4 address on given PCI device. It is needed if user + wishes to use ``ipv4_lookup`` node + - No + - Yes + * - ethdev ip6 addr add netmask + - Command to configure IPv6 address on given PCI device. It is needed if user + wishes to use ``ipv6_lookup`` node + - No + - Yes + * - help ethdev + - Command to dump ethdev help message + - Yes + - Yes Runtime configuration --------------------- @@ -121,6 +157,17 @@ Example: ``dpdk-graph`` is started with -h 10.28.35.207 and -p 50000 then graph> graph> + graph> help ethdev + + ----------------------------- ethdev command help ----------------------------- + ethdev rxq txq + ethdev ip4 addr add netmask + ethdev ip6 addr add netmask + ethdev promiscuous + ethdev mtu + ethdev show + graph> + Created graph for use case -------------------------- From patchwork Tue Sep 26 10:57:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131956 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 05E3842642; Tue, 26 Sep 2023 12:58:34 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3E95840DDC; Tue, 26 Sep 2023 12:58:07 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 47DDA40A76 for ; Tue, 26 Sep 2023 12:58:02 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38PNkg20032220 for ; Tue, 26 Sep 2023 03:58:01 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=JYlYPS3JFYvklMzBWMhJ5Ei+bzqIE4iU1nwHZOvE/Ag=; b=XY5k8xb8+E9ByWV6vM5QnACeJR4xjSwMKpT+aGI8sF51Z3ziH5rZd6nty7py5A4mbTE1 11P6ncgrpARvnKRC9N1oiIMpdWYBqgCqOnlEpCRDNxR/GXA9SR+F8b6n2NrFqk89VBii kN1jj88kcPOB8gawB5kpuzmZh8mt5f1/HPJqqNAqZVaY03AzGMyIOlbh9hsMbwYjw73c iuQJjZXnelIO031sTu5UAokhJdN+xkSqAF0bMX4uJju9uz321K3aDxFPPQeP7caKN7dt XgeX5wI/xO8qfCStUKgmHQMJYqIhmTVy24UwPzOfTDFyYzPR0sadRBK95zHL4gEPwW12 sQ== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3t9yhm0kgd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:58:01 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:57:59 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:57:59 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 020513F70A6; Tue, 26 Sep 2023 03:57:57 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 06/12] app/graph: add ipv4_lookup command line interfaces Date: Tue, 26 Sep 2023 16:27:36 +0530 Message-ID: <20230926105742.2638594-7-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: -syRbgkb2f-X8QHSbiQUE_IjtkJenNrz X-Proofpoint-ORIG-GUID: -syRbgkb2f-X8QHSbiQUE_IjtkJenNrz X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori It adds ipv4_lookup module to configure LPM table. This LPM table will be used for IPv4 lookup and forwarding. Following commands are exposed: - ipv4_lookup route add ipv4 netmask via - help ipv4_lookup Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/cli.c | 2 + app/graph/ethdev.c | 2 +- app/graph/ip4_route.c | 205 +++++++++++++++++++++++++++++++++++++ app/graph/meson.build | 1 + app/graph/module_api.h | 1 + app/graph/route.h | 26 +++++ app/graph/route_priv.h | 44 ++++++++ doc/guides/tools/graph.rst | 9 ++ 8 files changed, 289 insertions(+), 1 deletion(-) create mode 100644 app/graph/ip4_route.c create mode 100644 app/graph/route.h create mode 100644 app/graph/route_priv.h diff --git a/app/graph/cli.c b/app/graph/cli.c index c4b5cf3ce1..430750db6e 100644 --- a/app/graph/cli.c +++ b/app/graph/cli.c @@ -30,6 +30,8 @@ cmdline_parse_ctx_t modules_ctx[] = { (cmdline_parse_inst_t *)ðdev_ip6_cmd_ctx, (cmdline_parse_inst_t *)ðdev_cmd_ctx, (cmdline_parse_inst_t *)ðdev_help_cmd_ctx, + (cmdline_parse_inst_t *)&ipv4_lookup_cmd_ctx, + (cmdline_parse_inst_t *)&ipv4_lookup_help_cmd_ctx, NULL, }; diff --git a/app/graph/ethdev.c b/app/graph/ethdev.c index 81ad8c4757..cb29c9054d 100644 --- a/app/graph/ethdev.c +++ b/app/graph/ethdev.c @@ -160,7 +160,7 @@ ethdev_stop(void) } ethdev_list_clean(); - rte_eal_cleanup(); + route_ip4_list_clean(); printf("Bye...\n"); } diff --git a/app/graph/ip4_route.c b/app/graph/ip4_route.c new file mode 100644 index 0000000000..a8fb8ba8d5 --- /dev/null +++ b/app/graph/ip4_route.c @@ -0,0 +1,205 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "module_api.h" +#include "route_priv.h" + +static const char +cmd_ipv4_lookup_help[] = "ipv4_lookup route add ipv4 netmask via "; + +struct ip4_route route4 = TAILQ_HEAD_INITIALIZER(route4); + + +void +route_ip4_list_clean(void) +{ + struct route_ipv4_config *route; + + while (!TAILQ_EMPTY(&route4)) { + route = TAILQ_FIRST(&route4); + TAILQ_REMOVE(&route4, route, next); + } +} + +static struct route_ipv4_config * +find_route4_entry(struct route_ipv4_config *route) +{ + struct route_ipv4_config *ipv4route; + + TAILQ_FOREACH(ipv4route, &route4, next) { + if (!memcmp(ipv4route, route, sizeof(*route))) + return ipv4route; + } + return NULL; + +} + +static uint8_t +convert_netmask_to_depth(uint32_t netmask) +{ + uint8_t zerobits = 0; + + while ((netmask & 0x1) == 0) { + netmask = netmask >> 1; + zerobits++; + } + + return (32 - zerobits); +} + +static int +route_ip4_add(struct route_ipv4_config *route) +{ + struct route_ipv4_config *ipv4route; + + ipv4route = find_route4_entry(route); + + if (!ipv4route) { + ipv4route = malloc(sizeof(struct route_ipv4_config)); + if (!ipv4route) + return -ENOMEM; + } else { + return 0; + } + + ipv4route->ip = route->ip; + ipv4route->netmask = route->netmask; + ipv4route->via = route->via; + ipv4route->is_used = true; + + TAILQ_INSERT_TAIL(&route4, ipv4route, next); + return 0; +} + +int +route_ip4_add_to_lookup(void) +{ + struct route_ipv4_config *route = NULL; + int rc = -EINVAL; + uint8_t depth; + int portid; + + TAILQ_FOREACH(route, &route4, next) { + portid = ethdev_portid_by_ip4(route->via, route->netmask); + if (portid < 0) { + printf("Invalid portid found to install the route\n"); + return rc; + } + + depth = convert_netmask_to_depth(route->netmask); + + rc = rte_node_ip4_route_add(route->ip, depth, portid, + RTE_NODE_IP4_LOOKUP_NEXT_REWRITE); + if (rc < 0) + return rc; + } + + return 0; +} + +static void +cli_ipv4_lookup_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + size_t len; + + len = strlen(conn->msg_out); + conn->msg_out += len; + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n", + "--------------------------- ipv4_lookup command help ---------------------------", + cmd_ipv4_lookup_help); + + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; +} + +static void +cli_ipv4_lookup(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct ip4_lookup_cmd_tokens *res = parsed_result; + struct route_ipv4_config config; + int rc = -EINVAL; + + if (parser_ip4_read(&config.ip, res->ip)) { + printf(MSG_ARG_INVALID, "ipv4"); + return; + } + + if (parser_ip4_read(&config.netmask, res->mask)) { + printf(MSG_ARG_INVALID, "netmask"); + return; + } + + if (parser_ip4_read(&config.via, res->via_ip)) { + printf(MSG_ARG_INVALID, "via ip"); + return; + } + + rc = route_ip4_add(&config); + if (rc < 0) + printf(MSG_CMD_FAIL, res->cmd); +} + +cmdline_parse_token_string_t ip4_lookup_cmd = + TOKEN_STRING_INITIALIZER(struct ip4_lookup_cmd_tokens, cmd, "ipv4_lookup"); +cmdline_parse_token_string_t ip4_lookup_route = + TOKEN_STRING_INITIALIZER(struct ip4_lookup_cmd_tokens, route, "route"); +cmdline_parse_token_string_t ip4_lookup_add = + TOKEN_STRING_INITIALIZER(struct ip4_lookup_cmd_tokens, add, "add"); +cmdline_parse_token_string_t ip4_lookup_ip4 = + TOKEN_STRING_INITIALIZER(struct ip4_lookup_cmd_tokens, ip4, "ipv4"); +cmdline_parse_token_string_t ip4_lookup_ip = + TOKEN_STRING_INITIALIZER(struct ip4_lookup_cmd_tokens, ip, NULL); +cmdline_parse_token_string_t ip4_lookup_netmask = + TOKEN_STRING_INITIALIZER(struct ip4_lookup_cmd_tokens, netmask, "netmask"); +cmdline_parse_token_string_t ip4_lookup_mask = + TOKEN_STRING_INITIALIZER(struct ip4_lookup_cmd_tokens, mask, NULL); +cmdline_parse_token_string_t ip4_lookup_via = + TOKEN_STRING_INITIALIZER(struct ip4_lookup_cmd_tokens, via, "via"); +cmdline_parse_token_string_t ip4_lookup_via_ip = + TOKEN_STRING_INITIALIZER(struct ip4_lookup_cmd_tokens, via_ip, NULL); + +cmdline_parse_inst_t ipv4_lookup_cmd_ctx = { + .f = cli_ipv4_lookup, + .data = NULL, + .help_str = cmd_ipv4_lookup_help, + .tokens = { + (void *)&ip4_lookup_cmd, + (void *)&ip4_lookup_route, + (void *)&ip4_lookup_add, + (void *)&ip4_lookup_ip4, + (void *)&ip4_lookup_ip, + (void *)&ip4_lookup_netmask, + (void *)&ip4_lookup_mask, + (void *)&ip4_lookup_via, + (void *)&ip4_lookup_via_ip, + NULL, + }, +}; + +cmdline_parse_token_string_t ipv4_lookup_help_cmd = + TOKEN_STRING_INITIALIZER(struct ipv4_lookup_help_cmd_tokens, cmd, "help"); +cmdline_parse_token_string_t ipv4_lookup_help_module = + TOKEN_STRING_INITIALIZER(struct ipv4_lookup_help_cmd_tokens, module, "ipv4_lookup"); + +cmdline_parse_inst_t ipv4_lookup_help_cmd_ctx = { + .f = cli_ipv4_lookup_help, + .data = NULL, + .help_str = "", + .tokens = { + (void *)&ipv4_lookup_help_cmd, + (void *)&ipv4_lookup_help_module, + NULL, + }, +}; diff --git a/app/graph/meson.build b/app/graph/meson.build index d0369f1c09..b993d6375f 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -12,6 +12,7 @@ sources = files( 'cli.c', 'conn.c', 'ethdev.c', + 'ip4_route.c', 'main.c', 'mempool.c', 'utils.c', diff --git a/app/graph/module_api.h b/app/graph/module_api.h index e8a6ccb562..bd4d245c75 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -12,6 +12,7 @@ #include "conn.h" #include "ethdev.h" #include "mempool.h" +#include "route.h" #include "utils.h" /* * Externs diff --git a/app/graph/route.h b/app/graph/route.h new file mode 100644 index 0000000000..a44d401d55 --- /dev/null +++ b/app/graph/route.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_ROUTE_H +#define APP_GRAPH_ROUTE_H + +#define MAX_ROUTE_ENTRIES 32 + +extern cmdline_parse_inst_t ipv4_lookup_cmd_ctx; +extern cmdline_parse_inst_t ipv4_lookup_help_cmd_ctx; + +struct route_ipv4_config { + TAILQ_ENTRY(route_ipv4_config) next; + uint32_t ip; + uint32_t netmask; + uint32_t via; + bool is_used; +}; + +TAILQ_HEAD(ip4_route, route_ipv4_config); + +int route_ip4_add_to_lookup(void); +void route_ip4_list_clean(void); + +#endif diff --git a/app/graph/route_priv.h b/app/graph/route_priv.h new file mode 100644 index 0000000000..f363a551a9 --- /dev/null +++ b/app/graph/route_priv.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_ROUTE_PRIV_H +#define APP_GRAPH_ROUTE_PRIV_H + +#define MAX_ROUTE_ENTRIES 32 + +struct ip4_lookup_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t route; + cmdline_fixed_string_t add; + cmdline_fixed_string_t ip4; + cmdline_fixed_string_t ip; + cmdline_fixed_string_t netmask; + cmdline_fixed_string_t mask; + cmdline_fixed_string_t via; + cmdline_fixed_string_t via_ip; +}; + +struct ip6_lookup_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t route; + cmdline_fixed_string_t add; + cmdline_fixed_string_t ip6; + cmdline_fixed_string_t ip; + cmdline_fixed_string_t netmask; + cmdline_fixed_string_t mask; + cmdline_fixed_string_t via; + cmdline_fixed_string_t via_ip; +}; + +struct ipv4_lookup_help_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t module; +}; + +struct ipv6_lookup_help_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t module; +}; + +#endif diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 09416a32ce..e2b4a3dfd5 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -124,6 +124,15 @@ file to express the requested use case configuration. - Command to dump ethdev help message - Yes - Yes + * - ipv4_lookup route add ipv4 netmask via + - Command to add a route into ``ipv4_lookup`` LPM table. It is needed if user + wishes to route the packets based on LPM lookup table. + - No + - Yes + * - help ipv4_lookup + - Command to dump ipv4_lookup help message + - Yes + - Yes Runtime configuration --------------------- From patchwork Tue Sep 26 10:57:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131957 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 40FBB42642; Tue, 26 Sep 2023 12:58:40 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8830840E25; Tue, 26 Sep 2023 12:58:08 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 2F88E406B8 for ; Tue, 26 Sep 2023 12:58:04 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38Q6gkaD032209 for ; Tue, 26 Sep 2023 03:58:03 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=bOnJeXqA/pJg5AkUZu40tE/ejJXFDFsTY2Ix+yM8u8w=; b=jILdisrKIQEUTUYhS/tlQUg+swcZHTnSaawYWQp6GPAIjJBP2+L4waRvmEwTZ9ZpSC9l 2vPRnl+AfbJMmcLe0hREQC48jbO5S5yMIsNIDNkgYeks4l0gF2Q2wrMffQRrSxAZcql6 gZ8ymc7CjzLh5K1oXkG7Y+jkZrfjjkQAD+hy5fvcLAzrJYWPF0mM9zEwmOHmterT/1Pv fSjrQdJ96tpdUYSop0i2pra8AakWMWYJqXehqiD+8CNqfwz0+WjZqCTJCfnkLMQzlFB0 PA9m+mIUBZldjdZlUbF4IqX7aQYQ2T+LCM3rczAX3qBWrPCHVD/TgYwsrXa/jxv/mmEo xg== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3t9yhm0kgj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:58:03 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:58:01 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:58:01 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id EEEE73F70AA; Tue, 26 Sep 2023 03:57:59 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 07/12] app/graph: add ipv6_lookup command line interfaces Date: Tue, 26 Sep 2023 16:27:37 +0530 Message-ID: <20230926105742.2638594-8-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: lO0myvVbLThCEJpttLwiNIcZv0ovX7vT X-Proofpoint-ORIG-GUID: lO0myvVbLThCEJpttLwiNIcZv0ovX7vT X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla It adds ipv6_lookup module to configure LPM6 table. This LPM6 table will be used for IPv6 lookup and forwarding. Following commands are exposed: - ipv6_lookup route add ipv6 netmask via - help ipv6_lookup Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/cli.c | 2 + app/graph/ethdev.c | 1 + app/graph/ip6_route.c | 210 +++++++++++++++++++++++++++++++++++++ app/graph/meson.build | 1 + app/graph/route.h | 14 +++ doc/guides/tools/graph.rst | 9 ++ 6 files changed, 237 insertions(+) create mode 100644 app/graph/ip6_route.c diff --git a/app/graph/cli.c b/app/graph/cli.c index 430750db6e..7213a91ad2 100644 --- a/app/graph/cli.c +++ b/app/graph/cli.c @@ -32,6 +32,8 @@ cmdline_parse_ctx_t modules_ctx[] = { (cmdline_parse_inst_t *)ðdev_help_cmd_ctx, (cmdline_parse_inst_t *)&ipv4_lookup_cmd_ctx, (cmdline_parse_inst_t *)&ipv4_lookup_help_cmd_ctx, + (cmdline_parse_inst_t *)&ipv6_lookup_cmd_ctx, + (cmdline_parse_inst_t *)&ipv6_lookup_help_cmd_ctx, NULL, }; diff --git a/app/graph/ethdev.c b/app/graph/ethdev.c index cb29c9054d..0a4eb7be4f 100644 --- a/app/graph/ethdev.c +++ b/app/graph/ethdev.c @@ -161,6 +161,7 @@ ethdev_stop(void) ethdev_list_clean(); route_ip4_list_clean(); + route_ip6_list_clean(); printf("Bye...\n"); } diff --git a/app/graph/ip6_route.c b/app/graph/ip6_route.c new file mode 100644 index 0000000000..93c2c967aa --- /dev/null +++ b/app/graph/ip6_route.c @@ -0,0 +1,210 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "module_api.h" +#include "route_priv.h" + +static const char +cmd_ipv6_lookup_help[] = "ipv6_lookup route add ipv6 netmask via "; + +struct ip6_route route6 = TAILQ_HEAD_INITIALIZER(route6); + +void +route_ip6_list_clean(void) +{ + struct route_ipv6_config *route; + + while (!TAILQ_EMPTY(&route6)) { + route = TAILQ_FIRST(&route6); + TAILQ_REMOVE(&route6, route, next); + } +} + +static struct route_ipv6_config * +find_route6_entry(struct route_ipv6_config *route) +{ + struct route_ipv6_config *ipv6route; + + TAILQ_FOREACH(ipv6route, &route6, next) { + if (!memcmp(ipv6route, route, sizeof(*route))) + return ipv6route; + } + return NULL; +} + +static uint8_t +convert_ip6_netmask_to_depth(uint8_t *netmask) +{ + uint8_t setbits = 0; + uint8_t mask; + int i; + + for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++) { + mask = netmask[i]; + while (mask & 0x80) { + mask = mask << 1; + setbits++; + } + } + + return setbits; +} + +static int +route_ip6_add(struct route_ipv6_config *route) +{ + int j; + + struct route_ipv6_config *ipv6route; + + ipv6route = find_route6_entry(route); + if (!ipv6route) { + ipv6route = malloc(sizeof(struct route_ipv6_config)); + if (!ipv6route) + return -ENOMEM; + } else { + return 0; + } + + for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++) { + ipv6route->ip[j] = route->ip[j]; + ipv6route->mask[j] = route->mask[j]; + ipv6route->gateway[j] = route->gateway[j]; + } + ipv6route->is_used = true; + + return 0; +} + +int +route_ip6_add_to_lookup(void) +{ + struct route_ipv6_config *route = NULL; + int rc = -EINVAL; + uint8_t depth; + int portid; + + TAILQ_FOREACH(route, &route6, next) { + + portid = ethdev_portid_by_ip6(route->gateway, route->mask); + if (portid < 0) { + printf("Invalid portid found to install the route\n"); + return rc; + } + depth = convert_ip6_netmask_to_depth(route->mask); + + rc = rte_node_ip6_route_add(route->ip, depth, portid, + RTE_NODE_IP6_LOOKUP_NEXT_REWRITE); + if (rc < 0) + return rc; + } + + return 0; +} + +static void +cli_ipv6_lookup_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + size_t len; + + len = strlen(conn->msg_out); + conn->msg_out += len; + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n", + "--------------------------- ipv6_lookup command help ---------------------------", + cmd_ipv6_lookup_help); + + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; +} + +static void +cli_ipv6_lookup(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct ip6_lookup_cmd_tokens *res = parsed_result; + struct route_ipv6_config config; + int rc = -EINVAL; + + if (parser_ip6_read(config.ip, res->ip)) { + printf(MSG_ARG_INVALID, "ipv6"); + return; + } + + if (parser_ip6_read(config.mask, res->mask)) { + printf(MSG_ARG_INVALID, "netmask"); + return; + } + + if (parser_ip6_read(config.gateway, res->via_ip)) { + printf(MSG_ARG_INVALID, "gateway ip"); + return; + } + + rc = route_ip6_add(&config); + if (rc) + printf(MSG_CMD_FAIL, res->cmd); +} + +cmdline_parse_token_string_t ip6_lookup_cmd = + TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, cmd, "ipv6_lookup"); +cmdline_parse_token_string_t ip6_lookup_route = + TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, route, "route"); +cmdline_parse_token_string_t ip6_lookup_add = + TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, add, "add"); +cmdline_parse_token_string_t ip6_lookup_ip6 = + TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, ip6, "ipv6"); +cmdline_parse_token_string_t ip6_lookup_ip = + TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, ip, NULL); +cmdline_parse_token_string_t ip6_lookup_netmask = + TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, netmask, "netmask"); +cmdline_parse_token_string_t ip6_lookup_mask = + TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, mask, NULL); +cmdline_parse_token_string_t ip6_lookup_via = + TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, via, "via"); +cmdline_parse_token_string_t ip6_lookup_via_ip = + TOKEN_STRING_INITIALIZER(struct ip6_lookup_cmd_tokens, via_ip, NULL); + +cmdline_parse_inst_t ipv6_lookup_cmd_ctx = { + .f = cli_ipv6_lookup, + .data = NULL, + .help_str = cmd_ipv6_lookup_help, + .tokens = { + (void *)&ip6_lookup_cmd, + (void *)&ip6_lookup_route, + (void *)&ip6_lookup_add, + (void *)&ip6_lookup_ip6, + (void *)&ip6_lookup_ip, + (void *)&ip6_lookup_netmask, + (void *)&ip6_lookup_mask, + (void *)&ip6_lookup_via, + (void *)&ip6_lookup_via_ip, + NULL, + }, +}; + +cmdline_parse_token_string_t ipv6_lookup_help_cmd = + TOKEN_STRING_INITIALIZER(struct ipv6_lookup_help_cmd_tokens, cmd, "help"); +cmdline_parse_token_string_t ipv6_lookup_help_module = + TOKEN_STRING_INITIALIZER(struct ipv6_lookup_help_cmd_tokens, module, "ipv6_lookup"); + +cmdline_parse_inst_t ipv6_lookup_help_cmd_ctx = { + .f = cli_ipv6_lookup_help, + .data = NULL, + .help_str = "", + .tokens = { + (void *)&ipv6_lookup_help_cmd, + (void *)&ipv6_lookup_help_module, + NULL, + }, +}; diff --git a/app/graph/meson.build b/app/graph/meson.build index b993d6375f..6841a25eb6 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -13,6 +13,7 @@ sources = files( 'conn.c', 'ethdev.c', 'ip4_route.c', + 'ip6_route.c', 'main.c', 'mempool.c', 'utils.c', diff --git a/app/graph/route.h b/app/graph/route.h index a44d401d55..0d271d1350 100644 --- a/app/graph/route.h +++ b/app/graph/route.h @@ -8,7 +8,9 @@ #define MAX_ROUTE_ENTRIES 32 extern cmdline_parse_inst_t ipv4_lookup_cmd_ctx; +extern cmdline_parse_inst_t ipv6_lookup_cmd_ctx; extern cmdline_parse_inst_t ipv4_lookup_help_cmd_ctx; +extern cmdline_parse_inst_t ipv6_lookup_help_cmd_ctx; struct route_ipv4_config { TAILQ_ENTRY(route_ipv4_config) next; @@ -20,7 +22,19 @@ struct route_ipv4_config { TAILQ_HEAD(ip4_route, route_ipv4_config); +struct route_ipv6_config { + TAILQ_ENTRY(route_ipv6_config) next; + uint8_t ip[16]; + uint8_t mask[16]; + uint8_t gateway[16]; + bool is_used; +}; + +TAILQ_HEAD(ip6_route, route_ipv6_config); + int route_ip4_add_to_lookup(void); +int route_ip6_add_to_lookup(void); void route_ip4_list_clean(void); +void route_ip6_list_clean(void); #endif diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index e2b4a3dfd5..0782eb3461 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -133,6 +133,15 @@ file to express the requested use case configuration. - Command to dump ipv4_lookup help message - Yes - Yes + * - ipv6_lookup route add ipv6 netmask via + - Command to add a route into ``ipv6_lookup`` LPM table. It is needed if user + wishes to route the packets based on LPM6 lookup table. + - No + - Yes + * - help ipv6_lookup + - Command to dump ipv6_lookup help message + - Yes + - Yes Runtime configuration --------------------- From patchwork Tue Sep 26 10:57:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131958 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id B162A42642; Tue, 26 Sep 2023 12:58:48 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 86E8640E64; Tue, 26 Sep 2023 12:58:14 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id E4287406B8 for ; Tue, 26 Sep 2023 12:58:05 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38Q9xiwK012823 for ; Tue, 26 Sep 2023 03:58:05 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=3CVpNhTz+AdgQPW4zFs1krsn+8RXF7LFTY3ALC0XhW8=; b=RQ7tW9Yuk7JwPWpMRYWtrb/VLzuIUlc6DbmkkcPqQl5SX67H32QwHyRfre4v6cRkVALC Vp773abkmiQND1+4KFem6kKhKPGMwNv8DxK/tY1PMWoUHVDBbZnpp86SyC8s078z6yV7 e/M3kNREoQ2jZilioROy+C/u3vBwzfOUzEAFkjfTBsgtBAbVfJezvzzb07MuqsZNojkO YFHIg05QsqQaclWe6oCydY3oraiTcympzxTKeqcJs+jkeZwRG+uyaoAMQqDhpheP1w+d BBBtbkAlSIAqcmFGZsNqUa0w9CrxW3CMccsKKY/Th2g1TAufN2QL4nU5Tb3nObrjcRFu Dw== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3tbw5gg5hs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:58:04 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:58:03 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:58:03 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id E9AAB3F70B5; Tue, 26 Sep 2023 03:58:01 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 08/12] app/graph: add neigh command line interfaces Date: Tue, 26 Sep 2023 16:27:38 +0530 Message-ID: <20230926105742.2638594-9-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: kOOZBmlgnSmeZlt3i9saGfVoFZyPDOWq X-Proofpoint-ORIG-GUID: kOOZBmlgnSmeZlt3i9saGfVoFZyPDOWq X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori It adds neigh module to configure arp/neigh. This module uses ipv4_rewrite and ipv6_rewrite node to write neigh information. Following commands are exposed: - neigh add ipv4 - neigh add ipv6 - help neigh Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/cli.c | 3 + app/graph/ethdev.c | 2 + app/graph/meson.build | 1 + app/graph/module_api.h | 2 + app/graph/neigh.c | 331 +++++++++++++++++++++++++++++++++++++ app/graph/neigh.h | 17 ++ app/graph/neigh_priv.h | 49 ++++++ doc/guides/tools/graph.rst | 12 ++ 8 files changed, 417 insertions(+) create mode 100644 app/graph/neigh.c create mode 100644 app/graph/neigh.h create mode 100644 app/graph/neigh_priv.h diff --git a/app/graph/cli.c b/app/graph/cli.c index 7213a91ad2..36338d5173 100644 --- a/app/graph/cli.c +++ b/app/graph/cli.c @@ -34,6 +34,9 @@ cmdline_parse_ctx_t modules_ctx[] = { (cmdline_parse_inst_t *)&ipv4_lookup_help_cmd_ctx, (cmdline_parse_inst_t *)&ipv6_lookup_cmd_ctx, (cmdline_parse_inst_t *)&ipv6_lookup_help_cmd_ctx, + (cmdline_parse_inst_t *)&neigh_v4_cmd_ctx, + (cmdline_parse_inst_t *)&neigh_v6_cmd_ctx, + (cmdline_parse_inst_t *)&neigh_help_cmd_ctx, NULL, }; diff --git a/app/graph/ethdev.c b/app/graph/ethdev.c index 0a4eb7be4f..fc0bd8f05f 100644 --- a/app/graph/ethdev.c +++ b/app/graph/ethdev.c @@ -162,6 +162,8 @@ ethdev_stop(void) ethdev_list_clean(); route_ip4_list_clean(); route_ip6_list_clean(); + neigh4_list_clean(); + neigh6_list_clean(); printf("Bye...\n"); } diff --git a/app/graph/meson.build b/app/graph/meson.build index 6841a25eb6..c0b8418b89 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -16,5 +16,6 @@ sources = files( 'ip6_route.c', 'main.c', 'mempool.c', + 'neigh.c', 'utils.c', ) diff --git a/app/graph/module_api.h b/app/graph/module_api.h index bd4d245c75..e9e42da7cc 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -12,8 +12,10 @@ #include "conn.h" #include "ethdev.h" #include "mempool.h" +#include "neigh.h" #include "route.h" #include "utils.h" + /* * Externs */ diff --git a/app/graph/neigh.c b/app/graph/neigh.c new file mode 100644 index 0000000000..f59d61152b --- /dev/null +++ b/app/graph/neigh.c @@ -0,0 +1,331 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "neigh_priv.h" +#include "module_api.h" + +static const char +cmd_neigh_v4_help[] = "neigh add ipv4 "; + +static const char +cmd_neigh_v6_help[] = "neigh add ipv6 "; + +struct neigh4_head neigh4 = TAILQ_HEAD_INITIALIZER(neigh4); +struct neigh6_head neigh6 = TAILQ_HEAD_INITIALIZER(neigh6); + +void +neigh4_list_clean(void) +{ + struct neigh_ipv4_config *v4_config; + + while (!TAILQ_EMPTY(&neigh4)) { + v4_config = TAILQ_FIRST(&neigh4); + TAILQ_REMOVE(&neigh4, v4_config, next); + } +} + +void +neigh6_list_clean(void) +{ + struct neigh_ipv6_config *v6_config; + + while (!TAILQ_EMPTY(&neigh6)) { + v6_config = TAILQ_FIRST(&neigh6); + TAILQ_REMOVE(&neigh6, v6_config, next); + } +} + +static struct neigh_ipv4_config * +find_neigh4_entry(uint32_t ip, uint64_t mac) +{ + struct neigh_ipv4_config *v4_config; + + TAILQ_FOREACH(v4_config, &neigh4, next) { + if ((v4_config->ip == ip) && (v4_config->mac == mac)) + return v4_config; + } + return NULL; +} + +static struct neigh_ipv6_config * +find_neigh6_entry(uint8_t *ip, uint64_t mac) +{ + struct neigh_ipv6_config *v6_config; + + TAILQ_FOREACH(v6_config, &neigh6, next) { + if (!(memcmp(v6_config->ip, ip, 16)) && (v6_config->mac == mac)) + return v6_config; + } + return NULL; +} + +static int +neigh_ip4_add(uint32_t ip, uint64_t mac) +{ + struct neigh_ipv4_config *v4_config; + + v4_config = find_neigh4_entry(ip, mac); + + if (!v4_config) { + v4_config = malloc(sizeof(struct neigh_ipv4_config)); + if (!v4_config) + return -ENOMEM; + } + + v4_config->ip = ip; + v4_config->mac = mac; + v4_config->is_used = true; + + TAILQ_INSERT_TAIL(&neigh4, v4_config, next); + return 0; +} + +static int +neigh_ip6_add(uint8_t *ip, uint64_t mac) +{ + int j; + struct neigh_ipv6_config *v6_config; + + v6_config = find_neigh6_entry(ip, mac); + + if (!v6_config) { + v6_config = malloc(sizeof(struct neigh_ipv6_config)); + if (!v6_config) + return -ENOMEM; + } + + for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++) + v6_config->ip[j] = ip[j]; + + v6_config->mac = mac; + v6_config->is_used = true; + + TAILQ_INSERT_TAIL(&neigh6, v6_config, next); + return 0; +} + +int +neigh_ip4_add_to_rewrite(void) +{ + uint8_t data[2 * RTE_ETHER_ADDR_LEN]; + uint8_t len = 2 * RTE_ETHER_ADDR_LEN; + struct rte_ether_addr smac = {0}; + struct neigh_ipv4_config *neigh; + int16_t portid = 0; + int rc; + + TAILQ_FOREACH(neigh, &neigh4, next) { + portid = ethdev_portid_by_ip4(neigh->ip, 0); + if (portid < 0) { + printf("Invalid portid found to add neigh\n"); + return -EINVAL; + } + + memset(data, 0, len); + + /* Copy dst mac */ + rte_memcpy((void *)&data[0], (void *)&neigh->mac, RTE_ETHER_ADDR_LEN); + + /* Copy src mac */ + rc = rte_eth_macaddr_get(portid, &smac); + if (rc < 0) { + printf("Cannot get MAC address: err=%d, port=%d\n", rc, portid); + return rc; + } + + rte_memcpy(&data[RTE_ETHER_ADDR_LEN], smac.addr_bytes, RTE_ETHER_ADDR_LEN); + + rc = rte_node_ip4_rewrite_add(portid, data, len, portid); + if (rc < 0) { + printf("Error in writing rewrite data: err=%d, port=%d\n", rc, portid); + return rc; + } + } + return 0; +} + +int +neigh_ip6_add_to_rewrite(void) +{ + uint8_t data[2 * RTE_ETHER_ADDR_LEN]; + uint8_t len = 2 * RTE_ETHER_ADDR_LEN; + struct rte_ether_addr smac = {0}; + struct neigh_ipv6_config *neigh; + int16_t portid = 0; + int rc; + + + TAILQ_FOREACH(neigh, &neigh6, next) { + + portid = ethdev_portid_by_ip6(neigh->ip, NULL); + if (portid < 0) { + printf("Invalid portid found to add neigh\n"); + return -EINVAL; + } + + memset(data, 0, len); + + /* Copy dst mac */ + rte_memcpy((void *)&data[0], (void *)&neigh->mac, RTE_ETHER_ADDR_LEN); + + /* Copy src mac */ + rc = rte_eth_macaddr_get(portid, &smac); + if (rc < 0) { + printf("Cannot get MAC address: err=%d, port=%d\n", + rc, portid); + return rc; + } + + rte_memcpy(&data[RTE_ETHER_ADDR_LEN], smac.addr_bytes, RTE_ETHER_ADDR_LEN); + + rc = rte_node_ip6_rewrite_add(portid, data, len, portid); + if (rc < 0) { + printf("Error in writing rewrite data: err=%d, port=%d\n", rc, portid); + return rc; + } + } + + return 0; +} + +static void +cli_neigh_v4(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct neigh_v4_cmd_tokens *res = parsed_result; + int rc = -EINVAL; + uint64_t mac; + uint32_t ip; + + if (parser_ip4_read(&ip, res->ip)) { + printf(MSG_ARG_INVALID, "ip"); + return; + } + + if (parser_mac_read(&mac, res->mac)) { + printf(MSG_ARG_INVALID, "mac"); + return; + } + + rc = neigh_ip4_add(ip, mac); + if (rc < 0) + printf(MSG_CMD_FAIL, res->cmd); +} + +static void +cli_neigh_v6(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct neigh_v6_cmd_tokens *res = parsed_result; + uint8_t ip[ETHDEV_IPV6_ADDR_LEN]; + int rc = -EINVAL; + uint64_t mac; + + if (parser_ip6_read(ip, res->ip)) { + printf(MSG_ARG_INVALID, "ip"); + return; + } + + if (parser_mac_read(&mac, res->mac)) { + printf(MSG_ARG_INVALID, "mac"); + return; + } + + rc = neigh_ip6_add(ip, mac); + if (rc < 0) + printf(MSG_CMD_FAIL, res->cmd); +} + +static void +cli_neigh_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + size_t len; + + len = strlen(conn->msg_out); + conn->msg_out += len; + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n", + "--------------------------- neigh command help ---------------------------", + cmd_neigh_v4_help, cmd_neigh_v6_help); + + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; +} + +cmdline_parse_token_string_t neigh_v4_cmd = + TOKEN_STRING_INITIALIZER(struct neigh_v4_cmd_tokens, cmd, "neigh"); +cmdline_parse_token_string_t neigh_v4_add = + TOKEN_STRING_INITIALIZER(struct neigh_v4_cmd_tokens, add, "add"); +cmdline_parse_token_string_t neigh_v4_ip4 = + TOKEN_STRING_INITIALIZER(struct neigh_v4_cmd_tokens, ip4, "ipv4"); +cmdline_parse_token_string_t neigh_v4_ip = + TOKEN_STRING_INITIALIZER(struct neigh_v4_cmd_tokens, ip, NULL); +cmdline_parse_token_string_t neigh_v4_mac = + TOKEN_STRING_INITIALIZER(struct neigh_v4_cmd_tokens, mac, NULL); + +cmdline_parse_inst_t neigh_v4_cmd_ctx = { + .f = cli_neigh_v4, + .data = NULL, + .help_str = cmd_neigh_v4_help, + .tokens = { + (void *)&neigh_v4_cmd, + (void *)&neigh_v4_add, + (void *)&neigh_v4_ip4, + (void *)&neigh_v4_ip, + (void *)&neigh_v4_mac, + NULL, + }, +}; + +cmdline_parse_token_string_t neigh_v6_cmd = + TOKEN_STRING_INITIALIZER(struct neigh_v6_cmd_tokens, cmd, "neigh"); +cmdline_parse_token_string_t neigh_v6_add = + TOKEN_STRING_INITIALIZER(struct neigh_v6_cmd_tokens, add, "add"); +cmdline_parse_token_string_t neigh_v6_ip6 = + TOKEN_STRING_INITIALIZER(struct neigh_v6_cmd_tokens, ip6, "ipv6"); +cmdline_parse_token_string_t neigh_v6_ip = + TOKEN_STRING_INITIALIZER(struct neigh_v6_cmd_tokens, ip, NULL); +cmdline_parse_token_string_t neigh_v6_mac = + TOKEN_STRING_INITIALIZER(struct neigh_v6_cmd_tokens, mac, NULL); + +cmdline_parse_inst_t neigh_v6_cmd_ctx = { + .f = cli_neigh_v6, + .data = NULL, + .help_str = cmd_neigh_v6_help, + .tokens = { + (void *)&neigh_v6_cmd, + (void *)&neigh_v6_add, + (void *)&neigh_v6_ip6, + (void *)&neigh_v6_ip, + (void *)&neigh_v6_mac, + NULL, + }, +}; + +cmdline_parse_token_string_t neigh_help_cmd = + TOKEN_STRING_INITIALIZER(struct neigh_help_cmd_tokens, cmd, "help"); +cmdline_parse_token_string_t neigh_help_module = + TOKEN_STRING_INITIALIZER(struct neigh_help_cmd_tokens, module, "neigh"); + +cmdline_parse_inst_t neigh_help_cmd_ctx = { + .f = cli_neigh_help, + .data = NULL, + .help_str = "", + .tokens = { + (void *)&neigh_help_cmd, + (void *)&neigh_help_module, + NULL, + }, +}; diff --git a/app/graph/neigh.h b/app/graph/neigh.h new file mode 100644 index 0000000000..928981fc31 --- /dev/null +++ b/app/graph/neigh.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_NEIGH_H +#define APP_GRAPH_NEIGH_H + +extern cmdline_parse_inst_t neigh_v4_cmd_ctx; +extern cmdline_parse_inst_t neigh_v6_cmd_ctx; +extern cmdline_parse_inst_t neigh_help_cmd_ctx; + +void neigh4_list_clean(void); +void neigh6_list_clean(void); +int neigh_ip4_add_to_rewrite(void); +int neigh_ip6_add_to_rewrite(void); + +#endif diff --git a/app/graph/neigh_priv.h b/app/graph/neigh_priv.h new file mode 100644 index 0000000000..0ec9b1510f --- /dev/null +++ b/app/graph/neigh_priv.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_NEIGH_PRIV_H +#define APP_GRAPH_NEIGH_PRIV_H + +#define MAX_NEIGH_ENTRIES 32 + +struct neigh_v4_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t add; + cmdline_fixed_string_t ip4; + cmdline_fixed_string_t ip; + cmdline_fixed_string_t mac; +}; + +struct neigh_v6_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t add; + cmdline_fixed_string_t ip6; + cmdline_fixed_string_t ip; + cmdline_fixed_string_t mac; +}; + +struct neigh_help_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t module; +}; + +struct neigh_ipv4_config { + TAILQ_ENTRY(neigh_ipv4_config) next; + uint32_t ip; + uint64_t mac; + bool is_used; +}; + +TAILQ_HEAD(neigh4_head, neigh_ipv4_config); + +struct neigh_ipv6_config { + TAILQ_ENTRY(neigh_ipv6_config) next; + uint8_t ip[16]; + uint64_t mac; + bool is_used; +}; + +TAILQ_HEAD(neigh6_head, neigh_ipv6_config); + +#endif diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 0782eb3461..c46c8c5737 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -142,6 +142,18 @@ file to express the requested use case configuration. - Command to dump ipv6_lookup help message - Yes - Yes + * - neigh add ipv4 + - Command to add a neighbour information into ``ipv4_rewrite`` node. + - No + - Yes + * - neigh add ipv6 + - Command to add a neighbour information into ``ipv6_rewrite`` node. + - No + - Yes + * - help neigh + - Command to dump neigh help message + - Yes + - Yes Runtime configuration --------------------- From patchwork Tue Sep 26 10:57:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131959 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 2975142642; Tue, 26 Sep 2023 12:58:55 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C91CD40E78; Tue, 26 Sep 2023 12:58:15 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 2748F40E03 for ; Tue, 26 Sep 2023 12:58:08 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38QAYtgP010157 for ; Tue, 26 Sep 2023 03:58:07 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=aIpvP0nLZ2fX8uxpTaKzkXxAFmvrqJYRCfyrLBG+PYo=; b=SwxtXQMKhrtWLNn8dSRJE78Dgx/028RlZUjZjQFGvd2n4DnT6xrNDZSzCf90q2aJOUfp X1YGjPvpSLiCoopuWRAk11rj92jjMjEr3ReMdbdgBn7vJTNFnxGo/Cb56R9J60QuLLyG NlHGcIlrqaYownPK12DLeMRfzU/jD2whoNssRJBVGfunHfstwUotGvMRx2YlS47g4KxX /xSOA4kaScEcLgR3Jq0MFhuvcvkpub0QkvPjpzbxu3LqDGrHkYUkCvPrPIAom5kzaRzG heWc5hfGeje3ofcb8U0ppaRmhVjrHCMCXB2jnaG937PwWxdVO53hawOMjMTuLN2tnsGI WA== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3t9yhm0kgs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:58:07 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:58:05 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:58:05 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id E39763F70A6; Tue, 26 Sep 2023 03:58:03 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 09/12] app/graph: add ethdev_rx command line interfaces Date: Tue, 26 Sep 2023 16:27:39 +0530 Message-ID: <20230926105742.2638594-10-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: GgT_UqL5IbII8_tCioAGtKrphng5vO7G X-Proofpoint-ORIG-GUID: GgT_UqL5IbII8_tCioAGtKrphng5vO7G X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla It adds ethdev_rx module to create port-queue-core mapping. Mapping will be used to launch graph worker thread and dequeue packets on mentioned core from desired port/queue. Following commands are exposed: - ethdev_rx map port queue core - help ethdev_rx Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/cli.c | 2 + app/graph/ethdev_rx.c | 165 +++++++++++++++++++++++++++++++++++++ app/graph/ethdev_rx.h | 37 +++++++++ app/graph/ethdev_rx_priv.h | 39 +++++++++ app/graph/meson.build | 1 + app/graph/module_api.h | 1 + doc/guides/tools/graph.rst | 10 +++ 7 files changed, 255 insertions(+) create mode 100644 app/graph/ethdev_rx.c create mode 100644 app/graph/ethdev_rx.h create mode 100644 app/graph/ethdev_rx_priv.h diff --git a/app/graph/cli.c b/app/graph/cli.c index 36338d5173..e947f61ee4 100644 --- a/app/graph/cli.c +++ b/app/graph/cli.c @@ -30,6 +30,8 @@ cmdline_parse_ctx_t modules_ctx[] = { (cmdline_parse_inst_t *)ðdev_ip6_cmd_ctx, (cmdline_parse_inst_t *)ðdev_cmd_ctx, (cmdline_parse_inst_t *)ðdev_help_cmd_ctx, + (cmdline_parse_inst_t *)ðdev_rx_cmd_ctx, + (cmdline_parse_inst_t *)ðdev_rx_help_cmd_ctx, (cmdline_parse_inst_t *)&ipv4_lookup_cmd_ctx, (cmdline_parse_inst_t *)&ipv4_lookup_help_cmd_ctx, (cmdline_parse_inst_t *)&ipv6_lookup_cmd_ctx, diff --git a/app/graph/ethdev_rx.c b/app/graph/ethdev_rx.c new file mode 100644 index 0000000000..f2cb8cf9a5 --- /dev/null +++ b/app/graph/ethdev_rx.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "ethdev_rx_priv.h" +#include "module_api.h" + +static const char +cmd_ethdev_rx_help[] = "ethdev_rx map port queue core "; + +static struct lcore_params lcore_params_array[ETHDEV_RX_LCORE_PARAMS_MAX]; +struct rte_node_ethdev_config ethdev_conf[RTE_MAX_ETHPORTS]; +struct lcore_params *lcore_params = lcore_params_array; +struct lcore_conf lcore_conf[RTE_MAX_LCORE]; +uint16_t nb_lcore_params; + +static void +rx_map_configure(uint8_t port_id, uint32_t queue, uint32_t core) +{ + uint8_t n_rx_queue; + + n_rx_queue = lcore_conf[core].n_rx_queue; + lcore_conf[core].rx_queue_list[n_rx_queue].port_id = port_id; + lcore_conf[core].rx_queue_list[n_rx_queue].queue_id = queue; + lcore_conf[core].n_rx_queue++; +} + +uint8_t +ethdev_rx_num_rx_queues_get(uint16_t port) +{ + int queue = -1; + uint16_t i; + + for (i = 0; i < nb_lcore_params; ++i) { + if (lcore_params[i].port_id == port) { + if (lcore_params[i].queue_id == queue + 1) + queue = lcore_params[i].queue_id; + else + rte_exit(EXIT_FAILURE, + "Queue ids of the port %d must be" + " in sequence and must start with 0\n", + lcore_params[i].port_id); + } + } + + return (uint8_t)(++queue); +} + +static int +ethdev_rx_map_add(char *name, uint32_t queue, uint32_t core) +{ + uint64_t coremask; + uint16_t port_id; + int rc; + + if (nb_lcore_params >= ETHDEV_RX_LCORE_PARAMS_MAX) + return -EINVAL; + + rc = rte_eth_dev_get_port_by_name(name, &port_id); + if (rc) + return -EINVAL; + + coremask = 0xff; /* FIXME: Read from graph configuration */ + + if (!(coremask & (1 << core))) + return -EINVAL; + + rx_map_configure(port_id, queue, core); + + lcore_params_array[nb_lcore_params].port_id = port_id; + lcore_params_array[nb_lcore_params].queue_id = queue; + lcore_params_array[nb_lcore_params].lcore_id = core; + nb_lcore_params++; + return 0; +} + +static void +cli_ethdev_rx_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + size_t len; + + len = strlen(conn->msg_out); + conn->msg_out += len; + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n", + "----------------------------- ethdev_rx command help -----------------------------", + cmd_ethdev_rx_help); + + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; +} + +static void +cli_ethdev_rx(void *parsed_result, __rte_unused struct cmdline *cl, void *data __rte_unused) +{ + struct ethdev_rx_cmd_tokens *res = parsed_result; + int rc = -EINVAL; + + rc = ethdev_rx_map_add(res->dev, res->qid, res->core_id); + if (rc < 0) { + cli_exit(); + printf(MSG_CMD_FAIL, res->cmd); + rte_exit(EXIT_FAILURE, "input core is Invalid\n"); + } + +} + +cmdline_parse_token_string_t ethdev_rx_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_rx_cmd_tokens, cmd, "ethdev_rx"); +cmdline_parse_token_string_t ethdev_rx_map = + TOKEN_STRING_INITIALIZER(struct ethdev_rx_cmd_tokens, map, "map"); +cmdline_parse_token_string_t ethdev_rx_port = + TOKEN_STRING_INITIALIZER(struct ethdev_rx_cmd_tokens, port, "port"); +cmdline_parse_token_string_t ethdev_rx_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_rx_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_rx_queue = + TOKEN_STRING_INITIALIZER(struct ethdev_rx_cmd_tokens, queue, "queue"); +cmdline_parse_token_num_t ethdev_rx_qid = + TOKEN_NUM_INITIALIZER(struct ethdev_rx_cmd_tokens, qid, RTE_UINT32); +cmdline_parse_token_string_t ethdev_rx_core = + TOKEN_STRING_INITIALIZER(struct ethdev_rx_cmd_tokens, core, "core"); +cmdline_parse_token_num_t ethdev_rx_core_id = + TOKEN_NUM_INITIALIZER(struct ethdev_rx_cmd_tokens, core_id, RTE_UINT32); + +cmdline_parse_inst_t ethdev_rx_cmd_ctx = { + .f = cli_ethdev_rx, + .data = NULL, + .help_str = cmd_ethdev_rx_help, + .tokens = { + (void *)ðdev_rx_cmd, + (void *)ðdev_rx_map, + (void *)ðdev_rx_port, + (void *)ðdev_rx_dev, + (void *)ðdev_rx_queue, + (void *)ðdev_rx_qid, + (void *)ðdev_rx_core, + (void *)ðdev_rx_core_id, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_rx_help_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_rx_help_cmd_tokens, cmd, "help"); +cmdline_parse_token_string_t ethdev_rx_help_module = + TOKEN_STRING_INITIALIZER(struct ethdev_rx_help_cmd_tokens, module, "ethdev_rx"); + +cmdline_parse_inst_t ethdev_rx_help_cmd_ctx = { + .f = cli_ethdev_rx_help, + .data = NULL, + .help_str = "", + .tokens = { + (void *)ðdev_rx_help_cmd, + (void *)ðdev_rx_help_module, + NULL, + }, +}; diff --git a/app/graph/ethdev_rx.h b/app/graph/ethdev_rx.h new file mode 100644 index 0000000000..8e7b31448c --- /dev/null +++ b/app/graph/ethdev_rx.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_ETHDEV_RX_H +#define APP_GRAPH_ETHDEV_RX_H + +#include +#include + +#define ETHDEV_RX_LCORE_PARAMS_MAX 1024 +#define ETHDEV_RX_QUEUE_PER_LCORE_MAX 16 + +struct lcore_rx_queue { + uint16_t port_id; + uint8_t queue_id; + char node_name[RTE_NODE_NAMESIZE]; +}; + +struct lcore_conf { + uint16_t n_rx_queue; + struct lcore_rx_queue rx_queue_list[ETHDEV_RX_QUEUE_PER_LCORE_MAX]; + struct rte_graph *graph; + char name[RTE_GRAPH_NAMESIZE]; + rte_graph_t graph_id; +} __rte_cache_aligned; + +uint8_t ethdev_rx_num_rx_queues_get(uint16_t port); + +extern struct rte_node_ethdev_config ethdev_conf[RTE_MAX_ETHPORTS]; +extern struct lcore_conf lcore_conf[RTE_MAX_LCORE]; +extern cmdline_parse_inst_t ethdev_rx_help_cmd_ctx; +extern cmdline_parse_inst_t ethdev_rx_cmd_ctx; +extern struct lcore_params *lcore_params; +extern uint16_t nb_lcore_params; + +#endif diff --git a/app/graph/ethdev_rx_priv.h b/app/graph/ethdev_rx_priv.h new file mode 100644 index 0000000000..5d155be043 --- /dev/null +++ b/app/graph/ethdev_rx_priv.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_ETHDEV_RX_PRIV_H +#define APP_GRAPH_ETHDEV_RX_PRIV_H + +#include + +#include +#include + +#define MAX_RX_QUEUE_PER_PORT 128 +#define MAX_JUMBO_PKT_LEN 9600 +#define NB_SOCKETS 8 + +struct ethdev_rx_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t map; + cmdline_fixed_string_t port; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t queue; + cmdline_fixed_string_t core; + uint32_t core_id; + uint32_t qid; +}; + +struct ethdev_rx_help_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t module; +}; + +struct lcore_params { + uint16_t port_id; + uint8_t queue_id; + uint8_t lcore_id; +} __rte_cache_aligned; + +#endif diff --git a/app/graph/meson.build b/app/graph/meson.build index c0b8418b89..caf2d20735 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -11,6 +11,7 @@ deps += ['bus_pci', 'graph', 'eal', 'lpm', 'ethdev', 'node', 'cmdline'] sources = files( 'cli.c', 'conn.c', + 'ethdev_rx.c', 'ethdev.c', 'ip4_route.c', 'ip6_route.c', diff --git a/app/graph/module_api.h b/app/graph/module_api.h index e9e42da7cc..56b7c94ecc 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -11,6 +11,7 @@ #include "cli.h" #include "conn.h" #include "ethdev.h" +#include "ethdev_rx.h" #include "mempool.h" #include "neigh.h" #include "route.h" diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index c46c8c5737..56d8a08e5c 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -154,6 +154,16 @@ file to express the requested use case configuration. - Command to dump neigh help message - Yes - Yes + * - ethdev_rx map port queue core + - Command to add port-queue-core mapping to ``ethdev_rx`` node. ``ethdev_rx`` + node instance will be pinned on given core and will poll on requested + port/queue pair. + - No + - No + * - help ethdev_rx + - Command to dump ethdev_rx help message + - Yes + - Yes Runtime configuration --------------------- From patchwork Tue Sep 26 10:57:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131960 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id C4EFF42642; Tue, 26 Sep 2023 12:59:01 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 30E0840ED1; Tue, 26 Sep 2023 12:58:17 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id C377140E40 for ; Tue, 26 Sep 2023 12:58:09 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38QA020t013266 for ; Tue, 26 Sep 2023 03:58:09 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=t7/piM2WDI/fHi/z74T/8XE0BWn/BMqnhQSjM1dHhZM=; b=Vou6y9nUS1vpPulyMf/2bcXQr0jH0MrvoAseTidZxWLVo213QwR/Dck68m+T31Oy0UPo oAdG9NR0Xc34zdOA+LR5FC9tfrvpC8oUMomR4pagm/m78e0vKsb0Ev67ksBhhQNPbfQ/ mW7N818J4wiVOLYuPVIhlxZoHPCjzZoLALUd31yhFmchZXWvWFtPUBjeMQo/rMeh2d87 CLjQClx6psK7NEDYOjHrXIOOEy8NaqMAXVu0cIAsukny692Rnmwz4xW9werqnAqxoFnL YDBjsTynyZJfEz/6jpRFNB7fSfiExeojpOpHUCTJpHwDzGMmtBNLman6+PsaIVsxdJnm Nw== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3tbw5gg5j0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:58:08 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:58:07 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:58:07 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id DE9BB3F70A9; Tue, 26 Sep 2023 03:58:05 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 10/12] app/graph: add graph command line interfaces Date: Tue, 26 Sep 2023 16:27:40 +0530 Message-ID: <20230926105742.2638594-11-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: C4EwIMYNXpkzU5-W1LRCp6l_ZaO0aceH X-Proofpoint-ORIG-GUID: C4EwIMYNXpkzU5-W1LRCp6l_ZaO0aceH X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla It adds graph module to create a graph for a given use case like l3fwd. Following commands are exposed: - graph [bsz ] [tmo ] [coremask ] \ model pcap_enable <0 | 1> num_pcap_pkts \ pcap_file - graph start - graph stats show - help graph Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/cli.c | 4 + app/graph/ethdev_rx.c | 2 +- app/graph/graph.c | 536 +++++++++++++++++++++++++++++++++++++ app/graph/graph.h | 20 ++ app/graph/graph_priv.h | 70 +++++ app/graph/meson.build | 1 + app/graph/module_api.h | 1 + doc/guides/tools/graph.rst | 19 +- 8 files changed, 650 insertions(+), 3 deletions(-) create mode 100644 app/graph/graph.c create mode 100644 app/graph/graph.h create mode 100644 app/graph/graph_priv.h diff --git a/app/graph/cli.c b/app/graph/cli.c index e947f61ee4..c43af5925c 100644 --- a/app/graph/cli.c +++ b/app/graph/cli.c @@ -20,6 +20,10 @@ #define MAX_LINE_SIZE 2048 cmdline_parse_ctx_t modules_ctx[] = { + (cmdline_parse_inst_t *)&graph_config_cmd_ctx, + (cmdline_parse_inst_t *)&graph_start_cmd_ctx, + (cmdline_parse_inst_t *)&graph_stats_cmd_ctx, + (cmdline_parse_inst_t *)&graph_help_cmd_ctx, (cmdline_parse_inst_t *)&mempool_config_cmd_ctx, (cmdline_parse_inst_t *)&mempool_help_cmd_ctx, (cmdline_parse_inst_t *)ðdev_show_cmd_ctx, diff --git a/app/graph/ethdev_rx.c b/app/graph/ethdev_rx.c index f2cb8cf9a5..03f8effcca 100644 --- a/app/graph/ethdev_rx.c +++ b/app/graph/ethdev_rx.c @@ -69,7 +69,7 @@ ethdev_rx_map_add(char *name, uint32_t queue, uint32_t core) if (rc) return -EINVAL; - coremask = 0xff; /* FIXME: Read from graph configuration */ + coremask = graph_coremask_get(); if (!(coremask & (1 << core))) return -EINVAL; diff --git a/app/graph/graph.c b/app/graph/graph.c new file mode 100644 index 0000000000..1e543ea7aa --- /dev/null +++ b/app/graph/graph.c @@ -0,0 +1,536 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "graph_priv.h" +#include "module_api.h" + +#define RTE_LOGTYPE_APP_GRAPH RTE_LOGTYPE_USER1 + +static const char +cmd_graph_help[] = "graph bsz tmo coremask " + "model pcap_enable <0 | 1> num_pcap_pkts " + "pcap_file "; + +static const char * const supported_usecases[] = {"l3fwd"}; +struct graph_config graph_config; + +/* Check the link rc of all ports in up to 9s, and print them finally */ +static void +check_all_ports_link_status(uint32_t port_mask) +{ +#define CHECK_INTERVAL 100 /* 100ms */ +#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ + char link_rc_text[RTE_ETH_LINK_MAX_STR_LEN]; + uint8_t count, all_ports_up, print_flag = 0; + struct rte_eth_link link; + uint16_t portid; + int rc; + + printf("\nChecking link rc"); + fflush(stdout); + for (count = 0; count <= MAX_CHECK_TIME; count++) { + if (force_quit) + return; + + all_ports_up = 1; + RTE_ETH_FOREACH_DEV(portid) + { + if (force_quit) + return; + + if ((port_mask & (1 << portid)) == 0) + continue; + + memset(&link, 0, sizeof(link)); + rc = rte_eth_link_get_nowait(portid, &link); + if (rc < 0) { + all_ports_up = 0; + if (print_flag == 1) + printf("Port %u link get failed: %s\n", + portid, rte_strerror(-rc)); + continue; + } + + /* Print link rc if flag set */ + if (print_flag == 1) { + rte_eth_link_to_str(link_rc_text, sizeof(link_rc_text), + &link); + printf("Port %d %s\n", portid, link_rc_text); + continue; + } + + /* Clear all_ports_up flag if any link down */ + if (link.link_status == RTE_ETH_LINK_DOWN) { + all_ports_up = 0; + break; + } + } + + /* After finally printing all link rc, get out */ + if (print_flag == 1) + break; + + if (all_ports_up == 0) { + printf("."); + fflush(stdout); + rte_delay_ms(CHECK_INTERVAL); + } + + /* Set the print_flag if all ports up or timeout */ + if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { + print_flag = 1; + printf("Done\n"); + } + } +} + +static bool +parser_usecases_read(char *usecases) +{ + bool valid = false; + uint32_t i, j = 0; + char *token; + + token = strtok(usecases, ","); + while (token != NULL) { + for (i = 0; i < RTE_DIM(supported_usecases); i++) { + if (strcmp(supported_usecases[i], token) == 0) { + graph_config.usecases[j].enabled = true; + strcpy(graph_config.usecases[j].name, token); + valid = true; + j++; + break; + } + } + token = strtok(NULL, ","); + } + + return valid; +} + +static uint64_t +graph_worker_count_get(void) +{ + uint64_t nb_worker = 0; + uint64_t coremask; + + coremask = graph_config.params.coremask; + while (coremask) { + if (coremask & 0x1) + nb_worker++; + + coremask = (coremask >> 1); + } + + return nb_worker; +} + +static struct rte_node_ethdev_config * +graph_rxtx_node_config_get(uint32_t *num_conf, uint32_t *num_graphs) +{ + uint32_t n_tx_queue, nb_conf = 0, lcore_id; + uint16_t queueid, portid, nb_graphs = 0; + uint8_t nb_rx_queue, queue; + struct lcore_conf *qconf; + + n_tx_queue = graph_worker_count_get(); + if (n_tx_queue > RTE_MAX_ETHPORTS) + n_tx_queue = RTE_MAX_ETHPORTS; + + RTE_ETH_FOREACH_DEV(portid) { + /* Skip ports that are not enabled */ + if ((enabled_port_mask & (1 << portid)) == 0) { + printf("\nSkipping disabled port %d\n", portid); + continue; + } + + nb_rx_queue = ethdev_rx_num_rx_queues_get(portid); + + /* Setup ethdev node config */ + ethdev_conf[nb_conf].port_id = portid; + ethdev_conf[nb_conf].num_rx_queues = nb_rx_queue; + ethdev_conf[nb_conf].num_tx_queues = n_tx_queue; + ethdev_conf[nb_conf].mp = ethdev_mempool_list_by_portid(portid); + ethdev_conf[nb_conf].mp_count = 1; /* Check with pools */ + + nb_conf++; + } + + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (rte_lcore_is_enabled(lcore_id) == 0) + continue; + + qconf = &lcore_conf[lcore_id]; + printf("\nInitializing rx queues on lcore %u ... ", lcore_id); + fflush(stdout); + + /* Init RX queues */ + for (queue = 0; queue < qconf->n_rx_queue; ++queue) { + portid = qconf->rx_queue_list[queue].port_id; + queueid = qconf->rx_queue_list[queue].queue_id; + + /* Add this queue node to its graph */ + snprintf(qconf->rx_queue_list[queue].node_name, RTE_NODE_NAMESIZE, + "ethdev_rx-%u-%u", portid, queueid); + } + if (qconf->n_rx_queue) + nb_graphs++; + } + + printf("\n"); + + ethdev_start(); + check_all_ports_link_status(enabled_port_mask); + + *num_conf = nb_conf; + *num_graphs = nb_graphs; + return ethdev_conf; +} + +static void +graph_stats_print_to_file(void) +{ + struct rte_graph_cluster_stats_param s_param; + struct rte_graph_cluster_stats *stats; + const char *pattern = "worker_*"; + FILE *fp = NULL; + size_t sz, len; + + /* Prepare stats object */ + fp = fopen("/tmp/graph_stats.txt", "w+"); + memset(&s_param, 0, sizeof(s_param)); + s_param.f = fp; + s_param.socket_id = SOCKET_ID_ANY; + s_param.graph_patterns = &pattern; + s_param.nb_graph_patterns = 1; + + stats = rte_graph_cluster_stats_create(&s_param); + if (stats == NULL) + rte_exit(EXIT_FAILURE, "Unable to create stats object\n"); + + /* Clear screen and move to top left */ + rte_graph_cluster_stats_get(stats, 0); + rte_delay_ms(1E3); + + fseek(fp, 0L, SEEK_END); + sz = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + len = strlen(conn->msg_out); + conn->msg_out += len; + + sz = fread(conn->msg_out, sizeof(char), sz, fp); + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; + rte_graph_cluster_stats_destroy(stats); + + fclose(fp); +} + +static void +cli_graph_stats(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + graph_stats_print_to_file(); +} + +static void +cli_graph_start(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct rte_node_ethdev_config *conf; + uint32_t nb_graphs = 0, nb_conf, i; + + conf = graph_rxtx_node_config_get(&nb_conf, &nb_graphs); + for (i = 0; i < MAX_GRAPH_USECASES; i++) { + if (!strcmp(graph_config.usecases[i].name, "l3fwd")) { + if (graph_config.usecases[i].enabled) { + RTE_SET_USED(conf); + break; + } + } + } +} + +static int +graph_config_add(char *usecases, struct graph_config *config) +{ + uint64_t lcore_id, core_num; + uint64_t eal_coremask = 0; + + if (!parser_usecases_read(usecases)) + return -EINVAL; + + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (rte_lcore_is_enabled(lcore_id)) + eal_coremask |= 1 << lcore_id; + } + + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + core_num = 1 << lcore_id; + if (config->params.coremask & core_num) { + if (eal_coremask & core_num) + continue; + else + return -EINVAL; + } + } + + graph_config.params.bsz = config->params.bsz; + graph_config.params.tmo = config->params.tmo; + graph_config.params.coremask = config->params.coremask; + graph_config.model = config->model; + graph_config.pcap_ena = config->pcap_ena; + graph_config.num_pcap_pkts = config->num_pcap_pkts; + graph_config.pcap_file = strdup(config->pcap_file); + + return 0; +} + +void +graph_pcap_config_get(uint8_t *pcap_ena, uint64_t *num_pkts, char **file) +{ + + *pcap_ena = graph_config.pcap_ena; + *num_pkts = graph_config.num_pcap_pkts; + *file = graph_config.pcap_file; +} + +int +graph_walk_start(void *conf) +{ + struct lcore_conf *qconf; + struct rte_graph *graph; + uint32_t lcore_id; + + RTE_SET_USED(conf); + + lcore_id = rte_lcore_id(); + qconf = &lcore_conf[lcore_id]; + graph = qconf->graph; + + if (!graph) { + RTE_LOG(INFO, APP_GRAPH, "Lcore %u has nothing to do\n", lcore_id); + return 0; + } + + RTE_LOG(INFO, APP_GRAPH, "Entering main loop on lcore %u, graph %s(%p)\n", lcore_id, + qconf->name, graph); + + while (likely(!force_quit)) + rte_graph_walk(graph); + + return 0; +} + +void +graph_stats_print(void) +{ + const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'}; + const char clr[] = {27, '[', '2', 'J', '\0'}; + struct rte_graph_cluster_stats_param s_param; + struct rte_graph_cluster_stats *stats; + const char *pattern = "worker_*"; + + /* Prepare stats object */ + memset(&s_param, 0, sizeof(s_param)); + s_param.f = stdout; + s_param.socket_id = SOCKET_ID_ANY; + s_param.graph_patterns = &pattern; + s_param.nb_graph_patterns = 1; + + stats = rte_graph_cluster_stats_create(&s_param); + if (stats == NULL) + rte_exit(EXIT_FAILURE, "Unable to create stats object\n"); + + while (!force_quit) { + /* Clear screen and move to top left */ + printf("%s%s", clr, topLeft); + rte_graph_cluster_stats_get(stats, 0); + rte_delay_ms(1E3); + if (app_graph_exit()) + force_quit = true; + } + + rte_graph_cluster_stats_destroy(stats); +} + +uint64_t +graph_coremask_get(void) +{ + return graph_config.params.coremask; +} + +static void +cli_graph(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) +{ + struct graph_config_cmd_tokens *res = parsed_result; + struct graph_config config; + char *model_name; + uint8_t model; + int rc; + + model_name = res->model_name; + if (strcmp(model_name, "default") == 0) { + model = GRAPH_MODEL_RTC; + } else if (strcmp(model_name, "rtc") == 0) { + model = GRAPH_MODEL_RTC; + } else if (strcmp(model_name, "mcd") == 0) { + model = GRAPH_MODEL_MCD; + } else { + printf(MSG_ARG_NOT_FOUND, "model arguments"); + return; + } + + config.params.bsz = res->size; + config.params.tmo = res->ns; + config.params.coremask = res->mask; + config.model = model; + config.pcap_ena = res->pcap_ena; + config.num_pcap_pkts = res->num_pcap_pkts; + config.pcap_file = res->pcap_file; + rc = graph_config_add(res->usecase, &config); + if (rc < 0) { + cli_exit(); + printf(MSG_CMD_FAIL, res->graph); + rte_exit(EXIT_FAILURE, "coremask is Invalid\n"); + } +} + +static void +cli_graph_help(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + size_t len; + + len = strlen(conn->msg_out); + conn->msg_out += len; + snprintf(conn->msg_out, conn->msg_out_len_max, "\n%s\n%s\n%s\n", + "----------------------------- graph command help -----------------------------", + cmd_graph_help, "graph start"); + + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; +} + +cmdline_parse_token_string_t graph_display_graph = + TOKEN_STRING_INITIALIZER(struct graph_stats_cmd_tokens, graph, "graph"); +cmdline_parse_token_string_t graph_display_stats = + TOKEN_STRING_INITIALIZER(struct graph_stats_cmd_tokens, stats, "stats"); +cmdline_parse_token_string_t graph_display_show = + TOKEN_STRING_INITIALIZER(struct graph_stats_cmd_tokens, show, "show"); + +cmdline_parse_inst_t graph_stats_cmd_ctx = { + .f = cli_graph_stats, + .data = NULL, + .help_str = "graph stats show", + .tokens = { + (void *)&graph_display_graph, + (void *)&graph_display_stats, + (void *)&graph_display_show, + NULL, + }, +}; + +cmdline_parse_token_string_t graph_config_start_graph = + TOKEN_STRING_INITIALIZER(struct graph_start_cmd_tokens, graph, "graph"); +cmdline_parse_token_string_t graph_config_start = + TOKEN_STRING_INITIALIZER(struct graph_start_cmd_tokens, start, "start"); + +cmdline_parse_inst_t graph_start_cmd_ctx = { + .f = cli_graph_start, + .data = NULL, + .help_str = "graph start", + .tokens = { + (void *)&graph_config_start_graph, + (void *)&graph_config_start, + NULL, + }, +}; + +cmdline_parse_token_string_t graph_config_add_graph = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, graph, "graph"); +cmdline_parse_token_string_t graph_config_add_usecase = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, usecase, NULL); +cmdline_parse_token_string_t graph_config_add_coremask = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, coremask, "coremask"); +cmdline_parse_token_num_t graph_config_add_mask = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, mask, RTE_UINT64); +cmdline_parse_token_string_t graph_config_add_bsz = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, bsz, "bsz"); +cmdline_parse_token_num_t graph_config_add_size = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, size, RTE_UINT16); +cmdline_parse_token_string_t graph_config_add_tmo = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, tmo, "tmo"); +cmdline_parse_token_num_t graph_config_add_ns = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, ns, RTE_UINT64); +cmdline_parse_token_string_t graph_config_add_model = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, model, "model"); +cmdline_parse_token_string_t graph_config_add_model_name = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, model_name, "rtc#mcd#default"); +cmdline_parse_token_string_t graph_config_add_capt_ena = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, capt_ena, "pcap_enable"); +cmdline_parse_token_num_t graph_config_add_pcap_ena = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, pcap_ena, RTE_UINT8); +cmdline_parse_token_string_t graph_config_add_capt_pkts_count = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, capt_pkts_count, "num_pcap_pkts"); +cmdline_parse_token_num_t graph_config_add_num_pcap_pkts = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, num_pcap_pkts, RTE_UINT64); +cmdline_parse_token_string_t graph_config_add_capt_file = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, capt_file, "pcap_file"); +cmdline_parse_token_string_t graph_config_add_pcap_file = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, pcap_file, NULL); + +cmdline_parse_inst_t graph_config_cmd_ctx = { + .f = cli_graph, + .data = NULL, + .help_str = cmd_graph_help, + .tokens = { + (void *)&graph_config_add_graph, + (void *)&graph_config_add_usecase, + (void *)&graph_config_add_coremask, + (void *)&graph_config_add_mask, + (void *)&graph_config_add_bsz, + (void *)&graph_config_add_size, + (void *)&graph_config_add_tmo, + (void *)&graph_config_add_ns, + (void *)&graph_config_add_model, + (void *)&graph_config_add_model_name, + (void *)&graph_config_add_capt_ena, + (void *)&graph_config_add_pcap_ena, + (void *)&graph_config_add_capt_pkts_count, + (void *)&graph_config_add_num_pcap_pkts, + (void *)&graph_config_add_capt_file, + (void *)&graph_config_add_pcap_file, + NULL, + }, +}; + +cmdline_parse_token_string_t graph_help_cmd = + TOKEN_STRING_INITIALIZER(struct graph_help_cmd_tokens, help, "help"); +cmdline_parse_token_string_t graph_help_graph = + TOKEN_STRING_INITIALIZER(struct graph_help_cmd_tokens, graph, "graph"); + +cmdline_parse_inst_t graph_help_cmd_ctx = { + .f = cli_graph_help, + .data = NULL, + .help_str = "", + .tokens = { + (void *)&graph_help_cmd, + (void *)&graph_help_graph, + NULL, + }, +}; diff --git a/app/graph/graph.h b/app/graph/graph.h new file mode 100644 index 0000000000..1c3599ac8c --- /dev/null +++ b/app/graph/graph.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_H +#define APP_GRAPH_H + +#include + +extern cmdline_parse_inst_t graph_config_cmd_ctx; +extern cmdline_parse_inst_t graph_start_cmd_ctx; +extern cmdline_parse_inst_t graph_stats_cmd_ctx; +extern cmdline_parse_inst_t graph_help_cmd_ctx; + +int graph_walk_start(void *conf); +void graph_stats_print(void); +void graph_pcap_config_get(uint8_t *pcap_ena, uint64_t *num_pkts, char **file); +uint64_t graph_coremask_get(void); + +#endif diff --git a/app/graph/graph_priv.h b/app/graph/graph_priv.h new file mode 100644 index 0000000000..a48a35daa3 --- /dev/null +++ b/app/graph/graph_priv.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_PRIV_H +#define APP_GRAPH_PRIV_H + +#define MAX_GRAPH_USECASES 32 + +struct graph_help_cmd_tokens { + cmdline_fixed_string_t help; + cmdline_fixed_string_t graph; +}; + +struct graph_start_cmd_tokens { + cmdline_fixed_string_t graph; + cmdline_fixed_string_t start; +}; + +struct graph_stats_cmd_tokens { + cmdline_fixed_string_t show; + cmdline_fixed_string_t graph; + cmdline_fixed_string_t stats; +}; + +struct graph_config_cmd_tokens { + cmdline_fixed_string_t graph; + cmdline_fixed_string_t usecase; + cmdline_fixed_string_t bsz; + cmdline_fixed_string_t tmo; + cmdline_fixed_string_t coremask; + cmdline_fixed_string_t model; + cmdline_fixed_string_t capt_ena; + cmdline_fixed_string_t capt_pkts_count; + cmdline_fixed_string_t capt_file; + cmdline_fixed_string_t model_name; + cmdline_fixed_string_t pcap_file; + uint16_t size; + uint64_t ns; + uint64_t mask; + uint64_t num_pcap_pkts; + uint8_t pcap_ena; +}; + +enum graph_model { + GRAPH_MODEL_RTC = 0x01, + GRAPH_MODEL_MCD = 0x02, +}; + +struct usecases { + char name[32]; + bool enabled; +}; + +struct usecase_params { + uint64_t coremask; + uint32_t bsz; + uint32_t tmo; +}; + +struct graph_config { + struct usecases usecases[MAX_GRAPH_USECASES]; + struct usecase_params params; + enum graph_model model; + uint64_t num_pcap_pkts; + char *pcap_file; + uint8_t pcap_ena; +}; + +#endif diff --git a/app/graph/meson.build b/app/graph/meson.build index caf2d20735..6292fc9684 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -13,6 +13,7 @@ sources = files( 'conn.c', 'ethdev_rx.c', 'ethdev.c', + 'graph.c', 'ip4_route.c', 'ip6_route.c', 'main.c', diff --git a/app/graph/module_api.h b/app/graph/module_api.h index 56b7c94ecc..392dcfb222 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -12,6 +12,7 @@ #include "conn.h" #include "ethdev.h" #include "ethdev_rx.h" +#include "graph.h" #include "mempool.h" #include "neigh.h" #include "route.h" diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 56d8a08e5c..2c06f8e958 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -76,10 +76,25 @@ file to express the requested use case configuration. - Description - Dynamic - Optional - * - Dummy command - - Dummy command description + * - graph [bsz ] [tmo ] [coremask ] model + pcap_enable <0 | 1> num_pcap_pkts pcap_file + - Command to express the desired use case. Also enables/disable pcap capturing - No - No + * - graph start + - Command to start the graph. + This command triggers that no more commands are left to be parsed and graph + initialization can be started now. It must be the last command in ``.cli`` + - No + - No + * - graph stats show + - Command to dump current graph statistics + - Yes + - Yes + * - help graph + - Command to dump graph help message + - Yes + - Yes * - mempool size buffers cache numa - Command to create mempool which will be further associated to RxQ to dequeue the packets - No From patchwork Tue Sep 26 10:57:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131961 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id D21C942642; Tue, 26 Sep 2023 12:59:07 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6A5C840E13; Tue, 26 Sep 2023 12:58:18 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id F10C040E78 for ; Tue, 26 Sep 2023 12:58:11 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38QATmf2010403 for ; Tue, 26 Sep 2023 03:58:11 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=QDGmc50n2AJ87muUB+3Ci3Pu3xt+PMwkJZl287PJsTo=; b=gH6+YvxMbdPLE6gTScB+EBfO3d+S8ESp3+3NGaiorqXGWMMZ+TPy7dTGCQIAVa5duhSM n/IxjBfqlsss6g1HiSGQpgZATrnBSeYVpcbQ+KYqSS8Q/qJT6LaDOhq5uL3SbDe1vWVc QWtOkIXHiX43imZ7qj2Wa1RjFpIxYaNTOBv9Cbf2t2ZotV0JDiYl/oATsSnGVSl8yh91 Is7k4I4Le/zDgM6ZN+zAAry4WNBUTqOZrs3VvXCIVshDEcIeSmAOH4j+9r9FLASZKJeL dddjpt1HrZVRleDHhCEzKCkTxf9ngFrz4q+x0WlzDwz6pYYqc9bR7E7ja2h+YVigm7Uk JQ== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3t9yhm0kgw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:58:11 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:58:08 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:58:09 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id D46193F70AB; Tue, 26 Sep 2023 03:58:07 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 11/12] app/graph: add CLI option to enable graph stats Date: Tue, 26 Sep 2023 16:27:41 +0530 Message-ID: <20230926105742.2638594-12-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: fqg2e8lR_Wslu3L0j3TKR43YqexfaCBT X-Proofpoint-ORIG-GUID: fqg2e8lR_Wslu3L0j3TKR43YqexfaCBT X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori It adds application's command line parameter "--enable-graph-stats" to enable dumping graph stats on console. By default, no graph stats will be printed on console but same can be dumped via telnet session using "graph stats show" command. Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/main.c | 17 ++++++++++++++++- app/graph/module_api.h | 2 ++ doc/guides/tools/graph.rst | 4 ++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/app/graph/main.c b/app/graph/main.c index c1cb435588..465376425c 100644 --- a/app/graph/main.c +++ b/app/graph/main.c @@ -21,12 +21,13 @@ volatile bool force_quit; struct conn *conn; -static const char usage[] = "%s EAL_ARGS -- -s SCRIPT [-h HOST] [-p PORT] " +static const char usage[] = "%s EAL_ARGS -- -s SCRIPT [-h HOST] [-p PORT] [--enable-graph-stats] " "[--help]\n"; static struct app_params { struct conn_params conn; char *script_name; + bool enable_graph_stats; } app = { .conn = { .welcome = "\nWelcome!\n\n", @@ -40,6 +41,7 @@ static struct app_params { .msg_handle_arg = NULL, /* set later. */ }, .script_name = NULL, + .enable_graph_stats = false, }; static void @@ -56,6 +58,7 @@ app_args_parse(int argc, char **argv) { struct option lgopts[] = { {"help", 0, 0, 'H'}, + {"enable-graph-stats", 0, 0, 'g'}, }; int h_present, p_present, s_present, n_args, i; char *app_name = argv[0]; @@ -133,6 +136,12 @@ app_args_parse(int argc, char **argv) } break; + case 'g': + app.enable_graph_stats = true; + printf("WARNING! Telnet session can not be accessed with" + "--enable-graph-stats"); + break; + case 'H': default: printf(usage, app_name); @@ -144,6 +153,12 @@ app_args_parse(int argc, char **argv) return 0; } +bool +app_graph_stats_enabled(void) +{ + return app.enable_graph_stats; +} + bool app_graph_exit(void) { diff --git a/app/graph/module_api.h b/app/graph/module_api.h index 392dcfb222..a7d287f5c8 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -24,5 +24,7 @@ extern volatile bool force_quit; extern struct conn *conn; +bool app_graph_stats_enabled(void); bool app_graph_exit(void); + #endif diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 2c06f8e958..649e802d73 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -57,6 +57,10 @@ Following are the application command-line options: a mandatory parameter which will be used to create desired graph for a given use case. +* ``--enable-graph-stats`` + + Enable graph statistics printing on console. By default graph statistics are disabled. + * ``--help`` Dumps application usage From patchwork Tue Sep 26 10:57:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil Kumar Kori X-Patchwork-Id: 131962 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: 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]) by inbox.dpdk.org (Postfix) with ESMTP id 5DB4E42642; Tue, 26 Sep 2023 12:59:16 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7B3D140EDF; Tue, 26 Sep 2023 12:58:24 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 326B0402EB for ; Tue, 26 Sep 2023 12:58:14 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 38QA2eU5000381 for ; Tue, 26 Sep 2023 03:58:13 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=/P595fzE11TMp/kYny8oxq6sRiEY5r1lsn+PEnbiwRM=; b=Fw7Le8NbZW238I2O0we8C18+IBYroczzuallhJKssPem14ix8sHzeDZz1D5mfKYo0gO3 +MB628Qdzx1R2fn9MQiWGdK8BFLAtabdZ6QLNp6EkuVQuR5VN5WupChOObiobruRcGdj qpFK+dFWgkuAB2wxsLnjl1zxZVIzgB7VTgWXpz7Ct/7UjMGupLs/V4bkED52IutC0yxX zYrja61M4/nW5rCJVJGL4kwR64U8SppRx1Qbk3jhlkQNyLNlO64oKoGbY114KEoLhuUE hCNNKOQ33AfAtF/ygqVBldk7v8yp254gIkg5IJyIQuS7SKz58Djh2ejcDPbMo6KFZTIB NA== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3t9yhm0kgy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Tue, 26 Sep 2023 03:58:13 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 26 Sep 2023 03:58:10 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 26 Sep 2023 03:58:10 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id CFC913F70A6; Tue, 26 Sep 2023 03:58:09 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v6 12/12] app/graph: add l3fwd use case Date: Tue, 26 Sep 2023 16:27:42 +0530 Message-ID: <20230926105742.2638594-13-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230926105742.2638594-1-skori@marvell.com> References: <20230921100832.2036256-13-skori@marvell.com> <20230926105742.2638594-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: vEsh_uBMXoqxsXBFxiXxnaM-hJ7YDRR2 X-Proofpoint-ORIG-GUID: vEsh_uBMXoqxsXBFxiXxnaM-hJ7YDRR2 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-09-26_07,2023-09-25_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla It adds an use case l3fwd. It contains a dedicated l3fwd.cli file mentioning commands to configure the required resources. Once application successfully parses the l3fwd.cli then a graph is created having below nodes: - ethdev_rx -> pkt_cls - pkt_cls -> ip4_lookup - pkt_cls -> ip6_lookup - pkt_cls -> pkt_drop - ip4_lookup -> ip4_rewrite - ip4_lookup -> pkt_drop - ip6_lookup -> ip6_rewrite - ip6_lookup -> pkt_drop - ip4_rewrite -> ethdev_tx - ip4_rewrite -> pkt_drop - ip6_rewrite -> ethdev_tx - ip6_rewrite -> pkt_drop - ethdev_tx -> pkt_drop Signed-off-by: Sunil Kumar Kori Signed-off-by: Rakesh Kudurumalla --- app/graph/examples/l3fwd.cli | 87 ++++++++ app/graph/graph.c | 2 +- app/graph/l3fwd.c | 136 ++++++++++++ app/graph/l3fwd.h | 11 + app/graph/meson.build | 1 + app/graph/module_api.h | 1 + doc/guides/tools/graph.rst | 9 +- doc/guides/tools/img/graph-usecase-l3fwd.svg | 210 +++++++++++++++++++ 8 files changed, 455 insertions(+), 2 deletions(-) create mode 100644 app/graph/examples/l3fwd.cli create mode 100644 app/graph/l3fwd.c create mode 100644 app/graph/l3fwd.h create mode 100644 doc/guides/tools/img/graph-usecase-l3fwd.svg diff --git a/app/graph/examples/l3fwd.cli b/app/graph/examples/l3fwd.cli new file mode 100644 index 0000000000..1038fde04e --- /dev/null +++ b/app/graph/examples/l3fwd.cli @@ -0,0 +1,87 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2023 Marvell. + +; +; Graph configuration for given usecase +; +graph l3fwd coremask 0xff bsz 32 tmo 10 model default pcap_enable 1 num_pcap_pkts 100000 pcap_file /tmp/output.pcap + +; +; Mempools to be attached with ethdev +; +mempool mempool0 size 8192 buffers 4000 cache 256 numa 0 + +; +; DPDK devices and configuration. +; +; Note: Customize the parameters below to match your setup. +; +ethdev 0002:04:00.0 rxq 1 txq 8 mempool0 +ethdev 0002:05:00.0 rxq 1 txq 8 mempool0 +ethdev 0002:06:00.0 rxq 1 txq 8 mempool0 +ethdev 0002:07:00.0 rxq 1 txq 8 mempool0 +ethdev 0002:04:00.0 mtu 1700 +ethdev 0002:05:00.0 promiscuous on + +; +; IPv4 addresses assigned to DPDK devices +; +ethdev 0002:04:00.0 ip4 addr add 10.0.2.1 netmask 255.255.255.0 +ethdev 0002:05:00.0 ip4 addr add 20.0.2.1 netmask 255.255.255.0 +ethdev 0002:06:00.0 ip4 addr add 30.0.2.1 netmask 255.255.255.0 +ethdev 0002:07:00.0 ip4 addr add 40.0.2.1 netmask 255.255.255.0 + +; +; IPv6 addresses assigned to DPDK devices +; +ethdev 0002:04:00.0 ip6 addr add 52:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4A netmask FF:FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00 +ethdev 0002:05:00.0 ip6 addr add 62:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4B netmask FF:FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00 +ethdev 0002:06:00.0 ip6 addr add 72:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4C netmask FF:FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00 +ethdev 0002:07:00.0 ip6 addr add 82:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4D netmask FF:FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00 + +; +; IPv4 routes which are installed to ipv4_lookup node for LPM processing +; +ipv4_lookup route add ipv4 10.0.2.0 netmask 255.255.255.0 via 10.0.2.1 +ipv4_lookup route add ipv4 20.0.2.0 netmask 255.255.255.0 via 20.0.2.1 +ipv4_lookup route add ipv4 30.0.2.0 netmask 255.255.255.0 via 30.0.2.1 +ipv4_lookup route add ipv4 40.0.2.0 netmask 255.255.255.0 via 40.0.2.1 + +; +; IPv6 routes which are installed to ipv6_lookup node for LPM processing +; +ipv6_lookup route add ipv6 52:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4A netmask FF:FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00 via 52:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4A +ipv6_lookup route add ipv6 62:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4B netmask FF:FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00 via 62:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4B +ipv6_lookup route add ipv6 72:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4C netmask FF:FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00 via 72:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4C +ipv6_lookup route add ipv6 82:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4D netmask FF:FF:FF:FF:FF:FF:FF:FF:FF:00:00:00:00:00:00:00 via 82:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4D + +; +; Peer MAC and IPv4 address mapping +; +neigh add ipv4 10.0.2.2 52:20:DA:4F:68:70 +neigh add ipv4 20.0.2.2 62:20:DA:4F:68:70 +neigh add ipv4 30.0.2.2 72:20:DA:4F:68:70 +neigh add ipv4 40.0.2.2 82:20:DA:4F:68:70 + +; +; Peer MAC and IPv6 address mapping +; +neigh add ipv6 52:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4A 52:20:DA:4F:68:70 +neigh add ipv6 62:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4B 62:20:DA:4F:68:70 +neigh add ipv6 72:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4C 72:20:DA:4F:68:70 +neigh add ipv6 82:20:DA:4F:68:70:52:20:DA:4F:68:70:52:20:DA:4D 82:20:DA:4F:68:70 + +; +; Port-Queue-Core mapping for ethdev_rx node +; +ethdev_rx map port 0002:04:00.0 queue 0 core 1 +ethdev_rx map port 0002:05:00.0 queue 0 core 2 +ethdev_rx map port 0002:06:00.0 queue 0 core 3 +ethdev_rx map port 0002:07:00.0 queue 0 core 4 + +; +; Graph start command to create graph. +; +; Note: No more command should come after this. +; +graph start diff --git a/app/graph/graph.c b/app/graph/graph.c index 1e543ea7aa..f4b18051b7 100644 --- a/app/graph/graph.c +++ b/app/graph/graph.c @@ -258,7 +258,7 @@ cli_graph_start(__rte_unused void *parsed_result, __rte_unused struct cmdline *c for (i = 0; i < MAX_GRAPH_USECASES; i++) { if (!strcmp(graph_config.usecases[i].name, "l3fwd")) { if (graph_config.usecases[i].enabled) { - RTE_SET_USED(conf); + usecase_l3fwd_configure(conf, nb_conf, nb_graphs); break; } } diff --git a/app/graph/l3fwd.c b/app/graph/l3fwd.c new file mode 100644 index 0000000000..a2648df27d --- /dev/null +++ b/app/graph/l3fwd.c @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "module_api.h" + +static int +l3fwd_pattern_configure(void) +{ + /* Graph initialization. 8< */ + static const char * const default_patterns[] = { + "ip4*", + "ethdev_tx-*", + "pkt_drop", + }; + struct rte_graph_param graph_conf; + const char **node_patterns; + uint64_t pcap_pkts_count; + struct lcore_conf *qconf; + uint16_t nb_patterns; + uint8_t pcap_ena; + int rc, lcore_id; + char *pcap_file; + + nb_patterns = RTE_DIM(default_patterns); + node_patterns = malloc((ETHDEV_RX_QUEUE_PER_LCORE_MAX + nb_patterns) * + sizeof(*node_patterns)); + if (!node_patterns) + return -ENOMEM; + memcpy(node_patterns, default_patterns, + nb_patterns * sizeof(*node_patterns)); + + memset(&graph_conf, 0, sizeof(graph_conf)); + graph_conf.node_patterns = node_patterns; + + /* Pcap config */ + graph_pcap_config_get(&pcap_ena, &pcap_pkts_count, &pcap_file); + graph_conf.pcap_enable = pcap_ena; + graph_conf.num_pkt_to_capture = pcap_pkts_count; + graph_conf.pcap_filename = strdup(pcap_file); + + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + rte_graph_t graph_id; + rte_edge_t i; + + if (rte_lcore_is_enabled(lcore_id) == 0) + continue; + + qconf = &lcore_conf[lcore_id]; + + /* Skip graph creation if no source exists */ + if (!qconf->n_rx_queue) + continue; + + /* Add rx node patterns of this lcore */ + for (i = 0; i < qconf->n_rx_queue; i++) { + graph_conf.node_patterns[nb_patterns + i] = + qconf->rx_queue_list[i].node_name; + } + + graph_conf.nb_node_patterns = nb_patterns + i; + graph_conf.socket_id = rte_lcore_to_socket_id(lcore_id); + + snprintf(qconf->name, sizeof(qconf->name), "worker_%u", + lcore_id); + + graph_id = rte_graph_create(qconf->name, &graph_conf); + if (graph_id == RTE_GRAPH_ID_INVALID) + rte_exit(EXIT_FAILURE, + "rte_graph_create(): graph_id invalid" + " for lcore %u\n", lcore_id); + + qconf->graph_id = graph_id; + qconf->graph = rte_graph_lookup(qconf->name); + /* >8 End of graph initialization. */ + if (!qconf->graph) + rte_exit(EXIT_FAILURE, + "rte_graph_lookup(): graph %s not found\n", + qconf->name); + } + + rc = route_ip4_add_to_lookup(); + if (rc < 0) + rte_exit(EXIT_FAILURE, "Unable to add v4 route to lookup table\n"); + + rc = route_ip6_add_to_lookup(); + if (rc < 0) + rte_exit(EXIT_FAILURE, "Unable to add v6 route to lookup table\n"); + + rc = neigh_ip4_add_to_rewrite(); + if (rc < 0) + rte_exit(EXIT_FAILURE, "Unable to add v4 to rewrite node\n"); + + rc = neigh_ip6_add_to_rewrite(); + if (rc < 0) + rte_exit(EXIT_FAILURE, "Unable to add v6 to rewrite node\n"); + + /* Launch per-lcore init on every worker lcore */ + rte_eal_mp_remote_launch(graph_walk_start, NULL, SKIP_MAIN); + + /* Accumulate and print stats on main until exit */ + if (rte_graph_has_stats_feature() && app_graph_stats_enabled()) + graph_stats_print(); + + return rc; +} + +int +usecase_l3fwd_configure(struct rte_node_ethdev_config *conf, uint16_t nb_confs, uint16_t nb_graphs) +{ + int rc; + + rc = rte_node_eth_config(conf, nb_confs, nb_graphs); + if (rc) + rte_exit(EXIT_FAILURE, "rte_node_eth_config: err=%d\n", rc); + + rc = l3fwd_pattern_configure(); + if (rc) + rte_exit(EXIT_FAILURE, "l3fwd_pattern_failure: err=%d\n", rc); + + return rc; +} diff --git a/app/graph/l3fwd.h b/app/graph/l3fwd.h new file mode 100644 index 0000000000..e1d23165e6 --- /dev/null +++ b/app/graph/l3fwd.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_L3FWD_H +#define APP_GRAPH_L3FWD_H + +int usecase_l3fwd_configure(struct rte_node_ethdev_config *conf, uint16_t nb_conf, + uint16_t nb_graphs); + +#endif diff --git a/app/graph/meson.build b/app/graph/meson.build index 6292fc9684..d8434fc90f 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -16,6 +16,7 @@ sources = files( 'graph.c', 'ip4_route.c', 'ip6_route.c', + 'l3fwd.c', 'main.c', 'mempool.c', 'neigh.c', diff --git a/app/graph/module_api.h b/app/graph/module_api.h index a7d287f5c8..7193e0b616 100644 --- a/app/graph/module_api.h +++ b/app/graph/module_api.h @@ -13,6 +13,7 @@ #include "ethdev.h" #include "ethdev_rx.h" #include "graph.h" +#include "l3fwd.h" #include "mempool.h" #include "neigh.h" #include "route.h" diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 649e802d73..e32da251ad 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -12,7 +12,7 @@ Based on the input file, application creates a graph to cater the use case. Supported Use cases ------------------- - * + * l3fwd Running the Application ----------------------- @@ -232,3 +232,10 @@ Created graph for use case On the successful execution of ``.cli`` file, corresponding graph will be created. This section mentions the created graph for each use case. + +l3fwd +~~~~~ + +.. _figure_l3fwd_graph: + +.. figure:: img/graph-usecase-l3fwd.* diff --git a/doc/guides/tools/img/graph-usecase-l3fwd.svg b/doc/guides/tools/img/graph-usecase-l3fwd.svg new file mode 100644 index 0000000000..3b991c4cf0 --- /dev/null +++ b/doc/guides/tools/img/graph-usecase-l3fwd.svg @@ -0,0 +1,210 @@ + + + + + + + + + +dpdk_app_graph_l3fwd_nodes_flow + + + +ingress_port + +ingress_port + + + +ethdev_rx + +ethdev_rx + + + +ingress_port->ethdev_rx + + +ingress packet + + + +pkt_cls + +pkt_cls + + + +ethdev_rx->pkt_cls + + + + + +ip4_lookup + +ip4_lookup + + + +pkt_cls->ip4_lookup + + + + + +ip6_lookup + +ip6_lookup + + + +pkt_cls->ip6_lookup + + + + + +pkt_drop + +pkt_drop + + + +pkt_cls->pkt_drop + + + + + +ip4_rewrite + +ip4_rewrite + + + +ip4_lookup->ip4_rewrite + + + + + +ip4_lookup->pkt_drop + + + + + +ip6_rewrite + +ip6_rewrite + + + +ip6_lookup->ip6_rewrite + + + + + +ip6_lookup->pkt_drop + + + + + +ethdev_tx + +ethdev_tx + + + +ip4_rewrite->ethdev_tx + + + + + +ip4_rewrite->pkt_drop + + + + + +ip6_rewrite->ethdev_tx + + + + + +ip6_rewrite->pkt_drop + + + + + +ethdev_tx->pkt_drop + + + + + +egress_port + +egress_port + + + +ethdev_tx->egress_port + + +egress packet + + +