aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/devices/virtio/vhost_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/devices/virtio/vhost_user.c')
-rw-r--r--src/vnet/devices/virtio/vhost_user.c261
1 files changed, 128 insertions, 133 deletions
diff --git a/src/vnet/devices/virtio/vhost_user.c b/src/vnet/devices/virtio/vhost_user.c
index 573d6579cea..daa126064c5 100644
--- a/src/vnet/devices/virtio/vhost_user.c
+++ b/src/vnet/devices/virtio/vhost_user.c
@@ -467,6 +467,8 @@ vhost_user_socket_read (clib_file_t * uf)
VIRTIO_FEATURE (VIRTIO_F_VERSION_1);
msg.u64 &= vui->feature_mask;
+ if (vui->enable_event_idx)
+ msg.u64 |= VIRTIO_FEATURE (VIRTIO_RING_F_EVENT_IDX);
if (vui->enable_gso)
msg.u64 |= FEATURE_VIRTIO_NET_F_HOST_GUEST_TSO_FEATURE_BITS;
if (vui->enable_packed)
@@ -664,6 +666,8 @@ vhost_user_socket_read (clib_file_t * uf)
vui->vrings[msg.state.index].last_used_idx =
vui->vrings[msg.state.index].last_avail_idx =
vui->vrings[msg.state.index].used->idx;
+ vui->vrings[msg.state.index].last_kick =
+ vui->vrings[msg.state.index].last_used_idx;
/* tell driver that we don't want interrupts */
if (vhost_user_is_packed_ring_supported (vui))
@@ -865,6 +869,8 @@ vhost_user_socket_read (clib_file_t * uf)
*/
vui->vrings[msg.state.index].last_used_idx =
vui->vrings[msg.state.index].last_avail_idx;
+ vui->vrings[msg.state.index].last_kick =
+ vui->vrings[msg.state.index].last_used_idx;
vui->vrings[msg.state.index].used_wrap_counter =
vui->vrings[msg.state.index].avail_wrap_counter;
@@ -1196,7 +1202,7 @@ vhost_user_send_interrupt_process (vlib_main_t * vm,
if (txvq->n_since_last_int)
{
if (now >= txvq->int_deadline)
- vhost_user_send_call (vm, txvq);
+ vhost_user_send_call (vm, vui, txvq);
else
next_timeout = txvq->int_deadline - now;
}
@@ -1204,7 +1210,7 @@ vhost_user_send_interrupt_process (vlib_main_t * vm,
if (rxvq->n_since_last_int)
{
if (now >= rxvq->int_deadline)
- vhost_user_send_call (vm, rxvq);
+ vhost_user_send_call (vm, vui, rxvq);
else
next_timeout = rxvq->int_deadline - now;
}
@@ -1560,12 +1566,9 @@ vhost_user_create_ethernet (vnet_main_t * vnm, vlib_main_t * vm,
* Initialize vui with specified attributes
*/
static void
-vhost_user_vui_init (vnet_main_t * vnm,
- vhost_user_intf_t * vui,
- int server_sock_fd,
- const char *sock_filename,
- u64 feature_mask, u32 * sw_if_index, u8 enable_gso,
- u8 enable_packed)
+vhost_user_vui_init (vnet_main_t * vnm, vhost_user_intf_t * vui,
+ int server_sock_fd, vhost_user_create_if_args_t * args,
+ u32 * sw_if_index)
{
vnet_sw_interface_t *sw;
int q;
@@ -1589,16 +1592,17 @@ vhost_user_vui_init (vnet_main_t * vnm,
}
vui->sw_if_index = sw->sw_if_index;
- strncpy (vui->sock_filename, sock_filename,
+ strncpy (vui->sock_filename, args->sock_filename,
ARRAY_LEN (vui->sock_filename) - 1);
vui->sock_errno = 0;
vui->is_ready = 0;
- vui->feature_mask = feature_mask;
+ vui->feature_mask = args->feature_mask;
vui->clib_file_index = ~0;
vui->log_base_addr = 0;
vui->if_index = vui - vum->vhost_user_interfaces;
- vui->enable_gso = enable_gso;
- vui->enable_packed = enable_packed;
+ vui->enable_gso = args->enable_gso;
+ vui->enable_event_idx = args->enable_event_idx;
+ vui->enable_packed = args->enable_packed;
/*
* enable_gso takes precedence over configurable feature mask if there
* is a clash.
@@ -1611,8 +1615,8 @@ vhost_user_vui_init (vnet_main_t * vnm,
* gso feature mask, we don't support one sided GSO or partial GSO.
*/
if ((vui->enable_gso == 0) &&
- ((feature_mask & FEATURE_VIRTIO_NET_F_HOST_GUEST_TSO_FEATURE_BITS) ==
- (FEATURE_VIRTIO_NET_F_HOST_GUEST_TSO_FEATURE_BITS)))
+ ((args->feature_mask & FEATURE_VIRTIO_NET_F_HOST_GUEST_TSO_FEATURE_BITS)
+ == (FEATURE_VIRTIO_NET_F_HOST_GUEST_TSO_FEATURE_BITS)))
vui->enable_gso = 1;
vhost_user_update_gso_interface_count (vui, 1 /* add */ );
mhash_set_mem (&vum->if_index_by_sock_name, vui->sock_filename,
@@ -1637,12 +1641,7 @@ vhost_user_vui_init (vnet_main_t * vnm,
int
vhost_user_create_if (vnet_main_t * vnm, vlib_main_t * vm,
- const char *sock_filename,
- u8 is_server,
- u32 * sw_if_index,
- u64 feature_mask,
- u8 renumber, u32 custom_dev_instance, u8 * hwaddr,
- u8 enable_gso, u8 enable_packed)
+ vhost_user_create_if_args_t * args)
{
vhost_user_intf_t *vui = NULL;
u32 sw_if_idx = ~0;
@@ -1651,26 +1650,25 @@ vhost_user_create_if (vnet_main_t * vnm, vlib_main_t * vm,
vhost_user_main_t *vum = &vhost_user_main;
uword *if_index;
- if (sock_filename == NULL || !(strlen (sock_filename) > 0))
+ if (args->sock_filename == NULL || !(strlen (args->sock_filename) > 0))
{
return VNET_API_ERROR_INVALID_ARGUMENT;
}
- if_index = mhash_get (&vum->if_index_by_sock_name, (void *) sock_filename);
+ if_index = mhash_get (&vum->if_index_by_sock_name,
+ (void *) args->sock_filename);
if (if_index)
{
- if (sw_if_index)
- {
- vui = &vum->vhost_user_interfaces[*if_index];
- *sw_if_index = vui->sw_if_index;
- }
+ vui = &vum->vhost_user_interfaces[*if_index];
+ args->sw_if_index = vui->sw_if_index;
return VNET_API_ERROR_IF_ALREADY_EXISTS;
}
- if (is_server)
+ if (args->is_server)
{
if ((rv =
- vhost_user_init_server_sock (sock_filename, &server_sock_fd)) != 0)
+ vhost_user_init_server_sock (args->sock_filename,
+ &server_sock_fd)) != 0)
{
return rv;
}
@@ -1679,19 +1677,17 @@ vhost_user_create_if (vnet_main_t * vnm, vlib_main_t * vm,
/* Protect the uninitialized vui from being dispatched by rx/tx */
vlib_worker_thread_barrier_sync (vm);
pool_get (vhost_user_main.vhost_user_interfaces, vui);
- vhost_user_create_ethernet (vnm, vm, vui, hwaddr);
+ vhost_user_create_ethernet (vnm, vm, vui, args->hwaddr);
vlib_worker_thread_barrier_release (vm);
- vhost_user_vui_init (vnm, vui, server_sock_fd, sock_filename,
- feature_mask, &sw_if_idx, enable_gso, enable_packed);
+ vhost_user_vui_init (vnm, vui, server_sock_fd, args, &sw_if_idx);
vnet_sw_interface_set_mtu (vnm, vui->sw_if_index, 9000);
vhost_user_rx_thread_placement (vui, 1);
- if (renumber)
- vnet_interface_name_renumber (sw_if_idx, custom_dev_instance);
+ if (args->renumber)
+ vnet_interface_name_renumber (sw_if_idx, args->custom_dev_instance);
- if (sw_if_index)
- *sw_if_index = sw_if_idx;
+ args->sw_if_index = sw_if_idx;
// Process node must connect
vlib_process_signal_event (vm, vhost_user_process_node.index, 0, 0);
@@ -1701,11 +1697,7 @@ vhost_user_create_if (vnet_main_t * vnm, vlib_main_t * vm,
int
vhost_user_modify_if (vnet_main_t * vnm, vlib_main_t * vm,
- const char *sock_filename,
- u8 is_server,
- u32 sw_if_index,
- u64 feature_mask, u8 renumber, u32 custom_dev_instance,
- u8 enable_gso, u8 enable_packed)
+ vhost_user_create_if_args_t * args)
{
vhost_user_main_t *vum = &vhost_user_main;
vhost_user_intf_t *vui = NULL;
@@ -1715,13 +1707,12 @@ vhost_user_modify_if (vnet_main_t * vnm, vlib_main_t * vm,
vnet_hw_interface_t *hwif;
uword *if_index;
- if (!
- (hwif =
- vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index))
+ if (!(hwif = vnet_get_sup_hw_interface_api_visible_or_null (vnm,
+ args->sw_if_index))
|| hwif->dev_class_index != vhost_user_device_class.index)
return VNET_API_ERROR_INVALID_SW_IF_INDEX;
- if (sock_filename == NULL || !(strlen (sock_filename) > 0))
+ if (args->sock_filename == NULL || !(strlen (args->sock_filename) > 0))
return VNET_API_ERROR_INVALID_ARGUMENT;
vui = vec_elt_at_index (vum->vhost_user_interfaces, hwif->dev_instance);
@@ -1730,23 +1721,22 @@ vhost_user_modify_if (vnet_main_t * vnm, vlib_main_t * vm,
* Disallow changing the interface to have the same path name
* as other interface
*/
- if_index = mhash_get (&vum->if_index_by_sock_name, (void *) sock_filename);
+ if_index = mhash_get (&vum->if_index_by_sock_name,
+ (void *) args->sock_filename);
if (if_index && (*if_index != vui->if_index))
return VNET_API_ERROR_IF_ALREADY_EXISTS;
// First try to open server socket
- if (is_server)
- if ((rv = vhost_user_init_server_sock (sock_filename,
+ if (args->is_server)
+ if ((rv = vhost_user_init_server_sock (args->sock_filename,
&server_sock_fd)) != 0)
return rv;
vhost_user_term_if (vui);
- vhost_user_vui_init (vnm, vui, server_sock_fd,
- sock_filename, feature_mask, &sw_if_idx, enable_gso,
- enable_packed);
+ vhost_user_vui_init (vnm, vui, server_sock_fd, args, &sw_if_idx);
- if (renumber)
- vnet_interface_name_renumber (sw_if_idx, custom_dev_instance);
+ if (args->renumber)
+ vnet_interface_name_renumber (sw_if_idx, args->custom_dev_instance);
// Process node must connect
vlib_process_signal_event (vm, vhost_user_process_node.index, 0, 0);
@@ -1759,46 +1749,46 @@ vhost_user_connect_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
+ vnet_main_t *vnm = vnet_get_main ();
unformat_input_t _line_input, *line_input = &_line_input;
- u8 *sock_filename = NULL;
- u32 sw_if_index;
- u8 is_server = 0;
- u64 feature_mask = (u64) ~ (0ULL);
- u8 renumber = 0;
- u32 custom_dev_instance = ~0;
- u8 hwaddr[6];
- u8 *hw = NULL;
clib_error_t *error = NULL;
- u8 enable_gso = 0, enable_packed = 0;
+ vhost_user_create_if_args_t args = { 0 };
+ int rv;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
return 0;
+ args.feature_mask = (u64) ~ (0ULL);
+ args.custom_dev_instance = ~0;
/* GSO feature is disable by default */
- feature_mask &= ~FEATURE_VIRTIO_NET_F_HOST_GUEST_TSO_FEATURE_BITS;
+ args.feature_mask &= ~FEATURE_VIRTIO_NET_F_HOST_GUEST_TSO_FEATURE_BITS;
/* packed-ring feature is disable by default */
- feature_mask &= ~VIRTIO_FEATURE (VIRTIO_F_RING_PACKED);
+ args.feature_mask &= ~VIRTIO_FEATURE (VIRTIO_F_RING_PACKED);
+ /* event_idx feature is disable by default */
+ args.feature_mask &= ~VIRTIO_FEATURE (VIRTIO_RING_F_EVENT_IDX);
+
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
- if (unformat (line_input, "socket %s", &sock_filename))
+ if (unformat (line_input, "socket %s", &args.sock_filename))
;
else if (unformat (line_input, "server"))
- is_server = 1;
+ args.is_server = 1;
else if (unformat (line_input, "gso"))
- enable_gso = 1;
+ args.enable_gso = 1;
else if (unformat (line_input, "packed"))
- enable_packed = 1;
- else if (unformat (line_input, "feature-mask 0x%llx", &feature_mask))
+ args.enable_packed = 1;
+ else if (unformat (line_input, "event-idx"))
+ args.enable_event_idx = 1;
+ else if (unformat (line_input, "feature-mask 0x%llx",
+ &args.feature_mask))
;
- else
- if (unformat
- (line_input, "hwaddr %U", unformat_ethernet_address, hwaddr))
- hw = hwaddr;
- else if (unformat (line_input, "renumber %d", &custom_dev_instance))
- {
- renumber = 1;
- }
+ else if (unformat (line_input, "hwaddr %U", unformat_ethernet_address,
+ args.hwaddr))
+ ;
+ else if (unformat (line_input, "renumber %d",
+ &args.custom_dev_instance))
+ args.renumber = 1;
else
{
error = clib_error_return (0, "unknown input `%U'",
@@ -1807,23 +1797,17 @@ vhost_user_connect_command_fn (vlib_main_t * vm,
}
}
- vnet_main_t *vnm = vnet_get_main ();
-
- int rv;
- if ((rv = vhost_user_create_if (vnm, vm, (char *) sock_filename,
- is_server, &sw_if_index, feature_mask,
- renumber, custom_dev_instance, hw,
- enable_gso, enable_packed)))
+ if ((rv = vhost_user_create_if (vnm, vm, &args)))
{
error = clib_error_return (0, "vhost_user_create_if returned %d", rv);
goto done;
}
- vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
- sw_if_index);
+ vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnm,
+ args.sw_if_index);
done:
- vec_free (sock_filename);
+ vec_free (args.sock_filename);
unformat_free (line_input);
return error;
@@ -1937,26 +1921,14 @@ format_vhost_user_desc (u8 * s, va_list * args)
return s;
}
-static u8 *
-format_vhost_user_vring (u8 * s, va_list * args)
-{
- char *fmt = va_arg (*args, char *);
- vhost_user_intf_t *vui = va_arg (*args, vhost_user_intf_t *);
- int q = va_arg (*args, int);
-
- s = format (s, fmt, vui->vrings[q].avail->flags, vui->vrings[q].avail->idx,
- vui->vrings[q].used->flags, vui->vrings[q].used->idx);
- return s;
-}
-
static void
-vhost_user_show_fds (vlib_main_t * vm, vhost_user_intf_t * vui, int q)
+vhost_user_show_fds (vlib_main_t * vm, vhost_user_vring_t * vq)
{
- int kickfd = UNIX_GET_FD (vui->vrings[q].kickfd_idx);
- int callfd = UNIX_GET_FD (vui->vrings[q].callfd_idx);
+ int kickfd = UNIX_GET_FD (vq->kickfd_idx);
+ int callfd = UNIX_GET_FD (vq->callfd_idx);
vlib_cli_output (vm, " kickfd %d callfd %d errfd %d\n", kickfd, callfd,
- vui->vrings[q].errfd);
+ vq->errfd);
}
static void
@@ -1968,13 +1940,15 @@ vhost_user_show_desc (vlib_main_t * vm, vhost_user_intf_t * vui, int q,
u32 idx;
u32 n_entries;
vring_desc_t *desc_table;
+ vhost_user_vring_t *vq = &vui->vrings[q];
- if (vui->vrings[q].avail && vui->vrings[q].used)
- vlib_cli_output (vm, "%U", format_vhost_user_vring,
- " avail.flags %x avail.idx %d used.flags %x used.idx %d\n",
- vui, q);
+ if (vq->avail && vq->used)
+ vlib_cli_output (vm, " avail.flags %x avail event idx %u avail.idx %d "
+ "used event idx %u used.idx %d\n", vq->avail->flags,
+ vhost_user_avail_event_idx (vq), vq->avail->idx,
+ vhost_user_used_event_idx (vq), vq->used->idx);
- vhost_user_show_fds (vm, vui, q);
+ vhost_user_show_fds (vm, vq);
if (show_descr)
{
@@ -1985,9 +1959,9 @@ vhost_user_show_desc (vlib_main_t * vm, vhost_user_intf_t * vui, int q,
vlib_cli_output (vm,
" ===== ================== ===== ====== ===== "
"==================\n");
- for (j = 0; j < vui->vrings[q].qsz_mask + 1; j++)
+ for (j = 0; j < vq->qsz_mask + 1; j++)
{
- desc_table = vui->vrings[q].desc;
+ desc_table = vq->desc;
vlib_cli_output (vm, "%U", format_vhost_user_desc,
" %-5d 0x%016lx %-5d 0x%04x %-5d 0x%016lx\n", vui,
desc_table, j, &mem_hint);
@@ -2030,18 +2004,25 @@ format_vhost_user_packed_desc (u8 * s, va_list * args)
}
static u8 *
-format_vhost_user_vring_packed (u8 * s, va_list * args)
+format_vhost_user_event_idx_flags (u8 * s, va_list * args)
{
- char *fmt = va_arg (*args, char *);
- vhost_user_intf_t *vui = va_arg (*args, vhost_user_intf_t *);
- int q = va_arg (*args, int);
-
- s = format (s, fmt, vui->vrings[q].avail_event->flags,
- vui->vrings[q].avail_event->off_wrap,
- vui->vrings[q].used_event->flags,
- vui->vrings[q].used_event->off_wrap,
- vui->vrings[q].avail_wrap_counter,
- vui->vrings[q].used_wrap_counter);
+ u32 flags = va_arg (*args, u32);
+ typedef struct
+ {
+ u8 value;
+ char *str;
+ } event_idx_flags;
+ static event_idx_flags event_idx_array[] = {
+#define _(s,v) { .str = #s, .value = v, },
+ foreach_virtio_event_idx_flags
+#undef _
+ };
+ u32 num_entries = sizeof (event_idx_array) / sizeof (event_idx_flags);
+
+ if (flags < num_entries)
+ s = format (s, "%s", event_idx_array[flags].str);
+ else
+ s = format (s, "%u", flags);
return s;
}
@@ -2054,15 +2035,25 @@ vhost_user_show_desc_packed (vlib_main_t * vm, vhost_user_intf_t * vui, int q,
u32 idx;
u32 n_entries;
vring_packed_desc_t *desc_table;
+ vhost_user_vring_t *vq = &vui->vrings[q];
+ u16 off_wrap, event_idx;
+
+ off_wrap = vq->avail_event->off_wrap;
+ event_idx = off_wrap & 0x7fff;
+ vlib_cli_output (vm, " avail_event.flags %U avail_event.off_wrap %u "
+ "avail event idx %u\n", format_vhost_user_event_idx_flags,
+ (u32) vq->avail_event->flags, off_wrap, event_idx);
+
+ off_wrap = vq->used_event->off_wrap;
+ event_idx = off_wrap & 0x7fff;
+ vlib_cli_output (vm, " used_event.flags %U used_event.off_wrap %u "
+ "used event idx %u\n", format_vhost_user_event_idx_flags,
+ (u32) vq->used_event->flags, off_wrap, event_idx);
- if (vui->vrings[q].avail_event && vui->vrings[q].used_event)
- vlib_cli_output (vm, "%U", format_vhost_user_vring_packed,
- " avail_event.flags %x avail_event.off_wrap %u "
- "used_event.flags %x used_event.off_wrap %u\n"
- " avail wrap counter %u, used wrap counter %u\n",
- vui, q);
+ vlib_cli_output (vm, " avail wrap counter %u, used wrap counter %u\n",
+ vq->avail_wrap_counter, vq->used_wrap_counter);
- vhost_user_show_fds (vm, vui, q);
+ vhost_user_show_fds (vm, vq);
if (show_descr)
{
@@ -2073,9 +2064,9 @@ vhost_user_show_desc_packed (vlib_main_t * vm, vhost_user_intf_t * vui, int q,
vlib_cli_output (vm,
" ===== ================== ===== ====== ===== "
"==================\n");
- for (j = 0; j < vui->vrings[q].qsz_mask + 1; j++)
+ for (j = 0; j < vq->qsz_mask + 1; j++)
{
- desc_table = vui->vrings[q].packed_desc;
+ desc_table = vq->packed_desc;
vlib_cli_output (vm, "%U", format_vhost_user_packed_desc,
" %-5u 0x%016lx %-5u 0x%04x %-5u 0x%016lx\n", vui,
desc_table, j, &mem_hint);
@@ -2191,6 +2182,8 @@ show_vhost_user_command_fn (vlib_main_t * vm,
vlib_cli_output (vm, " GSO enable");
if (vui->enable_packed)
vlib_cli_output (vm, " Packed ring enable");
+ if (vui->enable_event_idx)
+ vlib_cli_output (vm, " Event index enable");
vlib_cli_output (vm, "virtio_net_hdr_sz %d\n"
" features mask (0x%llx): \n"
@@ -2287,10 +2280,12 @@ show_vhost_user_command_fn (vlib_main_t * vm,
vui->vrings[q].enabled ? "" : " disabled");
vlib_cli_output (vm,
- " qsz %d last_avail_idx %d last_used_idx %d\n",
+ " qsz %d last_avail_idx %d last_used_idx %d"
+ " last_kick %u\n",
vui->vrings[q].qsz_mask + 1,
vui->vrings[q].last_avail_idx,
- vui->vrings[q].last_used_idx);
+ vui->vrings[q].last_used_idx,
+ vui->vrings[q].last_kick);
if (vhost_user_is_packed_ring_supported (vui))
vhost_user_show_desc_packed (vm, vui, q, show_descr,
@@ -2368,7 +2363,7 @@ VLIB_CLI_COMMAND (vhost_user_connect_command, static) = {
.path = "create vhost-user",
.short_help = "create vhost-user socket <socket-filename> [server] "
"[feature-mask <hex>] [hwaddr <mac-addr>] [renumber <dev_instance>] [gso] "
- "[packed]",
+ "[packed] [event-idx]",
.function = vhost_user_connect_command_fn,
.is_mp_safe = 1,
};