diff options
Diffstat (limited to 'src/vnet/devices/virtio/vhost_user.c')
-rw-r--r-- | src/vnet/devices/virtio/vhost_user.c | 261 |
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, }; |