From 38c619115b0399bae8b0dcf66e57e623cc50809c Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Tue, 17 Oct 2023 16:06:26 +0000 Subject: dev: new device driver infra Type: feature Change-Id: I20c56e0d3103624407f18365c2bc1273dea5c199 Signed-off-by: Damjan Marion --- src/vnet/dev/cli.c | 315 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 src/vnet/dev/cli.c (limited to 'src/vnet/dev/cli.c') diff --git a/src/vnet/dev/cli.c b/src/vnet/dev/cli.c new file mode 100644 index 00000000000..d478f1d233c --- /dev/null +++ b/src/vnet/dev/cli.c @@ -0,0 +1,315 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#include +#include +#include +#include + +static clib_error_t * +device_attach_cmd_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_dev_api_attach_args_t a = {}; + vnet_dev_rv_t rv; + + if (!unformat_user (input, unformat_c_string_array, a.device_id, + sizeof (a.device_id))) + return clib_error_return (0, "please specify valid device id"); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (!a.driver_name[0] && + unformat (input, "driver %U", unformat_c_string_array, a.driver_name, + sizeof (a.driver_name))) + ; + else if (!a.flags.n && + unformat (input, "flags %U", unformat_vnet_dev_flags, &a.flags)) + ; + else if (!a.args && unformat (input, "args %v", &a.args)) + ; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + + rv = vnet_dev_api_attach (vm, &a); + + vec_free (a.args); + + if (rv != VNET_DEV_OK) + return clib_error_return (0, "unable to attach '%s': %U", a.device_id, + format_vnet_dev_rv, rv); + + return 0; +} + +VLIB_CLI_COMMAND (device_attach_cmd, static) = { + .path = "device attach", + .short_help = "device attach [driver ] " + "[args ]", + .function = device_attach_cmd_fn, +}; + +static clib_error_t * +device_detach_cmd_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_dev_api_detach_args_t a = {}; + vnet_dev_rv_t rv; + + if (!unformat_user (input, unformat_c_string_array, a.device_id, + sizeof (a.device_id))) + return clib_error_return (0, "please specify valid device id"); + + rv = vnet_dev_api_detach (vm, &a); + + if (rv != VNET_DEV_OK) + return clib_error_return (0, "unable to detach '%s': %U", a.device_id, + format_vnet_dev_rv, rv); + + return 0; +} + +VLIB_CLI_COMMAND (device_detach_cmd, static) = { + .path = "device detach", + .short_help = "device detach ", + .function = device_detach_cmd_fn, + .is_mp_safe = 1, +}; + +static clib_error_t * +device_reset_cmd_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_dev_api_reset_args_t a = {}; + vnet_dev_rv_t rv; + + if (!unformat_user (input, unformat_c_string_array, a.device_id, + sizeof (a.device_id))) + return clib_error_return (0, "please specify valid device id"); + + rv = vnet_dev_api_reset (vm, &a); + + if (rv != VNET_DEV_OK) + return clib_error_return (0, "unable to reset '%s': %U", a.device_id, + format_vnet_dev_rv, rv); + + return 0; +} + +VLIB_CLI_COMMAND (device_reset_cmd, static) = { + .path = "device reset", + .short_help = "device reset ", + .function = device_reset_cmd_fn, + .is_mp_safe = 1, +}; + +static clib_error_t * +device_create_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_dev_api_create_port_if_args_t a = {}; + vnet_dev_rv_t rv; + u32 n; + + if (!unformat_user (input, unformat_c_string_array, a.device_id, + sizeof (a.device_id))) + return clib_error_return (0, "please specify valid device id"); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (!a.intf_name[0] && + unformat (input, "if-name %U", unformat_c_string_array, a.intf_name, + sizeof (a.intf_name))) + ; + else if (!a.port_id && unformat (input, "port %u", &n)) + a.port_id = n; + else if (!a.flags.n && unformat (input, "flags %U", + unformat_vnet_dev_port_flags, &a.flags)) + ; + else if (!a.num_rx_queues && unformat (input, "num-rx-queues %u", &n)) + a.num_rx_queues = n; + else if (!a.num_tx_queues && unformat (input, "num-tx-queues %u", &n)) + a.num_tx_queues = n; + else if (!a.rx_queue_size && unformat (input, "rx-queues-size %u", &n)) + a.rx_queue_size = n; + else if (!a.tx_queue_size && unformat (input, "tx-queues-size %u", &n)) + a.tx_queue_size = n; + else if (!a.intf_name[0] && + unformat (input, "name %U", unformat_c_string_array, + &a.intf_name, sizeof (a.intf_name))) + ; + else if (!a.args && unformat (input, "args %v", &a.args)) + ; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + + rv = vnet_dev_api_create_port_if (vm, &a); + + vec_free (a.args); + + if (rv != VNET_DEV_OK) + return clib_error_return (0, "unable to create_if '%s': %U", a.device_id, + format_vnet_dev_rv, rv); + + return 0; +} + +VLIB_CLI_COMMAND (device_create_if_cmd, static) = { + .path = "device create-interface", + .short_help = "device create-interface [port ] " + "[args ]", + .function = device_create_if_cmd_fn, + .is_mp_safe = 1, +}; + +static clib_error_t * +device_remove_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_dev_api_remove_port_if_args_t a = { .sw_if_index = ~0 }; + vnet_main_t *vnm = vnet_get_main (); + vnet_dev_rv_t rv; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, + &a.sw_if_index)) + ; + else if (unformat (input, "sw-if-index %u", &a.sw_if_index)) + ; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + + if (a.sw_if_index == ~0) + return clib_error_return (0, "please specify existing interface name"); + + rv = vnet_dev_api_remove_port_if (vm, &a); + + if (rv != VNET_DEV_OK) + return clib_error_return (0, "unable to remove interface: %U", + format_vnet_dev_rv, rv); + + return 0; +} + +VLIB_CLI_COMMAND (device_remove_if_cmd, static) = { + .path = "device remove-interface", + .short_help = "device remove-interface [ | sw-if-index ]", + .function = device_remove_if_cmd_fn, + .is_mp_safe = 1, +}; + +static clib_error_t * +show_devices_cmd_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_dev_main_t *dm = &vnet_dev_main; + vnet_dev_format_args_t fa = {}, *a = &fa; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "counters")) + fa.counters = 1; + else if (unformat (input, "all")) + fa.show_zero_counters = 1; + else if (unformat (input, "debug")) + fa.debug = 1; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + + pool_foreach_pointer (dev, dm->devices) + { + vlib_cli_output (vm, "device '%s':", dev->device_id); + vlib_cli_output (vm, " %U", format_vnet_dev_info, a, dev); + foreach_vnet_dev_port (p, dev) + { + vlib_cli_output (vm, " Port %u:", p->port_id); + vlib_cli_output (vm, " %U", format_vnet_dev_port_info, a, p); + if (fa.counters) + vlib_cli_output (vm, " %U", format_vnet_dev_counters, a, + p->counter_main); + + foreach_vnet_dev_port_rx_queue (q, p) + { + vlib_cli_output (vm, " RX queue %u:", q->queue_id); + vlib_cli_output (vm, " %U", format_vnet_dev_rx_queue_info, + a, q); + } + + foreach_vnet_dev_port_tx_queue (q, p) + { + vlib_cli_output (vm, " TX queue %u:", q->queue_id); + vlib_cli_output (vm, " %U", format_vnet_dev_tx_queue_info, + a, q); + } + } + } + return 0; +} + +VLIB_CLI_COMMAND (show_devices_cmd, static) = { + .path = "show device", + .short_help = "show device [counters]", + .function = show_devices_cmd_fn, + .is_mp_safe = 1, +}; + +static clib_error_t * +show_device_counters_cmd_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + vnet_dev_main_t *dm = &vnet_dev_main; + vnet_dev_format_args_t fa = { .counters = 1 }; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "all")) + fa.show_zero_counters = 1; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + + pool_foreach_pointer (dev, dm->devices) + { + vlib_cli_output (vm, "device '%s':", dev->device_id); + foreach_vnet_dev_port (p, dev) + { + vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa, + p->counter_main); + + foreach_vnet_dev_port_rx_queue (q, p) + if (q->counter_main) + { + vlib_cli_output (vm, " RX queue %u:", q->queue_id); + vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa, + q->counter_main); + } + + foreach_vnet_dev_port_tx_queue (q, p) + if (q->counter_main) + { + vlib_cli_output (vm, " TX queue %u:", q->queue_id); + vlib_cli_output (vm, " %U", format_vnet_dev_counters, &fa, + q->counter_main); + } + } + } + return 0; +} + +VLIB_CLI_COMMAND (show_device_counters_cmd, static) = { + .path = "show device counters", + .short_help = "show device counters [all]", + .function = show_device_counters_cmd_fn, + .is_mp_safe = 1, +}; -- cgit 1.2.3-korg