From ddf6cec37027547ff7cc61e15bb8080664d41514 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Wed, 22 Nov 2023 16:25:55 +0000 Subject: dev: initial set of APIs Type: improvement Change-Id: I9ecbf705d460a1744f36c7005b08097dc58d9522 Signed-off-by: Damjan Marion --- src/vnet/CMakeLists.txt | 2 + src/vnet/dev/api.c | 15 ++-- src/vnet/dev/api.h | 10 ++- src/vnet/dev/cli.c | 32 ++++++-- src/vnet/dev/config.c | 3 +- src/vnet/dev/dev.api | 86 +++++++++++++++++++++ src/vnet/dev/dev.h | 2 - src/vnet/dev/dev_api.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++ src/vnet/dev/dev_funcs.h | 10 +++ src/vnet/dev/errors.h | 1 + src/vnet/dev/types.h | 10 +-- 11 files changed, 338 insertions(+), 24 deletions(-) create mode 100644 src/vnet/dev/dev.api create mode 100644 src/vnet/dev/dev_api.c diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt index 1e4bb155336..32255401654 100644 --- a/src/vnet/CMakeLists.txt +++ b/src/vnet/CMakeLists.txt @@ -32,6 +32,7 @@ list(APPEND VNET_SOURCES dev/config.c dev/counters.c dev/dev.c + dev/dev_api.c dev/error.c dev/format.c dev/handlers.c @@ -98,6 +99,7 @@ list(APPEND VNET_HEADERS ) list(APPEND VNET_API_FILES + dev/dev.api interface.api interface_types.api ip/ip_types.api diff --git a/src/vnet/dev/api.c b/src/vnet/dev/api.c index 72811f5dee2..114b63d6662 100644 --- a/src/vnet/dev/api.c +++ b/src/vnet/dev/api.c @@ -115,6 +115,8 @@ done: if (rv != VNET_DEV_OK && dev) vnet_dev_process_call_op_no_rv (vm, dev, vnet_dev_free); + else if (dev) + args->dev_index = dev->index; return rv; } @@ -122,7 +124,7 @@ done: vnet_dev_rv_t vnet_dev_api_detach (vlib_main_t *vm, vnet_dev_api_detach_args_t *args) { - vnet_dev_t *dev = vnet_dev_by_id (args->device_id); + vnet_dev_t *dev = vnet_dev_by_index (args->dev_index); log_debug (dev, "detach"); @@ -152,16 +154,16 @@ vnet_dev_rv_t vnet_dev_api_create_port_if (vlib_main_t *vm, vnet_dev_api_create_port_if_args_t *args) { - vnet_dev_t *dev = vnet_dev_by_id (args->device_id); + vnet_dev_t *dev = vnet_dev_by_index (args->dev_index); vnet_dev_port_t *port = 0; u16 n_threads = vlib_get_n_threads (); int default_is_intr_mode; vnet_dev_rv_t rv; log_debug (dev, - "create_port_if: device '%s' port %u intf_name '%s' num_rx_q %u " + "create_port_if: dev_index %u port %u intf_name '%s' num_rx_q %u " "num_tx_q %u rx_q_sz %u tx_q_sz %u, flags '%U' args '%v'", - args->device_id, args->port_id, args->intf_name, + args->dev_index, args->port_id, args->intf_name, args->num_rx_queues, args->num_tx_queues, args->rx_queue_size, args->tx_queue_size, format_vnet_dev_port_flags, &args->flags, args->args); @@ -237,7 +239,10 @@ vnet_dev_api_create_port_if (vlib_main_t *vm, clib_memcpy (port->intf.name, args->intf_name, sizeof (port->intf.name)); port->intf.default_is_intr_mode = default_is_intr_mode; - return vnet_dev_process_call_port_op (vm, port, vnet_dev_port_if_create); + rv = vnet_dev_process_call_port_op (vm, port, vnet_dev_port_if_create); + args->sw_if_index = (rv == VNET_DEV_OK) ? port->intf.sw_if_index : ~0; + + return rv; } vnet_dev_rv_t diff --git a/src/vnet/dev/api.h b/src/vnet/dev/api.h index 69a846296ed..1b7bf27d62a 100644 --- a/src/vnet/dev/api.h +++ b/src/vnet/dev/api.h @@ -15,6 +15,9 @@ typedef struct vnet_dev_driver_name_t driver_name; vnet_dev_flags_t flags; u8 *args; + + /* return */ + u32 dev_index; } vnet_dev_api_attach_args_t; vnet_dev_rv_t vnet_dev_api_attach (vlib_main_t *, @@ -22,7 +25,7 @@ vnet_dev_rv_t vnet_dev_api_attach (vlib_main_t *, typedef struct { - vnet_dev_device_id_t device_id; + u32 dev_index; } vnet_dev_api_detach_args_t; vnet_dev_rv_t vnet_dev_api_detach (vlib_main_t *, vnet_dev_api_detach_args_t *); @@ -35,7 +38,7 @@ vnet_dev_rv_t vnet_dev_api_reset (vlib_main_t *, vnet_dev_api_reset_args_t *); typedef struct { - vnet_dev_device_id_t device_id; + u32 dev_index; vnet_dev_if_name_t intf_name; u16 num_rx_queues; u16 num_tx_queues; @@ -44,6 +47,9 @@ typedef struct vnet_dev_port_id_t port_id; vnet_dev_port_flags_t flags; u8 *args; + + /* return */ + u32 sw_if_index; } vnet_dev_api_create_port_if_args_t; vnet_dev_rv_t diff --git a/src/vnet/dev/cli.c b/src/vnet/dev/cli.c index d478f1d233c..53be4483183 100644 --- a/src/vnet/dev/cli.c +++ b/src/vnet/dev/cli.c @@ -56,17 +56,26 @@ 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; + vnet_dev_device_id_t device_id = {}; + vnet_dev_t *dev; - if (!unformat_user (input, unformat_c_string_array, a.device_id, - sizeof (a.device_id))) + if (!unformat_user (input, unformat_c_string_array, device_id, + sizeof (device_id))) return clib_error_return (0, "please specify valid device id"); - rv = vnet_dev_api_detach (vm, &a); + 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", a.device_id, + return clib_error_return (0, "unable to detach '%s': %U", device_id, format_vnet_dev_rv, rv); return 0; @@ -112,12 +121,19 @@ device_create_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input, { 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, a.device_id, - sizeof (a.device_id))) + 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] && @@ -153,7 +169,7 @@ device_create_if_cmd_fn (vlib_main_t *vm, unformat_input_t *input, vec_free (a.args); if (rv != VNET_DEV_OK) - return clib_error_return (0, "unable to create_if '%s': %U", a.device_id, + return clib_error_return (0, "unable to create_if '%s': %U", device_id, format_vnet_dev_rv, rv); return 0; diff --git a/src/vnet/dev/config.c b/src/vnet/dev/config.c index 65238710271..8883e727ac2 100644 --- a/src/vnet/dev/config.c +++ b/src/vnet/dev/config.c @@ -107,8 +107,7 @@ vnet_dev_config_one_device (vlib_main_t *vm, unformat_input_t *input, { vec_foreach (if_args, if_args_vec) { - clib_memcpy (if_args->device_id, device_id, - sizeof (if_args->device_id)); + if_args->dev_index = args.dev_index; rv = vnet_dev_api_create_port_if (vm, if_args); if (rv != VNET_DEV_OK) break; diff --git a/src/vnet/dev/dev.api b/src/vnet/dev/dev.api new file mode 100644 index 00000000000..552b778949b --- /dev/null +++ b/src/vnet/dev/dev.api @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright(c) 2022 Cisco Systems, Inc. + */ + +option version = "0.0.1"; + +enumflag dev_flags : u32 +{ + VL_API_DEV_FLAG_NO_STATS = 0x1, +}; + +enumflag dev_port_flags : u32 +{ + VL_API_DEV_PORT_FLAG_INTERRUPT_MODE = 0x1, +}; + +autoendian define dev_attach +{ + u32 client_index; + u32 context; + string device_id[48]; + string driver_name[16]; + vl_api_dev_flags_t flags; + string args[]; +}; + +autoendian define dev_attach_reply +{ + u32 context; + u32 dev_index; + i32 retval; + string error_string[]; +}; + +autoendian define dev_detach +{ + u32 client_index; + u32 context; + u32 dev_index; +}; + +autoendian define dev_detach_reply +{ + u32 context; + i32 retval; + string error_string[]; +}; + +autoendian define dev_create_port_if +{ + u32 client_index; + u32 context; + u32 dev_index; + string intf_name[32]; + u16 num_rx_queues; + u16 num_tx_queues; + u16 rx_queue_size; + u16 tx_queue_size; + u16 port_id; + vl_api_dev_port_flags_t flags; + string args[]; +}; + +autoendian define dev_create_port_if_reply +{ + u32 client_index; + u32 context; + u32 sw_if_index; + i32 retval; + string error_string[]; +}; + +autoendian define dev_remove_port_if +{ + u32 client_index; + u32 context; + u32 sw_if_index; +}; + +autoendian define dev_remove_port_if_reply +{ + u32 context; + i32 retval; + string error_string[]; +}; + diff --git a/src/vnet/dev/dev.h b/src/vnet/dev/dev.h index c18d29a8d5b..59e1003b4a6 100644 --- a/src/vnet/dev/dev.h +++ b/src/vnet/dev/dev.h @@ -18,8 +18,6 @@ _ (0, UNKNOWN) \ _ (1, ETHERNET) -typedef char vnet_dev_device_id_t[32]; - typedef enum { #define _(b, n) VNET_DEV_PORT_TYPE_##n = (1U << (b)), diff --git a/src/vnet/dev/dev_api.c b/src/vnet/dev/dev_api.c new file mode 100644 index 00000000000..4161c3211bd --- /dev/null +++ b/src/vnet/dev/dev_api.c @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2023 Cisco Systems, Inc. + */ + +#include +#include +#include + +#include +#include + +/* define message IDs */ +#include +#include + +static u16 vnet_dev_api_msg_id_base; + +#define REPLY_MSG_ID_BASE (vnet_dev_api_msg_id_base) +#include + +#define _(b, n, d) \ + STATIC_ASSERT ((int) VL_API_DEV_FLAG_##n == (int) VNET_DEV_F_##n, ""); +foreach_vnet_dev_flag; +#undef _ + +#define _(b, n, d) \ + STATIC_ASSERT ((int) VL_API_DEV_PORT_FLAG_##n == (int) VNET_DEV_PORT_F_##n, \ + ""); +foreach_vnet_dev_port_flag; +#undef _ + +static void +vl_api_dev_attach_t_handler (vl_api_dev_attach_t *mp) +{ + vlib_main_t *vm = vlib_get_main (); + vl_api_dev_attach_reply_t *rmp; + vnet_dev_api_attach_args_t a = {}; + vnet_dev_rv_t rv; + u8 *error_string = 0; + + STATIC_ASSERT (sizeof (mp->device_id) == sizeof (a.device_id), ""); + STATIC_ASSERT (sizeof (mp->driver_name) == sizeof (a.driver_name), ""); + STATIC_ASSERT (sizeof (mp->flags) == sizeof (a.flags), ""); + + a.flags.n = mp->flags; + strncpy (a.device_id, (char *) mp->device_id, sizeof (a.device_id)); + strncpy (a.driver_name, (char *) mp->driver_name, sizeof (a.driver_name)); + vec_add (a.args, mp->args.buf, mp->args.length); + + rv = vnet_dev_api_attach (vm, &a); + + if (rv != VNET_DEV_OK) + error_string = format (0, "%U", format_vnet_dev_rv, rv); + + vec_free (a.args); + + REPLY_MACRO3 (VL_API_DEV_ATTACH_REPLY, vec_len (error_string), ({ + rmp->retval = rv; + if (error_string) + { + rmp->dev_index = ~0; + vl_api_vec_to_api_string (error_string, + &rmp->error_string); + } + else + rmp->dev_index = a.dev_index; + })); + + vec_free (a.args); + vec_free (error_string); +} + +static void +vl_api_dev_detach_t_handler (vl_api_dev_detach_t *mp) +{ + vlib_main_t *vm = vlib_get_main (); + vl_api_dev_detach_reply_t *rmp; + vnet_dev_api_detach_args_t a = {}; + vnet_dev_rv_t rv; + u8 *error_string = 0; + + a.dev_index = mp->dev_index; + + rv = vnet_dev_api_detach (vm, &a); + + if (rv != VNET_DEV_OK) + error_string = format (0, "%U", format_vnet_dev_rv, rv); + + REPLY_MACRO3 (VL_API_DEV_DETACH_REPLY, vec_len (error_string), ({ + rmp->retval = rv; + if (error_string) + vl_api_vec_to_api_string (error_string, + &rmp->error_string); + })); + + vec_free (error_string); +} + +static void +vl_api_dev_create_port_if_t_handler (vl_api_dev_create_port_if_t *mp) +{ + vlib_main_t *vm = vlib_get_main (); + vl_api_dev_create_port_if_reply_t *rmp; + vnet_dev_api_create_port_if_args_t a = {}; + vnet_dev_rv_t rv; + u8 *error_string = 0; + + STATIC_ASSERT (sizeof (mp->intf_name) == sizeof (a.intf_name), ""); + STATIC_ASSERT (sizeof (mp->flags) == sizeof (a.flags), ""); + + a.flags.n = mp->flags; +#define _(n) a.n = mp->n; + _ (dev_index) + _ (port_id) + _ (num_rx_queues) + _ (num_tx_queues) + _ (rx_queue_size) + _ (tx_queue_size) +#undef _ + + strncpy (a.intf_name, (char *) mp->intf_name, sizeof (a.intf_name)); + vec_add (a.args, mp->args.buf, mp->args.length); + + rv = vnet_dev_api_create_port_if (vm, &a); + + if (rv != VNET_DEV_OK) + error_string = format (0, "%U", format_vnet_dev_rv, rv); + + vec_free (a.args); + + REPLY_MACRO3 (VL_API_DEV_CREATE_PORT_IF_REPLY, vec_len (error_string), ({ + rmp->retval = rv; + if (error_string) + { + rmp->sw_if_index = ~0; + vl_api_vec_to_api_string (error_string, + &rmp->error_string); + } + else + rmp->sw_if_index = a.sw_if_index; + })); + + vec_free (a.args); + vec_free (error_string); +} + +static void +vl_api_dev_remove_port_if_t_handler (vl_api_dev_remove_port_if_t *mp) +{ + vlib_main_t *vm = vlib_get_main (); + vl_api_dev_remove_port_if_reply_t *rmp; + vnet_dev_api_remove_port_if_args_t a = {}; + vnet_dev_rv_t rv; + u8 *error_string = 0; + + a.sw_if_index = mp->sw_if_index; + + rv = vnet_dev_api_remove_port_if (vm, &a); + + if (rv != VNET_DEV_OK) + error_string = format (0, "%U", format_vnet_dev_rv, rv); + + REPLY_MACRO3 (VL_API_DEV_REMOVE_PORT_IF_REPLY, vec_len (error_string), ({ + rmp->retval = rv; + if (error_string) + vl_api_vec_to_api_string (error_string, + &rmp->error_string); + })); + + vec_free (error_string); +} + +/* set tup the API message handling tables */ + +#include + +static clib_error_t * +vnet_dev_api_hookup (vlib_main_t *vm) +{ + api_main_t *am = vlibapi_get_main (); + + /* ask for a correctly-sized block of API message decode slots */ + vnet_dev_api_msg_id_base = setup_message_id_table (); + + vl_api_set_msg_thread_safe (am, vnet_dev_api_msg_id_base + VL_API_DEV_ATTACH, + 1); + + return 0; +} + +VLIB_API_INIT_FUNCTION (vnet_dev_api_hookup); diff --git a/src/vnet/dev/dev_funcs.h b/src/vnet/dev/dev_funcs.h index a74d3399511..521157abbec 100644 --- a/src/vnet/dev/dev_funcs.h +++ b/src/vnet/dev/dev_funcs.h @@ -74,6 +74,16 @@ vnet_dev_get_port_from_hw_if_index (u32 hw_if_index) return port; } +static_always_inline vnet_dev_t * +vnet_dev_by_index (u32 index) +{ + vnet_dev_main_t *dm = &vnet_dev_main; + if (pool_is_free_index (dm->devices, index)) + return 0; + + return *pool_elt_at_index (dm->devices, index); +} + static_always_inline vnet_dev_t * vnet_dev_by_id (char *id) { diff --git a/src/vnet/dev/errors.h b/src/vnet/dev/errors.h index 1f45ce2ba97..47e72957da3 100644 --- a/src/vnet/dev/errors.h +++ b/src/vnet/dev/errors.h @@ -35,6 +35,7 @@ _ (PROCESS_REPLY, "dev process reply error") \ _ (RESOURCE_NOT_AVAILABLE, "resource not available") \ _ (TIMEOUT, "timeout") \ + _ (UNKNOWN_DEVICE, "unknown device") \ _ (UNKNOWN_INTERFACE, "unknown interface") \ _ (UNSUPPORTED_CONFIG, "unsupported config") \ _ (UNSUPPORTED_DEVICE, "unsupported device") \ diff --git a/src/vnet/dev/types.h b/src/vnet/dev/types.h index 1a82c9746ef..006d18e5bc5 100644 --- a/src/vnet/dev/types.h +++ b/src/vnet/dev/types.h @@ -8,7 +8,7 @@ #include #include -typedef char vnet_dev_device_id_t[32]; +typedef char vnet_dev_device_id_t[48]; typedef char vnet_dev_if_name_t[32]; typedef char vnet_dev_driver_name_t[16]; typedef char vnet_dev_bus_name_t[8]; @@ -35,7 +35,7 @@ typedef enum } vnet_dev_rv_t; /* do not change bit assignments - API dependency */ -#define foreach_vnet_dev_flag _ (3, NO_STATS, "don't poll device stats") +#define foreach_vnet_dev_flag _ (0, NO_STATS, "don't poll device stats") typedef union { @@ -45,12 +45,12 @@ typedef union foreach_vnet_dev_flag #undef _ } e; - u64 n; + u32 n; } vnet_dev_flags_t; /* do not change bit assignments - API dependency */ #define foreach_vnet_dev_port_flag \ - _ (3, INTERRUPT_MODE, "enable interrupt mode") + _ (0, INTERRUPT_MODE, "enable interrupt mode") typedef union { @@ -60,7 +60,7 @@ typedef union foreach_vnet_dev_port_flag #undef _ } e; - u64 n; + u32 n; } vnet_dev_port_flags_t; #endif /* _VNET_DEV_TYPES_H_ */ -- cgit 1.2.3-korg