From 592ab76f9f0f41993bebb44da85c37750a93ece9 Mon Sep 17 00:00:00 2001 From: David Marchand Date: Tue, 24 May 2022 22:06:42 +0200 Subject: [PATCH] app/testpmd: register driver specific commands 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 Acked-by: Thomas Monjalon Acked-by: Andrew Rybchenko --- app/test-pmd/cmdline.c | 73 ++++++++++++++++++--- 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, 122 insertions(+), 17 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 67a226217f..fdd0cada3b 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_driver_commands) driver_commands_head = + TAILQ_HEAD_INITIALIZER(driver_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_driver_commands *c; + unsigned int i; + + cmdline_printf( + cl, + "\n" + "Driver specific:\n" + "----------------\n" + ); + TAILQ_FOREACH(c, &driver_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, @@ -17810,7 +17829,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, @@ -18097,6 +18116,47 @@ static cmdline_parse_ctx_t main_ctx[] = { NULL, }; +void +testpmd_add_driver_commands(struct testpmd_driver_commands *c) +{ + TAILQ_INSERT_TAIL(&driver_commands_head, c, next); +} + +int +init_cmdline(void) +{ + struct testpmd_driver_commands *c; + unsigned int count; + unsigned int i; + + /* initialize non-constant commands */ + cmd_set_fwd_mode_init(); + cmd_set_fwd_retry_mode_init(); + + count = 0; + for (i = 0; builtin_ctx[i] != NULL; i++) + count++; + TAILQ_FOREACH(c, &driver_commands_head, next) { + for (i = 0; c->commands[i].ctx != NULL; i++) + count++; + } + + /* cmdline expects a NULL terminated array */ + main_ctx = calloc(count + 1, sizeof(main_ctx[0])); + if (main_ctx == NULL) + return -1; + + count = 0; + for (i = 0; builtin_ctx[i] != NULL; i++, count++) + main_ctx[count] = builtin_ctx[i]; + TAILQ_FOREACH(c, &driver_commands_head, next) { + for (i = 0; c->commands[i].ctx != NULL; i++, count++) + main_ctx[count] = c->commands[i].ctx; + } + + return 0; +} + /* read cmdline commands from file */ void cmdline_read_from_file(const char *filename) @@ -18124,9 +18184,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..d13e98125e 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 commands are located in driver directories. +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 99f2a31bb8..fc1b64b60d 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -4364,6 +4364,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 63e19c9aef..6693813dda 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -16,7 +16,13 @@ #include #endif #include +#include +#include +#include + #include +#include + #include #ifdef RTE_HAS_JANSSON #include @@ -884,6 +890,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); @@ -1188,6 +1195,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 driver specific testpmd commands. */ +struct testpmd_driver_commands { + TAILQ_ENTRY(testpmd_driver_commands) next; + struct { + cmdline_parse_inst_t *ctx; + const char *help; + } commands[]; +}; + +void testpmd_add_driver_commands(struct testpmd_driver_commands *c); +#define TESTPMD_ADD_DRIVER_COMMANDS(c) \ +RTE_INIT(__##c) \ +{ \ + testpmd_add_driver_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.39.5