From patchwork Thu Oct 19 10:49:49 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: 132973 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 6825F431A9; Thu, 19 Oct 2023 12:50:17 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6E72E40E6E; Thu, 19 Oct 2023 12:50:11 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 7EC6A406BA for ; Thu, 19 Oct 2023 12:50:10 +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 39J01WH4008133; Thu, 19 Oct 2023 03:50:09 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=rBXTWausK3POv3JrFpKZZWAaFNfcKBkcJYzge8gz19o=; b=kjPqYkz3niulkzP8+I/rVsvH0Kpp/iS1VslQ+5734GZy+qGWZo1UodXOVetYQyhELNqV oKPGSynxFO5F1wWQKxXjIHbEp9xGLZp6cO3e1XtW/LUQmXPmPoIPe8Sjx/aGSu05dhON gW+7NgCE08jJSWYKDkYA4nogWIpfkedkSjrpNfUqQoePR2tWkizKnfwlTM6ceOH1kXqg 1eBvlW5N8h6dYXxCUv2PhJxeYe656wTtTJ5zNOQ9aHiE+2cyrudfh4g0MOl7F1MfCen6 eOPiIVJMYQpjKpJ8LYzVmBEyRSgSkNb8MolUAoW+w1pFB0fzrpmOI/FIbOvoMp1uH3Yi ow== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshua3bk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 19 Oct 2023 03:50:09 -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 03:50:07 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Thu, 19 Oct 2023 03:50:07 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 033715B6958; Thu, 19 Oct 2023 03:50:05 -0700 (PDT) From: To: Thomas Monjalon , Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v10 01/12] app/graph: support application CLI framework Date: Thu, 19 Oct 2023 16:19:49 +0530 Message-ID: <20231019105000.520914-2-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: pAaFyYrHYcRQAgY5VI1LtcsmBQ5RuhAH X-Proofpoint-ORIG-GUID: pAaFyYrHYcRQAgY5VI1LtcsmBQ5RuhAH 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- 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 10:49:50 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: 132974 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 4CD41431A9; Thu, 19 Oct 2023 12:50:25 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 82FAF40EE7; Thu, 19 Oct 2023 12:50:13 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id CE1CC40EE4 for ; Thu, 19 Oct 2023 12:50:12 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39J6Z5Pj013930 for ; Thu, 19 Oct 2023 03:50:12 -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=W0xkvjeZGhnUVz64UhBvqSp59QqVJ9/KN9M9oDoAGqLowqGggqtGqXBHyUa76WlF7JPS hPVVAuJu+KDgt0CFR48/6DGpjD6E8AMWoYtKG3U3m/+Bgsf9REXWPrBcl+IW1XlQtsx9 csO7PNoJNAvGGTQkxuh4LVnbiN7aQIcw87ynjF/FAnrTIIMhOhTzR8ChdWC5dSn1afMk YJ9+3DsRU2+dbdp/06IUBONsefWsZC1Y0+2W9n3iianL5z8T+TmHlr1d0olQPUTwInxW OJqinyNXZqq3LT/ne8jf82azmvhG7cj/d/w5hNxwwHE8D5q6lpvpM3knxuVQtYdhLJ23 Ag== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3tstb41v4j-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50:11 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Thu, 19 Oct 2023 03:50:09 -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 03:50:09 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 1FE775B6926; Thu, 19 Oct 2023 03:50:07 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v10 02/12] app/graph: support telnet connectivity framework Date: Thu, 19 Oct 2023 16:19:50 +0530 Message-ID: <20231019105000.520914-3-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: thJKoyNKSGaSJu1GhZabXWw_7a2zOz0E X-Proofpoint-GUID: thJKoyNKSGaSJu1GhZabXWw_7a2zOz0E 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- 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 10:49:51 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: 132975 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 20CCD431A9; Thu, 19 Oct 2023 12:50:35 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id D948D41149; Thu, 19 Oct 2023 12:50:15 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 0759D410F2 for ; Thu, 19 Oct 2023 12:50:14 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39J8fCku027267 for ; Thu, 19 Oct 2023 03:50:14 -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=Idxtzl8RWMlrsVr/FrJywQGDv0HFxtaSfiG8IBYEmAVc9GIs55FQq2gEEtW07m8KJE5P KmJAewrg/oXUEgZ0GdPfB4VC0prFYly4GeSzJch1fQdSOGcc/XCddqUkGh2XTrbp+7tl 0v8lXA/dWlisS1ouyioSDqEKFIVZ8A44myZy5Q6iseVyfDCL/cvc0HFp6aA2PojCtloi 0IK3p8brquAvFtFtaUaLMfrcAnQJ2Li0J8/9xSZYZZSO25dtxWGmNdHcnE5G0DunQaqx uvzCL4vle/JsKTfK9+DcWyOM2leVUoriyZtT9C8viol6CGxDvGbtYwKIBYQ6yZcpXB01 IA== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3tstb41v4s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50:13 -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 03:50:11 -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 03:50:11 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 3A7365B6958; Thu, 19 Oct 2023 03:50:09 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v10 03/12] app/graph: support parser utility APIs Date: Thu, 19 Oct 2023 16:19:51 +0530 Message-ID: <20231019105000.520914-4-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: 7m0dfmcrSxMANZmssL1HNc6WllAWZ32T X-Proofpoint-GUID: 7m0dfmcrSxMANZmssL1HNc6WllAWZ32T 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- 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 10:49:52 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: 132976 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 91AB9431A9; Thu, 19 Oct 2023 12:50:42 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E29D642686; Thu, 19 Oct 2023 12:50:16 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 1792141611 for ; Thu, 19 Oct 2023 12:50:16 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39J8fCkw027267 for ; Thu, 19 Oct 2023 03:50:15 -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=c3tOaNP3FVzcO+RKd4pmpnQQFiMf3gDuHLTci84zZ6zYBiRtI9VTP0zDMuY1bYt0hMDZ 7DVGEHoP5FnFFSn+XKhovCzIbgmE73juMCscY0Wk+r8aba1XDBPdjHfAGAtlSDe5OtSK s1VCcrqeRXqS4GBpKiaKD5+HxOw+8Ofo34Tn2oOWLeMZLqR2cuaRsuC0k0cMlF0Tb4U/ Pgv1rIdwQJyTIfjujU3zBWqorczM9/AfxP0C4mUMqhMAQ4GQA/FsIy30mJAFQJq8e1P+ dP+oJY/8fcrLg1yN8AJ19T0dFur094V5+chnU+lxCm15nhJ2IZoXuy52ST9qgvUNJc62 ig== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3tstb41v4s-3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50:15 -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 03:50:13 -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 03:50:13 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 585A05B6926; Thu, 19 Oct 2023 03:50:12 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v10 04/12] app/graph: support mempool command line interfaces Date: Thu, 19 Oct 2023 16:19:52 +0530 Message-ID: <20231019105000.520914-5-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: rjvvs-KGlDLtWXrdX5UT77w-EJZDw7lj X-Proofpoint-GUID: rjvvs-KGlDLtWXrdX5UT77w-EJZDw7lj 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- 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 10:49:53 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: 132977 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 82D84431A9; Thu, 19 Oct 2023 12:50:50 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 28D9C410F2; Thu, 19 Oct 2023 12:50:21 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 671B54021F for ; Thu, 19 Oct 2023 12:50:19 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39INWtrq018791 for ; Thu, 19 Oct 2023 03:50:18 -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=TQX6bmjhTRYVxe26d9QN083pLVit/Fh8kA7ji7eVVew=; b=XzlbTuZh9HdKP0QJwHkZFij1mGB6CtbkkaT5pgFG3I0uDL8YEPRy8NIdBe3QSg0dc5k4 MfNk3HCblVg7JVT7C5rf0JAvPKEJGiiMy7tqXfjE3NGjvQmBrk9/qwSJkERK53/SPCJu bMEyUb3Fy4hpyGqD51fxGBznDdXj+Qh2unuMQ1Oh0+kboLm3HU10RVb4VUAcAhusU8wZ CM3U8Yb4hIIUmFQ2tNQ+WzDBSxXI7j8cMhJVXL6eqQWk6A2TGedNJLxzdi51eDEaME4u jyNTLwxhrUfnJxOGV5QAbi05Z4tAsnpMH55vZG7h1PRfNyRS6mXQ/S0dS2qKfqHGbZB/ ZQ== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3tstb41v5n-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50:18 -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 03:50:16 -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 03:50:16 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 73A4A5B6953; Thu, 19 Oct 2023 03:50:14 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v10 05/12] app/graph: support ethdev command line interfaces Date: Thu, 19 Oct 2023 16:19:53 +0530 Message-ID: <20231019105000.520914-6-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: 8qaHFZL9Ad4EzhuEffNEgOogieDzjZpD X-Proofpoint-GUID: 8qaHFZL9Ad4EzhuEffNEgOogieDzjZpD 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- app/graph/cli.c | 8 + app/graph/ethdev.c | 882 +++++++++++++++++++++++++++++++++++++ app/graph/ethdev.h | 40 ++ app/graph/ethdev_priv.h | 112 +++++ app/graph/main.c | 1 + app/graph/meson.build | 1 + app/graph/module_api.h | 1 + doc/guides/tools/graph.rst | 45 +- 8 files changed, 1089 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..74e80679d9 --- /dev/null +++ b/app/graph/ethdev.c @@ -0,0 +1,882 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ethdev_priv.h" +#include "module_api.h" + +static const char +cmd_ethdev_mtu_help[] = "ethdev mtu "; + +static const char +cmd_ethdev_prom_mode_help[] = "ethdev promiscuous "; + +static const char +cmd_ethdev_help[] = "ethdev rxq txq "; +static const char +cmd_ethdev_show_help[] = "ethdev show"; + +static const char +cmd_ethdev_ip4_addr_help[] = "ethdev ip4 addr add netmask "; + +static const char +cmd_ethdev_ip6_addr_help[] = "ethdev ip6 addr add netmask "; + +static struct rte_eth_conf port_conf_default = { + .link_speeds = 0, + .rxmode = { + .mq_mode = RTE_ETH_MQ_RX_NONE, + .mtu = 9000 - (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN), /* Jumbo frame MTU */ + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_key_len = 40, + .rss_hf = 0, + }, + }, + .txmode = { + .mq_mode = RTE_ETH_MQ_TX_NONE, + }, + .lpbk_mode = 0, +}; + +uint32_t enabled_port_mask; +static struct ethdev_head eth_node = TAILQ_HEAD_INITIALIZER(eth_node); + + +static struct ethdev* +ethdev_port_by_id(uint16_t port_id) +{ + struct ethdev *port; + + TAILQ_FOREACH(port, ð_node, next) { + if (port->config.port_id == port_id) + return port; + } + return NULL; +} + +void * +ethdev_mempool_list_by_portid(uint16_t portid) +{ + struct ethdev *port; + + if (portid >= RTE_MAX_ETHPORTS) + return NULL; + + port = ethdev_port_by_id(portid); + if (port) + return &(port->config.rx.mp); + else + return NULL; +} + +int16_t +ethdev_portid_by_ip4(uint32_t ip, uint32_t mask) +{ + int portid = -EINVAL; + struct ethdev *port; + + TAILQ_FOREACH(port, ð_node, next) { + if (mask == 0) { + if ((port->ip4_addr.ip & port->ip4_addr.mask) == (ip & port->ip4_addr.mask)) + return port->config.port_id; + } else { + if ((port->ip4_addr.ip & port->ip4_addr.mask) == (ip & mask)) + return port->config.port_id; + } + } + + return portid; +} + +int16_t +ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask) +{ + int portid = -EINVAL; + struct ethdev *port; + int j; + + TAILQ_FOREACH(port, ð_node, next) { + for (j = 0; j < ETHDEV_IPV6_ADDR_LEN; j++) { + if (mask == NULL) { + if ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) != + (ip[j] & port->ip6_addr.mask[j])) + break; + + } else { + if ((port->ip6_addr.ip[j] & port->ip6_addr.mask[j]) != + (ip[j] & mask[j])) + break; + } + } + if (j == ETHDEV_IPV6_ADDR_LEN) + return port->config.port_id; + } + + return portid; +} + +void +ethdev_list_clean(void) +{ + struct ethdev *port; + + while (!TAILQ_EMPTY(ð_node)) { + port = TAILQ_FIRST(ð_node); + TAILQ_REMOVE(ð_node, port, next); + } +} + +void +ethdev_stop(void) +{ + uint16_t portid; + int rc; + + RTE_ETH_FOREACH_DEV(portid) { + if ((enabled_port_mask & (1 << portid)) == 0) + continue; + printf("Closing port %d...", portid); + rc = rte_eth_dev_stop(portid); + if (rc != 0) + printf("Failed to stop port %u: %s\n", + portid, rte_strerror(-rc)); + rte_eth_dev_close(portid); + printf(" Done\n"); + } + + ethdev_list_clean(); + rte_eal_cleanup(); + printf("Bye...\n"); +} + +void +ethdev_start(void) +{ + uint16_t portid; + int rc; + + RTE_ETH_FOREACH_DEV(portid) + { + if ((enabled_port_mask & (1 << portid)) == 0) + continue; + + rc = rte_eth_dev_start(portid); + if (rc < 0) + rte_exit(EXIT_FAILURE, "rte_eth_dev_start: err=%d, port=%d\n", rc, portid); + } +} + + +static int +ethdev_show(const char *name) +{ + uint16_t mtu = 0, port_id = 0; + struct rte_eth_dev_info info; + struct rte_eth_stats stats; + struct rte_ether_addr addr; + struct rte_eth_link link; + uint32_t length; + int rc; + + rc = rte_eth_dev_get_port_by_name(name, &port_id); + if (rc < 0) + return rc; + + rte_eth_dev_info_get(port_id, &info); + rte_eth_stats_get(port_id, &stats); + rte_eth_macaddr_get(port_id, &addr); + rte_eth_link_get(port_id, &link); + rte_eth_dev_get_mtu(port_id, &mtu); + + length = strlen(conn->msg_out); + conn->msg_out += length; + snprintf(conn->msg_out, conn->msg_out_len_max, + "%s: flags=<%s> mtu %u\n" + "\tether " RTE_ETHER_ADDR_PRT_FMT " rxqueues %u txqueues %u\n" + "\tport# %u speed %s\n" + "\tRX packets %" PRIu64" bytes %" PRIu64"\n" + "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n" + "\tTX packets %" PRIu64" bytes %" PRIu64"\n" + "\tTX errors %" PRIu64"\n\n", + name, + link.link_status ? "UP" : "DOWN", + mtu, + RTE_ETHER_ADDR_BYTES(&addr), + info.nb_rx_queues, + info.nb_tx_queues, + port_id, + rte_eth_link_speed_to_str(link.link_speed), + stats.ipackets, + stats.ibytes, + stats.ierrors, + stats.imissed, + stats.rx_nombuf, + stats.opackets, + stats.obytes, + stats.oerrors); + + length = strlen(conn->msg_out); + conn->msg_out_len_max -= length; + return 0; +} + +static int +ethdev_ip4_addr_add(const char *name, struct ipv4_addr_config *config) +{ + struct ethdev *eth_hdl; + uint16_t portid = 0; + int rc; + + rc = rte_eth_dev_get_port_by_name(name, &portid); + if (rc < 0) + return rc; + + eth_hdl = ethdev_port_by_id(portid); + + if (eth_hdl) { + eth_hdl->ip4_addr.ip = config->ip; + eth_hdl->ip4_addr.mask = config->mask; + return 0; + } + + rc = -EINVAL; + return rc; +} + +static int +ethdev_ip6_addr_add(const char *name, struct ipv6_addr_config *config) +{ + struct ethdev *eth_hdl; + uint16_t portid = 0; + int rc, i; + + rc = rte_eth_dev_get_port_by_name(name, &portid); + if (rc < 0) + return rc; + + eth_hdl = ethdev_port_by_id(portid); + + if (eth_hdl) { + for (i = 0; i < ETHDEV_IPV6_ADDR_LEN; i++) { + eth_hdl->ip6_addr.ip[i] = config->ip[i]; + eth_hdl->ip6_addr.mask[i] = config->mask[i]; + } + return 0; + } + rc = -EINVAL; + return rc; +} + +static int +ethdev_prom_mode_config(const char *name, bool enable) +{ + struct ethdev *eth_hdl; + uint16_t portid = 0; + int rc; + + rc = rte_eth_dev_get_port_by_name(name, &portid); + if (rc < 0) + return rc; + + eth_hdl = ethdev_port_by_id(portid); + + if (eth_hdl) { + if (enable) + rc = rte_eth_promiscuous_enable(portid); + else + rc = rte_eth_promiscuous_disable(portid); + if (rc < 0) + return rc; + + eth_hdl->config.promiscuous = enable; + return 0; + } + + rc = -EINVAL; + return rc; +} + +static int +ethdev_mtu_config(const char *name, uint32_t mtu) +{ + struct ethdev *eth_hdl; + uint16_t portid = 0; + int rc; + + rc = rte_eth_dev_get_port_by_name(name, &portid); + if (rc < 0) + return rc; + + eth_hdl = ethdev_port_by_id(portid); + + if (eth_hdl) { + rc = rte_eth_dev_set_mtu(portid, mtu); + if (rc < 0) + return rc; + + eth_hdl->config.mtu = mtu; + return 0; + } + + rc = -EINVAL; + return rc; +} + + +static int +ethdev_process(const char *name, struct ethdev_config *params) +{ + struct rte_eth_dev_info port_info; + struct rte_eth_conf port_conf; + struct ethdev_rss_config *rss; + struct rte_mempool *mempool; + struct ethdev *ethdev_port; + struct rte_ether_addr smac; + 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", + "----------------------------- ethdev command help -----------------------------", + cmd_ethdev_help, cmd_ethdev_ip4_addr_help, cmd_ethdev_ip6_addr_help, + cmd_ethdev_prom_mode_help, cmd_ethdev_mtu_help, cmd_ethdev_show_help); + + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; +} + +cmdline_parse_token_string_t ethdev_stats_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_stats_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_stats_stats = + TOKEN_STRING_INITIALIZER(struct ethdev_stats_cmd_tokens, stats, "stats"); + +cmdline_parse_inst_t ethdev_stats_cmd_ctx = { + .f = cli_ethdev_stats, + .data = NULL, + .help_str = "", + .tokens = { + (void *)ðdev_stats_cmd, + (void *)ðdev_stats_dev, + (void *)ðdev_stats_stats, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_show_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_show_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_show_show = + TOKEN_STRING_INITIALIZER(struct ethdev_show_cmd_tokens, show, "show"); + +cmdline_parse_inst_t ethdev_show_cmd_ctx = { + .f = cli_ethdev_show, + .data = NULL, + .help_str = cmd_ethdev_show_help, + .tokens = { + (void *)ðdev_show_cmd, + (void *)ðdev_show_dev, + (void *)ðdev_show_show, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_mtu_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_mtu_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_mtu_mtu = + TOKEN_STRING_INITIALIZER(struct ethdev_mtu_cmd_tokens, mtu, "mtu"); +cmdline_parse_token_num_t ethdev_mtu_size = + TOKEN_NUM_INITIALIZER(struct ethdev_mtu_cmd_tokens, size, RTE_UINT16); + +cmdline_parse_inst_t ethdev_mtu_cmd_ctx = { + .f = cli_ethdev_mtu, + .data = NULL, + .help_str = cmd_ethdev_mtu_help, + .tokens = { + (void *)ðdev_mtu_cmd, + (void *)ðdev_mtu_dev, + (void *)ðdev_mtu_mtu, + (void *)ðdev_mtu_size, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_prom_mode_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_prom_mode_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_prom_mode_prom = + TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, prom, "promiscuous"); +cmdline_parse_token_string_t ethdev_prom_mode_enable = + TOKEN_STRING_INITIALIZER(struct ethdev_prom_mode_cmd_tokens, enable, "on#off"); + +cmdline_parse_inst_t ethdev_prom_mode_cmd_ctx = { + .f = cli_ethdev_prom_mode, + .data = NULL, + .help_str = cmd_ethdev_prom_mode_help, + .tokens = { + (void *)ðdev_prom_mode_cmd, + (void *)ðdev_prom_mode_dev, + (void *)ðdev_prom_mode_prom, + (void *)ðdev_prom_mode_enable, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_ip4_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_ip4_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_ip4_ip4 = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, ip4, "ip4"); +cmdline_parse_token_string_t ethdev_ip4_addr = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, addr, "addr"); +cmdline_parse_token_string_t ethdev_ip4_add = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, add, "add"); +cmdline_parse_token_string_t ethdev_ip4_ip = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, ip, NULL); +cmdline_parse_token_string_t ethdev_ip4_netmask = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, netmask, "netmask"); +cmdline_parse_token_string_t ethdev_ip4_mask = + TOKEN_STRING_INITIALIZER(struct ethdev_ip4_cmd_tokens, mask, NULL); + +cmdline_parse_inst_t ethdev_ip4_cmd_ctx = { + .f = cli_ip4_addr, + .data = NULL, + .help_str = cmd_ethdev_ip4_addr_help, + .tokens = { + (void *)ðdev_ip4_cmd, + (void *)ðdev_ip4_dev, + (void *)ðdev_ip4_ip4, + (void *)ðdev_ip4_addr, + (void *)ðdev_ip4_add, + (void *)ðdev_ip4_ip, + (void *)ðdev_ip4_netmask, + (void *)ðdev_ip4_mask, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_ip6_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_ip6_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_ip6_ip6 = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, ip6, "ip6"); +cmdline_parse_token_string_t ethdev_ip6_addr = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, addr, "addr"); +cmdline_parse_token_string_t ethdev_ip6_add = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, add, "add"); +cmdline_parse_token_string_t ethdev_ip6_ip = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, ip, NULL); +cmdline_parse_token_string_t ethdev_ip6_netmask = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, netmask, "netmask"); +cmdline_parse_token_string_t ethdev_ip6_mask = + TOKEN_STRING_INITIALIZER(struct ethdev_ip6_cmd_tokens, mask, NULL); + +cmdline_parse_inst_t ethdev_ip6_cmd_ctx = { + .f = cli_ip6_addr, + .data = NULL, + .help_str = cmd_ethdev_ip6_addr_help, + .tokens = { + (void *)ðdev_ip6_cmd, + (void *)ðdev_ip6_dev, + (void *)ðdev_ip6_ip6, + (void *)ðdev_ip6_addr, + (void *)ðdev_ip6_add, + (void *)ðdev_ip6_ip, + (void *)ðdev_ip6_netmask, + (void *)ðdev_ip6_mask, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, cmd, "ethdev"); +cmdline_parse_token_string_t ethdev_dev = + TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, dev, NULL); +cmdline_parse_token_string_t ethdev_rxq = + TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, rxq, "rxq"); +cmdline_parse_token_num_t ethdev_nb_rxq = + TOKEN_NUM_INITIALIZER(struct ethdev_cmd_tokens, nb_rxq, RTE_UINT16); +cmdline_parse_token_string_t ethdev_txq = + TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, txq, "txq"); +cmdline_parse_token_num_t ethdev_nb_txq = + TOKEN_NUM_INITIALIZER(struct ethdev_cmd_tokens, nb_txq, RTE_UINT16); +cmdline_parse_token_string_t ethdev_mempool = + TOKEN_STRING_INITIALIZER(struct ethdev_cmd_tokens, mempool, NULL); + +cmdline_parse_inst_t ethdev_cmd_ctx = { + .f = cli_ethdev, + .data = NULL, + .help_str = cmd_ethdev_help, + .tokens = { + (void *)ðdev_cmd, + (void *)ðdev_dev, + (void *)ðdev_rxq, + (void *)ðdev_nb_rxq, + (void *)ðdev_txq, + (void *)ðdev_nb_txq, + (void *)ðdev_mempool, + NULL, + }, +}; + +cmdline_parse_token_string_t ethdev_help_cmd = + TOKEN_STRING_INITIALIZER(struct ethdev_help_cmd_tokens, help, "help"); +cmdline_parse_token_string_t ethdev_help_ethdev = + TOKEN_STRING_INITIALIZER(struct ethdev_help_cmd_tokens, ethdev, "ethdev"); + +cmdline_parse_inst_t ethdev_help_cmd_ctx = { + .f = cli_ethdev_help, + .data = NULL, + .help_str = "", + .tokens = { + (void *)ðdev_help_cmd, + (void *)ðdev_help_ethdev, + NULL, + }, +}; diff --git a/app/graph/ethdev.h b/app/graph/ethdev.h new file mode 100644 index 0000000000..94d3247a2c --- /dev/null +++ b/app/graph/ethdev.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_ETHDEV_H +#define APP_GRAPH_ETHDEV_H + +#include + +#define ETHDEV_IPV6_ADDR_LEN 16 + +extern cmdline_parse_inst_t ethdev_show_cmd_ctx; +extern cmdline_parse_inst_t ethdev_stats_cmd_ctx; +extern cmdline_parse_inst_t ethdev_mtu_cmd_ctx; +extern cmdline_parse_inst_t ethdev_prom_mode_cmd_ctx; +extern cmdline_parse_inst_t ethdev_ip4_cmd_ctx; +extern cmdline_parse_inst_t ethdev_ip6_cmd_ctx; +extern cmdline_parse_inst_t ethdev_cmd_ctx; +extern cmdline_parse_inst_t ethdev_help_cmd_ctx; + +struct ipv4_addr_config { + uint32_t ip; + uint32_t mask; +}; + +struct ipv6_addr_config { + uint8_t ip[ETHDEV_IPV6_ADDR_LEN]; + uint8_t mask[ETHDEV_IPV6_ADDR_LEN]; +}; + +extern uint32_t enabled_port_mask; + +void ethdev_start(void); +void ethdev_stop(void); +void *ethdev_mempool_list_by_portid(uint16_t portid); +int16_t ethdev_portid_by_ip4(uint32_t ip, uint32_t mask); +int16_t ethdev_portid_by_ip6(uint8_t *ip, uint8_t *mask); +void ethdev_list_clean(void); + +#endif diff --git a/app/graph/ethdev_priv.h b/app/graph/ethdev_priv.h new file mode 100644 index 0000000000..f231f3f3e1 --- /dev/null +++ b/app/graph/ethdev_priv.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Marvell. + */ + +#ifndef APP_GRAPH_ETHDEV_PRIV_H +#define APP_GRAPH_ETHDEV_PRIV_H + +#include "ethdev.h" + +#define NS_PER_SEC 1E9 + +#define ETHDEV_RXQ_RSS_MAX 16 +#define ETHDEV_RX_DESC_DEFAULT 1024 +#define ETHDEV_TX_DESC_DEFAULT 1024 + +struct ethdev_show_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t show; +}; + +struct ethdev_stats_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t stats; +}; + +struct ethdev_mtu_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t mtu; + uint16_t size; +}; + +struct ethdev_prom_mode_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t prom; + cmdline_fixed_string_t enable; +}; + +struct ethdev_ip4_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t ip4; + cmdline_fixed_string_t addr; + cmdline_fixed_string_t add; + cmdline_fixed_string_t ip; + cmdline_fixed_string_t netmask; + cmdline_fixed_string_t mask; +}; + +struct ethdev_ip6_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t ip6; + cmdline_fixed_string_t addr; + cmdline_fixed_string_t add; + cmdline_fixed_string_t ip; + cmdline_fixed_string_t netmask; + cmdline_fixed_string_t mask; +}; + +struct ethdev_cmd_tokens { + cmdline_fixed_string_t cmd; + cmdline_fixed_string_t dev; + cmdline_fixed_string_t rxq; + cmdline_fixed_string_t txq; + cmdline_fixed_string_t mempool; + uint16_t nb_rxq; + uint16_t nb_txq; +}; + +struct ethdev_help_cmd_tokens { + cmdline_fixed_string_t help; + cmdline_fixed_string_t ethdev; +}; + +struct ethdev_rss_config { + uint32_t queue_id[ETHDEV_RXQ_RSS_MAX]; + uint32_t n_queues; +}; + +struct ethdev_config { + char dev_name[RTE_ETH_NAME_MAX_LEN]; + uint16_t port_id; + + struct { + uint32_t n_queues; + uint32_t queue_size; + char mempool_name[RTE_MEMPOOL_NAMESIZE]; + struct rte_mempool *mp; + struct ethdev_rss_config *rss; + } rx; + + struct { + uint32_t n_queues; + uint32_t queue_size; + } tx; + + int promiscuous; + uint32_t mtu; +}; + +struct ethdev { + TAILQ_ENTRY(ethdev) next; + struct ethdev_config config; + struct ipv4_addr_config ip4_addr; + struct ipv6_addr_config ip6_addr; +}; +TAILQ_HEAD(ethdev_head, ethdev); +#endif diff --git a/app/graph/main.c b/app/graph/main.c index 96548f49e7..c1cb435588 100644 --- a/app/graph/main.c +++ b/app/graph/main.c @@ -215,6 +215,7 @@ main(int argc, char **argv) exit: conn_free(conn); + ethdev_stop(); cli_exit(); rte_eal_cleanup(); return 0; diff --git a/app/graph/meson.build b/app/graph/meson.build index 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..124c16e546 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,17 @@ Example: ``dpdk-graph`` is started with -h 10.28.35.207 and -p 50000 then graph> graph> + graph> help ethdev + + ----------------------------- ethdev command help ----------------------------- + ethdev rxq txq + ethdev ip4 addr add netmask + ethdev ip6 addr add netmask + ethdev promiscuous + ethdev mtu + ethdev show + graph> + Created graph for use case -------------------------- From patchwork Thu Oct 19 10:49:54 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: 132978 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 98FD3431A9; Thu, 19 Oct 2023 12:51:01 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A655A42D3F; Thu, 19 Oct 2023 12:50: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 7B151427DC for ; Thu, 19 Oct 2023 12:50: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 39J01XJp008186 for ; Thu, 19 Oct 2023 03:50: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=Rvw6HrGUruGEHHPgsYhY5lIA49RdPj8kzMS4VsPpyyk=; b=XfmEZbPAWRRua88oAuocr0TkmlF0fsPfnJpdxCUawPhia84pPcpAWNV1oJfDpZlseDWh LDR66qHEvqtcr0fcsNxmNdN4vp1xFni49KPPy60rc3B8zDRykoTlMuYUiq6tf0uLSkNb X1O3cesQ7AuUIEiS8qgtye2lsVwJ9E3/sSzKcqTo19s6yecwN5mooVY5Y5JhzbJ9PdPm c7RjFOGCcH2OLWVHfYPTWMqnqVTv67dkNxj7udgKYX9UBlvoMr9kMcrv1oVEEpISBmAu VBUbp8NLSi/Tw7hkTQOx4EynhCkzFFoIyicthg8xgXRjKrA+0wBse9lG6KiuukUrJJYI 0g== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshua3cx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50:21 -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 03:50: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 03:50:19 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id CF6E15B698B; Thu, 19 Oct 2023 03:50:16 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v10 06/12] app/graph: support IPv4 lookup command line interfaces Date: Thu, 19 Oct 2023 16:19:54 +0530 Message-ID: <20231019105000.520914-7-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: 9j5MEa4rV3s53rPwhlWuOmutCCp1V3Iv X-Proofpoint-ORIG-GUID: 9j5MEa4rV3s53rPwhlWuOmutCCp1V3Iv 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- 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 74e80679d9..4d2bc73e7c 100644 --- a/app/graph/ethdev.c +++ b/app/graph/ethdev.c @@ -160,7 +160,7 @@ ethdev_stop(void) } ethdev_list_clean(); - rte_eal_cleanup(); + route_ip4_list_clean(); printf("Bye...\n"); } diff --git a/app/graph/ip4_route.c b/app/graph/ip4_route.c new file mode 100644 index 0000000000..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 124c16e546..d5f86575b9 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 10:49:55 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: 132979 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 4B757431A9; Thu, 19 Oct 2023 12:51:10 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C143B42D80; Thu, 19 Oct 2023 12:50:25 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id CF76D427E4 for ; Thu, 19 Oct 2023 12:50:22 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39J7T8Im012394 for ; Thu, 19 Oct 2023 03:50: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=Qge2Aw+sTQcOU0WlcZ37MOxjl7Zogm52WzrNBdZi5NA=; b=IZ3xc9xb5rQBM/ezElcYEs5MTRnjhVzA0Uoor4vn/V0ehmDmNRCiLg8ApGgVbKBqgh1Z LIxvWlKcimfNNVEQdGlZXEiGEYl5YVQABTiFBQjgLAPRCNBET74CqhNq7LQUIxkLC+MY RNCqwYGCdxgA4BfMivHTm1aDewVa9Po9AGmvzwldVFL/vSnAh5eAEA/xTjfyF0YszlmK mLTB+Q/lSXXNLhvwQFO+IA0Aro7yydKwFvEUW8ijerR7aHr6PvUPA+Xce+BAXGBM0YCV sjoo91M1atqrbJIwJCc3tUZFI0Da7tsdi9FGBUzarrqP1lpYQqRjHurw0wLVT8xD/N1R 2w== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3tstb41v5v-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50: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 03:50: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 03:50:19 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id AD3335B6926; Thu, 19 Oct 2023 03:50:18 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v10 07/12] app/graph: support IPv6 lookup command line interfaces Date: Thu, 19 Oct 2023 16:19:55 +0530 Message-ID: <20231019105000.520914-8-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: 5-wwIYaVggYJ3F2yMd1bgVu8qYdIO8tf X-Proofpoint-GUID: 5-wwIYaVggYJ3F2yMd1bgVu8qYdIO8tf 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- 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 4d2bc73e7c..4c70953b99 100644 --- a/app/graph/ethdev.c +++ b/app/graph/ethdev.c @@ -161,6 +161,7 @@ ethdev_stop(void) ethdev_list_clean(); route_ip4_list_clean(); + route_ip6_list_clean(); printf("Bye...\n"); } diff --git a/app/graph/ip6_route.c b/app/graph/ip6_route.c new file mode 100644 index 0000000000..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 d5f86575b9..6405f1fde6 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 10:49:56 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: 132980 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 F1B7B431A9; Thu, 19 Oct 2023 12:51:18 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id DC28342DC0; Thu, 19 Oct 2023 12:50:26 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id AD91342D6B for ; Thu, 19 Oct 2023 12:50:24 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39J7A9AF013996 for ; Thu, 19 Oct 2023 03:50: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=NnPOjmLjkkzicsqqIWpu0EyoBOGKwlOZ8Jc7hhBaGPw=; b=DJJmbqottmE5TNvq55yOyYr2jp4KO5xVR5jBGdvj6MqvUtRdjwXs9MKsh46RNOB7Xm8c SRHvrx0KolK8kMRxZ111E15L97Ik22GS/tZUpGlsc+aAdR2/BiE8ljJp2kPQw6IK18Uo DdAx6OF3We69EAatPoRmPNZ2m/aH4lajSeKktUYCXNgPrYHLoHl3NNG5xwORBeb0J9VO jCqk/Fcja3hAGvSyRNkn3vbGqmlHrW8wQpgLVQlPmV2we6f1LtX5fdpPKP46DSB+2Y7Y w35fJ6bdclYeB0vKMFGAtiVsjvBI+1/6F8hyhEQmGUg/ViEfxiRCa2zwQjujdtoLk99y Hw== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3tstb41v64-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50:23 -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 03:50:21 -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 03:50:21 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 8E23D5B6928; Thu, 19 Oct 2023 03:50:20 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v10 08/12] app/graph: support neigh command line interfaces Date: Thu, 19 Oct 2023 16:19:56 +0530 Message-ID: <20231019105000.520914-9-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: Z8KOej4Jhn3VSMTtyeo-8JDQkTiv_h53 X-Proofpoint-GUID: Z8KOej4Jhn3VSMTtyeo-8JDQkTiv_h53 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- 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 4c70953b99..b43b16c300 100644 --- a/app/graph/ethdev.c +++ b/app/graph/ethdev.c @@ -162,6 +162,8 @@ ethdev_stop(void) ethdev_list_clean(); route_ip4_list_clean(); route_ip6_list_clean(); + neigh4_list_clean(); + neigh6_list_clean(); printf("Bye...\n"); } diff --git a/app/graph/meson.build b/app/graph/meson.build index 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 6405f1fde6..7c12cf697e 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 10:49:57 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: 132981 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 48E78431A9; Thu, 19 Oct 2023 12:51:27 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 1982F42DC5; Thu, 19 Oct 2023 12:50:28 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 8ACFB42DA1 for ; Thu, 19 Oct 2023 12:50:26 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39INXAPM018716 for ; Thu, 19 Oct 2023 03:50: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=Bt4q0ciF1jsXCu9qX9nuso4S3jU2xB2ofnPXnTloF3c=; b=I7dewFMLh3M3uOYpQ6/d04EqFvfxhL+Lt1xwQltki7rysPL3oLPrjWJj2qMXqIAr5TO5 KKMfEw8um5OeWgIo1YDTy8rARsy5vn8C+Lv9LdOMUSpBkPJtNImjdOhAZc0SwA2spgVo PzhNCZVUdpuI7Snch7rcRlId+RBxzR9P7e+tN8y6iCDd0uUOHzgmCfKQ9Cc5FzSis4sm Ylk/n4av5G523FmTH+cJYWAUXg1TmJw9eoaKgEiMoelHPlUc+Y9jsaR5q6o8ej3k5JuX 9lpt8u/j7Ec42nH9Y51iZlPGjSzObvKFEhoaqGdvNCnbd7TGGGfCgH29x1qC5+xvRVzA 7g== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3tstb41v6g-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50:25 -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 03:50:23 -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 03:50:23 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 6E8635B6926; Thu, 19 Oct 2023 03:50:22 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v10 09/12] app/graph: support ethdev Rx command line interfaces Date: Thu, 19 Oct 2023 16:19:57 +0530 Message-ID: <20231019105000.520914-10-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: UqSL-gwO2FvhII1MFsZ1knVsuPDwNxNl X-Proofpoint-GUID: UqSL-gwO2FvhII1MFsZ1knVsuPDwNxNl 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- 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 7c12cf697e..5c69a568d1 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 10:49:58 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: 132982 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 A31DB431A9; Thu, 19 Oct 2023 12:51:37 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 9576542DEE; Thu, 19 Oct 2023 12:50: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 5FD6942DD3 for ; Thu, 19 Oct 2023 12:50:28 +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 39J01WtW008128 for ; Thu, 19 Oct 2023 03:50:27 -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=8f3YC57+ie9B6jBd5YnLebahAt5NhZbRUS6+Evp0Efc=; b=doMCpohj/fd1/4yiRTK9RGt6B40Toaw0NTWYAapHxrzMiMjr/kNoQ99LeI/ZW34ybmPy 0NWD0oX4+5UbKi9Sqoj6c0G0AGqGQk8A+IswXyCAs7UFf/opJTvLnftA3QE1ugu8ZalY dWlFza1iYeZfwjjy9s3x2gYC84Y3Hro3phWZCoz+ZJipvQprUXShl+PSdgvFj1o1/k6q H5eznKXlCKUVPNeo6gJZwLsEpFIUIT3PyBXHKVokri9m1CjNYz3MgdrM4TFCtrrUdsmO PXNSo2kXM9ZWwLbAS4LVZI19uQb9EYmNMWrHu+0MSASUiQXqQYPb318qXwoLCQ79NcCC Vw== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshua3ey-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50:27 -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 03:50:25 -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 03:50:25 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 51B225B6928; Thu, 19 Oct 2023 03:50:24 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v10 10/12] app/graph: support graph command line interfaces Date: Thu, 19 Oct 2023 16:19:58 +0530 Message-ID: <20231019105000.520914-11-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: zRlj5SQPQD9Sc4Rm3RbKxLf8zZ33qe3N X-Proofpoint-ORIG-GUID: zRlj5SQPQD9Sc4Rm3RbKxLf8zZ33qe3N 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- 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..4396f02da5 --- /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, "Errot 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", + "----------------------------- graph command help -----------------------------", + cmd_graph_help, "graph start"); + + len = strlen(conn->msg_out); + conn->msg_out_len_max -= len; +} + +cmdline_parse_token_string_t graph_display_graph = + TOKEN_STRING_INITIALIZER(struct graph_stats_cmd_tokens, graph, "graph"); +cmdline_parse_token_string_t graph_display_stats = + TOKEN_STRING_INITIALIZER(struct graph_stats_cmd_tokens, stats, "stats"); +cmdline_parse_token_string_t graph_display_show = + TOKEN_STRING_INITIALIZER(struct graph_stats_cmd_tokens, show, "show"); + +cmdline_parse_inst_t graph_stats_cmd_ctx = { + .f = cli_graph_stats, + .data = NULL, + .help_str = "graph stats show", + .tokens = { + (void *)&graph_display_graph, + (void *)&graph_display_stats, + (void *)&graph_display_show, + NULL, + }, +}; + +cmdline_parse_token_string_t graph_config_start_graph = + TOKEN_STRING_INITIALIZER(struct graph_start_cmd_tokens, graph, "graph"); +cmdline_parse_token_string_t graph_config_start = + TOKEN_STRING_INITIALIZER(struct graph_start_cmd_tokens, start, "start"); + +cmdline_parse_inst_t graph_start_cmd_ctx = { + .f = cli_graph_start, + .data = NULL, + .help_str = "graph start", + .tokens = { + (void *)&graph_config_start_graph, + (void *)&graph_config_start, + NULL, + }, +}; + +cmdline_parse_token_string_t graph_config_add_graph = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, graph, "graph"); +cmdline_parse_token_string_t graph_config_add_usecase = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, usecase, NULL); +cmdline_parse_token_string_t graph_config_add_coremask = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, coremask, "coremask"); +cmdline_parse_token_num_t graph_config_add_mask = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, mask, RTE_UINT64); +cmdline_parse_token_string_t graph_config_add_bsz = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, bsz, "bsz"); +cmdline_parse_token_num_t graph_config_add_size = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, size, RTE_UINT16); +cmdline_parse_token_string_t graph_config_add_tmo = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, tmo, "tmo"); +cmdline_parse_token_num_t graph_config_add_ns = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, ns, RTE_UINT64); +cmdline_parse_token_string_t graph_config_add_model = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, model, "model"); +cmdline_parse_token_string_t graph_config_add_model_name = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, model_name, "rtc#mcd#default"); +cmdline_parse_token_string_t graph_config_add_capt_ena = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, capt_ena, "pcap_enable"); +cmdline_parse_token_num_t graph_config_add_pcap_ena = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, pcap_ena, RTE_UINT8); +cmdline_parse_token_string_t graph_config_add_capt_pkts_count = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, capt_pkts_count, "num_pcap_pkts"); +cmdline_parse_token_num_t graph_config_add_num_pcap_pkts = + TOKEN_NUM_INITIALIZER(struct graph_config_cmd_tokens, num_pcap_pkts, RTE_UINT64); +cmdline_parse_token_string_t graph_config_add_capt_file = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, capt_file, "pcap_file"); +cmdline_parse_token_string_t graph_config_add_pcap_file = + TOKEN_STRING_INITIALIZER(struct graph_config_cmd_tokens, pcap_file, NULL); + +cmdline_parse_inst_t graph_config_cmd_ctx = { + .f = cli_graph, + .data = NULL, + .help_str = cmd_graph_help, + .tokens = { + (void *)&graph_config_add_graph, + (void *)&graph_config_add_usecase, + (void *)&graph_config_add_coremask, + (void *)&graph_config_add_mask, + (void *)&graph_config_add_bsz, + (void *)&graph_config_add_size, + (void *)&graph_config_add_tmo, + (void *)&graph_config_add_ns, + (void *)&graph_config_add_model, + (void *)&graph_config_add_model_name, + (void *)&graph_config_add_capt_ena, + (void *)&graph_config_add_pcap_ena, + (void *)&graph_config_add_capt_pkts_count, + (void *)&graph_config_add_num_pcap_pkts, + (void *)&graph_config_add_capt_file, + (void *)&graph_config_add_pcap_file, + NULL, + }, +}; + +cmdline_parse_token_string_t graph_help_cmd = + TOKEN_STRING_INITIALIZER(struct graph_help_cmd_tokens, help, "help"); +cmdline_parse_token_string_t graph_help_graph = + TOKEN_STRING_INITIALIZER(struct graph_help_cmd_tokens, graph, "graph"); + +cmdline_parse_inst_t graph_help_cmd_ctx = { + .f = cli_graph_help, + .data = NULL, + .help_str = "", + .tokens = { + (void *)&graph_help_cmd, + (void *)&graph_help_graph, + NULL, + }, +}; diff --git a/app/graph/graph.h b/app/graph/graph.h new file mode 100644 index 0000000000..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 5c69a568d1..c861ae8eb5 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 10:49:59 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: 132983 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 9EB5D431A9; Thu, 19 Oct 2023 12:51:48 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 14B7142DFB; Thu, 19 Oct 2023 12:50:33 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 4E43B42DE8 for ; Thu, 19 Oct 2023 12:50:30 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 39INXAPN018716 for ; Thu, 19 Oct 2023 03:50: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=hD5OwCnakexv/FbWRisi/wh5GL5r/mr+LDe23nO76Fo=; b=eAKDZVS/h3J1lUNXH/5tYdZHygh2rLoNI42ZNkvrAOZ/3+H5XiwZkwjQuijiHKrca1gm ZoEV/ZCwDDzDXkHe5lat1kkVe/Xy42vQ6see7qJJ76Zybn5Yt61JTdKyCoVs6rKxwcoF H2t88FVmyZNnRFUlAWNlUyrkv+Cwn0sSKnNkZxJOxtfXScZ51sOA8QtEPW3mZNydJDKP It4U79WHbYCD4GxMAiIeQyVxRBkgdu2sbyqJnumfWqMAdZ+tJZai8qWM380qWKVCZFoX S65ji/mZF2SCbhvln3UsLz+A09WFw+h3SWlltTqHVi38TKmhPm5AP2/VPjTRqcI91E1S Og== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3tstb41v6t-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50:29 -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 03:50:27 -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 03:50:27 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 2CD865B6926; Thu, 19 Oct 2023 03:50:25 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: , Jerin Jacob Subject: [PATCH v10 11/12] app/graph: support CLI option to enable graph stats Date: Thu, 19 Oct 2023 16:19:59 +0530 Message-ID: <20231019105000.520914-12-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: bbM8yA__YJlKf9oX4CYRPUGt_C5iJcVK X-Proofpoint-GUID: bbM8yA__YJlKf9oX4CYRPUGt_C5iJcVK 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 --- 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 c861ae8eb5..0be4a09a9a 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 10:50: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: 132984 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 ECC06431A9; Thu, 19 Oct 2023 12:51:56 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 30AE942DD7; Thu, 19 Oct 2023 12:50:34 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 6C8DF4021F for ; Thu, 19 Oct 2023 12:50:32 +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 39J01XJu008186 for ; Thu, 19 Oct 2023 03:50:31 -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=ULZAR6BGQfnae8ewoEuNRUBQAcpdUF64Cif1TGhsESA=; b=H6VEB9P8I8D3291h0Uft4KhWDhZZoMh9I4o0t+pnC1TdMme69oKa9wosHRGDTS9Imu8r KN9ZkOX4YK/65dYFAHEJrbB94DeZnXIMBCzIMbITqVDdsGrdyqBHykSMQkRMm5TJeMnr LBaWP7nMwKQEN1NftqqrpaATknxZCAfxOUK3dg4of1Dk48vhYH3g0Bp9FgAkZmwP9dNJ zbBaNzkk+jdsqPMpXn3b3IgFzunFrB7INmOLjKgv78PiqpmPGYE/78hUNbK+Xdf9WajS hNvzc+M7/+pOTZRZ5XqQP8VqF0cT2R9OgS/cLnCBJABu5QtgxBcyXt4x/xnXLuOdY8zj 9Q== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3ttshua3f7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Thu, 19 Oct 2023 03:50:31 -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 03:50:29 -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 03:50:29 -0700 Received: from localhost.localdomain (unknown [10.28.34.25]) by maili.marvell.com (Postfix) with ESMTP id 4BD5F5B6953; Thu, 19 Oct 2023 03:50:28 -0700 (PDT) From: To: Sunil Kumar Kori , Rakesh Kudurumalla CC: Subject: [PATCH v10 12/12] app/graph: support l3fwd use case Date: Thu, 19 Oct 2023 16:20:00 +0530 Message-ID: <20231019105000.520914-13-skori@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231019105000.520914-1-skori@marvell.com> References: <20231018063347.68081-13-skori@marvell.com> <20231019105000.520914-1-skori@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: ptuyqzFVMChvKmwRtnOM1VhEsVCAA0W_ X-Proofpoint-ORIG-GUID: ptuyqzFVMChvKmwRtnOM1VhEsVCAA0W_ 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_08,2023-10-19_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions 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 Acked-By: Nithin Dabilpuram --- 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 | 109 ++++++++++ doc/guides/tools/img/graph-usecase-l3fwd.svg | 210 +++++++++++++++++++ 9 files changed, 613 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 4396f02da5..496105eef1 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 0be4a09a9a..2fd150052c 100644 --- a/doc/guides/tools/graph.rst +++ b/doc/guides/tools/graph.rst @@ -12,6 +12,14 @@ 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. +Supported Use cases +------------------- + * l3fwd + +This use case is supported for both PF and PCAP network devices. To demonstrate, +corresponding .cli files are available at ```` +named as ``l3fwd.cli`` and ``l3fwd_pcap.cli`` respectively. + Running the Application ----------------------- @@ -63,6 +71,26 @@ Following are the application command-line options: Dumps application usage +Examples +~~~~~~~~ + +For PF 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 + +Refer section :ref:`verifying_traffic` to create .pcap file used here. + Supported CLI commands ---------------------- @@ -223,3 +251,84 @@ 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.* + +.. _verifying_traffic: + +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 + + aSPY//YASa + apyyyyCY//////////YCa | + sY//////YSpcs scpCY//Pp | Welcome to Scapy + ayp ayyyyyyySCP//Pp syY//C | Version 2.4.3 + AYAsAYYYYYYYY///Ps cY//S | + pCCCCY//p cSSps y//Y | https://github.com/secdev/scapy + SPPPP///a pP///AC//Y | + A//A cyP////C | Have fun! + p///Ac sC///a | + P////YCpc A//A | We are in France, we say Skappee. + scccccp///pSP///p p//Y | OK? Merci. + sY/////////y caa S//P | -- Sebastien Chabal + cayCyayP//Ya pY/Ya | + sY/PsY////YCc aC//Yp + sc sccaCY//PCypaapyCP//YSs + spCPY//////YPSps + ccaacs + using IPython 7.13.0 + >>> + >>> + >>> 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 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 + + +