diff options
author | Damjan Marion <damarion@cisco.com> | 2023-10-17 16:06:26 +0000 |
---|---|---|
committer | Damjan Marion <damarion@cisco.com> | 2023-11-02 13:41:32 +0000 |
commit | 38c619115b0399bae8b0dcf66e57e623cc50809c (patch) | |
tree | 2d40af83187c2dce0e971328ab7add4d9940ac57 /src/vnet/dev/config.c | |
parent | d3ef00098cd27e01bb24db15e3440fabbc025aa8 (diff) |
dev: new device driver infra
Type: feature
Change-Id: I20c56e0d3103624407f18365c2bc1273dea5c199
Signed-off-by: Damjan Marion <damarion@cisco.com>
Diffstat (limited to 'src/vnet/dev/config.c')
-rw-r--r-- | src/vnet/dev/config.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/vnet/dev/config.c b/src/vnet/dev/config.c new file mode 100644 index 00000000000..c98524c9b7e --- /dev/null +++ b/src/vnet/dev/config.c @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#include "vppinfra/error.h" +#include "vppinfra/pool.h" +#include <vnet/vnet.h> +#include <vnet/ethernet/ethernet.h> +#include <vnet/dev/dev.h> +#include <vnet/dev/api.h> +#include <vnet/dev/log.h> + +VLIB_REGISTER_LOG_CLASS (dev_log, static) = { + .class_name = "dev", + .subclass_name = "config", +}; + +static clib_error_t * +vnet_dev_config_one_interface (vlib_main_t *vm, unformat_input_t *input, + vnet_dev_api_create_port_if_args_t *args) +{ + clib_error_t *err = 0; + + log_debug (0, "port %u %U", args->port_id, format_unformat_input, input); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + u32 n; + + if (unformat (input, "name %U", unformat_c_string_array, args->intf_name, + sizeof (args->intf_name))) + ; + else if (unformat (input, "num-rx-queues %u", &n)) + args->num_rx_queues = n; + else if (unformat (input, "num-tx-queues %u", &n)) + args->num_tx_queues = n; + else if (unformat (input, "rx-queue-size %u", &n)) + args->rx_queue_size = n; + else if (unformat (input, "tx-queue-size %u", &n)) + args->tx_queue_size = n; + else if (unformat (input, "flags %U", unformat_vnet_dev_port_flags, + &args->flags)) + ; + else + { + err = clib_error_return (0, "unknown input '%U'", + format_unformat_error, input); + break; + } + } + return err; +} + +static clib_error_t * +vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *input, + char *device_id) +{ + log_debug (0, "device %s %U", device_id, format_unformat_input, input); + clib_error_t *err = 0; + vnet_dev_api_attach_args_t args = {}; + vnet_dev_api_create_port_if_args_t *if_args_vec = 0, *if_args; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + unformat_input_t sub_input; + u32 n; + + if (unformat (input, "driver %U", unformat_c_string_array, + args.driver_name, sizeof (args.driver_name))) + ; + else if (unformat (input, "flags %U", unformat_vnet_dev_flags, + &args.flags)) + ; + else if (unformat (input, "port %u %U", &n, unformat_vlib_cli_sub_input, + &sub_input)) + { + vnet_dev_api_create_port_if_args_t *if_args; + vec_add2 (if_args_vec, if_args, 1); + if_args->port_id = n; + err = vnet_dev_config_one_interface (vm, &sub_input, if_args); + unformat_free (&sub_input); + if (err) + break; + } + else + { + err = clib_error_return (0, "unknown input '%U'", + format_unformat_error, input); + break; + } + } + + if (err == 0) + { + vnet_dev_rv_t rv; + + clib_memcpy (args.device_id, device_id, sizeof (args.device_id)); + rv = vnet_dev_api_attach (vm, &args); + + if (rv == VNET_DEV_OK) + { + vec_foreach (if_args, if_args_vec) + { + clib_memcpy (if_args->device_id, device_id, + sizeof (if_args->device_id)); + rv = vnet_dev_api_create_port_if (vm, if_args); + if (rv != VNET_DEV_OK) + break; + } + + if (rv != VNET_DEV_OK) + err = clib_error_return (0, "error: %U for device '%s'", + format_vnet_dev_rv, rv, device_id); + } + } + + vec_free (if_args_vec); + return err; +} + +uword +dev_config_process_node_fn (vlib_main_t *vm, vlib_node_runtime_t *rt, + vlib_frame_t *f) +{ + vnet_dev_main_t *dm = &vnet_dev_main; + unformat_input_t input; + clib_error_t *err = 0; + + if (dm->startup_config == 0) + return 0; + + unformat_init_vector (&input, dm->startup_config); + dm->startup_config = 0; + + while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT) + { + unformat_input_t sub_input; + vnet_dev_device_id_t device_id; + if (unformat (&input, "dev %U %U", unformat_c_string_array, device_id, + sizeof (device_id), unformat_vlib_cli_sub_input, + &sub_input)) + { + err = vnet_dev_config_one_device (vm, &sub_input, device_id); + unformat_free (&sub_input); + if (err) + break; + } + else + { + err = clib_error_return (0, "unknown input '%U'", + format_unformat_error, input); + break; + } + } + + unformat_free (&input); + + vlib_node_set_state (vm, rt->node_index, VLIB_NODE_STATE_DISABLED); + vlib_node_rename (vm, rt->node_index, "deleted-%u", rt->node_index); + vec_add1 (dm->free_process_node_indices, rt->node_index); + return 0; +} + +VLIB_REGISTER_NODE (dev_config_process_node) = { + .function = dev_config_process_node_fn, + .type = VLIB_NODE_TYPE_PROCESS, + .name = "dev-config", +}; + +static clib_error_t * +devices_config (vlib_main_t *vm, unformat_input_t *input) +{ + vnet_dev_main_t *dm = &vnet_dev_main; + uword c; + + while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) + vec_add1 (dm->startup_config, c); + + return 0; +} + +VLIB_CONFIG_FUNCTION (devices_config, "devices"); |