dev: initial set of APIs
Type: improvement Change-Id: I9ecbf705d460a1744f36c7005b08097dc58d9522 Signed-off-by: Damjan Marion <damarion@cisco.com>
This commit is contained in:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
86
src/vnet/dev/dev.api
Normal file
86
src/vnet/dev/dev.api
Normal file
@ -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[];
|
||||
};
|
||||
|
@ -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)),
|
||||
|
191
src/vnet/dev/dev_api.c
Normal file
191
src/vnet/dev/dev_api.c
Normal file
@ -0,0 +1,191 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright (c) 2023 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/dev/dev.h>
|
||||
#include <vnet/dev/api.h>
|
||||
|
||||
#include <vlibapi/api.h>
|
||||
#include <vlibmemory/api.h>
|
||||
|
||||
/* define message IDs */
|
||||
#include <dev/dev.api_enum.h>
|
||||
#include <dev/dev.api_types.h>
|
||||
|
||||
static u16 vnet_dev_api_msg_id_base;
|
||||
|
||||
#define REPLY_MSG_ID_BASE (vnet_dev_api_msg_id_base)
|
||||
#include <vlibapi/api_helper_macros.h>
|
||||
|
||||
#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 <dev/dev.api.c>
|
||||
|
||||
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);
|
@ -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)
|
||||
{
|
||||
|
@ -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") \
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <vppinfra/types.h>
|
||||
#include <vnet/dev/errors.h>
|
||||
|
||||
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_ */
|
||||
|
Reference in New Issue
Block a user