bool dequeue_zero_copy;
bool iommu_support;
bool use_builtin_virtio_net;
+ bool extbuf;
+ bool linearbuf;
/*
* The "supported_features" indicates the feature bits the
ret = recvmsg(sockfd, &msgh, 0);
if (ret <= 0) {
- RTE_LOG(ERR, VHOST_CONFIG, "recvmsg failed\n");
+ if (ret)
+ VHOST_LOG_CONFIG(ERR, "recvmsg failed\n");
return ret;
}
if (msgh.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
- RTE_LOG(ERR, VHOST_CONFIG, "truncted msg\n");
+ VHOST_LOG_CONFIG(ERR, "truncated msg\n");
return -1;
}
msgh.msg_controllen = sizeof(control);
cmsg = CMSG_FIRSTHDR(&msgh);
if (cmsg == NULL) {
- RTE_LOG(ERR, VHOST_CONFIG, "cmsg == NULL\n");
+ VHOST_LOG_CONFIG(ERR, "cmsg == NULL\n");
errno = EINVAL;
return -1;
}
} while (ret < 0 && errno == EINTR);
if (ret < 0) {
- RTE_LOG(ERR, VHOST_CONFIG, "sendmsg error\n");
+ VHOST_LOG_CONFIG(ERR, "sendmsg error\n");
return ret;
}
if (vsocket->dequeue_zero_copy)
vhost_enable_dequeue_zero_copy(vid);
- RTE_LOG(INFO, VHOST_CONFIG, "new device, handle is %d\n", vid);
+ if (vsocket->extbuf)
+ vhost_enable_extbuf(vid);
+
+ if (vsocket->linearbuf)
+ vhost_enable_linearbuf(vid);
+
+ VHOST_LOG_CONFIG(INFO, "new device, handle is %d\n", vid);
if (vsocket->notify_ops->new_connection) {
ret = vsocket->notify_ops->new_connection(vid);
if (ret < 0) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"failed to add vhost user connection with fd %d\n",
fd);
goto err_cleanup;
ret = fdset_add(&vhost_user.fdset, fd, vhost_user_read_cb,
NULL, conn);
if (ret < 0) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"failed to add fd %d into vhost server fdset\n",
fd);
if (fd < 0)
return;
- RTE_LOG(INFO, VHOST_CONFIG, "new vhost user connection is %d\n", fd);
+ VHOST_LOG_CONFIG(INFO, "new vhost user connection is %d\n", fd);
vhost_user_add_connection(fd, vsocket);
}
ret = vhost_user_msg_handler(conn->vid, connfd);
if (ret < 0) {
+ struct virtio_net *dev = get_device(conn->vid);
+
close(connfd);
*remove = 1;
- vhost_destroy_device(conn->vid);
+
+ if (dev)
+ vhost_destroy_device_notify(dev);
if (vsocket->notify_ops->destroy_connection)
vsocket->notify_ops->destroy_connection(conn->vid);
- pthread_mutex_lock(&vsocket->conn_mutex);
- TAILQ_REMOVE(&vsocket->conn_list, conn, next);
- pthread_mutex_unlock(&vsocket->conn_mutex);
-
- free(conn);
+ vhost_destroy_device(conn->vid);
if (vsocket->reconnect) {
create_unix_socket(vsocket);
vhost_user_start_client(vsocket);
}
+
+ pthread_mutex_lock(&vsocket->conn_mutex);
+ TAILQ_REMOVE(&vsocket->conn_list, conn, next);
+ pthread_mutex_unlock(&vsocket->conn_mutex);
+
+ free(conn);
}
}
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0)
return -1;
- RTE_LOG(INFO, VHOST_CONFIG, "vhost-user %s: socket created, fd: %d\n",
+ VHOST_LOG_CONFIG(INFO, "vhost-user %s: socket created, fd: %d\n",
vsocket->is_server ? "server" : "client", fd);
if (!vsocket->is_server && fcntl(fd, F_SETFL, O_NONBLOCK)) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"vhost-user: can't set nonblocking mode for socket, fd: "
"%d (%s)\n", fd, strerror(errno));
close(fd);
*/
ret = bind(fd, (struct sockaddr *)&vsocket->un, sizeof(vsocket->un));
if (ret < 0) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"failed to bind to %s: %s; remove it and try again\n",
path, strerror(errno));
goto err;
}
- RTE_LOG(INFO, VHOST_CONFIG, "bind to %s\n", path);
+ VHOST_LOG_CONFIG(INFO, "bind to %s\n", path);
ret = listen(fd, MAX_VIRTIO_BACKLOG);
if (ret < 0)
ret = fdset_add(&vhost_user.fdset, fd, vhost_user_server_new_connection,
NULL, vsocket);
if (ret < 0) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"failed to add listen fd %d to vhost server fdset\n",
fd);
goto err;
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"can't get flags for connfd %d\n", fd);
return -2;
}
if ((flags & O_NONBLOCK) && fcntl(fd, F_SETFL, flags & ~O_NONBLOCK)) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"can't disable nonblocking on fd %d\n", fd);
return -2;
}
sizeof(reconn->un));
if (ret == -2) {
close(reconn->fd);
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"reconnection for fd %d failed\n",
reconn->fd);
goto remove_fd;
if (ret == -1)
continue;
- RTE_LOG(INFO, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(INFO,
"%s: connected\n", reconn->vsocket->path);
vhost_user_add_connection(reconn->fd, reconn->vsocket);
remove_fd:
ret = pthread_mutex_init(&reconn_list.mutex, NULL);
if (ret < 0) {
- RTE_LOG(ERR, VHOST_CONFIG, "failed to initialize mutex");
+ VHOST_LOG_CONFIG(ERR, "failed to initialize mutex");
return ret;
}
TAILQ_INIT(&reconn_list.head);
ret = rte_ctrl_thread_create(&reconn_tid, "vhost_reconn", NULL,
vhost_user_client_reconnect, NULL);
if (ret != 0) {
- RTE_LOG(ERR, VHOST_CONFIG, "failed to create reconnect thread");
+ VHOST_LOG_CONFIG(ERR, "failed to create reconnect thread");
if (pthread_mutex_destroy(&reconn_list.mutex)) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"failed to destroy reconnect mutex");
}
}
return 0;
}
- RTE_LOG(WARNING, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(WARNING,
"failed to connect to %s: %s\n",
path, strerror(errno));
return -1;
}
- RTE_LOG(INFO, VHOST_CONFIG, "%s: reconnecting...\n", path);
+ VHOST_LOG_CONFIG(INFO, "%s: reconnecting...\n", path);
reconn = malloc(sizeof(*reconn));
if (reconn == NULL) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"failed to allocate memory for reconnect\n");
close(fd);
return -1;
{
int i;
+ if (path == NULL)
+ return NULL;
+
for (i = 0; i < vhost_user.vsocket_cnt; i++) {
struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
{
struct vhost_user_socket *vsocket;
- if (rte_vdpa_get_device(did) == NULL)
+ if (rte_vdpa_get_device(did) == NULL || path == NULL)
return -1;
pthread_mutex_lock(&vhost_user.mutex);
pthread_mutex_lock(&vhost_user.mutex);
vsocket = find_vhost_user_socket(path);
if (!vsocket) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"socket file %s is not registered yet.\n", path);
ret = -1;
goto unlock_exit;
goto unlock_exit;
}
- if (vdpa_dev->ops->get_features(did, &vdpa_features) < 0) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ if (vdpa_dev->ops->get_features(vdpa_dev, &vdpa_features) < 0) {
+ VHOST_LOG_CONFIG(ERR,
"failed to get vdpa features "
"for socket file %s.\n", path);
ret = -1;
pthread_mutex_lock(&vhost_user.mutex);
vsocket = find_vhost_user_socket(path);
if (!vsocket) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"socket file %s is not registered yet.\n", path);
ret = -1;
goto unlock_exit;
goto unlock_exit;
}
- if (vdpa_dev->ops->get_protocol_features(did,
+ if (vdpa_dev->ops->get_protocol_features(vdpa_dev,
&vdpa_protocol_features) < 0) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"failed to get vdpa protocol features "
"for socket file %s.\n", path);
ret = -1;
pthread_mutex_lock(&vhost_user.mutex);
vsocket = find_vhost_user_socket(path);
if (!vsocket) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"socket file %s is not registered yet.\n", path);
ret = -1;
goto unlock_exit;
goto unlock_exit;
}
- if (vdpa_dev->ops->get_queue_num(did, &vdpa_queue_num) < 0) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ if (vdpa_dev->ops->get_queue_num(vdpa_dev, &vdpa_queue_num) < 0) {
+ VHOST_LOG_CONFIG(ERR,
"failed to get vdpa queue number "
"for socket file %s.\n", path);
ret = -1;
pthread_mutex_lock(&vhost_user.mutex);
if (vhost_user.vsocket_cnt == MAX_VHOST_SOCKET) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"error: the number of vhost sockets reaches maximum\n");
goto out;
}
memset(vsocket, 0, sizeof(struct vhost_user_socket));
vsocket->path = strdup(path);
if (vsocket->path == NULL) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"error: failed to copy socket path string\n");
vhost_user_socket_mem_free(vsocket);
goto out;
TAILQ_INIT(&vsocket->conn_list);
ret = pthread_mutex_init(&vsocket->conn_mutex, NULL);
if (ret) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"error: failed to init connection mutex\n");
goto out_free;
}
+ vsocket->vdpa_dev_id = -1;
vsocket->dequeue_zero_copy = flags & RTE_VHOST_USER_DEQUEUE_ZERO_COPY;
+ vsocket->extbuf = flags & RTE_VHOST_USER_EXTBUF_SUPPORT;
+ vsocket->linearbuf = flags & RTE_VHOST_USER_LINEARBUF_SUPPORT;
+
+ if (vsocket->dequeue_zero_copy &&
+ (flags & RTE_VHOST_USER_IOMMU_SUPPORT)) {
+ VHOST_LOG_CONFIG(ERR,
+ "error: enabling dequeue zero copy and IOMMU features "
+ "simultaneously is not supported\n");
+ goto out_mutex;
+ }
/*
* Set the supported features correctly for the builtin vhost-user
* not compatible with postcopy.
*/
if (vsocket->dequeue_zero_copy) {
+ if (vsocket->extbuf) {
+ VHOST_LOG_CONFIG(ERR,
+ "error: zero copy is incompatible with external buffers\n");
+ ret = -1;
+ goto out_mutex;
+ }
+ if (vsocket->linearbuf) {
+ VHOST_LOG_CONFIG(ERR,
+ "error: zero copy is incompatible with linear buffers\n");
+ ret = -1;
+ goto out_mutex;
+ }
+ if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
+ VHOST_LOG_CONFIG(ERR,
+ "error: zero copy is incompatible with vhost client mode\n");
+ ret = -1;
+ goto out_mutex;
+ }
vsocket->supported_features &= ~(1ULL << VIRTIO_F_IN_ORDER);
vsocket->features &= ~(1ULL << VIRTIO_F_IN_ORDER);
- RTE_LOG(INFO, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(INFO,
"Dequeue zero copy requested, disabling postcopy support\n");
vsocket->protocol_features &=
~(1ULL << VHOST_USER_PROTOCOL_F_PAGEFAULT);
}
+ /*
+ * We'll not be able to receive a buffer from guest in linear mode
+ * without external buffer if it will not fit in a single mbuf, which is
+ * likely if segmentation offloading enabled.
+ */
+ if (vsocket->linearbuf && !vsocket->extbuf) {
+ uint64_t seg_offload_features =
+ (1ULL << VIRTIO_NET_F_HOST_TSO4) |
+ (1ULL << VIRTIO_NET_F_HOST_TSO6) |
+ (1ULL << VIRTIO_NET_F_HOST_UFO);
+
+ VHOST_LOG_CONFIG(INFO,
+ "Linear buffers requested without external buffers, "
+ "disabling host segmentation offloading support\n");
+ vsocket->supported_features &= ~seg_offload_features;
+ vsocket->features &= ~seg_offload_features;
+ }
+
if (!(flags & RTE_VHOST_USER_IOMMU_SUPPORT)) {
vsocket->supported_features &= ~(1ULL << VIRTIO_F_IOMMU_PLATFORM);
vsocket->features &= ~(1ULL << VIRTIO_F_IOMMU_PLATFORM);
~(1ULL << VHOST_USER_PROTOCOL_F_PAGEFAULT);
} else {
#ifndef RTE_LIBRTE_VHOST_POSTCOPY
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"Postcopy requested but not compiled\n");
ret = -1;
goto out_mutex;
out_mutex:
if (pthread_mutex_destroy(&vsocket->conn_mutex)) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"error: failed to destroy connection mutex\n");
}
out_free:
int count;
struct vhost_user_connection *conn, *next;
+ if (path == NULL)
+ return -1;
+
again:
pthread_mutex_lock(&vhost_user.mutex);
next = TAILQ_NEXT(conn, next);
/*
- * If r/wcb is executing, release the
- * conn_mutex lock, and try again since
- * the r/wcb may use the conn_mutex lock.
+ * If r/wcb is executing, release vsocket's
+ * conn_mutex and vhost_user's mutex locks, and
+ * try again since the r/wcb may use the
+ * conn_mutex and mutex locks.
*/
if (fdset_try_del(&vhost_user.fdset,
conn->connfd) == -1) {
goto again;
}
- RTE_LOG(INFO, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(INFO,
"free connfd = %d for device '%s'\n",
conn->connfd, path);
close(conn->connfd);
pthread_mutex_unlock(&vsocket->conn_mutex);
if (vsocket->is_server) {
- fdset_del(&vhost_user.fdset,
- vsocket->socket_fd);
+ /*
+ * If r/wcb is executing, release vhost_user's
+ * mutex lock, and try again since the r/wcb
+ * may use the mutex lock.
+ */
+ if (fdset_try_del(&vhost_user.fdset,
+ vsocket->socket_fd) == -1) {
+ pthread_mutex_unlock(&vhost_user.mutex);
+ goto again;
+ }
+
close(vsocket->socket_fd);
unlink(path);
} else if (vsocket->reconnect) {
* rebuild the wait list of poll.
*/
if (fdset_pipe_init(&vhost_user.fdset) < 0) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"failed to create pipe for vhost fdset\n");
return -1;
}
"vhost-events", NULL, fdset_event_dispatch,
&vhost_user.fdset);
if (ret != 0) {
- RTE_LOG(ERR, VHOST_CONFIG,
+ VHOST_LOG_CONFIG(ERR,
"failed to create fdset handling thread");
fdset_pipe_uninit(&vhost_user.fdset);