From patchwork Thu Oct 19 17:30:00 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: 133018 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 4667C431B0; Thu, 19 Oct 2023 19:30:26 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A5D0B40E03; Thu, 19 Oct 2023 19:30:23 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 81C7C40DD8 for ; Thu, 19 Oct 2023 19:30:22 +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 39JCcSYZ008128; Thu, 19 Oct 2023 10:30:21 -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=GKyr+vfdQ8Q6/SmXYy97t3qu/GPxMxA1ZSF64CIQR+E=; b=Cn3vYBYeimfNzBuexo1bWvKgzwFlT3P1OAg30fuiBiMNqqEyC9qCihYhw47eMCi/hnX9 B98i7PLE1Qkoslrbh5aeWun4m90CWrbH32WDCmfME3H4REHdCC8jXwJdhZ+TNUHupFiw a3ChYVEp20bYoJf28NnRRHDM76ST4EkupWRXKaCs+O4ppIBBIC4oT2+66wddFezZxG8C uLfTiicSBnhvRKwuxRNeT8tsmfe/+SsvHrYnPXfMZyBa99OBXEFff1P9Vtr2a5elSkJ5 Q7UGuen0MJD7RRb6Lr3eR649qyLzAiTrkrrk/K03V6i5O/7ZPho406hUAG5UG4zSC8yx Yw== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs3d-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 19 Oct 2023 10:30:21 -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; Thu, 19 Oct 2023 10:30:19 -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; Thu, 19 Oct 2023 10:30:19 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 0901A5B699A; Thu, 19 Oct 2023 10:30:16 -0700 (PDT) From: To: Thomas Monjalon , Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v11 01/12] app/graph: support application CLI framework Date: Thu, 19 Oct 2023 23:00:00 +0530 Message-ID: <20231019173011.1186656-2-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: AaUE9vnG78H1MSJyQjwqnQ5id3gDlp2y X-Proofpoint-ORIG-GUID: AaUE9vnG78H1MSJyQjwqnQ5id3gDlp2y X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori 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 Acked-By: Nithin Dabilpuram --- v10..v11 - Add information to kill telnet session in user guide. - Merge l3fwd related information in a single section in user guide. - Fix spellings. v9..v10 - Add l3fwd_pcap.cli for pcap devices. - Update table generation mechanism user guide document v8..v9: - Replace strcpy() to rte_strscpy() - Update release note. - Update user guide v7..v8: - Fix klocwork issues. v6..v7: - Fix FreeBSD build error. - Make route and neigh runtime configuration too. 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 | 115 ++++++++++++++++++++++ app/graph/cli.h | 32 +++++++ app/graph/main.c | 128 +++++++++++++++++++++++++ app/graph/meson.build | 15 +++ app/graph/module_api.h | 16 ++++ app/meson.build | 1 + doc/guides/rel_notes/release_23_11.rst | 7 ++ doc/guides/tools/graph.rst | 75 +++++++++++++++ doc/guides/tools/index.rst | 1 + 10 files changed, 397 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 4083658697..88a71d5455 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1818,6 +1818,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..df4f8fcbb8 --- /dev/null +++ b/app/graph/cli.c @@ -0,0 +1,115 @@ +/* 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; + int rc = -EINVAL; + 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 rc; + + msg_in = malloc(msg_in_len_max + 1); + msg_out = malloc(msg_out_len_max + 1); + if ((msg_in == NULL) || (msg_out == NULL)) { + rc = -ENOMEM; + goto exit; + } + + /* Open input file */ + f = fopen(file_name, "r"); + if (f == NULL) { + rc = -EIO; + goto exit; + } + + /* 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); + rc = 0; + +exit: + free(msg_out); + free(msg_in); + return rc; +} 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..ed33a04476 --- /dev/null +++ b/app/graph/meson.build @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Marvell. + +# override default name to drop the hyphen +name = 'graph' +build = cc.has_header('sys/epoll.h') +if not build + subdir_done() +endif + +deps += ['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/rel_notes/release_23_11.rst b/doc/guides/rel_notes/release_23_11.rst index 0a6fc76a9d..f43b416565 100644 --- a/doc/guides/rel_notes/release_23_11.rst +++ b/doc/guides/rel_notes/release_23_11.rst @@ -243,6 +243,13 @@ New Features Added dispatcher library which purpose is to help decouple different parts (modules) of an eventdev-based application. +* **Added CLI based graph application.** + + Added CLI based graph application which exercises on different usecases. + Application provides a framework so that each usecase can be added via CLI + file. Each CLI will further be translated into a graph representing user's + required usecase. + Removed Items ------------- diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst new file mode 100644 index 0000000000..cb005e7856 --- /dev/null +++ b/doc/guides/tools/graph.rst @@ -0,0 +1,75 @@ +.. 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. + +Also this application framework can be used by other graph based applications. + +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. + +.. table:: Exposed CLIs + :widths: auto + + +--------------------------------------+-----------------------------------+---------+----------+ + | Command | Description | Dynamic | Optional | + +======================================+===================================+=========+==========+ + | | | | | + +--------------------------------------+-----------------------------------+---------+----------+ + +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 Thu Oct 19 17:30:01 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: 133019 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 1A02E431B0; Thu, 19 Oct 2023 19:30:34 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B617840F16; Thu, 19 Oct 2023 19:30:24 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id C285440E03 for ; Thu, 19 Oct 2023 19:30:22 +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 39JCcSYa008128 for ; Thu, 19 Oct 2023 10:30:22 -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=zoNWkrJoGOy7GKeK9Lx4W2kHWcSYyoxDIocPAQ3l4Vo=; b=DeeYZeyYzs5wDgstUR2Uh/8BtTWv6Rwcxb3Ze9uCtI2udLqgr9BoGK9pdWYTnnn7+gzr 7tISqN7/3NWWC4Jh6aw943AaCUxnzgt8OX/kxY7CBinyCQSLABf4tRnSgEc3E3v+2ZQh f5lFGcW0WTtj2HlCse4Tb2LPSF2Eu5+J+13DOKYVtRCBCmoWKALncsT2bGNMBP7rUHmF /Pplxukd2XdBb1GsMhalZJqBYAx/VRSkjoWCiKPvNWozTvmQHSgL5oUR0e2PV/JgvrFq IMaPUFuynAhLtbQJfzpd4qDkqFZvD3wfmA97Gi+MYTsKOO5yGeeFWnkbCcuCXNhQc0eG hg== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs3d-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:21 -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; Thu, 19 Oct 2023 10:30:20 -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; Thu, 19 Oct 2023 10:30:20 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 217333F7094; Thu, 19 Oct 2023 10:30:18 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v11 02/12] app/graph: support telnet connectivity framework Date: Thu, 19 Oct 2023 23:00:01 +0530 Message-ID: <20231019173011.1186656-3-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: 1TBNaG1xPjCkTUqxk0BH-j43S6aQruKg X-Proofpoint-ORIG-GUID: 1TBNaG1xPjCkTUqxk0BH-j43S6aQruKg X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori 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 Acked-by: Jerin Jacob Acked-By: Nithin Dabilpuram --- app/graph/conn.c | 284 +++++++++++++++++++++++++++++++++++++ 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, 470 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..44934602c7 --- /dev/null +++ b/app/graph/conn.c @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#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 */ + rte_strscpy(conn->welcome, p->welcome, CONN_WELCOME_LEN_MAX); + rte_strscpy(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 ed33a04476..c8d2b41b69 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -11,5 +11,6 @@ endif deps += ['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 cb005e7856..943f915049 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -39,6 +39,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 @@ -67,7 +77,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 +IP 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 Thu Oct 19 17:30:02 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: 133020 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 50745431B0; Thu, 19 Oct 2023 19:30:45 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 477AF427DD; Thu, 19 Oct 2023 19:30:27 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 39489410F2 for ; Thu, 19 Oct 2023 19:30:25 +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 39JCkOAT008134 for ; Thu, 19 Oct 2023 10:30:24 -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=6c8nVKcgZl6lzsuZah0UNd/X6+dqQwLnE1YwXGSQUT8=; b=c9Z2f6HNmZ8K3m65L2M4Lsd6ulDwEiaLuAdUBadwC+9HXKwpXi84WaxDb5hjnT0pI0W1 9w171qxnHBA2cq8FvcLgcsxZ0txanR/E1d14VZ5Sati2rm4J+Em3dtgp1i8TdjRI1duK wjdvtTRz+2XzohaHm/rRgBXL/2hzfLHFYsVP5KcrJnktm9GRQIt+2y0doRK7QEgJTsia tKsTmB2ZKzYfD6a0xJ+T1uMsrCOUo2KuswjqzeF0STUUVHQyZGNoGCzxT3o0AvnW5U3B YOloifJRD/lCKlPnoTsbO2jTQ23nXcU0eNNV/B/triH7OEEpx4PfGkyNGEDkb/mHBJVh 0A== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs40-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:24 -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; Thu, 19 Oct 2023 10:30:22 -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; Thu, 19 Oct 2023 10:30:22 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 3A6613F703F; Thu, 19 Oct 2023 10:30:20 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v11 03/12] app/graph: support parser utility APIs Date: Thu, 19 Oct 2023 23:00:02 +0530 Message-ID: <20231019173011.1186656-4-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: _12rOfpkB5o3zQlTF7KwZEd14flPStOt X-Proofpoint-ORIG-GUID: _12rOfpkB5o3zQlTF7KwZEd14flPStOt X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori 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 Acked-by: Jerin Jacob Acked-By: Nithin Dabilpuram --- 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 c8d2b41b69..fd71036a95 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -13,4 +13,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 Thu Oct 19 17:30:03 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: 133021 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 B27E7431B0; Thu, 19 Oct 2023 19:30:53 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 9307742DA1; Thu, 19 Oct 2023 19:30:28 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 62A5E4281D for ; Thu, 19 Oct 2023 19:30:27 +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 39JCfFli008154 for ; Thu, 19 Oct 2023 10:30:26 -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=LPOzDsIFm54zE9E1DKR9mi8kT+q9s8IYFstrfHJ6NW0=; b=W7eRqDChBEEOkqOmrH3yxHTdD3sVpnxTaaeh6zhCYPUdL5OZTcp22F0+I8Z6wNnMEb1z glIFBn9QvPF11kXDjYyb50nz5vUR23bYtzWWE1Vna4uSiaACf43i8/ti7pu1yNfhZZmW kaI9S0KTXZ4FW62NY1S7mpaB60rFs5Bu+T4e9QUHAzd+xi9IIrx8P4TTu4XsnGG+5S/E vR8HBy4it28duLrNrL0iqOWZYvZpV23GnYBjFWZUGF7guu2hxHs/L7qmeUoHBZweRNrE QIvetbK1Ipz2PpRzPwZKEjjmWSZL8UTElevpnNwTEDA+qD51b3oVG9CCaHJEYdjEhqS+ Qw== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs4x-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:26 -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; Thu, 19 Oct 2023 10:30:24 -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; Thu, 19 Oct 2023 10:30:24 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 53D9F3F7094; Thu, 19 Oct 2023 10:30:23 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v11 04/12] app/graph: support mempool command line interfaces Date: Thu, 19 Oct 2023 23:00:03 +0530 Message-ID: <20231019173011.1186656-5-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: OtGD3CIot-Ub-FlV1aZgJZ47qGHilmQz X-Proofpoint-ORIG-GUID: OtGD3CIot-Ub-FlV1aZgJZ47qGHilmQz X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla 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 Acked-by: Jerin Jacob Acked-By: Nithin Dabilpuram --- 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 | 7 ++ 7 files changed, 210 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 df4f8fcbb8..cf544d5f8f 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..9fd3f8460b --- /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; + rte_strscpy(mpconfig.config[nb_pools].name, config->name, RTE_MEMPOOL_NAMESIZE); + 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, + 128, 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; + + + rte_strscpy(config.name, res->name, RTE_MEMPOOL_NAMESIZE); + 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 fd71036a95..5dc23c875b 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -13,5 +13,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 943f915049..6009b0c291 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -71,6 +71,13 @@ file to express the requested use case configuration. +--------------------------------------+-----------------------------------+---------+----------+ | Command | Description | Dynamic | Optional | +======================================+===================================+=========+==========+ + | | mempool size | | Command to create mempool which | No | No | + | | buffers | | will be further associated to | | | + | | | | RxQ to dequeue the packets. | | | + | | cache numa | | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | help mempool | | Command to dump mempool help | Yes | Yes | + | | | message. | | | | | | | | +--------------------------------------+-----------------------------------+---------+----------+ From patchwork Thu Oct 19 17:30:04 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: 133022 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 A831E431B0; Thu, 19 Oct 2023 19:31:01 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C92C542D68; Thu, 19 Oct 2023 19:30:30 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id CFB094161A for ; Thu, 19 Oct 2023 19:30:29 +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 39JCZ9wJ008186 for ; Thu, 19 Oct 2023 10:30:29 -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=BIqdXD0NE/d4tdzw2C2kAnzm3zT+58LJXiN29jZtt7Q=; b=ZR/6iFclEO5C3YONwns+ji7sUQq01aDQ4f4si3KnQl0Tonv1H1obz8NF3UxSCvZ53RiL ylza/jJq9qR6YdXrB8jsd7E44lxdQDK/GWykHCNWhTDbEckGXSCw8QEjOHHL5bmCV11J TmfBg0qm4CFfHwe2MwICBAGtG4jwYO0tZQO105zjhrCck2m73VRIG7KvAERj24YpiU8V jg7QXqV6IDLhKD2MSQ1dwczOz91AkJPtpmkeS15hPdBeGZ3R0pcwLnnHshTeV+PNplhu BxCi5N030dhXE7LGJwrdWjEdBEP4JA2mrZSvkyRBTgkoUp00afLa2jPrx82GkJqrL/jt Ig== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs5y-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:28 -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; Thu, 19 Oct 2023 10:30:26 -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; Thu, 19 Oct 2023 10:30:26 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 6FB433F7098; Thu, 19 Oct 2023 10:30:25 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v11 05/12] app/graph: support ethdev command line interfaces Date: Thu, 19 Oct 2023 23:00:04 +0530 Message-ID: <20231019173011.1186656-6-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: 7NS357sOcnlPHbta_ExX_h-1izF-v-Hb X-Proofpoint-ORIG-GUID: 7NS357sOcnlPHbta_ExX_h-1izF-v-Hb X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori 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 Acked-by: Jerin Jacob Acked-By: Nithin Dabilpuram --- app/graph/cli.c | 8 + app/graph/ethdev.c | 887 +++++++++++++++++++++++++++++++++++++ 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 | 50 ++- 8 files changed, 1099 insertions(+), 1 deletion(-) 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 cf544d5f8f..fa394fade6 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..8df55b4b12 --- /dev/null +++ b/app/graph/ethdev.c @@ -0,0 +1,887 @@ +/* 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_stats_help[] = "ethdev stats"; + +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; + uint16_t port_id = 0; + int numa_node, rc; + 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%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_stats_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 5dc23c875b..c17e0cc63e 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -12,6 +12,7 @@ deps += ['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 6009b0c291..5dedea97de 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -78,7 +78,39 @@ file to express the requested use case configuration. +--------------------------------------+-----------------------------------+---------+----------+ | help mempool | | Command to dump mempool help | Yes | Yes | | | | message. | | | - | | | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | | ethdev rxq | | Command to create DPDK port with| No | No | + | | txq | | given number of Rx and Tx queues| | | + | | | . Also attach RxQ with given | | | + | | | mempool. Each port can have | | | + | | | single mempool only i.e. all | | | + | | | RxQs will share the same mempool| | | + | | | . | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | ethdev mtu | | Command to configure MTU of DPDK| Yes | Yes | + | | | port. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | | ethdev promiscuous | | Command to enable/disable | Yes | Yes | + | | | | promiscuous mode on DPDK port. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | ethdev show | | Command to dump current ethdev | Yes | Yes | + | | | configuration. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | ethdev stats | | Command to dump current ethdev | Yes | Yes | + | | | statistics. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | | ethdev ip4 addr add | | Command to configure IPv4 | Yes | Yes | + | | netmask | | address on given PCI device. It | | | + | | | is needed if user wishes to use | | | + | | | ``ipv4_lookup`` node. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | | ethdev ip6 addr add | | Command to configure IPv6 | Yes | Yes | + | | netmask | | address on given PCI device. It | | | + | | | is needed if user wishes to use | | | + | | | ``ipv6_lookup`` node. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | help ethdev | | Command to dump ethdev help | Yes | Yes | + | | | message. | | | +--------------------------------------+-----------------------------------+---------+----------+ Runtime configuration @@ -113,6 +145,22 @@ 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 stats + ethdev show + graph> + +To exit the telnet session, type ``Ctrl + ]``. This changes the ``graph>`` command prompt to +``telnet>`` command prompt. Now running ``close`` or ``quit`` command on ``telnet>`` prompt +will terminate the telnet session. + Created graph for use case -------------------------- From patchwork Thu Oct 19 17:30:05 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: 133023 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 2C3B7431B0; Thu, 19 Oct 2023 19:31:12 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 38E7E42DC0; Thu, 19 Oct 2023 19:30:36 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 86AEF42DE4 for ; Thu, 19 Oct 2023 19:30:33 +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 39JCXquL008133 for ; Thu, 19 Oct 2023 10:30:32 -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=LKMOUEOgDcAqQsT6dNpJB9y8eGX4L08hYriUFHe1ClM=; b=hkokCWrVx48d4eszqQ3jJVlBxB0HF7s/eyrZ69r41/MSdbRR8d2wtGzXwVfY/Vyph+NL wn/JnT3rGcDYPGTwLBBYLzUPg0zYIbghgZEkbBuSnnATODVhCKX/r0fnqN9ml4tvMutr 2oUqd53cR7o6P+NbJStLSpYFhDrWrcUvhKfhWqbjc0WgMyj+t6mOrRFKmURl0QOT/rhf vp/U0WHkmBGgfPV3obWQ+zmGwoqD7gDd1TBbx4PAFWwW/7IJXI33RCDF4apnPGTEG1sz dfR02gu3SshtW38zJQEGtbOPIk71w7hcNQzfSOrCD1mwRcHaEbzZcf8IYAu9W0efnIBE CQ== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs6m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:32 -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; Thu, 19 Oct 2023 10:30:28 -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; Thu, 19 Oct 2023 10:30:28 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id C77E35B6926; Thu, 19 Oct 2023 10:30:27 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v11 06/12] app/graph: support IPv4 lookup command line interfaces Date: Thu, 19 Oct 2023 23:00:05 +0530 Message-ID: <20231019173011.1186656-7-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: KtD8zivDySJCVGh6EFZqUz8-Qi8aWsas X-Proofpoint-ORIG-GUID: KtD8zivDySJCVGh6EFZqUz8-Qi8aWsas X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori 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 Acked-By: Nithin Dabilpuram --- app/graph/cli.c | 2 + app/graph/ethdev.c | 2 +- app/graph/ip4_route.c | 221 +++++++++++++++++++++++++++++++++++++ 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, 305 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 fa394fade6..25785ea4dc 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 8df55b4b12..4e4d23b692 100644 --- a/app/graph/ethdev.c +++ b/app/graph/ethdev.c @@ -164,7 +164,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..db3354c270 --- /dev/null +++ b/app/graph/ip4_route.c @@ -0,0 +1,221 @@ +/* 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 +route4_rewirte_table_update(struct route_ipv4_config *ipv4route) +{ + uint8_t depth; + int portid; + + portid = ethdev_portid_by_ip4(ipv4route->via, ipv4route->netmask); + if (portid < 0) { + printf("Invalid portid found to install the route\n"); + return portid; + } + + depth = convert_netmask_to_depth(ipv4route->netmask); + + return rte_node_ip4_route_add(ipv4route->ip, depth, portid, + RTE_NODE_IP4_LOOKUP_NEXT_REWRITE); +} + +static int +route_ip4_add(struct route_ipv4_config *route) +{ + struct route_ipv4_config *ipv4route; + int rc = -EINVAL; + + 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; + + /* FIXME: Get graph status here and then update table */ + rc = route4_rewirte_table_update(ipv4route); + if (rc) + goto free; + + TAILQ_INSERT_TAIL(&route4, ipv4route, next); + return 0; +free: + free(ipv4route); + return rc; +} + +int +route_ip4_add_to_lookup(void) +{ + struct route_ipv4_config *route = NULL; + int rc = -EINVAL; + + TAILQ_FOREACH(route, &route4, next) { + rc = route4_rewirte_table_update(route); + 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 c17e0cc63e..1f35f82583 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -13,6 +13,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 5dedea97de..7530ef6f65 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -112,6 +112,15 @@ file to express the requested use case configuration. | help ethdev | | Command to dump ethdev help | Yes | Yes | | | | message. | | | +--------------------------------------+-----------------------------------+---------+----------+ + | | ipv4_lookup route add ipv4 | | Command to add a route into | Yes | Yes | + | | netmask via | | ``ipv4_lookup`` LPM table. It is| | | + | | | needed if user wishes to route | | | + | | | the packets based on LPM lookup | | | + | | | table. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | help ipv4_lookup | | Command to dump ``ipv4_lookup`` | Yes | Yes | + | | | help message. | | | + +--------------------------------------+-----------------------------------+---------+----------+ Runtime configuration --------------------- From patchwork Thu Oct 19 17:30:06 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: 133024 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 24DCB431B0; Thu, 19 Oct 2023 19:31:19 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 48E0242DF2; Thu, 19 Oct 2023 19:30:37 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id F1FE242DE6 for ; Thu, 19 Oct 2023 19:30:33 +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 39JCXquM008133 for ; Thu, 19 Oct 2023 10:30:33 -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=4juaL9QmmG+C/Qz3+YSXNDs7m7OigePsjGqLH0a0skc=; b=UtrC84pt0dA2UTDBnExW4ad6rUr+lN4a7aXRRGPkyDIwypvLG0k1toeGBh8hcKcrjWa/ GJLQwPN8IAJVw7raNU+CaslNoOUrQg8UJb5S1OkSYaJSbNCoZgFEfn/oTGCkO1dguOmv Dy2We7Bx+Bji0RkV0QU44sx5YtAg0rGAU7MFj/KniWzp0nE4zjcw/nx51mX+Zp1ViROu tBGjEbpcy/19JFXW/z7xEni//gD136RgT8i8mCT6/4MBIkgjfecjjJJrCIs8RT/O5wng 8q2CWhjWksxlvZK7UcXNpGF2wqJIwYbBwwxxudH2QLQwynbDbWkAVKVmmzR1GaFMgohK cw== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs6m-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:32 -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; Thu, 19 Oct 2023 10:30:30 -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; Thu, 19 Oct 2023 10:30:30 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id A2D703F703F; Thu, 19 Oct 2023 10:30:29 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v11 07/12] app/graph: support IPv6 lookup command line interfaces Date: Thu, 19 Oct 2023 23:00:06 +0530 Message-ID: <20231019173011.1186656-8-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: 3nhUxzGU-a7Bhm3Zq8p2UiGdxqgMJ4Ll X-Proofpoint-ORIG-GUID: 3nhUxzGU-a7Bhm3Zq8p2UiGdxqgMJ4Ll X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla 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 Acked-By: Nithin Dabilpuram --- app/graph/cli.c | 2 + app/graph/ethdev.c | 1 + app/graph/ip6_route.c | 226 +++++++++++++++++++++++++++++++++++++ app/graph/meson.build | 1 + app/graph/route.h | 14 +++ doc/guides/tools/graph.rst | 9 ++ 6 files changed, 253 insertions(+) create mode 100644 app/graph/ip6_route.c diff --git a/app/graph/cli.c b/app/graph/cli.c index 25785ea4dc..1280422388 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 4e4d23b692..e3f9ee3e0c 100644 --- a/app/graph/ethdev.c +++ b/app/graph/ethdev.c @@ -165,6 +165,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..e793cde830 --- /dev/null +++ b/app/graph/ip6_route.c @@ -0,0 +1,226 @@ +/* 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 +route6_rewirte_table_update(struct route_ipv6_config *ipv6route) +{ + uint8_t depth; + int portid; + + portid = ethdev_portid_by_ip6(ipv6route->gateway, ipv6route->mask); + if (portid < 0) { + printf("Invalid portid found to install the route\n"); + return portid; + } + depth = convert_ip6_netmask_to_depth(ipv6route->mask); + + return rte_node_ip6_route_add(ipv6route->ip, depth, portid, + RTE_NODE_IP6_LOOKUP_NEXT_REWRITE); + +} + +static int +route_ip6_add(struct route_ipv6_config *route) +{ + struct route_ipv6_config *ipv6route; + int rc = -EINVAL; + int j; + + 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; + + /* FIXME: Get graph status here and then update table */ + rc = route6_rewirte_table_update(ipv6route); + if (rc) + goto free; + + TAILQ_INSERT_TAIL(&route6, ipv6route, next); + return 0; +free: + free(ipv6route); + return rc; +} + +int +route_ip6_add_to_lookup(void) +{ + struct route_ipv6_config *route = NULL; + int rc = -EINVAL; + + TAILQ_FOREACH(route, &route6, next) { + rc = route6_rewirte_table_update(route); + 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 1f35f82583..413bbefc4e 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -14,6 +14,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 7530ef6f65..56c2eaad26 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -121,6 +121,15 @@ file to express the requested use case configuration. | help ipv4_lookup | | Command to dump ``ipv4_lookup`` | Yes | Yes | | | | help message. | | | +--------------------------------------+-----------------------------------+---------+----------+ + | | ipv6_lookup route add ipv6 | | Command to add a route into | Yes | Yes | + | | netmask via | | ``ipv6_lookup`` LPM table. It is| | | + | | | needed if user wishes to route | | | + | | | the packets based on LPM6 lookup| | | + | | | table. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | help ipv6_lookup | | Command to dump ``ipv6_lookup`` | Yes | Yes | + | | | help message. | | | + +--------------------------------------+-----------------------------------+---------+----------+ Runtime configuration --------------------- From patchwork Thu Oct 19 17:30:07 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: 133025 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 CE75E431B0; Thu, 19 Oct 2023 19:31:26 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6787042E0D; Thu, 19 Oct 2023 19:30:39 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 5E25342DC0 for ; Thu, 19 Oct 2023 19:30:35 +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 39JCcSYo008128 for ; Thu, 19 Oct 2023 10:30:34 -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=AwvdAJ9HmDFp8ZwNizJyZ+00GE8uA55Tunj3QZDppz4=; b=f29BJmoAvA8XXkl7U2Gpqa2kEf8cbqDh6kwB7QonlWPszhAFH/b9Cm1IkPrwhVYsyO5G qJOOkmxVEBcZ+3vhGLrAF6EGeMMYTl6IQpyijx0OK0YhFrX3p1URFriwXGOm5Mykl4Z7 p9HNahvl8wmZn3LZLo1S+3gN4jugdIgqpiUlnjArGlozaaAXeSl95ps6zG0Z9VwH/EQp /CxBcgYxof4VnbLOGqAwQ4qC68qBzp1JNnaVjMi9UorGE8EIPqGfcHewf1qf0c4tEyNZ yeQUKxJ9GZZE67TM7mrzLI/okUByXCtHghhIiBMYm1u9DhdPTAdyprQ4q9WkYUM64YEh SQ== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs7p-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:34 -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; Thu, 19 Oct 2023 10:30:32 -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; Thu, 19 Oct 2023 10:30:32 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 806423F7097; Thu, 19 Oct 2023 10:30:31 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v11 08/12] app/graph: support neigh command line interfaces Date: Thu, 19 Oct 2023 23:00:07 +0530 Message-ID: <20231019173011.1186656-9-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: A4irGtoi98FbQir752RVdW_uUh9dsOtw X-Proofpoint-ORIG-GUID: A4irGtoi98FbQir752RVdW_uUh9dsOtw X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori 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 Acked-By: Nithin Dabilpuram --- 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 | 358 +++++++++++++++++++++++++++++++++++++ app/graph/neigh.h | 17 ++ app/graph/neigh_priv.h | 49 +++++ doc/guides/tools/graph.rst | 11 ++ 8 files changed, 443 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 1280422388..f564362da1 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 e3f9ee3e0c..c9b09168c1 100644 --- a/app/graph/ethdev.c +++ b/app/graph/ethdev.c @@ -166,6 +166,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 413bbefc4e..8fa9d605b9 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -17,5 +17,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..0cee502719 --- /dev/null +++ b/app/graph/neigh.c @@ -0,0 +1,358 @@ +/* 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 +ip6_rewrite_node_add(struct neigh_ipv6_config *v6_config) +{ + uint8_t data[2 * RTE_ETHER_ADDR_LEN]; + uint8_t len = 2 * RTE_ETHER_ADDR_LEN; + struct rte_ether_addr smac; + int16_t portid = 0; + int rc; + + portid = ethdev_portid_by_ip6(v6_config->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 *)&v6_config->mac, RTE_ETHER_ADDR_LEN); + + /* Copy src mac */ + rc = rte_eth_macaddr_get(portid, &smac); + if (rc < 0) + return rc; + + rte_memcpy(&data[RTE_ETHER_ADDR_LEN], smac.addr_bytes, RTE_ETHER_ADDR_LEN); + + return rte_node_ip6_rewrite_add(portid, data, len, portid); +} + +static int +ip4_rewrite_node_add(struct neigh_ipv4_config *v4_config) +{ + uint8_t data[2 * RTE_ETHER_ADDR_LEN]; + uint8_t len = 2 * RTE_ETHER_ADDR_LEN; + struct rte_ether_addr smac; + int16_t portid = 0; + int rc; + + portid = ethdev_portid_by_ip4(v4_config->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 *)&v4_config->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); + + return rte_node_ip4_rewrite_add(portid, data, len, portid); +} + + +static int +neigh_ip4_add(uint32_t ip, uint64_t mac) +{ + struct neigh_ipv4_config *v4_config; + int rc = -EINVAL; + + 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; + + /* FIXME: Get graph status here and then update table */ + rc = ip4_rewrite_node_add(v4_config); + if (rc) + goto free; + + TAILQ_INSERT_TAIL(&neigh4, v4_config, next); + return 0; +free: + free(v4_config); + return rc; +} + +static int +neigh_ip6_add(uint8_t *ip, uint64_t mac) +{ + struct neigh_ipv6_config *v6_config; + int rc = -EINVAL; + int j; + + 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; + + /* FIXME: Get graph status here and then update table */ + rc = ip6_rewrite_node_add(v6_config); + if (rc) + goto free; + + TAILQ_INSERT_TAIL(&neigh6, v6_config, next); + return 0; +free: + free(v6_config); + return rc; +} + +int +neigh_ip4_add_to_rewrite(void) +{ + struct neigh_ipv4_config *neigh; + int rc; + + TAILQ_FOREACH(neigh, &neigh4, next) { + rc = ip4_rewrite_node_add(neigh); + if (rc) + return rc; + } + return 0; +} + +int +neigh_ip6_add_to_rewrite(void) +{ + struct neigh_ipv6_config *neigh; + int rc; + + + TAILQ_FOREACH(neigh, &neigh6, next) { + rc = ip6_rewrite_node_add(neigh); + if (rc < 0) + 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 56c2eaad26..b1bd2e6048 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -130,6 +130,17 @@ file to express the requested use case configuration. | help ipv6_lookup | | Command to dump ``ipv6_lookup`` | Yes | Yes | | | | help message. | | | +--------------------------------------+-----------------------------------+---------+----------+ + | neigh add ipv4 | | Command to add a neighbour | Yes | Yes | + | | | information into | | | + | | | ``ipv4_rewrite`` node. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | neigh add ipv6 | | Command to add a neighbour | Yes | Yes | + | | | information into | | | + | | | ``ipv6_rewrite`` node. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | help neigh | | Command to dump neigh help | Yes | Yes | + | | | message. | | | + +--------------------------------------+-----------------------------------+---------+----------+ Runtime configuration --------------------- From patchwork Thu Oct 19 17:30:08 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: 133026 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 F399F431B0; Thu, 19 Oct 2023 19:31:33 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 9360442E16; Thu, 19 Oct 2023 19:30:40 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 1502E42DD3 for ; Thu, 19 Oct 2023 19:30:36 +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 39JCXquT008133 for ; Thu, 19 Oct 2023 10:30:36 -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=OKX9ywoUIsXLOE6zgDplrwed78dS23CwFJP2LXCO1j4=; b=Yo3CnzCCAYah4om7gnaKbIXgiFHyxQGV5wvmjjgUOvJn/yJgGQ1y4Xih4w0X1NVka9N/ YrkpD8Ar8AAfIa7kVGbwH1qxJblE8hBf/ulj3ccLWCB0gs2IPZxO0J+GWRWsfVod2tRc oeIfXJNQPXmFeD1AYMSZFhgftT6zso773O/OeCLBc3lG8J0/8sYuYTl6M0rSDP0QnvmY 2gfu9QUcjc+g+ZtNKm4UIGGMk0BAVG08raT17A07F4GolMlRQNdERdim0DYNoMCVSQUH fqgWFIIkYC3hDoYevo0uQscP/mH0O9HTIx+QTp9pXvAOhANlEVR0INyMaEV6l9kF0RCG xQ== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs8b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:36 -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; Thu, 19 Oct 2023 10:30:34 -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; Thu, 19 Oct 2023 10:30:34 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 5C4403F709A; Thu, 19 Oct 2023 10:30:33 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v11 09/12] app/graph: support ethdev Rx command line interfaces Date: Thu, 19 Oct 2023 23:00:08 +0530 Message-ID: <20231019173011.1186656-10-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: oT4Icqx0UFKa4EYtC-Bq46c71thnvCZq X-Proofpoint-ORIG-GUID: oT4Icqx0UFKa4EYtC-Bq46c71thnvCZq X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla 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 Acked-By: Nithin Dabilpuram --- 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 f564362da1..ad7d7deadf 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 8fa9d605b9..d8391d5cae 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -12,6 +12,7 @@ deps += ['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 b1bd2e6048..318d92a0fb 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -141,6 +141,16 @@ file to express the requested use case configuration. | help neigh | | Command to dump neigh help | Yes | Yes | | | | message. | | | +--------------------------------------+-----------------------------------+---------+----------+ + | | ethdev_rx map port | | Command to add port-queue-core | No | No | + | | 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. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | help ethdev_rx | | Command to dump ethdev_rx help | Yes | Yes | + | | | message. | | | + +--------------------------------------+-----------------------------------+---------+----------+ Runtime configuration --------------------- From patchwork Thu Oct 19 17:30:09 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: 133027 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 D2C9A431B0; Thu, 19 Oct 2023 19:31:43 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E8BFD42E33; Thu, 19 Oct 2023 19:30:41 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id B427242E0F for ; Thu, 19 Oct 2023 19:30:39 +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 39JCa4FQ008125 for ; Thu, 19 Oct 2023 10:30:38 -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=Nu6DDdQdyvw1pd81LUoRhDhLtycyY39REQDbG500Gik=; b=XKBep0esqPLpgKegaArCwb3PxMCyVJYMHWcSOwNOoW+RMDX06Gnpc+TpdvnDVQ0pHAWy NAFkw8HQDbLUPxhdU6KlNRuGtMrNKxTfks4pqII7BKR12SXSCCZpOJCnQGvA7mK3gaGn gIEgEOFcfDgWPry973pb3BsC9KgmlrGJizDK5OgUM4goKucnT+HdE08xIbsKfjzMK+WD szbkZRzbfjqx6hMrEXWT7u+jAhTPQ11Fleu0LTFE3H+h2x2Z4brQOji+FnHJOKcz3JrO BwpjrqKQY8QzCl3boWERDqq3poQi75u5jfII1LTuGKJMj5qYpSeq6GKuPdHWlWDNV7TO Kw== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs8g-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:37 -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; Thu, 19 Oct 2023 10:30:36 -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; Thu, 19 Oct 2023 10:30:36 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 3BF6C3F7094; Thu, 19 Oct 2023 10:30:34 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v11 10/12] app/graph: support graph command line interfaces Date: Thu, 19 Oct 2023 23:00:09 +0530 Message-ID: <20231019173011.1186656-11-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: V9MjZs90garQIBt3J-Gq1hTw8PhLVYb0 X-Proofpoint-ORIG-GUID: V9MjZs90garQIBt3J-Gq1hTw8PhLVYb0 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla 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 Acked-By: Nithin Dabilpuram --- app/graph/cli.c | 4 + app/graph/ethdev_rx.c | 2 +- app/graph/graph.c | 550 +++++++++++++++++++++++++++++++++++++ app/graph/graph.h | 21 ++ app/graph/graph_priv.h | 70 +++++ app/graph/ip4_route.c | 5 +- app/graph/ip6_route.c | 5 +- app/graph/meson.build | 1 + app/graph/module_api.h | 1 + app/graph/neigh.c | 10 +- doc/guides/tools/graph.rst | 19 ++ 11 files changed, 683 insertions(+), 5 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 ad7d7deadf..30b12312d6 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..74a99dd68e --- /dev/null +++ b/app/graph/graph.c @@ -0,0 +1,550 @@ +/* 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; +bool graph_started; + +/* 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 status..."); + 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; + rte_strscpy(graph_config.usecases[j].name, token, 31); + 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+"); + if (fp == NULL) + rte_exit(EXIT_FAILURE, "Error in opening stats file\n"); + + 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(); +} + +bool +graph_status_get(void) +{ + return graph_started; +} + +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; + int rc = -EINVAL; + + 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; + } + } + } + + if (!rc) + graph_started = true; +} + +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 |= RTE_BIT64(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%s\n", + "----------------------------- graph command help -----------------------------", + cmd_graph_help, "graph start", "graph stats show"); + + 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..a14fa37ccd --- /dev/null +++ b/app/graph/graph.h @@ -0,0 +1,21 @@ +/* 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); +bool graph_status_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/ip4_route.c b/app/graph/ip4_route.c index db3354c270..fc83586427 100644 --- a/app/graph/ip4_route.c +++ b/app/graph/ip4_route.c @@ -97,11 +97,14 @@ route_ip4_add(struct route_ipv4_config *route) ipv4route->via = route->via; ipv4route->is_used = true; - /* FIXME: Get graph status here and then update table */ + if (!graph_status_get()) + goto exit; + rc = route4_rewirte_table_update(ipv4route); if (rc) goto free; +exit: TAILQ_INSERT_TAIL(&route4, ipv4route, next); return 0; free: diff --git a/app/graph/ip6_route.c b/app/graph/ip6_route.c index e793cde830..1fa4865220 100644 --- a/app/graph/ip6_route.c +++ b/app/graph/ip6_route.c @@ -102,11 +102,14 @@ route_ip6_add(struct route_ipv6_config *route) } ipv6route->is_used = true; - /* FIXME: Get graph status here and then update table */ + if (!graph_status_get()) + goto exit; + rc = route6_rewirte_table_update(ipv6route); if (rc) goto free; +exit: TAILQ_INSERT_TAIL(&route6, ipv6route, next); return 0; free: diff --git a/app/graph/meson.build b/app/graph/meson.build index d8391d5cae..15d16a302e 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -14,6 +14,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/app/graph/neigh.c b/app/graph/neigh.c index 0cee502719..22be7361e3 100644 --- a/app/graph/neigh.c +++ b/app/graph/neigh.c @@ -154,11 +154,14 @@ neigh_ip4_add(uint32_t ip, uint64_t mac) v4_config->mac = mac; v4_config->is_used = true; - /* FIXME: Get graph status here and then update table */ + if (!graph_status_get()) + goto exit; + rc = ip4_rewrite_node_add(v4_config); if (rc) goto free; +exit: TAILQ_INSERT_TAIL(&neigh4, v4_config, next); return 0; free: @@ -187,11 +190,14 @@ neigh_ip6_add(uint8_t *ip, uint64_t mac) v6_config->mac = mac; v6_config->is_used = true; - /* FIXME: Get graph status here and then update table */ + if (!graph_status_get()) + goto exit; + rc = ip6_rewrite_node_add(v6_config); if (rc) goto free; +exit: TAILQ_INSERT_TAIL(&neigh6, v6_config, next); return 0; free: diff --git a/doc/guides/tools/graph.rst b/doc/guides/tools/graph.rst index 318d92a0fb..08ec57b7f8 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -71,6 +71,25 @@ file to express the requested use case configuration. +--------------------------------------+-----------------------------------+---------+----------+ | Command | Description | Dynamic | Optional | +======================================+===================================+=========+==========+ + | | graph [bsz ] | | Command to express the desired | No | No | + | | [tmo ] [coremask ] | | use case. Also enables/disable | | | + | | model pcap_enable| | pcap capturing. | | | + | | <0/1> num_pcap_pkts pcap_file| | | | + | | | | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | graph start | | Command to start the graph. | No | No | + | | | 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 usecase.cli | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | graph stats show | | Command to dump current graph | Yes | Yes | + | | | statistics. | | | + +--------------------------------------+-----------------------------------+---------+----------+ + | help graph | | Command to dump graph help | Yes | Yes | + | | | message. | | | + +--------------------------------------+-----------------------------------+---------+----------+ | | mempool size | | Command to create mempool which | No | No | | | buffers | | will be further associated to | | | | | | | RxQ to dequeue the packets. | | | From patchwork Thu Oct 19 17:30:10 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: 133028 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 6FC71431B0; Thu, 19 Oct 2023 19:31:52 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 873ED42E1C; Thu, 19 Oct 2023 19:30:43 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id D964242E2B for ; Thu, 19 Oct 2023 19:30:41 +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 39JCXquU008133 for ; Thu, 19 Oct 2023 10:30:41 -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=4Mq/8hgu6tF5sfU3HoHCt9+GAQCakY3M1osrATbZk6c=; b=XR3mlNiLZz2Nj9kgsA5WC7MrrYKynM3+mQoXieNXc6ChApKujLbaVscgF4dVT59g0BqI 7I/DWBTuP6lmXa04dpRgji/a+GOLP1GslCj/geCJB3DRHjzzhHGydg6Zi8FPvWTrBBXd smY40SfF0CbQaz2AJdk7HlLpL6F9n3PP5hwPl6sPlXVwM66Y+jXnrJfVaJ3G6I9TNH+D pPbgVp/AOxS+rSLV07Z4rmpDuEamXWxNydHeM78U5Wa/7SgQRAiONMaMIL/E5yZP5UfZ RlCIEJfueaW/XUty5xfPUIT6chryamVAZTjNNUrjE+5Ulv+/4OF4cUC3ohus5vvuvyFv Qw== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs8j-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:39 -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; Thu, 19 Oct 2023 10:30:38 -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; Thu, 19 Oct 2023 10:30:38 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 12AFF3F7097; Thu, 19 Oct 2023 10:30:36 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v11 11/12] app/graph: support CLI option to enable graph stats Date: Thu, 19 Oct 2023 23:00:10 +0530 Message-ID: <20231019173011.1186656-12-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: a23qHt75I5j3fZ1oos49tK2nSgN-sqDO X-Proofpoint-ORIG-GUID: a23qHt75I5j3fZ1oos49tK2nSgN-sqDO X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Sunil Kumar Kori 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 Acked-by: Jerin Jacob Acked-By: Nithin Dabilpuram --- 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 08ec57b7f8..bd8611a3d0 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -55,6 +55,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 Thu Oct 19 17:30:11 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: 133029 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 D72A4431B0; Thu, 19 Oct 2023 19:31:58 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A6FEF42E3F; Thu, 19 Oct 2023 19:30:48 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id A620E42E49 for ; Thu, 19 Oct 2023 19:30:43 +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 39JCa4FS008125 for ; Thu, 19 Oct 2023 10:30:42 -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=yAuBGkGvWo0MKPjiHdtD+w+5sc7AV781DxRmFADBr3w=; b=Zh1EHBLsUSB2lLGPbYEJP+RqT8epysOqj3Vb54/acnG0xTVTDQZSk7NVBoVJ9VlyMKHv kBsQ3sE7honJ0JWEGIIysXAGztGdfk1y5BhuAGqkZj4Hk8y4CoS9zzd07mONuS7HBrWv opzxKC5dTjVFW8P4vKJl3UCsRauM9yz9P7MQprCKA10BDrKxjcPQ6HsjdOZmUh8g2Fzt eeZZvOUBXolqyhZrJzZ8YdZRBj8+1Wf3Uyfoh+DwmHiqQYNJ+lrXxtIsD0TGLHpXuIGu nrwepa4MAuKsmHxT8GqtqUMXMN45x4ASjeqF3Lwy/g4Ndewu463FBmUJzZw4Gzlo6Jaq hA== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshubs8q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 10:30:42 -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; Thu, 19 Oct 2023 10:30:40 -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; Thu, 19 Oct 2023 10:30:40 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 2D97C3F7098; Thu, 19 Oct 2023 10:30:38 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v11 12/12] app/graph: support l3fwd use case Date: Thu, 19 Oct 2023 23:00:11 +0530 Message-ID: <20231019173011.1186656-13-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019173011.1186656-1-skori@marvell.com> References: <20231019105000.520914-13-skori@marvell.com> <20231019173011.1186656-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: J7rhqU2oayenSn-cMrX-2NrVjzuft6V1 X-Proofpoint-ORIG-GUID: J7rhqU2oayenSn-cMrX-2NrVjzuft6V1 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-10-19_16,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Rakesh Kudurumalla 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 Acked-by: Jerin Jacob --- app/graph/examples/l3fwd.cli | 73 +++++++ app/graph/examples/l3fwd_pcap.cli | 71 +++++++ 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 | 84 ++++++++ doc/guides/tools/img/graph-usecase-l3fwd.svg | 210 +++++++++++++++++++ 9 files changed, 588 insertions(+), 1 deletion(-) create mode 100644 app/graph/examples/l3fwd.cli create mode 100644 app/graph/examples/l3fwd_pcap.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..c4977d4322 --- /dev/null +++ b/app/graph/examples/l3fwd.cli @@ -0,0 +1,73 @@ +; 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:02:00.0 rxq 1 txq 8 mempool0 +ethdev 0002:03:00.0 rxq 1 txq 8 mempool0 +ethdev 0002:02:00.0 mtu 1700 +ethdev 0002:03:00.0 mtu 1700 +ethdev 0002:02:00.0 promiscuous on +ethdev 0002:03:00.0 promiscuous on + +; +; IPv4 addresses assigned to DPDK devices +; +ethdev 0002:02:00.0 ip4 addr add 10.0.2.1 netmask 255.255.255.0 +ethdev 0002:03:00.0 ip4 addr add 20.0.2.1 netmask 255.255.255.0 + +; +; IPv6 addresses assigned to DPDK devices +; +ethdev 0002:02: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:03: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 + +; +; 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 + +; +; 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 + +; +; 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 + +; +; 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 + +; +; Port-Queue-Core mapping for ethdev_rx node +; +ethdev_rx map port 0002:02:00.0 queue 0 core 1 +ethdev_rx map port 0002:03:00.0 queue 0 core 2 + +; +; Graph start command to create graph. +; +; Note: No more command should come after this. +; +graph start diff --git a/app/graph/examples/l3fwd_pcap.cli b/app/graph/examples/l3fwd_pcap.cli new file mode 100644 index 0000000000..30dde74a65 --- /dev/null +++ b/app/graph/examples/l3fwd_pcap.cli @@ -0,0 +1,71 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2023 Marvell. + +; +; Graph configuration for given usecase +; +graph l3fwd coremask 0x03 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 net_pcap0 rxq 1 txq 1 mempool0 +ethdev net_pcap1 rxq 1 txq 1 mempool0 +ethdev net_pcap0 promiscuous on +ethdev net_pcap1 promiscuous on + +; +; IPv4 addresses assigned to DPDK devices +; +ethdev net_pcap0 ip4 addr add 10.0.2.1 netmask 255.255.255.0 +ethdev net_pcap1 ip4 addr add 20.0.2.1 netmask 255.255.255.0 + +; +; IPv6 addresses assigned to DPDK devices +; +ethdev net_pcap0 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 net_pcap1 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 + +; +; 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 + +; +; 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 + +; +; 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 + +; +; 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 + +; +; Port-Queue-Core mapping for ethdev_rx node +; +ethdev_rx map port net_pcap0 queue 0 core 1 +ethdev_rx map port net_pcap1 queue 0 core 1 + +; +; 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 74a99dd68e..a65723a196 100644 --- a/app/graph/graph.c +++ b/app/graph/graph.c @@ -269,7 +269,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); + rc = 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 15d16a302e..5b0f966d99 100644 --- a/app/graph/meson.build +++ b/app/graph/meson.build @@ -17,6 +17,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 bd8611a3d0..2c04531552 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -63,6 +63,83 @@ Following are the application command-line options: Dumps application usage +Supported Use cases +------------------- + * l3fwd + +l3fwd +~~~~~ + +This use case is supported for both H/W and PCAP vdev network devices. To demonstrate, +corresponding .cli files are available at ```` +named as ``l3fwd.cli`` and ``l3fwd_pcap.cli`` respectively. + +Example Commands +^^^^^^^^^^^^^^^^ +For H/W devices + +.. code-block:: console + + ./dpdk-graph -c 0xff -a 0002:02:00.0 -a 0002:03:00.0 -- + -s /app/graph/examples/l3fwd.cli + +For net_pcapX devices + +.. code-block:: console + + ./dpdk-graph -c 0xff --vdev=net_pcap0,rx_pcap=in_net_pcap0.pcap,tx_pcap=out_net_pcap1.pcap + --vdev=net_pcap1,rx_pcap=in_net_pcap1.pcap,tx_pcap=out_net_pcap0.pcap + -- -s /app/graph/examples/l3fwd_pcap.cli + +Verifying traffic +^^^^^^^^^^^^^^^^^ + +``l3fwd.cli`` and ``l3fwd_pcap.cli`` creates setup with two network ports. Routing between +these ports are done by lookup node routing information. For current use case, following +routing table is used: + +.. code-block:: console + + DIP port + 10.0.2.2 1 + 20.0.2.2 0 + +On the successful execution of ``l3fwd.cli`` or ``l3fwd_pcap.cli``, user needs to send traffic +with mentioned DIP. + +For net_pcapX devices, required pcap file should be created and passed to application. These +pcap files can be created in several ways. Scapy is one of the method to get the same: + +.. code-block:: console + + # scapy + >>> pkts=[Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="10.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="10.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="10.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="10.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="10.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="10.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="10.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="10.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="10.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="10.0.2.2")] + >>> + >>> wrpcap("in_net_pcap1.pcap",pkts) + >>> + >>> pkts=[Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="29.0.0.1", dst="20.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="29.0.0.1", dst="20.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="29.0.0.1", dst="20.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="29.0.0.1", dst="20.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="29.0.0.1", dst="20.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="29.0.0.1", dst="20.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="29.0.0.1", dst="20.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="29.0.0.1", dst="20.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="29.0.0.1", dst="20.0.2.2"), + Ether(dst="FA:09:F9:D7:E0:9D", src="10:70:1d:2f:42:2d")/IP(src="28.0.0.1", dst="20.0.2.2")] + >>> + >>> wrpcap("in_net_pcap0.pcap",pkts) + >>> quit + Supported CLI commands ---------------------- @@ -228,3 +305,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 + + +