r = _mm_blend_epi16 (r, _mm_and_si128 (rl, rh), 0x88);
r = _mm_shuffle_epi8 (r, _mm_set_epi64x (0, 0x0e060c040a020800));
- i = __builtin_ctzll (_mm_movemask_epi8 (r));
+ i = __builtin_ctzll (_mm_movemask_epi8 (r) |
+ (1 << VHOST_MEMORY_MAX_NREGIONS));
if (i < vui->nregions)
{
if (PREDICT_FALSE
(vum->cpus[cpu_index].rx_buffers_len == 0))
{
+ /* Cancel speculation */
+ to_next--;
+ n_left_to_next++;
+
/*
* Checking if there are some left buffers.
* If not, just rewind the used buffers and stop.
/* redirect if feature path enabled */
vnet_feature_start_device_input_x1 (vui->sw_if_index, &next0,
- b_head, 0);
+ b_head);
u32 bi = to_next[-1]; //Cannot use to_next[-1] in the macro
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
+ VNET_INTERFACE_COUNTER_RX,
os_get_cpu_number (), vui->sw_if_index, n_rx_packets, n_rx_bytes);
+ vnet_device_increment_rx_packets (cpu_index, n_rx_packets);
+
return n_rx_packets;
}
strncpy (sun.sun_path, (char *) vui->sock_filename,
sizeof (sun.sun_path) - 1);
+ /* Avoid hanging VPP if the other end does not accept */
+ if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0)
+ clib_unix_warning ("fcntl");
+
if (connect (sockfd, (struct sockaddr *) &sun,
sizeof (struct sockaddr_un)) == 0)
{
+ /* Set the socket to blocking as it was before */
+ if (fcntl(sockfd, F_SETFL, 0) < 0)
+ clib_unix_warning ("fcntl2");
+
vui->sock_errno = 0;
template.file_descriptor = sockfd;
template.private_data =
static void
vhost_user_term_if (vhost_user_intf_t * vui)
{
+ int q;
+
// Delete configured thread pinning
vec_reset_length (vui->workers);
// disconnect interface sockets
vhost_user_if_disconnect (vui);
vhost_user_update_iface_state (vui);
+ for (q = 0; q < VHOST_VRING_MAX_N; q++)
+ {
+ clib_mem_free ((void *) vui->vring_locks[q]);
+ }
+
if (vui->unix_server_index != ~0)
{
//Close server socket
// Disable and reset interface
vhost_user_term_if (vui);
- // Back to pool
- pool_put (vum->vhost_user_interfaces, vui);
-
// Reset renumbered iface
if (hwif->dev_instance <
vec_len (vum->show_dev_instance_by_real_dev_instance))
// Delete ethernet interface
ethernet_delete_interface (vnm, vui->hw_if_index);
+
+ // Back to pool
+ pool_put (vum->vhost_user_interfaces, vui);
+
return rv;
}
vhost_user_intf_t * vui,
int server_sock_fd,
const char *sock_filename,
- u64 feature_mask, u32 * sw_if_index)
+ u64 feature_mask, u32 * sw_if_index, u8 operation_mode)
{
vnet_sw_interface_t *sw;
sw = vnet_get_hw_sw_interface (vnm, vui->hw_if_index);
vui->feature_mask = feature_mask;
vui->unix_file_index = ~0;
vui->log_base_addr = 0;
+ vui->operation_mode = operation_mode;
for (q = 0; q < VHOST_VRING_MAX_N; q++)
vhost_user_vring_init (vui, q);
u8 is_server,
u32 * sw_if_index,
u64 feature_mask,
- u8 renumber, u32 custom_dev_instance, u8 * hwaddr)
+ u8 renumber, u32 custom_dev_instance, u8 * hwaddr,
+ u8 operation_mode)
{
vhost_user_intf_t *vui = NULL;
u32 sw_if_idx = ~0;
int rv = 0;
int server_sock_fd = -1;
+ if (operation_mode != VHOST_USER_POLLING_MODE)
+ return VNET_API_ERROR_UNIMPLEMENTED;
+
+ if (sock_filename == NULL || !(strlen (sock_filename) > 0))
+ {
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+
if (is_server)
{
if ((rv =
vhost_user_create_ethernet (vnm, vm, vui, hwaddr);
vhost_user_vui_init (vnm, vui, server_sock_fd, sock_filename,
- feature_mask, &sw_if_idx);
+ feature_mask, &sw_if_idx, operation_mode);
if (renumber)
vnet_interface_name_renumber (sw_if_idx, custom_dev_instance);
const char *sock_filename,
u8 is_server,
u32 sw_if_index,
- u64 feature_mask, u8 renumber, u32 custom_dev_instance)
+ u64 feature_mask, u8 renumber, u32 custom_dev_instance,
+ u8 operation_mode)
{
vhost_user_main_t *vum = &vhost_user_main;
vhost_user_intf_t *vui = NULL;
int rv = 0;
vnet_hw_interface_t *hwif;
+ if (operation_mode != VHOST_USER_POLLING_MODE)
+ return VNET_API_ERROR_UNIMPLEMENTED;
if (!(hwif = vnet_get_sup_hw_interface (vnm, sw_if_index)) ||
hwif->dev_class_index != vhost_user_dev_class.index)
return VNET_API_ERROR_INVALID_SW_IF_INDEX;
vhost_user_term_if (vui);
vhost_user_vui_init (vnm, vui, server_sock_fd,
- sock_filename, feature_mask, &sw_if_idx);
+ sock_filename, feature_mask, &sw_if_idx,
+ operation_mode);
if (renumber)
vnet_interface_name_renumber (sw_if_idx, custom_dev_instance);
u32 custom_dev_instance = ~0;
u8 hwaddr[6];
u8 *hw = NULL;
+ clib_error_t *error = NULL;
+ u8 operation_mode = VHOST_USER_POLLING_MODE;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
renumber = 1;
}
else
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
+ {
+ error = clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
}
- unformat_free (line_input);
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)))
+ renumber, custom_dev_instance, hw,
+ operation_mode)))
{
- vec_free (sock_filename);
- return clib_error_return (0, "vhost_user_create_if returned %d", rv);
+ error = clib_error_return (0, "vhost_user_create_if returned %d", rv);
+ goto done;
}
- vec_free (sock_filename);
vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (),
sw_if_index);
- return 0;
+
+done:
+ vec_free (sock_filename);
+ unformat_free (line_input);
+
+ return error;
}
clib_error_t *
unformat_input_t _line_input, *line_input = &_line_input;
u32 sw_if_index = ~0;
vnet_main_t *vnm = vnet_get_main ();
+ clib_error_t *error = NULL;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
vnet_get_sup_hw_interface (vnm, sw_if_index);
if (hwif == NULL ||
vhost_user_dev_class.index != hwif->dev_class_index)
- return clib_error_return (0, "Not a vhost interface");
+ {
+ error = clib_error_return (0, "Not a vhost interface");
+ goto done;
+ }
}
else
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
+ {
+ error = clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
}
- unformat_free (line_input);
+
vhost_user_delete_if (vnm, vm, sw_if_index);
- return 0;
+
+done:
+ unformat_free (line_input);
+
+ return error;
}
int
vui = pool_elt_at_index (vum->vhost_user_interfaces, hi->dev_instance);
vec_add2 (r_vuids, vuid, 1);
+ vuid->operation_mode = vui->operation_mode;
vuid->sw_if_index = vui->sw_if_index;
vuid->virtio_net_hdr_sz = vui->virtio_net_hdr_sz;
vuid->features = vui->features;
vuid->num_regions = vui->nregions;
+ vuid->is_server = vui->unix_server_index != ~0;
vuid->sock_errno = vui->sock_errno;
strncpy ((char *) vuid->sock_filename, (char *) vui->sock_filename,
ARRAY_LEN (vuid->sock_filename) - 1);
u32 sw_if_index;
u8 del = 0;
int rv;
+ clib_error_t *error = NULL;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
(line_input, "%U %d", unformat_vnet_sw_interface, vnet_get_main (),
&sw_if_index, &worker_thread_index))
{
- unformat_free (line_input);
- return clib_error_return (0, "unknown input `%U'",
- format_unformat_error, input);
+ error = clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, line_input);
+ goto done;
}
if (unformat (line_input, "del"))
if ((rv =
vhost_user_thread_placement (sw_if_index, worker_thread_index, del)))
- return clib_error_return (0, "vhost_user_thread_placement returned %d",
- rv);
- return 0;
+ {
+ error = clib_error_return (0, "vhost_user_thread_placement returned %d",
+ rv);
+ goto done;
+ }
+
+done:
+ unformat_free (line_input);
+
+ return error;
}