blob: 6002a2f0dee551070bc132ca82ad7e11b892d70a [file] [log] [blame]
/* SPDX-License-Identifier: Apache-2.0
* Copyright (c) 2023 Cisco Systems, Inc.
*/
#include <vnet/vnet.h>
#include <vnet/dev/dev.h>
#include <vnet/dev/counters.h>
#include <vnet/dev/api.h>
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 <device-id> [driver <name>] "
"[args <dev-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_rv_t rv;
vnet_dev_device_id_t device_id = {};
vnet_dev_t *dev;
if (!unformat_user (input, unformat_c_string_array, device_id,
sizeof (device_id)))
return clib_error_return (0, "please specify valid device id");
dev = vnet_dev_by_id (device_id);
if (dev)
{
vnet_dev_api_detach_args_t a = { .dev_index = dev->index };
rv = vnet_dev_api_detach (vm, &a);
}
else
rv = VNET_DEV_ERR_UNKNOWN_DEVICE;
if (rv != VNET_DEV_OK)
return clib_error_return (0, "unable to detach '%s': %U", device_id,
format_vnet_dev_rv, rv);
return 0;
}
VLIB_CLI_COMMAND (device_detach_cmd, static) = {
.path = "device detach",
.short_help = "device detach <device-id>",
.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 <device-id>",
.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;
vnet_dev_device_id_t device_id = {};
vnet_dev_t *dev = 0;
u32 n;
if (unformat_user (input, unformat_c_string_array, device_id,
sizeof (device_id)))
dev = vnet_dev_by_id (device_id);
if (!dev)
return clib_error_return (0, "please specify valid device id");
a.dev_index = dev->index;
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", 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 <device-id> [port <port-id>] "
"[args <iface-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 [<interface-name> | sw-if-index <n>]",
.function = device_remove_if_cmd_fn,
.is_mp_safe = 1,
};
static clib_error_t *
device_create_sec_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd)
{
vnet_dev_api_port_add_sec_if_args_t a = {};
vnet_main_t *vnm = vnet_get_main ();
vnet_dev_rv_t rv;
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 (unformat (input, "primary-if-name %U",
unformat_vnet_sw_interface, vnm,
&a.primary_sw_if_index))
;
else if (unformat (input, "primary-sw-if-index %u",
&a.primary_sw_if_index))
;
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_port_add_sec_if (vm, &a);
vec_free (a.args);
if (rv != VNET_DEV_OK)
return clib_error_return (0, "unable to create secondary interface: %U",
format_vnet_dev_rv, rv);
return 0;
}
VLIB_CLI_COMMAND (device_create_sec_if_cmd, static) = {
.path = "device create-secondary-interface",
.short_help = "device create-secondary-interface [<interface-name> | "
"sw-if-index <n>] id <n> [args <sec-if-args>]",
.function = device_create_sec_if_cmd_fn,
.is_mp_safe = 1,
};
static clib_error_t *
device_remove_sec_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input,
vlib_cli_command_t *cmd)
{
vnet_dev_api_port_del_sec_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 secondary interface name");
rv = vnet_dev_api_port_del_sec_if (vm, &a);
if (rv != VNET_DEV_OK)
return clib_error_return (0, "unable to remove secondary interface: %U",
format_vnet_dev_rv, rv);
return 0;
}
VLIB_CLI_COMMAND (device_remove_sec_if_cmd, static) = {
.path = "device remove-secondary-interface",
.short_help =
"device remove-secondary-interface [<interface-name> | sw-if-index <n>]",
.function = device_remove_sec_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, " Port %u:", p->port_id);
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,
};