From patchwork Fri Oct 27 11:01:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 133493 X-Patchwork-Delegate: david.marchand@redhat.com 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 BD96243215; Fri, 27 Oct 2023 13:01:32 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id AE70C40DF6; Fri, 27 Oct 2023 13:01:32 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by mails.dpdk.org (Postfix) with ESMTP id 78E8C40698 for ; Fri, 27 Oct 2023 13:01:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698404492; x=1729940492; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zYs/j+i0x2Evu12BS3CXCVNXHOoSmhFrNuolq1OsTos=; b=SRv178cN9+ZJpHQcxVDf++DucKEB4AuENEdlx5sQMK9oK3rq2vmETJ2e C48iqtoa9dcE6b6HBRaQVu/XvP40B0BjFIL/GJuF3hgzqAVYV3Mn2aGPN upszqGvJN9kLBnWojj3L4BARGDWgbKj9uKbss4ebxUAjQj34JSDsznPlI EPyMBOUGZme0eZIOtdVha9pT6PdoeIdI9rWw7MScP2BWgNFJYLEJ1dgEG M09ILOyFl1LGL8eFX3k41b+L0MOoKDsgaSE192iVjz7K8iPY6EMeYeTVB TBcQ64StURaEdzOzZEu7R9yBTz/UJu7PUPHC/u4/s2+Nktu1XLYLoHCiz Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="546669" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="546669" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Oct 2023 04:01:31 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="883157823" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="883157823" Received: from silpixa00401385.ir.intel.com ([10.237.214.154]) by orsmga004.jf.intel.com with ESMTP; 27 Oct 2023 04:01:28 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: david.marchand@redhat.com, rjarry@redhat.com, Bruce Richardson Subject: [PATCH v7 1/9] doc/prog_guide: new chapter on cmdline library Date: Fri, 27 Oct 2023 12:01:09 +0100 Message-Id: <20231027110117.70995-2-bruce.richardson@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231027110117.70995-1-bruce.richardson@intel.com> References: <20230802170052.955323-1-bruce.richardson@intel.com> <20231027110117.70995-1-bruce.richardson@intel.com> MIME-Version: 1.0 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 The cmdline library was not documented in our programmers guide, so add a new chapter on it. This chapter covers step-by-step how to use the library, rather than focusing on the library internals. This complements the existing cmdline example app document, providing more details on the process of using the library. Signed-off-by: Bruce Richardson --- app/test/commands.c | 2 + doc/guides/prog_guide/cmdline.rst | 337 ++++++++++++++++++++++++++++++ doc/guides/prog_guide/index.rst | 1 + 3 files changed, 340 insertions(+) create mode 100644 doc/guides/prog_guide/cmdline.rst diff --git a/app/test/commands.c b/app/test/commands.c index 31259e5c21..497d8e9952 100644 --- a/app/test/commands.c +++ b/app/test/commands.c @@ -108,6 +108,7 @@ dump_struct_sizes(void) #undef DUMP_SIZE } +/* Add the dump_* tests cases 8< */ static void cmd_dump_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) @@ -155,6 +156,7 @@ cmdline_parse_inst_t cmd_dump = { NULL, }, }; +/* >8 End of add the dump_* tests cases */ /****************/ diff --git a/doc/guides/prog_guide/cmdline.rst b/doc/guides/prog_guide/cmdline.rst new file mode 100644 index 0000000000..40f49a30cc --- /dev/null +++ b/doc/guides/prog_guide/cmdline.rst @@ -0,0 +1,337 @@ +.. SPDX-License-Identifier: BSD-3-Clause + Copyright(c) 2023 Intel Corporation. + +Command-line Library +==================== + +Since its earliest versions, DPDK has included a command-line library - +primarily for internal use by, for example, ``dpdk-testpmd`` and the ``dpdk-test`` binaries, +but the library is also exported on install and can be used by any end application. +This chapter covers the basics of the command-line library and how to use it in an application. + +Library Features +---------------- + +The DPDK command-line library supports the following features: + +* Tab-completion available for interactive terminal sessions + +* Ability to read and process commands taken from an input file, e.g. startup script + +* Parameterized commands able to take multiple parameters with different datatypes: + + * Strings + * Signed/unsigned 16/32/64-bit integers + * IP Addresses + * Ethernet Addresses + +* Ability to multiplex multiple commands to a single callback function + +Adding Command-line to an Application +------------------------------------- + +Adding a command-line instance to an application involves a number of coding steps. + +1. Define the result structure for the command, specifying the command parameters + +2. Provide an initializer for each field in the result + +3. Define the callback function for the command + +4. Provide a parse result structure instance for the command, linking the callback to the command + +5. Add the parse result structure to a command-line context + +6. Within your main application code, create a new command-line instance passing in the context. + +The next few subsections will cover each of these steps in more detail, +working through an example to add two commands to a command-line instance. +Those two commands will be: + +1. ``quit`` - as the name suggests, to close the application + +2. ``show port stats `` - to display on-screen the statistics for a given ethernet port + +.. note:: + + For further examples of use of the command-line, see + :doc:`cmdline example application <../sample_app_ug/cmd_line>` + +Defining Command Result Structure +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The first structure to be defined is the structure which will be created on successful parse of a command. +This structure contains one member field for each token, or word, in the command. +The simplest case is for a one-word command, like ``quit``. +For this, we only need to define a structure with a single string parameter to contain that word. + +.. code-block:: c + + struct cmd_quit_result { + cmdline_fixed_string_t quit; + }; + +For readability, the name of the struct member should match that of the token in the command. + +For our second command, we need a structure with four member fields in it, +as there are four words/tokens in our command. +The first three are strings, and the final one is a 16-bit numeric value. +The resulting struct looks like: + +.. code-block:: c + + struct cmd_show_port_stats_result { + cmdline_fixed_string_t show; + cmdline_fixed_string_t port; + cmdline_fixed_string_t stats; + uint16_t n; + }; + +As before, we choose names to match the tokens in the command. +Since our numeric parameter is a 16-bit value, we use ``uint16_t`` type for it. +Any of the standard sized integer types can be used as parameters, depending on the desired result. + +Beyond the standard integer types, +the library also allows variable parameters to be of a number of other types, +as called out in the feature list above. + +* For variable string parameters, + the type should be ``cmdline_fixed_string_t`` - the same as for fixed tokens, + but these will be initialized differently (as described below). + +* For ethernet addresses use type ``struct rte_ether_addr`` + +* For IP addresses use type ``cmdline_ipaddr_t`` + +Providing Field Initializers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each field of our result structure needs an initializer. +For fixed string tokens, like "quit", "show" and "port", the initializer will be the string itself. + +.. code-block:: c + + static cmdline_parse_token_string_t cmd_quit_quit_tok = + TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); + +The convention for naming used here is to include the base name of the overall result structure - +``cmd_quit`` in this case, +as well as the name of the field within that structure - ``quit`` in this case, followed by ``_tok``. +(This is why there is a double ``quit`` in the name above). + +This naming convention is seen in our second example, +which also demonstrates how to define a numeric initializer. + + +.. code-block:: c + + static cmdline_parse_token_string_t cmd_show_port_stats_show_tok = + TOKEN_STRING_INITIALIZER(struct cmd_show_port_stats_result, show, "show"); + static cmdline_parse_token_string_t cmd_show_port_stats_port_tok = + TOKEN_STRING_INITIALIZER(struct cmd_show_port_stats_result, port, "port"); + static cmdline_parse_token_string_t cmd_show_port_stats_stats_tok = + TOKEN_STRING_INITIALIZER(struct cmd_show_port_stats_result, stats, "stats"); + static cmdline_parse_token_num_t cmd_show_port_stats_n_tok = + TOKEN_NUM_INITIALIZER(struct cmd_show_port_stats_result, n, RTE_UINT16); + +For variable string tokens, the same ``TOKEN_STRING_INITIALIZER`` macro should be used. +However, the final parameter should be ``NULL`` rather than a hard-coded token string. + +For numeric parameters, the final parameter to the ``TOKEN_NUM_INITIALIZER`` macro should be the +cmdline type matching the variable type defined in the result structure, +e.g. RTE_UINT8, RTE_UINT32, etc. + +For IP addresses, the macro ``TOKEN_IPADDR_INITIALIZER`` should be used. + +For ethernet addresses, the macro ``TOKEN_ETHERADDR_INITIALIZER`` should be used. + +Defining Callback Function +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For each command, we need to define a function to be called once the command has been recognised. +The callback function should have type: + +.. code:: c + + void (*f)(void *, struct cmdline *, void *) + +where the first parameter is a pointer to the result structure defined above, +the second parameter is the command-line instance, +and the final parameter is a user-defined pointer provided when we associate the callback with the command. +Most callback functions only use the first parameter, or none at all, +but the additional two parameters provide some extra flexibility, +to allow the callback to work with non-global state in your application. + +For our two example commands, the relevant callback functions would look very similar in definition. +However, within the function body, +we assume that the user would need to reference the result structure to extract the port number in +the second case. + +.. code:: c + + void + cmd_quit_parsed(void *parsed_result, struct cmdline *cl, void *data) + { + quit = 1; + } + void + cmd_show_port_stats_parsed(void *parsed_result, struct cmdline *cl, void *data) + { + struct cmd_show_port_stats_result *res = parsed_result; + uint16_t port_id = res->n; + ... + } + + +Associating Callback and Command +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``cmdline_parse_inst_t`` type defines a "parse instance", +i.e. a sequence of tokens to be matched and then an associated function to be called. +Also included in the instance type are a field for help text for the command, +and any additional user-defined parameter to be passed to the callback functions referenced above. +For example, for our simple "quit" command: + +.. code-block:: c + + static cmdline_parse_inst_t cmd_quit = { + .f = cmd_quit_parsed, + .data = NULL, + .help_str = "Close the application", + .tokens = { + (void *)&cmd_quit_quit_tok, + NULL + } + }; + +In this case, we firstly identify the callback function to be called, +then set the user-defined parameter to NULL, +provide a help message to be given, on request, to the user explaining the command, +before finally listing out the single token to be matched for this command instance. + +For our second, port stats, example, +as well as making things a little more complicated by having multiple tokens to be matched, +we can also demonstrate passing in a parameter to the function. +Let us suppose that our application does not always use all the ports available to it, +but instead only uses a subset of the ports, stored in an array called ``active_ports``. +Our stats command, therefore, should only display stats for the currently in-use ports, +so we pass this ``active_ports`` array. +(For simplicity of illustration, we shall assume that the array uses a terminating marker, +e.g. -1 for the end of the port list, so we don't need to pass in a length parameter too.) + +.. code-block:: c + + extern int16_t active_ports[]; + ... + static cmdline_parse_inst_t cmd_show_port_stats = { + .f = cmd_show_port_stats_parsed, + .data = active_ports, + .help_str = "Show statistics for active network ports", + .tokens = { + (void *)&cmd_show_port_stats_show_tok, + (void *)&cmd_show_port_stats_port_tok, + (void *)&cmd_show_port_stats_stats_tok, + (void *)&cmd_show_port_stats_n_tok, + NULL + } + }; + + +Adding Command to Command-line Context +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Now that we have configured each individual command and callback, +we need to merge these into a single array of command-line "contexts". +This context array will be used to create the actual command-line instance in the application. +Thankfully, each context entry is the same as each parse instance, +so our array is defined by simply listing out the previously defined command parse instances. + +.. code-block:: c + + static cmdline_parse_ctx_t ctx[] = { + &cmd_quit, + &cmd_show_port_stats, + NULL + }; + +The context list must be terminated by a NULL entry. + +Creating a Command-line Instance +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once we have our ``ctx`` variable defined, +we now just need to call the API to create the new command-line instance in our application. +The basic API is ``cmdline_new`` which will create an interactive command-line with all commands available. +However, if additional features for interactive use - such as tab-completion - +are desired, it is recommended that ``cmdline_new_stdin`` be used instead. + +A pattern that can be used in applications is to use ``cmdline_new`` for processing any startup commands, +either from file or from the environment (as is done in the "dpdk-test" application), +and then using ``cmdline_stdin_new`` thereafter to handle the interactive part. +For example, to handle a startup file and then provide an interactive prompt: + +.. code-block:: c + + struct cmdline *cl; + int fd = open(startup_file, O_RDONLY); + + if (fd >= 0) { + cl = cmdline_new(ctx, "", fd, STDOUT_FILENO); + if (cl == NULL) { + /* error handling */ + } + cmdline_interact(cl); + cmdline_quit(cl); + close(fd); + } + + cl = cmdline_stdin_new(ctx, "Proxy>> "); + if (cl == NULL) { + /* error handling */ + } + cmdline_interact(cl); + cmdline_stdin_exit(cl); + + +Multiplexing Multiple Commands to a Single Function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To reduce the amount of boiler-plate code needed when creating a command-line for an application, +it is possible to merge a number of commands together to have them call a separate function. +This can be done in a number of different ways: + +* A callback function can be used as the target for a number of different commands. + Which command was used for entry to the function can be determined by examining the first parameter, + ``parsed_result`` in our examples above. + +* For simple string commands, multiple options can be concatenated using the "#" character. + For example: ``exit#quit``, specified as a token initializer, + will match either on the string "exit" or the string "quit". + +As a concrete example, +these two techniques are used in the DPDK unit test application ``dpdk-test``, +where a single command ``cmdline_parse_t`` instance is used for all the "dump_" test cases. + +.. literalinclude:: ../../../app/test/commands.c + :language: c + :start-after: Add the dump_* tests cases 8< + :end-before: >8 End of add the dump_* tests cases + + +Examples of Command-line Use in DPDK +------------------------------------ + +To help the user follow the steps provided above, +the following DPDK files can be consulted for examples of command-line use. + +.. note:: + + This is not an exhaustive list of examples of command-line use in DPDK. + It is simply a list of a few files that may be of use to the application developer. + Some of these referenced files contain more complex examples of use that others. + +* ``commands.c/.h`` in ``examples/cmdline`` + +* ``mp_commands.c/.h`` in ``examples/multi_process/simple_mp`` + +* ``commands.c`` in ``app/test`` diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst index e517f0e259..94964357ff 100644 --- a/doc/guides/prog_guide/index.rst +++ b/doc/guides/prog_guide/index.rst @@ -13,6 +13,7 @@ Programmer's Guide source_org env_abstraction_layer log_lib + cmdline service_cores trace_lib rcu_lib From patchwork Fri Oct 27 11:01:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 133494 X-Patchwork-Delegate: david.marchand@redhat.com 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 72E7043215; Fri, 27 Oct 2023 13:01:44 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2D42D42831; Fri, 27 Oct 2023 13:01:35 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by mails.dpdk.org (Postfix) with ESMTP id 2194240F16 for ; Fri, 27 Oct 2023 13:01:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698404494; x=1729940494; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=cKoyzD6rwHZe2+y4k2RcrY4M6hWlBHfTuV4CDrL3/i0=; b=aB3dH9cqvayT3D/K6O03pzmHXgCnucA9S19VeZ5uDXKquwAxjpnvEVPi cSZlL1b+Dbk5xmrSJ62pzwaQBV8FGz/fLs71Ibhp4BX2pRC8y5oMm8Nlx LqCyIXE1OMCXYAko5tcw9AOV0RLdMnP5YYtA61pTYG9gG3vhpudoIBXEg reHD/UH0dtGuFdQ3sMkjBJ4FySJnyq27eQys7oSHJ63Xl1KxkPy6banYJ Ocyfqf3klj+p9ML/BOt04V1CMoPDlinYj1NZ/UhQf+TjhJe6k812ZNMWk qB+DxKxtIZMA90CmRVkcGaK6WIu8fH1eYYY5pyRIFAqFEsOCk+cx42zMf A==; X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="546680" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="546680" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Oct 2023 04:01:32 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="883157839" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="883157839" Received: from silpixa00401385.ir.intel.com ([10.237.214.154]) by orsmga004.jf.intel.com with ESMTP; 27 Oct 2023 04:01:30 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: david.marchand@redhat.com, rjarry@redhat.com, Bruce Richardson Subject: [PATCH v7 2/9] buildtools: script to generate cmdline boilerplate Date: Fri, 27 Oct 2023 12:01:10 +0100 Message-Id: <20231027110117.70995-3-bruce.richardson@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231027110117.70995-1-bruce.richardson@intel.com> References: <20230802170052.955323-1-bruce.richardson@intel.com> <20231027110117.70995-1-bruce.richardson@intel.com> MIME-Version: 1.0 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 Provide a "dpdk-cmdline-gen.py" script for application developers to quickly generate the boilerplate code necessary for using the cmdline library. Example of use: The script takes an input file with a list of commands the user wants in the app, where the parameter variables are tagged with the type. For example: $ cat commands.list list add x y echo message add socket path quit When run through the script as "./dpdk-cmdline-gen.py commands.list", the output will be the contents of a header file with all the boilerplate necessary for a commandline instance with those commands. If the flag --stubs is passed, an output header filename must also be passed, in which case both a header file with the definitions and a C file with function stubs in it is written to disk. The separation is so that the header file can be rewritten at any future point to add more commands, while the C file can be kept as-is and extended by the user with any additional functions needed. Signed-off-by: Bruce Richardson --- buildtools/dpdk-cmdline-gen.py | 195 ++++++++++++++++++++++++++++++ buildtools/meson.build | 7 ++ doc/guides/prog_guide/cmdline.rst | 131 +++++++++++++++++++- 3 files changed, 332 insertions(+), 1 deletion(-) create mode 100755 buildtools/dpdk-cmdline-gen.py diff --git a/buildtools/dpdk-cmdline-gen.py b/buildtools/dpdk-cmdline-gen.py new file mode 100755 index 0000000000..c208121363 --- /dev/null +++ b/buildtools/dpdk-cmdline-gen.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation +# +""" +Script to automatically generate boilerplate for using DPDK cmdline library. +""" + +import argparse +import sys + +PARSE_FN_PARAMS = "void *parsed_result, struct cmdline *cl, void *data" +PARSE_FN_BODY = """ + /* TODO: command action */ + RTE_SET_USED(parsed_result); + RTE_SET_USED(cl); + RTE_SET_USED(data); +""" +NUMERIC_TYPES = [ + "UINT8", + "UINT16", + "UINT32", + "UINT64", + "INT8", + "INT16", + "INT32", + "INT64", +] + + +def process_command(lineno, tokens, comment): + """Generate the structures and definitions for a single command.""" + out = [] + cfile_out = [] + + if tokens[0].startswith("<"): + raise ValueError(f"Error line {lineno + 1}: command must start with a literal string") + + name_tokens = [] + for t in tokens: + if t.startswith("<"): + break + name_tokens.append(t) + name = "_".join(name_tokens) + + result_struct = [] + initializers = [] + token_list = [] + for t in tokens: + if t.startswith("<"): + t_type, t_name = t[1:].split(">") + t_val = "NULL" + else: + t_type = "STRING" + t_name = t + t_val = f'"{t}"' + + if t_type == "STRING": + result_struct.append(f"\tcmdline_fixed_string_t {t_name};") + initializers.append( + f"static cmdline_parse_token_string_t cmd_{name}_{t_name}_tok =\n" + f"\tTOKEN_STRING_INITIALIZER(struct cmd_{name}_result, {t_name}, {t_val});" + ) + elif t_type in NUMERIC_TYPES: + result_struct.append(f"\t{t_type.lower()}_t {t_name};") + initializers.append( + f"static cmdline_parse_token_num_t cmd_{name}_{t_name}_tok =\n" + f"\tTOKEN_NUM_INITIALIZER(struct cmd_{name}_result, {t_name}, RTE_{t_type});" + ) + elif t_type in ["IP", "IP_ADDR", "IPADDR"]: + result_struct.append(f"\tcmdline_ipaddr_t {t_name};") + initializers.append( + f"cmdline_parse_token_ipaddr_t cmd_{name}_{t_name}_tok =\n" + f"\tTOKEN_IPV4_INITIALIZER(struct cmd_{name}_result, {t_name});" + ) + else: + raise TypeError(f"Error line {lineno + 1}: unknown token type '{t_type}'") + token_list.append(f"cmd_{name}_{t_name}_tok") + + out.append(f'/* Auto-generated handling for command "{" ".join(tokens)}" */') + # output function prototype + func_sig = f"void\ncmd_{name}_parsed({PARSE_FN_PARAMS})" + out.append(f"extern {func_sig};\n") + # output result data structure + out.append(f"struct cmd_{name}_result {{\n" + "\n".join(result_struct) + "\n};\n") + # output the initializer tokens + out.append("\n".join(initializers) + "\n") + # output the instance structure + inst_elems = "\n".join([f"\t\t(void *)&{t}," for t in token_list]) + out.append( + f"""\ +static cmdline_parse_inst_t cmd_{name} = {{ +\t.f = cmd_{name}_parsed, +\t.data = NULL, +\t.help_str = "{comment}", +\t.tokens = {{ +{inst_elems} +\t\tNULL, +\t}} +}}; +""" + ) + # output function template if C file being written + cfile_out.append(f"{func_sig}\n{{{PARSE_FN_BODY}}}\n") + + # return the instance structure name + return (f"cmd_{name}", out, cfile_out) + + +def process_commands(infile, hfile, cfile, ctxname): + """Generate boilerplate output for a list of commands from infile.""" + instances = [] + + hfile.write( + f"""\ +/* File autogenerated by {sys.argv[0]} */ +#ifndef GENERATED_COMMANDS_H +#define GENERATED_COMMANDS_H +#include +#include +#include +#include +#include + +""" + ) + + for lineno, line in enumerate(infile.readlines()): + if line.lstrip().startswith("#"): + continue + if "#" not in line: + line = line + "#" # ensure split always works, even if no help text + tokens, comment = line.split("#", 1) + cmd_inst, h_out, c_out = process_command(lineno, tokens.strip().split(), comment.strip()) + hfile.write("\n".join(h_out)) + if cfile: + cfile.write("\n".join(c_out)) + instances.append(cmd_inst) + + inst_join_str = ",\n\t&" + hfile.write( + f""" +static __rte_used cmdline_parse_ctx_t {ctxname}[] = {{ +\t&{inst_join_str.join(instances)}, +\tNULL +}}; + +#endif /* GENERATED_COMMANDS_H */ +""" + ) + + +def main(): + """Application main entry point.""" + ap = argparse.ArgumentParser(description=__doc__) + ap.add_argument( + "--stubs", + action="store_true", + help="Produce C file with empty function stubs for each command", + ) + ap.add_argument( + "--output-file", + "-o", + default="-", + help="Output header filename [default to stdout]", + ) + ap.add_argument( + "--context-name", + default="ctx", + help="Name given to the cmdline context variable in the output header [default=ctx]", + ) + ap.add_argument("infile", type=argparse.FileType("r"), help="File with list of commands") + args = ap.parse_args() + + if not args.stubs: + if args.output_file == "-": + process_commands(args.infile, sys.stdout, None, args.context_name) + else: + with open(args.output_file, "w") as hfile: + process_commands(args.infile, hfile, None, args.context_name) + else: + if not args.output_file.endswith(".h"): + ap.error( + "-o/--output-file: specify an output filename ending with .h when creating stubs" + ) + + cfilename = args.output_file[:-2] + ".c" + with open(args.output_file, "w") as hfile: + with open(cfilename, "w") as cfile: + cfile.write(f'#include "{args.output_file}"\n\n') + process_commands(args.infile, hfile, cfile, args.context_name) + + +if __name__ == "__main__": + main() diff --git a/buildtools/meson.build b/buildtools/meson.build index 948ac17dd2..72447b60a0 100644 --- a/buildtools/meson.build +++ b/buildtools/meson.build @@ -19,6 +19,13 @@ get_cpu_count_cmd = py3 + files('get-cpu-count.py') get_numa_count_cmd = py3 + files('get-numa-count.py') get_test_suites_cmd = py3 + files('get-test-suites.py') has_hugepages_cmd = py3 + files('has-hugepages.py') +cmdline_gen_cmd = py3 + files('dpdk-cmdline-gen.py') + +# install any build tools that end-users might want also +install_data([ + 'dpdk-cmdline-gen.py', + ], + install_dir: 'bin') # select library and object file format pmdinfo = py3 + files('gen-pmdinfo-cfile.py') + [meson.current_build_dir()] diff --git a/doc/guides/prog_guide/cmdline.rst b/doc/guides/prog_guide/cmdline.rst index 40f49a30cc..0b96b770e2 100644 --- a/doc/guides/prog_guide/cmdline.rst +++ b/doc/guides/prog_guide/cmdline.rst @@ -44,7 +44,136 @@ Adding a command-line instance to an application involves a number of coding ste 6. Within your main application code, create a new command-line instance passing in the context. -The next few subsections will cover each of these steps in more detail, +Many of these steps can be automated using the script ``dpdk-cmdline-gen.py`` installed by DPDK, +and found in the ``buildtools`` folder in the source tree. +This section covers adding a command-line using this script to generate the boiler plate, +while the following section, +`Worked Example of Adding Command-line to an Application`_ covers the steps to do so manually. + +Creating a Command List File +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``dpdk-cmdline-gen.py`` script takes as input a list of commands to be used by the application. +While these can be piped to it via standard input, using a list file is probably best. + +The format of the list file must be: + +* Comment lines start with '#' as first non-whitespace character + +* One command per line + +* Variable fields are prefixed by the type-name in angle-brackets, for example: + + * ``message`` + + * ``port_id`` + + * ``src_ip`` + +* The help text for a command is given in the form of a comment on the same line as the command + +An example list file, with a variety of (unrelated) commands, is shown below:: + + # example list file + list # show all entries + add x y # add x and y + echo message # print message to screen + add socket path # add unix socket with the given path + quit # close the application + +Running the Generator Script +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To generate the necessary definitions for a command-line, run ``dpdk-cmdline-gen.py`` passing the list file as parameter. +The script will output the generated C code to standard output, +the contents of which are in the form of a C header file. +Optionally, an output filename may be specified via the ``-o/--output-file`` argument. + +The generated content includes: + +* The result structure definitions for each command + +* The token initializers for each structure field + +* An "extern" function prototype for the callback for each command + +* A parse context for each command, including the per-command comments as help string + +* A command-line context array definition, suitable for passing to ``cmdline_new`` + +If so desired, the script can also output function stubs for the callback functions for each command. +This behaviour is triggered by passing the ``--stubs`` flag to the script. +In this case, an output file must be provided with a filename ending in ".h", +and the callback stubs will be written to an equivalent ".c" file. + +.. note:: + + The stubs are written to a separate file, + to allow continuous use of the script to regenerate the command-line header, + without overwriting any code the user has added to the callback functions. + This makes it easy to incrementally add new commands to an existing application. + +Providing the Function Callbacks +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As discussed above, the script output is a header file, containing structure definitions, +but the callback functions themselves obviously have to be provided by the user. +These callback functions must be provided as non-static functions in a C file, +and named ``cmd__parsed``. +The function prototypes can be seen in the generated output header. + +The "cmdname" part of the function name is built up by combining the non-variable initial tokens in the command. +So, given the commands in our worked example below: ``quit`` and ``show port stats ``, +the callback functions would be: + +.. code:: c + + void + cmd_quit_parsed(void *parsed_result, struct cmdline *cl, void *data) + { + ... + } + + void + cmd_show_port_stats_parsed(void *parsed_result, struct cmdline *cl, void *data) + { + ... + } + +These functions must be provided by the developer, but, as stated above, +stub functions may be generated by the script automatically using the ``--stubs`` parameter. + +The same "cmdname" stem is used in the naming of the generated structures too. +To get at the results structure for each command above, +the ``parsed_result`` parameter should be cast to ``struct cmd_quit_result`` +or ``struct cmd_show_port_stats_result`` respectively. + +Integrating with the Application +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To integrate the script output with the application, +we must ``#include`` the generated header into our applications C file, +and then have the command-line created via either ``cmdline_new`` or ``cmdline_stdin_new``. +The first parameter to the function call should be the context array in the generated header file, +``ctx`` by default. (Modifiable via script parameter). + +The callback functions may be in this same file, or in a separate one - +they just need to be available to the linker at build-time. + +Limitations of the Script Approach +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The script approach works for most commands that a user may wish to add to an application. +However, it does not support the full range of functions possible with the DPDK command-line library. +For example, +it is not possible using the script to multiplex multiple commands into a single callback function. +To use this functionality, the user should follow the instructions in the next section +`Worked Example of Adding Command-line to an Application`_ to manually configure a command-line instance. + +Worked Example of Adding Command-line to an Application +------------------------------------------------------- + +The next few subsections will cover each of the steps listed in `Adding Command-line to an Application`_ in more detail, working through an example to add two commands to a command-line instance. Those two commands will be: From patchwork Fri Oct 27 11:01:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 133495 X-Patchwork-Delegate: david.marchand@redhat.com 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 5464E43215; Fri, 27 Oct 2023 13:01:54 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4D33840698; Fri, 27 Oct 2023 13:01:36 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by mails.dpdk.org (Postfix) with ESMTP id 4627D42831 for ; Fri, 27 Oct 2023 13:01:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698404495; x=1729940495; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Jz2dynU2x+m0JylnErYqJwKYKNcdBfxLxTIYKN84SI8=; b=oC+V3Nr0CsH3PnpcQ2pkwFHVagyr9FbpsebltDLHcUZ6qGVJabSLxKkN kz6HHp7Ydb4e+Pt3/bBW7XCnMwyX2oEq1nDHMa64HSctEDL0/hDB4xrwo h6MjHKdF8T20tI8gRQT0Q/f0dzQLxFNAPydRohTEE6TC3O82xsQGV2wic 7ka2m0GsvZaBtwkYH6nwt47Kqqw8jAi5RQzSJ//myPFGPIav4FXxIdAao 8jzgpSf7nNcYdCqBxA+OCE8jKlUaobAC4+cg3RW2eQyoAQSaWryUTMZuG Iy38u4DhfdMGLRVcBqi4Awey7Pcb3/wCkg6R2X6Qcps8KkCR+p63OeFGN w==; X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="546688" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="546688" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Oct 2023 04:01:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="883157852" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="883157852" Received: from silpixa00401385.ir.intel.com ([10.237.214.154]) by orsmga004.jf.intel.com with ESMTP; 27 Oct 2023 04:01:32 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: david.marchand@redhat.com, rjarry@redhat.com, Bruce Richardson , Aaron Conole Subject: [PATCH v7 3/9] ci: allow use of DPDK tools when building examples Date: Fri, 27 Oct 2023 12:01:11 +0100 Message-Id: <20231027110117.70995-4-bruce.richardson@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231027110117.70995-1-bruce.richardson@intel.com> References: <20230802170052.955323-1-bruce.richardson@intel.com> <20231027110117.70995-1-bruce.richardson@intel.com> MIME-Version: 1.0 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 To allow use of the DPDK python scripts (installed in $(prefix)/bin) from within the makefiles of our examples, we need to export the PATH variable with the location of our installed scripts from within our CI scripts. This matches what is already done for other paths e.g. the PKG_CONFIG_PATH variable. Signed-off-by: Bruce Richardson Reviewed-by: Aaron Conole --- .ci/linux-build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh index b09df07b55..4cdbe9b9e9 100755 --- a/.ci/linux-build.sh +++ b/.ci/linux-build.sh @@ -178,6 +178,7 @@ fi if [ "$BUILD_EXAMPLES" = "true" ]; then [ -d install ] || DESTDIR=$(pwd)/install meson install -C build export LD_LIBRARY_PATH=$(dirname $(find $(pwd)/install -name librte_eal.so)):$LD_LIBRARY_PATH + export PATH=$(dirname $(find $(pwd)/install -name dpdk-devbind.py)):$PATH export PKG_CONFIG_PATH=$(dirname $(find $(pwd)/install -name libdpdk.pc)):$PKG_CONFIG_PATH export PKGCONF="pkg-config --define-prefix" find build/examples -maxdepth 1 -type f -name "dpdk-*" | From patchwork Fri Oct 27 11:01:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 133496 X-Patchwork-Delegate: david.marchand@redhat.com 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 B31B343215; Fri, 27 Oct 2023 13:02:02 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7639742D7B; Fri, 27 Oct 2023 13:01:39 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by mails.dpdk.org (Postfix) with ESMTP id E95B642D66 for ; Fri, 27 Oct 2023 13:01:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698404496; x=1729940496; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AW56G/IYSfPHaAJnXp20C322BHIJo0FWAQ6wc3RIWrA=; b=T/vOXI2DTfGoOg3MrS5+09JxiXG+Px6bbonASaqsHXoF7Qp2kFIt4M6V Yufo3wao+dUztRlXlx+AY4BesrZFzYesWUNuIfkdRfjKXlfL1ztF80xl4 Kix9wBEEe17l9MQvcyNhdXirEr+HSxLhPhWLR1vydZgXFHMPrmjwlNQDD SlsmhnDdxeWMX7lqV31ET81kR78iIngDGZxyIPhAhZWsrvEQskp7eg0G4 l7+/oFKCowdXAHBRMZXyB5OMKQWleW/9gwEIRvh713sqAvKF3ozwppAT4 X99IBc9J/RHj/FQ43bVQYVdwX7mhWpfu6aYA6UvK2OmXrInCo/BFZi3pT Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="546694" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="546694" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Oct 2023 04:01:36 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="883157856" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="883157856" Received: from silpixa00401385.ir.intel.com ([10.237.214.154]) by orsmga004.jf.intel.com with ESMTP; 27 Oct 2023 04:01:34 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: david.marchand@redhat.com, rjarry@redhat.com, Bruce Richardson Subject: [PATCH v7 4/9] examples/simple_mp: auto-generate cmdline boilerplate Date: Fri, 27 Oct 2023 12:01:12 +0100 Message-Id: <20231027110117.70995-5-bruce.richardson@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231027110117.70995-1-bruce.richardson@intel.com> References: <20230802170052.955323-1-bruce.richardson@intel.com> <20231027110117.70995-1-bruce.richardson@intel.com> MIME-Version: 1.0 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 Use the dpdk-cmdline-gen script to autogenerate all the boilerplate structs and defines for the commandline part of the app. Signed-off-by: Bruce Richardson --- examples/multi_process/simple_mp/Makefile | 12 +- examples/multi_process/simple_mp/meson.build | 9 ++ .../multi_process/simple_mp/mp_commands.c | 106 ++---------------- .../multi_process/simple_mp/mp_commands.h | 14 --- .../multi_process/simple_mp/mp_commands.list | 3 + 5 files changed, 30 insertions(+), 114 deletions(-) delete mode 100644 examples/multi_process/simple_mp/mp_commands.h create mode 100644 examples/multi_process/simple_mp/mp_commands.list diff --git a/examples/multi_process/simple_mp/Makefile b/examples/multi_process/simple_mp/Makefile index 1d0a260e64..890b6b7e62 100644 --- a/examples/multi_process/simple_mp/Makefile +++ b/examples/multi_process/simple_mp/Makefile @@ -6,6 +6,7 @@ APP = simple_mp # all source are stored in SRCS-y SRCS-y := main.c mp_commands.c +SRC-DEPS := build/mp_commands.h PKGCONF ?= pkg-config @@ -22,10 +23,13 @@ static: build/$(APP)-static ln -sf $(APP)-static build/$(APP) PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null) -CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) +CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) -I build/ LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk) LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk) +build/mp_commands.h: mp_commands.list Makefile + dpdk-cmdline-gen.py -o $@ --context-name=simple_mp_ctx $< + ifeq ($(MAKECMDGOALS),static) # check for broken pkg-config ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),) @@ -36,10 +40,10 @@ endif CFLAGS += -DALLOW_EXPERIMENTAL_API -build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(SRC-DEPS) $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) -build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build +build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build $(SRC-DEPS) $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) build: @@ -47,5 +51,5 @@ build: .PHONY: clean clean: - rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared + rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared build/mp_commands.h test -d build && rmdir -p build || true diff --git a/examples/multi_process/simple_mp/meson.build b/examples/multi_process/simple_mp/meson.build index 359af4384d..e99b7a3f6f 100644 --- a/examples/multi_process/simple_mp/meson.build +++ b/examples/multi_process/simple_mp/meson.build @@ -7,7 +7,16 @@ # DPDK instance, use 'make' allow_experimental_apis = true + +cmd_h = custom_target('commands_hdr', + output: 'mp_commands.h', + input: files('mp_commands.list'), + capture: true, + command: [cmdline_gen_cmd, '--context-name=simple_mp_ctx', '@INPUT@'] +) + sources = files( 'mp_commands.c', 'main.c', ) +sources += cmd_h diff --git a/examples/multi_process/simple_mp/mp_commands.c b/examples/multi_process/simple_mp/mp_commands.c index a5f91b00be..df9fa94208 100644 --- a/examples/multi_process/simple_mp/mp_commands.c +++ b/examples/multi_process/simple_mp/mp_commands.c @@ -1,44 +1,18 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation + * Copyright(c) 2010-2023 Intel Corporation */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include #include -#include #include #include -#include -#include -#include -#include -#include #include "mp_commands.h" -/**********************************************************/ - -struct cmd_send_result { - cmdline_fixed_string_t action; - cmdline_fixed_string_t message; -}; +extern struct rte_ring *send_ring, *recv_ring; +extern struct rte_mempool *message_pool; +extern volatile int quit; -static void cmd_send_parsed(void *parsed_result, +void +cmd_send_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) { @@ -54,29 +28,8 @@ static void cmd_send_parsed(void *parsed_result, } } -cmdline_parse_token_string_t cmd_send_action = - TOKEN_STRING_INITIALIZER(struct cmd_send_result, action, "send"); -cmdline_parse_token_string_t cmd_send_message = - TOKEN_STRING_INITIALIZER(struct cmd_send_result, message, NULL); - -cmdline_parse_inst_t cmd_send = { - .f = cmd_send_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "send a string to another process", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_send_action, - (void *)&cmd_send_message, - NULL, - }, -}; - -/**********************************************************/ - -struct cmd_quit_result { - cmdline_fixed_string_t quit; -}; - -static void cmd_quit_parsed(__rte_unused void *parsed_result, +void +cmd_quit_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { @@ -84,26 +37,8 @@ static void cmd_quit_parsed(__rte_unused void *parsed_result, cmdline_quit(cl); } -cmdline_parse_token_string_t cmd_quit_quit = - TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); - -cmdline_parse_inst_t cmd_quit = { - .f = cmd_quit_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "close the application", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_quit_quit, - NULL, - }, -}; - -/**********************************************************/ - -struct cmd_help_result { - cmdline_fixed_string_t help; -}; - -static void cmd_help_parsed(__rte_unused void *parsed_result, +void +cmd_help_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { @@ -112,24 +47,3 @@ static void cmd_help_parsed(__rte_unused void *parsed_result, "send commands to the simple app. Commands supported are:\n\n" "- send [string]\n" "- help\n" "- quit\n\n"); } - -cmdline_parse_token_string_t cmd_help_help = - TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); - -cmdline_parse_inst_t cmd_help = { - .f = cmd_help_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "show help", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_help_help, - NULL, - }, -}; - -/****** CONTEXT (list of instruction) */ -cmdline_parse_ctx_t simple_mp_ctx[] = { - (cmdline_parse_inst_t *)&cmd_send, - (cmdline_parse_inst_t *)&cmd_quit, - (cmdline_parse_inst_t *)&cmd_help, - NULL, -}; diff --git a/examples/multi_process/simple_mp/mp_commands.h b/examples/multi_process/simple_mp/mp_commands.h deleted file mode 100644 index 5d67413e7c..0000000000 --- a/examples/multi_process/simple_mp/mp_commands.h +++ /dev/null @@ -1,14 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef _SIMPLE_MP_COMMANDS_H_ -#define _SIMPLE_MP_COMMANDS_H_ - -extern struct rte_ring *send_ring; -extern struct rte_mempool *message_pool; -extern volatile int quit; - -extern cmdline_parse_ctx_t simple_mp_ctx[]; - -#endif /* _SIMPLE_MP_COMMANDS_H_ */ diff --git a/examples/multi_process/simple_mp/mp_commands.list b/examples/multi_process/simple_mp/mp_commands.list new file mode 100644 index 0000000000..c8890cb071 --- /dev/null +++ b/examples/multi_process/simple_mp/mp_commands.list @@ -0,0 +1,3 @@ +send message # send a string to another process +help # show help +quit # close the application From patchwork Fri Oct 27 11:01:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 133497 X-Patchwork-Delegate: david.marchand@redhat.com 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 A52F043215; Fri, 27 Oct 2023 13:02:12 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id ACD0A42DC3; Fri, 27 Oct 2023 13:01:40 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by mails.dpdk.org (Postfix) with ESMTP id DA76B42D66 for ; Fri, 27 Oct 2023 13:01:37 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698404498; x=1729940498; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=uasJXdRcLITlzLkh3GtIW4niegt0hfdvu945Ddp2i1A=; b=e0N/Sj2nXGukI0dBgK9GEhMYV2totbvqBcGCR1xDCpwEuHtKEV3ukDjJ FTKi7nLuQFhZiOcgyrriAhF4wyIkTiC6E+wjsBt1on8jtU8JyYN4dGU71 CIhMdxbmQhNwXK3bem86HgfKVAsW/6YQtOH76yDBtkRNr/imJhwzbR6W9 XquJQ6zFjg03Aqy//3NxGkJBYGOP6+AP4lhPGehujL+Aea/1pTCrznKV4 o/gvKH8ejXu2hjbMNde9KiYY4Bz6vFQ1cnSJtsdOiE1EMI4Q0XxESjfYx kv03oSfm1K7BUZ6wY9cxZoqM/0GrmTT4Hwwr8frZqPM6sftYkyigC6+cN Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="546699" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="546699" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Oct 2023 04:01:38 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="883157861" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="883157861" Received: from silpixa00401385.ir.intel.com ([10.237.214.154]) by orsmga004.jf.intel.com with ESMTP; 27 Oct 2023 04:01:35 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: david.marchand@redhat.com, rjarry@redhat.com, Bruce Richardson Subject: [PATCH v7 5/9] examples/hotplug_mp: auto-generate cmdline boilerplate Date: Fri, 27 Oct 2023 12:01:13 +0100 Message-Id: <20231027110117.70995-6-bruce.richardson@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231027110117.70995-1-bruce.richardson@intel.com> References: <20230802170052.955323-1-bruce.richardson@intel.com> <20231027110117.70995-1-bruce.richardson@intel.com> MIME-Version: 1.0 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 Use the dpdk-cmdline-gen script to autogenerate all the boilerplate structs and defines for the commandline part of the app. Signed-off-by: Bruce Richardson --- examples/multi_process/hotplug_mp/Makefile | 12 +- examples/multi_process/hotplug_mp/commands.c | 147 ++---------------- examples/multi_process/hotplug_mp/commands.h | 10 -- .../multi_process/hotplug_mp/commands.list | 8 + examples/multi_process/hotplug_mp/meson.build | 9 ++ 5 files changed, 38 insertions(+), 148 deletions(-) delete mode 100644 examples/multi_process/hotplug_mp/commands.h create mode 100644 examples/multi_process/hotplug_mp/commands.list diff --git a/examples/multi_process/hotplug_mp/Makefile b/examples/multi_process/hotplug_mp/Makefile index 6b20d6e49a..81ee85cd6b 100644 --- a/examples/multi_process/hotplug_mp/Makefile +++ b/examples/multi_process/hotplug_mp/Makefile @@ -6,6 +6,7 @@ APP = hotplug_mp # all source are stored in SRCS-y SRCS-y := main.c commands.c +SRC-DEPS := build/commands.h PKGCONF ?= pkg-config @@ -22,10 +23,13 @@ static: build/$(APP)-static ln -sf $(APP)-static build/$(APP) PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null) -CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) +CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) -I build/ LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk) LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk) +build/commands.h: commands.list Makefile + dpdk-cmdline-gen.py -o $@ --context-name=main_ctx $< + ifeq ($(MAKECMDGOALS),static) # check for broken pkg-config ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),) @@ -36,10 +40,10 @@ endif CFLAGS += -DALLOW_EXPERIMENTAL_API -build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(SRC-DEPS) $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) -build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build +build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build $(SRC-DEPS) $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) build: @@ -47,5 +51,5 @@ build: .PHONY: clean clean: - rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared + rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared build/commands.h test -d build && rmdir -p build || true diff --git a/examples/multi_process/hotplug_mp/commands.c b/examples/multi_process/hotplug_mp/commands.c index 88f44e00a0..900eb9f774 100644 --- a/examples/multi_process/hotplug_mp/commands.c +++ b/examples/multi_process/hotplug_mp/commands.c @@ -1,24 +1,12 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018 Intel Corporation. + * Copyright(c) 2018-2023 Intel Corporation. */ -#include -#include -#include -#include -#include -#include - #include #include +#include "commands.h" -/**********************************************************/ - -struct cmd_help_result { - cmdline_fixed_string_t help; -}; - -static void cmd_help_parsed(__rte_unused void *parsed_result, +void cmd_help_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { @@ -29,52 +17,16 @@ static void cmd_help_parsed(__rte_unused void *parsed_result, "- list\n\n"); } -cmdline_parse_token_string_t cmd_help_help = - TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); - -cmdline_parse_inst_t cmd_help = { - .f = cmd_help_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "show help", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_help_help, - NULL, - }, -}; - -/**********************************************************/ - -struct cmd_quit_result { - cmdline_fixed_string_t quit; -}; - -static void cmd_quit_parsed(__rte_unused void *parsed_result, +void +cmd_quit_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { cmdline_quit(cl); } -cmdline_parse_token_string_t cmd_quit_quit = - TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); - -cmdline_parse_inst_t cmd_quit = { - .f = cmd_quit_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "quit", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_quit_quit, - NULL, - }, -}; - -/**********************************************************/ - -struct cmd_list_result { - cmdline_fixed_string_t list; -}; - -static void cmd_list_parsed(__rte_unused void *parsed_result, +void +cmd_list_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { @@ -92,31 +44,12 @@ static void cmd_list_parsed(__rte_unused void *parsed_result, } } -cmdline_parse_token_string_t cmd_list_list = - TOKEN_STRING_INITIALIZER(struct cmd_list_result, list, "list"); - -cmdline_parse_inst_t cmd_list = { - .f = cmd_list_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "list all devices", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_list_list, - NULL, - }, -}; - -/**********************************************************/ - -struct cmd_dev_attach_result { - cmdline_fixed_string_t attach; - cmdline_fixed_string_t devargs; -}; - -static void cmd_dev_attach_parsed(void *parsed_result, +void +cmd_attach_parsed(void *parsed_result, struct cmdline *cl, __rte_unused void *data) { - struct cmd_dev_attach_result *res = parsed_result; + struct cmd_attach_result *res = parsed_result; struct rte_devargs da; memset(&da, 0, sizeof(da)); @@ -134,35 +67,12 @@ static void cmd_dev_attach_parsed(void *parsed_result, rte_devargs_reset(&da); } -cmdline_parse_token_string_t cmd_dev_attach_attach = - TOKEN_STRING_INITIALIZER(struct cmd_dev_attach_result, attach, - "attach"); -cmdline_parse_token_string_t cmd_dev_attach_devargs = - TOKEN_STRING_INITIALIZER(struct cmd_dev_attach_result, devargs, NULL); - -cmdline_parse_inst_t cmd_attach_device = { - .f = cmd_dev_attach_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "attach a device", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_dev_attach_attach, - (void *)&cmd_dev_attach_devargs, - NULL, - }, -}; - -/**********************************************************/ - -struct cmd_dev_detach_result { - cmdline_fixed_string_t detach; - cmdline_fixed_string_t devargs; -}; - -static void cmd_dev_detach_parsed(void *parsed_result, +void +cmd_detach_parsed(void *parsed_result, struct cmdline *cl, __rte_unused void *data) { - struct cmd_dev_detach_result *res = parsed_result; + struct cmd_detach_result *res = parsed_result; struct rte_devargs da; memset(&da, 0, sizeof(da)); @@ -181,34 +91,3 @@ static void cmd_dev_detach_parsed(void *parsed_result, da.name); rte_devargs_reset(&da); } - -cmdline_parse_token_string_t cmd_dev_detach_detach = - TOKEN_STRING_INITIALIZER(struct cmd_dev_detach_result, detach, - "detach"); - -cmdline_parse_token_string_t cmd_dev_detach_devargs = - TOKEN_STRING_INITIALIZER(struct cmd_dev_detach_result, devargs, NULL); - -cmdline_parse_inst_t cmd_detach_device = { - .f = cmd_dev_detach_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "detach a device", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_dev_detach_detach, - (void *)&cmd_dev_detach_devargs, - NULL, - }, -}; - -/**********************************************************/ -/**********************************************************/ -/****** CONTEXT (list of instruction) */ - -cmdline_parse_ctx_t main_ctx[] = { - (cmdline_parse_inst_t *)&cmd_help, - (cmdline_parse_inst_t *)&cmd_quit, - (cmdline_parse_inst_t *)&cmd_list, - (cmdline_parse_inst_t *)&cmd_attach_device, - (cmdline_parse_inst_t *)&cmd_detach_device, - NULL, -}; diff --git a/examples/multi_process/hotplug_mp/commands.h b/examples/multi_process/hotplug_mp/commands.h deleted file mode 100644 index afcf177dba..0000000000 --- a/examples/multi_process/hotplug_mp/commands.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018 Intel Corporation - */ - -#ifndef _COMMANDS_H_ -#define _COMMANDS_H_ - -extern cmdline_parse_ctx_t main_ctx[]; - -#endif /* _COMMANDS_H_ */ diff --git a/examples/multi_process/hotplug_mp/commands.list b/examples/multi_process/hotplug_mp/commands.list new file mode 100644 index 0000000000..8064df77c0 --- /dev/null +++ b/examples/multi_process/hotplug_mp/commands.list @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation +# +attach devargs # attach a device +detach devargs # detach a device +list # list all devices +help # show help +quit # quit diff --git a/examples/multi_process/hotplug_mp/meson.build b/examples/multi_process/hotplug_mp/meson.build index a1ad98ca2e..7a0e9ca47a 100644 --- a/examples/multi_process/hotplug_mp/meson.build +++ b/examples/multi_process/hotplug_mp/meson.build @@ -7,7 +7,16 @@ # DPDK instance, use 'make' allow_experimental_apis = true + +cmd_h = custom_target('commands_hdr', + output: 'commands.h', + input: files('commands.list'), + capture: true, + command: [cmdline_gen_cmd, '--context-name=main_ctx', '@INPUT@'] +) + sources = files( 'commands.c', 'main.c', ) +sources += cmd_h From patchwork Fri Oct 27 11:01:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 133498 X-Patchwork-Delegate: david.marchand@redhat.com 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 9B17E43215; Fri, 27 Oct 2023 13:02:21 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id DE91F42DE0; Fri, 27 Oct 2023 13:01:41 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by mails.dpdk.org (Postfix) with ESMTP id A35AD42DC3 for ; Fri, 27 Oct 2023 13:01:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698404500; x=1729940500; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5icIuUY+8/2afBY+54eoAIutWNrbC2j868jtw+6qSBE=; b=MTYOIEcGPMvX2DV+KpUBRIg+XcATMvzXWZkxP53x61dIWGSofrSt2rtA E7Q16vSCoyBP7vQyizrxV0s4rf1MPlv6UtNH9VgGCkELFwFSuHLTuWu5+ H2bxf+U+PdPJW+f6+JSGy7suBNKXEGohlVa+aS/XImDqiEdERaf95FUOV wpIZP966RQDkOo5OIM1t4z/+BE43W+Hxh3Q6Z5vrLHVngis7CLhtG6asC +qq7VbNy/cY4PrnGJ3slXKWX4H2k7tdPk82YRmS/ad3yABKhLDPRFm5eu TQgLbXd3eCU69nXLZockedLGc4w0RJeh+XA4wIAUCUBsn5yuWU00f7eVk w==; X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="546705" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="546705" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Oct 2023 04:01:39 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="883157864" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="883157864" Received: from silpixa00401385.ir.intel.com ([10.237.214.154]) by orsmga004.jf.intel.com with ESMTP; 27 Oct 2023 04:01:37 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: david.marchand@redhat.com, rjarry@redhat.com, Bruce Richardson Subject: [PATCH v7 6/9] examples/bond: auto-generate cmdline boilerplate Date: Fri, 27 Oct 2023 12:01:14 +0100 Message-Id: <20231027110117.70995-7-bruce.richardson@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231027110117.70995-1-bruce.richardson@intel.com> References: <20230802170052.955323-1-bruce.richardson@intel.com> <20231027110117.70995-1-bruce.richardson@intel.com> MIME-Version: 1.0 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 Use the dpdk-cmdline-gen script to autogenerate all the boilerplate structs and defines for the commandline part of the app. Signed-off-by: Bruce Richardson --- Note: the original help text on some of the commands in this example were not useful "this command do not handle any arguments". Therefore, when converting over to the command script, the per-command help info has been updated with reference to the code rather than a literal transfer of the existing help text, as was done with the previous 2 example apps. --- examples/bond/Makefile | 12 +- examples/bond/commands.list | 6 + examples/bond/main.c | 161 ++---------------- examples/bond/main.h | 10 -- examples/bond/meson.build | 8 + .../multi_process/simple_mp/mp_commands.list | 3 + 6 files changed, 40 insertions(+), 160 deletions(-) create mode 100644 examples/bond/commands.list delete mode 100644 examples/bond/main.h diff --git a/examples/bond/Makefile b/examples/bond/Makefile index ad711a5bee..d87c7a32ba 100644 --- a/examples/bond/Makefile +++ b/examples/bond/Makefile @@ -6,6 +6,7 @@ APP = bond_app # all source are stored in SRCS-y SRCS-y := main.c +SRC-DEPS := build/commands.h PKGCONF ?= pkg-config @@ -24,10 +25,13 @@ static: build/$(APP)-static LDFLAGS += -lrte_net_bond PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null) -CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) +CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) -I build/ LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk) LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk) +build/commands.h: commands.list Makefile + dpdk-cmdline-gen.py -o $@ --context-name=main_ctx $< + ifeq ($(MAKECMDGOALS),static) # check for broken pkg-config ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),) @@ -38,10 +42,10 @@ endif CFLAGS += -DALLOW_EXPERIMENTAL_API -build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(SRC-DEPS) $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) -build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build +build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build $(SRC-DEPS) $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) build: @@ -49,5 +53,5 @@ build: .PHONY: clean clean: - rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared + rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared build/*.h test -d build && rmdir -p build || true diff --git a/examples/bond/commands.list b/examples/bond/commands.list new file mode 100644 index 0000000000..a10bf75708 --- /dev/null +++ b/examples/bond/commands.list @@ -0,0 +1,6 @@ +send ip # sends one ARPrequest through bonding for IP +start # starts listening if not started at startup +stop # stops listening +show # shows some bond info, e.g. active members +help # show help +quit # close application diff --git a/examples/bond/main.c b/examples/bond/main.c index 90f422ec11..8528abf675 100644 --- a/examples/bond/main.c +++ b/examples/bond/main.c @@ -45,16 +45,8 @@ #include #include -#include -#include -#include -#include -#include -#include #include -#include - -#include "main.h" +#include "commands.h" #define RTE_LOGTYPE_DCB RTE_LOGTYPE_USER1 @@ -462,11 +454,7 @@ static int lcore_main(__rte_unused void *arg1) return 0; } -struct cmd_obj_send_result { - cmdline_fixed_string_t action; - cmdline_ipaddr_t ip; -}; -static inline void get_string(struct cmd_obj_send_result *res, char *buf, uint8_t size) +static inline void get_string(struct cmd_send_result *res, char *buf, uint8_t size) { snprintf(buf, size, NIPQUAD_FMT, ((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[0]), @@ -475,12 +463,11 @@ static inline void get_string(struct cmd_obj_send_result *res, char *buf, uint8_ ((unsigned)((unsigned char *)&(res->ip.addr.ipv4))[3]) ); } -static void cmd_obj_send_parsed(void *parsed_result, - __rte_unused struct cmdline *cl, - __rte_unused void *data) +void +cmd_send_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) { - struct cmd_obj_send_result *res = parsed_result; + struct cmd_send_result *res = parsed_result; char ip_str[INET6_ADDRSTRLEN]; struct rte_ether_addr bond_mac_addr; @@ -544,29 +531,8 @@ static void cmd_obj_send_parsed(void *parsed_result, cmdline_printf(cl, "\n"); } -cmdline_parse_token_string_t cmd_obj_action_send = - TOKEN_STRING_INITIALIZER(struct cmd_obj_send_result, action, "send"); -cmdline_parse_token_ipaddr_t cmd_obj_ip = - TOKEN_IPV4_INITIALIZER(struct cmd_obj_send_result, ip); - -cmdline_parse_inst_t cmd_obj_send = { - .f = cmd_obj_send_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "send client_ip", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_obj_action_send, - (void *)&cmd_obj_ip, - NULL, - }, -}; - -struct cmd_start_result { - cmdline_fixed_string_t start; -}; - -static void cmd_start_parsed(__rte_unused void *parsed_result, - struct cmdline *cl, - __rte_unused void *data) +void +cmd_start_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { int worker_core_id = rte_lcore_id(); @@ -605,26 +571,8 @@ static void cmd_start_parsed(__rte_unused void *parsed_result, ); } -cmdline_parse_token_string_t cmd_start_start = - TOKEN_STRING_INITIALIZER(struct cmd_start_result, start, "start"); - -cmdline_parse_inst_t cmd_start = { - .f = cmd_start_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "starts listening if not started at startup", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_start_start, - NULL, - }, -}; - -struct cmd_help_result { - cmdline_fixed_string_t help; -}; - -static void cmd_help_parsed(__rte_unused void *parsed_result, - struct cmdline *cl, - __rte_unused void *data) +void +cmd_help_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { cmdline_printf(cl, "ALB - link bonding mode 6 example\n" @@ -637,26 +585,8 @@ static void cmd_help_parsed(__rte_unused void *parsed_result, ); } -cmdline_parse_token_string_t cmd_help_help = - TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); - -cmdline_parse_inst_t cmd_help = { - .f = cmd_help_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "show help", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_help_help, - NULL, - }, -}; - -struct cmd_stop_result { - cmdline_fixed_string_t stop; -}; - -static void cmd_stop_parsed(__rte_unused void *parsed_result, - struct cmdline *cl, - __rte_unused void *data) +void +cmd_stop_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { rte_spinlock_lock(&global_flag_stru_p->lock); if (global_flag_stru_p->LcoreMainIsRunning == 0) { @@ -678,26 +608,8 @@ static void cmd_stop_parsed(__rte_unused void *parsed_result, rte_spinlock_unlock(&global_flag_stru_p->lock); } -cmdline_parse_token_string_t cmd_stop_stop = - TOKEN_STRING_INITIALIZER(struct cmd_stop_result, stop, "stop"); - -cmdline_parse_inst_t cmd_stop = { - .f = cmd_stop_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "this command do not handle any arguments", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_stop_stop, - NULL, - }, -}; - -struct cmd_quit_result { - cmdline_fixed_string_t quit; -}; - -static void cmd_quit_parsed(__rte_unused void *parsed_result, - struct cmdline *cl, - __rte_unused void *data) +void +cmd_quit_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { rte_spinlock_lock(&global_flag_stru_p->lock); if (global_flag_stru_p->LcoreMainIsRunning == 0) { @@ -721,26 +633,8 @@ static void cmd_quit_parsed(__rte_unused void *parsed_result, cmdline_quit(cl); } -cmdline_parse_token_string_t cmd_quit_quit = - TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); - -cmdline_parse_inst_t cmd_quit = { - .f = cmd_quit_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "this command do not handle any arguments", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_quit_quit, - NULL, - }, -}; - -struct cmd_show_result { - cmdline_fixed_string_t show; -}; - -static void cmd_show_parsed(__rte_unused void *parsed_result, - struct cmdline *cl, - __rte_unused void *data) +void +cmd_show_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { uint16_t members[16] = {0}; uint8_t len = 16; @@ -772,31 +666,6 @@ static void cmd_show_parsed(__rte_unused void *parsed_result, rte_spinlock_unlock(&global_flag_stru_p->lock); } -cmdline_parse_token_string_t cmd_show_show = - TOKEN_STRING_INITIALIZER(struct cmd_show_result, show, "show"); - -cmdline_parse_inst_t cmd_show = { - .f = cmd_show_parsed, /* function to call */ - .data = NULL, /* 2nd arg of func */ - .help_str = "this command do not handle any arguments", - .tokens = { /* token list, NULL terminated */ - (void *)&cmd_show_show, - NULL, - }, -}; - -/****** CONTEXT (list of instruction) */ - -cmdline_parse_ctx_t main_ctx[] = { - (cmdline_parse_inst_t *)&cmd_start, - (cmdline_parse_inst_t *)&cmd_obj_send, - (cmdline_parse_inst_t *)&cmd_stop, - (cmdline_parse_inst_t *)&cmd_show, - (cmdline_parse_inst_t *)&cmd_quit, - (cmdline_parse_inst_t *)&cmd_help, - NULL, -}; - /* prompt function, called from main on MAIN lcore */ static void prompt(__rte_unused void *arg1) { diff --git a/examples/bond/main.h b/examples/bond/main.h deleted file mode 100644 index f91ed9c885..0000000000 --- a/examples/bond/main.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2015 Intel Corporation - */ - -#ifndef _MAIN_H_ -#define _MAIN_H_ - -int main(int argc, char *argv[]); - -#endif /* ifndef _MAIN_H_ */ diff --git a/examples/bond/meson.build b/examples/bond/meson.build index ed22b7887d..bfbec04ecd 100644 --- a/examples/bond/meson.build +++ b/examples/bond/meson.build @@ -11,3 +11,11 @@ allow_experimental_apis = true sources = files( 'main.c', ) + +cmd_h = custom_target('commands_hdr', + output: 'commands.h', + input: files('commands.list'), + capture: true, + command: [cmdline_gen_cmd, '--context-name=main_ctx', '@INPUT@'] +) +sources += cmd_h diff --git a/examples/multi_process/simple_mp/mp_commands.list b/examples/multi_process/simple_mp/mp_commands.list index c8890cb071..afce5eb1c1 100644 --- a/examples/multi_process/simple_mp/mp_commands.list +++ b/examples/multi_process/simple_mp/mp_commands.list @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation +# send message # send a string to another process help # show help quit # close the application From patchwork Fri Oct 27 11:01:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 133499 X-Patchwork-Delegate: david.marchand@redhat.com 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 9817843215; Fri, 27 Oct 2023 13:02:32 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7D8B642E0A; Fri, 27 Oct 2023 13:01:44 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by mails.dpdk.org (Postfix) with ESMTP id 4D40142DDA for ; Fri, 27 Oct 2023 13:01:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698404502; x=1729940502; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=eHJRZHmN4kFqKeivEFmViSHUGQL6TI2gSbwpJ0KbhFQ=; b=BK9lf3L4L+MM/CUmYyhhlrbZ88Kl9KbgmEBKbqZ+9hfoIlYsbne1pAs8 8RRTqe3D02I08i4rGmlKh8tFbchN8CZ1uv2dXcxkLh3x6+nZqyHMQL0El jb12wl2OXs8JYyeZ9yjTURmaM4e4CfIOHT9K+91ZAXm4eyWZ7PfbGHAie 93w1ZVKT4a5ItpIpA1wsd9WYL0sE0qZiE8VsWT11pB/qy6jWzzbm5rGQj r95jxw/YWkp1BsKmNcwqbI+1qEMMh9485zA52e8DaBTpPx952OlcqZQDe fFIvWlF1RbDss8XNbaQ6Vr2YTLuZI3HaTfSh4KilFHfiIcuOmRwN7CFEn A==; X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="546710" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="546710" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Oct 2023 04:01:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="883157872" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="883157872" Received: from silpixa00401385.ir.intel.com ([10.237.214.154]) by orsmga004.jf.intel.com with ESMTP; 27 Oct 2023 04:01:39 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: david.marchand@redhat.com, rjarry@redhat.com, Bruce Richardson Subject: [PATCH v7 7/9] examples/vdpa: auto-generate cmdline boilerplate Date: Fri, 27 Oct 2023 12:01:15 +0100 Message-Id: <20231027110117.70995-8-bruce.richardson@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231027110117.70995-1-bruce.richardson@intel.com> References: <20230802170052.955323-1-bruce.richardson@intel.com> <20231027110117.70995-1-bruce.richardson@intel.com> MIME-Version: 1.0 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 Use the dpdk-cmdline-gen script to autogenerate all the boilerplate structs and defines for the commandline part of the app. Signed-off-by: Bruce Richardson --- examples/vdpa/Makefile | 12 ++-- examples/vdpa/commands.list | 8 +++ examples/vdpa/main.c | 131 ++---------------------------------- examples/vdpa/meson.build | 7 ++ 4 files changed, 30 insertions(+), 128 deletions(-) create mode 100644 examples/vdpa/commands.list diff --git a/examples/vdpa/Makefile b/examples/vdpa/Makefile index d974db4f40..aa60a000cf 100644 --- a/examples/vdpa/Makefile +++ b/examples/vdpa/Makefile @@ -6,6 +6,7 @@ APP = vdpa # all source are stored in SRCS-y SRCS-y := main.c +SRC-DEPS := build/commands.h CFLAGS += -DALLOW_EXPERIMENTAL_API PKGCONF ?= pkg-config @@ -23,10 +24,13 @@ static: build/$(APP)-static ln -sf $(APP)-static build/$(APP) PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null) -CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) +CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) -I build/ LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk) LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk) +build/commands.h: commands.list Makefile + dpdk-cmdline-gen.py -o $@ --context-name=main_ctx $< + ifeq ($(MAKECMDGOALS),static) # check for broken pkg-config ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),) @@ -35,10 +39,10 @@ $(error "Cannot generate statically-linked binaries with this version of pkg-con endif endif -build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(SRC-DEPS) $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) -build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build +build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build $(SRC-DEPS) $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) build: @@ -46,5 +50,5 @@ build: .PHONY: clean clean: - rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared + rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared build/*.h test -d build && rmdir -p build || true diff --git a/examples/vdpa/commands.list b/examples/vdpa/commands.list new file mode 100644 index 0000000000..1eb8486c45 --- /dev/null +++ b/examples/vdpa/commands.list @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation +# +help # show help +list # list all available vdpa devices +create socket_path bdf # create a new vdpa port +stats bdf qid # show device statistics +quit # exit application diff --git a/examples/vdpa/main.c b/examples/vdpa/main.c index 4d3203f3a7..289db26498 100644 --- a/examples/vdpa/main.c +++ b/examples/vdpa/main.c @@ -16,11 +16,8 @@ #include #include -#include #include -#include -#include -#include +#include "commands.h" /* auto-generated file from commands.list */ #include "vdpa_blk_compact.h" #define MAX_PATH_LEN 128 @@ -301,14 +298,9 @@ signal_handler(int signum) } } -/* interactive cmds */ +/* interactive cmd functions */ -/* *** Help command with introduction. *** */ -struct cmd_help_result { - cmdline_fixed_string_t help; -}; - -static void cmd_help_parsed(__rte_unused void *parsed_result, +void cmd_help_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { @@ -325,25 +317,7 @@ static void cmd_help_parsed(__rte_unused void *parsed_result, ); } -cmdline_parse_token_string_t cmd_help_help = - TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); - -cmdline_parse_inst_t cmd_help = { - .f = cmd_help_parsed, - .data = NULL, - .help_str = "show help", - .tokens = { - (void *)&cmd_help_help, - NULL, - }, -}; - -/* *** List all available vdpa devices *** */ -struct cmd_list_result { - cmdline_fixed_string_t action; -}; - -static void cmd_list_vdpa_devices_parsed( +void cmd_list_parsed( __rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) @@ -376,27 +350,7 @@ static void cmd_list_vdpa_devices_parsed( } } -cmdline_parse_token_string_t cmd_action_list = - TOKEN_STRING_INITIALIZER(struct cmd_list_result, action, "list"); - -cmdline_parse_inst_t cmd_list_vdpa_devices = { - .f = cmd_list_vdpa_devices_parsed, - .data = NULL, - .help_str = "list all available vdpa devices", - .tokens = { - (void *)&cmd_action_list, - NULL, - }, -}; - -/* *** Create new vdpa port *** */ -struct cmd_create_result { - cmdline_fixed_string_t action; - cmdline_fixed_string_t socket_path; - cmdline_fixed_string_t bdf; -}; - -static void cmd_create_vdpa_port_parsed(void *parsed_result, +void cmd_create_parsed(void *parsed_result, struct cmdline *cl, __rte_unused void *data) { @@ -417,33 +371,7 @@ static void cmd_create_vdpa_port_parsed(void *parsed_result, devcnt++; } -cmdline_parse_token_string_t cmd_action_create = - TOKEN_STRING_INITIALIZER(struct cmd_create_result, action, "create"); -cmdline_parse_token_string_t cmd_socket_path = - TOKEN_STRING_INITIALIZER(struct cmd_create_result, socket_path, NULL); -cmdline_parse_token_string_t cmd_bdf = - TOKEN_STRING_INITIALIZER(struct cmd_create_result, bdf, NULL); - -cmdline_parse_inst_t cmd_create_vdpa_port = { - .f = cmd_create_vdpa_port_parsed, - .data = NULL, - .help_str = "create a new vdpa port", - .tokens = { - (void *)&cmd_action_create, - (void *)&cmd_socket_path, - (void *)&cmd_bdf, - NULL, - }, -}; - -/* *** STATS *** */ -struct cmd_stats_result { - cmdline_fixed_string_t stats; - cmdline_fixed_string_t bdf; - uint16_t qid; -}; - -static void cmd_device_stats_parsed(void *parsed_result, struct cmdline *cl, +void cmd_stats_parsed(void *parsed_result, struct cmdline *cl, __rte_unused void *data) { struct cmd_stats_result *res = parsed_result; @@ -525,31 +453,7 @@ static void cmd_device_stats_parsed(void *parsed_result, struct cmdline *cl, } } -cmdline_parse_token_string_t cmd_device_stats_ = - TOKEN_STRING_INITIALIZER(struct cmd_stats_result, stats, "stats"); -cmdline_parse_token_string_t cmd_device_bdf = - TOKEN_STRING_INITIALIZER(struct cmd_stats_result, bdf, NULL); -cmdline_parse_token_num_t cmd_queue_id = - TOKEN_NUM_INITIALIZER(struct cmd_stats_result, qid, RTE_UINT32); - -cmdline_parse_inst_t cmd_device_stats = { - .f = cmd_device_stats_parsed, - .data = NULL, - .help_str = "stats: show device statistics", - .tokens = { - (void *)&cmd_device_stats_, - (void *)&cmd_device_bdf, - (void *)&cmd_queue_id, - NULL, - }, -}; - -/* *** QUIT *** */ -struct cmd_quit_result { - cmdline_fixed_string_t quit; -}; - -static void cmd_quit_parsed(__rte_unused void *parsed_result, +void cmd_quit_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) { @@ -557,27 +461,6 @@ static void cmd_quit_parsed(__rte_unused void *parsed_result, cmdline_quit(cl); } -cmdline_parse_token_string_t cmd_quit_quit = - TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); - -cmdline_parse_inst_t cmd_quit = { - .f = cmd_quit_parsed, - .data = NULL, - .help_str = "quit: exit application", - .tokens = { - (void *)&cmd_quit_quit, - NULL, - }, -}; -cmdline_parse_ctx_t main_ctx[] = { - (cmdline_parse_inst_t *)&cmd_help, - (cmdline_parse_inst_t *)&cmd_list_vdpa_devices, - (cmdline_parse_inst_t *)&cmd_create_vdpa_port, - (cmdline_parse_inst_t *)&cmd_device_stats, - (cmdline_parse_inst_t *)&cmd_quit, - NULL, -}; - int main(int argc, char *argv[]) { diff --git a/examples/vdpa/meson.build b/examples/vdpa/meson.build index bd086050dc..a48028da4d 100644 --- a/examples/vdpa/meson.build +++ b/examples/vdpa/meson.build @@ -16,3 +16,10 @@ allow_experimental_apis = true sources = files( 'main.c', ) +cmd_h = custom_target('commands_hdr', + output: 'commands.h', + input: files('commands.list'), + capture: true, + command: [cmdline_gen_cmd, '--context-name=main_ctx', '@INPUT@'] +) +sources += cmd_h From patchwork Fri Oct 27 11:01:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 133500 X-Patchwork-Delegate: david.marchand@redhat.com 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 F0A8743215; Fri, 27 Oct 2023 13:02:40 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id C0E2042E16; Fri, 27 Oct 2023 13:01:45 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by mails.dpdk.org (Postfix) with ESMTP id B0FFC42DE4 for ; Fri, 27 Oct 2023 13:01:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698404503; x=1729940503; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=v7tOydz7c2Oi7K1r/7WRSvnD7983WFxKHsT4L58/8bk=; b=oERTwo6Ye4NyZsCmQJhH+8GWBv3Vd+Y8OhVgWfM0PWJRavF1ImEkPSIZ xZHlZdmHv4/Z1gVJYWTlfcnQgq1T1JsBj0hpxauHX3gagcxI622U9XBEh zgaeTslZow1ywotAaYTtfU/Fb5LSWSVytE0dDEJOI0p8XQoveDqJpFFoa JMOk3l67hAx2SEqO96lvMrXkcsdm4zTf+5GlraXX86T2QacgqkRqjY7Rx kXtZwDHm+3bLHu2Ho/+T52xO7UGN9l28yinC7QTKmfKqOq1aYQdPT/U+4 ZKVMxXsi9pgVy2V1T5qnDhau75c0nDeL8Hy+QS+Nffj2G131ZrLb2Tybn Q==; X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="546715" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="546715" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Oct 2023 04:01:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="883157876" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="883157876" Received: from silpixa00401385.ir.intel.com ([10.237.214.154]) by orsmga004.jf.intel.com with ESMTP; 27 Oct 2023 04:01:41 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: david.marchand@redhat.com, rjarry@redhat.com, Bruce Richardson Subject: [PATCH v7 8/9] buildtools/dpdk-cmdline-gen: support option strings Date: Fri, 27 Oct 2023 12:01:16 +0100 Message-Id: <20231027110117.70995-9-bruce.richardson@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231027110117.70995-1-bruce.richardson@intel.com> References: <20230802170052.955323-1-bruce.richardson@intel.com> <20231027110117.70995-1-bruce.richardson@intel.com> MIME-Version: 1.0 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 Add support to the commandline generator for option strings, where there are only a limited number of acceptable values to be passed as a parameter. Signed-off-by: Bruce Richardson --- buildtools/dpdk-cmdline-gen.py | 7 +++++++ doc/guides/prog_guide/cmdline.rst | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/buildtools/dpdk-cmdline-gen.py b/buildtools/dpdk-cmdline-gen.py index c208121363..8922bb5fc3 100755 --- a/buildtools/dpdk-cmdline-gen.py +++ b/buildtools/dpdk-cmdline-gen.py @@ -73,6 +73,13 @@ def process_command(lineno, tokens, comment): f"cmdline_parse_token_ipaddr_t cmd_{name}_{t_name}_tok =\n" f"\tTOKEN_IPV4_INITIALIZER(struct cmd_{name}_result, {t_name});" ) + elif t_type.startswith("(") and t_type.endswith(")"): + result_struct.append(f"\tcmdline_fixed_string_t {t_name};") + t_val = f'"{t_type[1:-1].replace(",","#")}"' + initializers.append( + f"static cmdline_parse_token_string_t cmd_{name}_{t_name}_tok =\n" + f"\tTOKEN_STRING_INITIALIZER(struct cmd_{name}_result, {t_name}, {t_val});" + ) else: raise TypeError(f"Error line {lineno + 1}: unknown token type '{t_type}'") token_list.append(f"cmd_{name}_{t_name}_tok") diff --git a/doc/guides/prog_guide/cmdline.rst b/doc/guides/prog_guide/cmdline.rst index 0b96b770e2..42e6a54bf4 100644 --- a/doc/guides/prog_guide/cmdline.rst +++ b/doc/guides/prog_guide/cmdline.rst @@ -70,6 +70,12 @@ The format of the list file must be: * ``src_ip`` +* Variable fields, which take their values from a list of options, + have the comma-separated option list placed in braces, rather than a the type name. + For example, + + * ``<(rx,tx,rxtx)>mode`` + * The help text for a command is given in the form of a comment on the same line as the command An example list file, with a variety of (unrelated) commands, is shown below:: @@ -79,6 +85,7 @@ An example list file, with a variety of (unrelated) commands, is shown below:: add x y # add x and y echo message # print message to screen add socket path # add unix socket with the given path + set mode <(rx,tx)>rxtx # set Rx-only or Tx-only mode quit # close the application Running the Generator Script From patchwork Fri Oct 27 11:01:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruce Richardson X-Patchwork-Id: 133501 X-Patchwork-Delegate: david.marchand@redhat.com 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 844DD43215; Fri, 27 Oct 2023 13:02:50 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6D07042E27; Fri, 27 Oct 2023 13:01:47 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.8]) by mails.dpdk.org (Postfix) with ESMTP id 964CB42E10 for ; Fri, 27 Oct 2023 13:01:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698404505; x=1729940505; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=XcIW41mdP/aND+hYsOeIRwGJJMHt9INJPO52QPeCgiA=; b=fZg+WrE9DIqeJnjxY0QRHnwL9un8QKcbGX4qKAjGMJ2eLyxumDU/51X8 gbTCV7KwqMOVQG26zMNrM0lnJaPuhiz+qh9NMMImJl+NndQ2Tzvhb8w3t Zc0L6AYU4E97Z6TyLTiqMGDRkJ6Cs4tuK4aGXHztG4ufkxEftvAr+WqNX xtO+lI821xop3OiQYR0jsMcBc8Q3nVQ+6HJXxTMMOBIWm7WtU8dv2CA2n evZ+saE62u3nXx8wT1r7YRbcCxfHmSPCIJN1+6rW8CjbWQVtrEWDkr12Y ZvGKp+XIcSGAdZmIcZh780qYvtwqS/5oqeS0kAE4CkWfANBMYkpINAQF4 A==; X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="546720" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="546720" Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmvoesa102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Oct 2023 04:01:44 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10875"; a="883157879" X-IronPort-AV: E=Sophos;i="6.03,256,1694761200"; d="scan'208";a="883157879" Received: from silpixa00401385.ir.intel.com ([10.237.214.154]) by orsmga004.jf.intel.com with ESMTP; 27 Oct 2023 04:01:42 -0700 From: Bruce Richardson To: dev@dpdk.org Cc: david.marchand@redhat.com, rjarry@redhat.com, Bruce Richardson Subject: [PATCH v7 9/9] examples/ntb: auto-generate cmdline boilerplate Date: Fri, 27 Oct 2023 12:01:17 +0100 Message-Id: <20231027110117.70995-10-bruce.richardson@intel.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20231027110117.70995-1-bruce.richardson@intel.com> References: <20230802170052.955323-1-bruce.richardson@intel.com> <20231027110117.70995-1-bruce.richardson@intel.com> MIME-Version: 1.0 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 Use the dpdk-cmdline-gen script to autogenerate all the boilerplate structs and defines for the commandline part of the app. Signed-off-by: Bruce Richardson --- examples/ntb/Makefile | 12 ++- examples/ntb/commands.list | 11 ++ examples/ntb/meson.build | 7 ++ examples/ntb/ntb_fwd.c | 200 ++++--------------------------------- 4 files changed, 47 insertions(+), 183 deletions(-) create mode 100644 examples/ntb/commands.list diff --git a/examples/ntb/Makefile b/examples/ntb/Makefile index d9b6e53090..f5b3405c47 100644 --- a/examples/ntb/Makefile +++ b/examples/ntb/Makefile @@ -6,6 +6,7 @@ APP = ntb_fwd # all source are stored in SRCS-y SRCS-y := ntb_fwd.c +SRC-DEPS := build/commands.h PKGCONF ?= pkg-config @@ -25,10 +26,13 @@ CFLAGS += -D_FILE_OFFSET_BITS=64 LDFLAGS += -pthread PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null) -CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) +CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk) -I build/ LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk) LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk) +build/commands.h: commands.list Makefile + dpdk-cmdline-gen.py -o $@ --context-name=main_ctx $< + ifeq ($(MAKECMDGOALS),static) # check for broken pkg-config ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),) @@ -39,10 +43,10 @@ endif CFLAGS += -DALLOW_EXPERIMENTAL_API -build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build $(SRC-DEPS) $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) -build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build +build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build $(SRC-DEPS) $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) build: @@ -50,5 +54,5 @@ build: .PHONY: clean clean: - rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared + rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared build/*.h test -d build && rmdir -p build || true diff --git a/examples/ntb/commands.list b/examples/ntb/commands.list new file mode 100644 index 0000000000..a26b8acfa3 --- /dev/null +++ b/examples/ntb/commands.list @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation +# +help # show help +quit # exit application +send filepath # send +start # start pkt fwd between ntb and ethdev +stop # stop packet forwarding +show port stats # show statistics for all ports +clear port stats # clear all port statistics +set fwd <(file-trans,iofwd,txonly,rxonly)>mode # set forwarding mode as file-trans|rxonly|txonly|iofwd diff --git a/examples/ntb/meson.build b/examples/ntb/meson.build index 18eaffdf21..6c23081c41 100644 --- a/examples/ntb/meson.build +++ b/examples/ntb/meson.build @@ -17,3 +17,10 @@ cflags += ['-D_FILE_OFFSET_BITS=64'] sources = files( 'ntb_fwd.c', ) +cmd_h = custom_target('commands_hdr', + output: 'commands.h', + input: files('commands.list'), + capture: true, + command: [cmdline_gen_cmd, '--context-name=main_ctx', '@INPUT@'] +) +sources += cmd_h diff --git a/examples/ntb/ntb_fwd.c b/examples/ntb/ntb_fwd.c index 585aad9d70..95a6148c82 100644 --- a/examples/ntb/ntb_fwd.c +++ b/examples/ntb/ntb_fwd.c @@ -21,6 +21,7 @@ #include #include #include +#include "commands.h" /* Per-port statistics struct */ struct ntb_port_statistics { @@ -103,12 +104,7 @@ static struct rte_eth_conf eth_port_conf = { }, }; -/* *** Help command with introduction. *** */ -struct cmd_help_result { - cmdline_fixed_string_t help; -}; - -static void +void cmd_help_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) @@ -134,26 +130,7 @@ cmd_help_parsed(__rte_unused void *parsed_result, ); } - -cmdline_parse_token_string_t cmd_help_help = - TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help"); - -cmdline_parse_inst_t cmd_help = { - .f = cmd_help_parsed, - .data = NULL, - .help_str = "show help", - .tokens = { - (void *)&cmd_help_help, - NULL, - }, -}; - -/* *** QUIT *** */ -struct cmd_quit_result { - cmdline_fixed_string_t quit; -}; - -static void +void cmd_quit_parsed(__rte_unused void *parsed_result, struct cmdline *cl, __rte_unused void *data) @@ -188,31 +165,12 @@ cmd_quit_parsed(__rte_unused void *parsed_result, cmdline_quit(cl); } -cmdline_parse_token_string_t cmd_quit_quit = - TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit"); - -cmdline_parse_inst_t cmd_quit = { - .f = cmd_quit_parsed, - .data = NULL, - .help_str = "exit application", - .tokens = { - (void *)&cmd_quit_quit, - NULL, - }, -}; - -/* *** SEND FILE PARAMETERS *** */ -struct cmd_sendfile_result { - cmdline_fixed_string_t send_string; - char filepath[]; -}; - -static void -cmd_sendfile_parsed(void *parsed_result, +void +cmd_send_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) { - struct cmd_sendfile_result *res = parsed_result; + struct cmd_send_result *res = parsed_result; struct rte_rawdev_buf *pkts_send[NTB_MAX_PKT_BURST]; struct rte_mbuf *mbuf_send[NTB_MAX_PKT_BURST]; uint64_t size, count, i, j, nb_burst; @@ -327,24 +285,6 @@ cmd_sendfile_parsed(void *parsed_result, fclose(file); } -cmdline_parse_token_string_t cmd_send_file_send = - TOKEN_STRING_INITIALIZER(struct cmd_sendfile_result, send_string, - "send"); -cmdline_parse_token_string_t cmd_send_file_filepath = - TOKEN_STRING_INITIALIZER(struct cmd_sendfile_result, filepath, NULL); - - -cmdline_parse_inst_t cmd_send_file = { - .f = cmd_sendfile_parsed, - .data = NULL, - .help_str = "send ", - .tokens = { - (void *)&cmd_send_file_send, - (void *)&cmd_send_file_filepath, - NULL, - }, -}; - #define RECV_FILE_LEN 30 static int start_polling_recv_file(void *param) @@ -788,12 +728,7 @@ start_pkt_fwd(void) } } -/* *** START FWD PARAMETERS *** */ -struct cmd_start_result { - cmdline_fixed_string_t start; -}; - -static void +void cmd_start_parsed(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) @@ -801,25 +736,7 @@ cmd_start_parsed(__rte_unused void *parsed_result, start_pkt_fwd(); } -cmdline_parse_token_string_t cmd_start_start = - TOKEN_STRING_INITIALIZER(struct cmd_start_result, start, "start"); - -cmdline_parse_inst_t cmd_start = { - .f = cmd_start_parsed, - .data = NULL, - .help_str = "start pkt fwd between ntb and ethdev", - .tokens = { - (void *)&cmd_start_start, - NULL, - }, -}; - -/* *** STOP *** */ -struct cmd_stop_result { - cmdline_fixed_string_t stop; -}; - -static void +void cmd_stop_parsed(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) @@ -844,19 +761,6 @@ cmd_stop_parsed(__rte_unused void *parsed_result, printf("\nDone.\n"); } -cmdline_parse_token_string_t cmd_stop_stop = - TOKEN_STRING_INITIALIZER(struct cmd_stop_result, stop, "stop"); - -cmdline_parse_inst_t cmd_stop = { - .f = cmd_stop_parsed, - .data = NULL, - .help_str = "stop: Stop packet forwarding", - .tokens = { - (void *)&cmd_stop_stop, - NULL, - }, -}; - static void ntb_stats_clear(void) { @@ -975,58 +879,28 @@ ntb_stats_display(void) free(ids); } -/* *** SHOW/CLEAR PORT STATS *** */ -struct cmd_stats_result { - cmdline_fixed_string_t show; - cmdline_fixed_string_t port; - cmdline_fixed_string_t stats; -}; - -static void -cmd_stats_parsed(void *parsed_result, +void +cmd_show_port_stats_parsed(__rte_unused void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) { - struct cmd_stats_result *res = parsed_result; - if (!strcmp(res->show, "clear")) - ntb_stats_clear(); - else - ntb_stats_display(); + ntb_stats_display(); } -cmdline_parse_token_string_t cmd_stats_show = - TOKEN_STRING_INITIALIZER(struct cmd_stats_result, show, "show#clear"); -cmdline_parse_token_string_t cmd_stats_port = - TOKEN_STRING_INITIALIZER(struct cmd_stats_result, port, "port"); -cmdline_parse_token_string_t cmd_stats_stats = - TOKEN_STRING_INITIALIZER(struct cmd_stats_result, stats, "stats"); - - -cmdline_parse_inst_t cmd_stats = { - .f = cmd_stats_parsed, - .data = NULL, - .help_str = "show|clear port stats", - .tokens = { - (void *)&cmd_stats_show, - (void *)&cmd_stats_port, - (void *)&cmd_stats_stats, - NULL, - }, -}; - -/* *** SET FORWARDING MODE *** */ -struct cmd_set_fwd_mode_result { - cmdline_fixed_string_t set; - cmdline_fixed_string_t fwd; - cmdline_fixed_string_t mode; -}; +void +cmd_clear_port_stats_parsed(__rte_unused void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + ntb_stats_clear(); +} -static void -cmd_set_fwd_mode_parsed(__rte_unused void *parsed_result, +void +cmd_set_fwd_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) { - struct cmd_set_fwd_mode_result *res = parsed_result; + struct cmd_set_fwd_result *res = parsed_result; int i; if (in_test) { @@ -1043,38 +917,6 @@ cmd_set_fwd_mode_parsed(__rte_unused void *parsed_result, printf("Invalid %s packet forwarding mode.\n", res->mode); } -cmdline_parse_token_string_t cmd_setfwd_set = - TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, set, "set"); -cmdline_parse_token_string_t cmd_setfwd_fwd = - TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, fwd, "fwd"); -cmdline_parse_token_string_t cmd_setfwd_mode = - TOKEN_STRING_INITIALIZER(struct cmd_set_fwd_mode_result, mode, - "file-trans#iofwd#txonly#rxonly"); - -cmdline_parse_inst_t cmd_set_fwd_mode = { - .f = cmd_set_fwd_mode_parsed, - .data = NULL, - .help_str = "set forwarding mode as file-trans|rxonly|txonly|iofwd", - .tokens = { - (void *)&cmd_setfwd_set, - (void *)&cmd_setfwd_fwd, - (void *)&cmd_setfwd_mode, - NULL, - }, -}; - -/* list of instructions */ -cmdline_parse_ctx_t main_ctx[] = { - (cmdline_parse_inst_t *)&cmd_help, - (cmdline_parse_inst_t *)&cmd_send_file, - (cmdline_parse_inst_t *)&cmd_start, - (cmdline_parse_inst_t *)&cmd_stop, - (cmdline_parse_inst_t *)&cmd_stats, - (cmdline_parse_inst_t *)&cmd_set_fwd_mode, - (cmdline_parse_inst_t *)&cmd_quit, - NULL, -}; - /* prompt function, called from main on MAIN lcore */ static void prompt(void)