Introduce a testpmd API so that drivers can register specific commands. A driver can list some files to compile with testpmd, by setting them in the testpmd_sources (driver local) meson variable. drivers/meson.build then takes care of appending this to a global meson variable, and adding the driver to testpmd dependency.
Note: testpmd.h is fixed to that it is self sufficient when being included. Signed-off-by: David Marchand <david.march...@redhat.com> --- Changes since RFC v2: - fixed registering issue (again..), - updated internals and names of structure so that a usage string is associated to each cmdline ctx, - updated documentation, Changes since RFC v1: - fixed registering issue, --- app/test-pmd/cmdline.c | 85 +++++++++++++++++++-- app/test-pmd/meson.build | 5 ++ app/test-pmd/testpmd.c | 4 + app/test-pmd/testpmd.h | 23 ++++++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 27 ++++--- drivers/meson.build | 5 ++ meson.build | 2 + 7 files changed, 134 insertions(+), 17 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 498fe2c2b7..cd7724d4e3 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -69,6 +69,9 @@ #include "bpf_cmd.h" static struct cmdline *testpmd_cl; +static cmdline_parse_ctx_t *main_ctx; +static TAILQ_HEAD(, testpmd_commands) commands_head = + TAILQ_HEAD_INITIALIZER(commands_head); static void cmd_reconfig_device_queue(portid_t id, uint8_t dev, uint8_t queue); @@ -93,7 +96,8 @@ static void cmd_help_brief_parsed(__rte_unused void *parsed_result, " help registers : Reading and setting port registers.\n" " help filters : Filters configuration help.\n" " help traffic_management : Traffic Management commands.\n" - " help devices : Device related cmds.\n" + " help devices : Device related commands.\n" + " help drivers : Driver specific commands.\n" " help all : All of the above sections.\n\n" ); @@ -1177,6 +1181,21 @@ static void cmd_help_long_parsed(void *parsed_result, ); } + if (show_all || !strcmp(res->section, "drivers")) { + struct testpmd_commands *c; + unsigned int i; + + cmdline_printf( + cl, + "\n" + "Driver specific:\n" + "----------------\n" + ); + TAILQ_FOREACH(c, &commands_head, next) { + for (i = 0; c->commands[i].ctx != NULL; i++) + cmdline_printf(cl, "%s\n", c->commands[i].help); + } + } } static cmdline_parse_token_string_t cmd_help_long_help = @@ -1184,14 +1203,14 @@ static cmdline_parse_token_string_t cmd_help_long_help = static cmdline_parse_token_string_t cmd_help_long_section = TOKEN_STRING_INITIALIZER(struct cmd_help_long_result, section, - "all#control#display#config#" - "ports#registers#filters#traffic_management#devices"); + "all#control#display#config#ports#registers#" + "filters#traffic_management#devices#drivers"); static cmdline_parse_inst_t cmd_help_long = { .f = cmd_help_long_parsed, .data = NULL, .help_str = "help all|control|display|config|ports|register|" - "filters|traffic_management|devices: " + "filters|traffic_management|devices|drivers: " "Show help", .tokens = { (void *)&cmd_help_long_help, @@ -17800,7 +17819,7 @@ static cmdline_parse_inst_t cmd_show_port_flow_transfer_proxy = { /* ******************************************************************************** */ /* list of instructions */ -static cmdline_parse_ctx_t main_ctx[] = { +static cmdline_parse_ctx_t builtin_ctx[] = { (cmdline_parse_inst_t *)&cmd_help_brief, (cmdline_parse_inst_t *)&cmd_help_long, (cmdline_parse_inst_t *)&cmd_quit, @@ -18086,6 +18105,59 @@ static cmdline_parse_ctx_t main_ctx[] = { NULL, }; +void +testpmd_add_commands(struct testpmd_commands *c) +{ + TAILQ_INSERT_TAIL(&commands_head, c, next); +} + +int +init_cmdline(void) +{ + struct testpmd_commands *c; + cmdline_parse_ctx_t *ctx; + unsigned int count = 0; + unsigned int i; + + /* initialize non-constant commands */ + cmd_set_fwd_mode_init(); + cmd_set_fwd_retry_mode_init(); + + main_ctx = NULL; + for (i = 0; builtin_ctx[i] != NULL; i++) { + ctx = realloc(main_ctx, (count + i + 1) * sizeof(*ctx)); + if (ctx == NULL) + goto err; + main_ctx = ctx; + main_ctx[count + i] = builtin_ctx[i]; + } + count += i; + + TAILQ_FOREACH(c, &commands_head, next) { + for (i = 0; c->commands[i].ctx != NULL; i++) { + ctx = realloc(main_ctx, (count + i + 1) * sizeof(*ctx)); + if (ctx == NULL) + goto err; + main_ctx = ctx; + main_ctx[count + i] = c->commands[i].ctx; + } + count += i; + } + + /* cmdline expects a NULL terminated array */ + ctx = realloc(main_ctx, (count + 1) * sizeof(*ctx)); + if (ctx == NULL) + goto err; + main_ctx = ctx; + main_ctx[count] = NULL; + count += 1; + + return 0; +err: + free(main_ctx); + return -1; +} + /* read cmdline commands from file */ void cmdline_read_from_file(const char *filename) @@ -18113,9 +18185,6 @@ void prompt(void) { int ret; - /* initialize non-constant commands */ - cmd_set_fwd_mode_init(); - cmd_set_fwd_retry_mode_init(); testpmd_cl = cmdline_stdin_new(main_ctx, "testpmd> "); if (testpmd_cl == NULL) diff --git a/app/test-pmd/meson.build b/app/test-pmd/meson.build index 43130c8856..46a7511e9a 100644 --- a/app/test-pmd/meson.build +++ b/app/test-pmd/meson.build @@ -73,3 +73,8 @@ endif if dpdk_conf.has('RTE_NET_DPAA') deps += ['bus_dpaa', 'mempool_dpaa', 'net_dpaa'] endif + +# Driver specific sources include some testpmd headers. +includes = include_directories('.') +sources += testpmd_drivers_sources +deps += testpmd_drivers_deps diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 79bb23264b..93ec930b15 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -4275,6 +4275,10 @@ main(int argc, char** argv) } #endif #ifdef RTE_LIB_CMDLINE + if (init_cmdline() != 0) + rte_exit(EXIT_FAILURE, + "Could not initialise cmdline context.\n"); + if (strlen(cmdline_filename) != 0) cmdline_read_from_file(cmdline_filename); diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 31f766c965..54d2cd09e9 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -16,7 +16,13 @@ #include <rte_gso.h> #endif #include <rte_os_shim.h> +#include <rte_ethdev.h> +#include <rte_flow.h> +#include <rte_mbuf_dyn.h> + #include <cmdline.h> +#include <cmdline_parse.h> + #include <sys/queue.h> #ifdef RTE_HAS_JANSSON #include <jansson.h> @@ -866,6 +872,7 @@ unsigned int parse_item_list(const char *str, const char *item_name, unsigned int *parsed_items, int check_unique_values); void launch_args_parse(int argc, char** argv); void cmdline_read_from_file(const char *filename); +int init_cmdline(void); void prompt(void); void prompt_exit(void); void nic_stats_display(portid_t port_id); @@ -1169,6 +1176,22 @@ extern int flow_parse(const char *src, void *result, unsigned int size, struct rte_flow_item **pattern, struct rte_flow_action **actions); +/* For registering testpmd commands. */ +struct testpmd_commands { + TAILQ_ENTRY(testpmd_commands) next; + struct { + cmdline_parse_inst_t *ctx; + const char *help; + } commands[]; +}; + +extern void testpmd_add_commands(struct testpmd_commands *c); +#define TESTPMD_ADD_DRIVER_COMMANDS(c) \ +RTE_INIT(__##c) \ +{ \ + testpmd_add_commands(&c); \ +} + /* * Work-around of a compilation error with ICC on invocations of the * rte_be_to_cpu_16() function. diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index 1083c6d538..bbeba554eb 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -49,15 +49,18 @@ These are divided into sections and can be accessed using help, help section or .. code-block:: console testpmd> help - - help control : Start and stop forwarding. - help display : Displaying port, stats and config information. - help config : Configuration information. - help ports : Configuring ports. - help registers : Reading and setting port registers. - help filters : Filters configuration help. - help all : All of the above sections. - + Help is available for the following sections: + + help control : Start and stop forwarding. + help display : Displaying port, stats and config information. + help config : Configuration information. + help ports : Configuring ports. + help registers : Reading and setting port registers. + help filters : Filters configuration help. + help traffic_management : Traffic Management commands. + help devices : Device related commands. + help drivers : Driver specific commands. + help all : All of the above sections. Command File Functions ---------------------- @@ -5702,3 +5705,9 @@ Flex pattern can be shared between ports. testpmd> flow create 0 ingress pattern eth / ipv4 / udp / flex item is 3 pattern is 2 / end actions mark id 1 / queue index 0 / end Flow rule #0 created + +Driver specific commands +------------------------ + +Some drivers provide specific features. +See: diff --git a/drivers/meson.build b/drivers/meson.build index 1d8123b00c..4daa2658b7 100644 --- a/drivers/meson.build +++ b/drivers/meson.build @@ -102,6 +102,7 @@ foreach subpath:subdirs # static builds. ext_deps = [] pkgconfig_extra_libs = [] + testpmd_sources = [] if not enable_drivers.contains(drv_path) build = false @@ -246,6 +247,10 @@ foreach subpath:subdirs set_variable('shared_@0@'.format(lib_name), shared_dep) set_variable('static_@0@'.format(lib_name), static_dep) dependency_name = ''.join(lib_name.split('rte_')) + if testpmd_sources.length() != 0 + testpmd_drivers_sources += testpmd_sources + testpmd_drivers_deps += dependency_name + endif if developer_mode message('drivers/@0@: Defining dependency "@1@"'.format( drv_path, dependency_name)) diff --git a/meson.build b/meson.build index 937f6110c0..5561171617 100644 --- a/meson.build +++ b/meson.build @@ -42,6 +42,8 @@ dpdk_drivers = [] dpdk_extra_ldflags = [] dpdk_libs_disabled = [] dpdk_drvs_disabled = [] +testpmd_drivers_sources = [] +testpmd_drivers_deps = [] abi_version_file = files('ABI_VERSION') if host_machine.cpu_family().startswith('x86') -- 2.36.1