[RFC,18/27] vhost: add VDUSE device creation and destruction

Message ID 20230331154259.1447831-19-maxime.coquelin@redhat.com (mailing list archive)
State Superseded, archived
Delegated to: Maxime Coquelin
Headers
Series Add VDUSE support to Vhost library |

Commit Message

Maxime Coquelin March 31, 2023, 3:42 p.m. UTC
  This patch adds initial support for VDUSE, which includes
the device creation and destruction.

It does not include the virtqueues configuration, so this is
not functionnal at this point.

Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/vhost/meson.build |   4 +
 lib/vhost/socket.c    |  34 +++++---
 lib/vhost/vduse.c     | 184 ++++++++++++++++++++++++++++++++++++++++++
 lib/vhost/vduse.h     |  33 ++++++++
 lib/vhost/vhost.h     |   2 +
 5 files changed, 245 insertions(+), 12 deletions(-)
 create mode 100644 lib/vhost/vduse.c
 create mode 100644 lib/vhost/vduse.h
  

Comments

Chenbo Xia May 9, 2023, 5:31 a.m. UTC | #1
> -----Original Message-----
> From: Maxime Coquelin <maxime.coquelin@redhat.com>
> Sent: Friday, March 31, 2023 11:43 PM
> To: dev@dpdk.org; david.marchand@redhat.com; Xia, Chenbo
> <chenbo.xia@intel.com>; mkp@redhat.com; fbl@redhat.com;
> jasowang@redhat.com; Liang, Cunming <cunming.liang@intel.com>; Xie, Yongji
> <xieyongji@bytedance.com>; echaudro@redhat.com; eperezma@redhat.com;
> amorenoz@redhat.com
> Cc: Maxime Coquelin <maxime.coquelin@redhat.com>
> Subject: [RFC 18/27] vhost: add VDUSE device creation and destruction
> 
> This patch adds initial support for VDUSE, which includes
> the device creation and destruction.
> 
> It does not include the virtqueues configuration, so this is
> not functionnal at this point.
> 
> Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> ---
>  lib/vhost/meson.build |   4 +
>  lib/vhost/socket.c    |  34 +++++---
>  lib/vhost/vduse.c     | 184 ++++++++++++++++++++++++++++++++++++++++++
>  lib/vhost/vduse.h     |  33 ++++++++
>  lib/vhost/vhost.h     |   2 +
>  5 files changed, 245 insertions(+), 12 deletions(-)
>  create mode 100644 lib/vhost/vduse.c
>  create mode 100644 lib/vhost/vduse.h
> 
> diff --git a/lib/vhost/meson.build b/lib/vhost/meson.build
> index cdcd403df3..a57a15937f 100644
> --- a/lib/vhost/meson.build
> +++ b/lib/vhost/meson.build
> @@ -30,6 +30,10 @@ sources = files(
>          'virtio_net.c',
>          'virtio_net_ctrl.c',
>  )
> +if cc.has_header('linux/vduse.h')
> +    sources += files('vduse.c')
> +    cflags += '-DVHOST_HAS_VDUSE'
> +endif
>  headers = files(
>          'rte_vdpa.h',
>          'rte_vhost.h',
> diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c
> index e95c3ffeac..a8a1c4cd2b 100644
> --- a/lib/vhost/socket.c
> +++ b/lib/vhost/socket.c
> @@ -18,6 +18,7 @@
>  #include <rte_log.h>
> 
>  #include "fd_man.h"
> +#include "vduse.h"
>  #include "vhost.h"
>  #include "vhost_user.h"
> 
> @@ -35,6 +36,7 @@ struct vhost_user_socket {
>  	int socket_fd;
>  	struct sockaddr_un un;
>  	bool is_server;
> +	bool is_vduse;
>  	bool reconnect;
>  	bool iommu_support;
>  	bool use_builtin_virtio_net;
> @@ -992,18 +994,21 @@ rte_vhost_driver_register(const char *path, uint64_t
> flags)
>  #endif
>  	}
> 
> -	if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
> -		vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
> -		if (vsocket->reconnect && reconn_tid == 0) {
> -			if (vhost_user_reconnect_init() != 0)
> -				goto out_mutex;
> -		}
> +	if (!strncmp("/dev/vduse/", path, strlen("/dev/vduse/"))) {
> +		vsocket->is_vduse = true;
>  	} else {
> -		vsocket->is_server = true;
> -	}
> -	ret = create_unix_socket(vsocket);
> -	if (ret < 0) {
> -		goto out_mutex;
> +		if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
> +			vsocket->reconnect = !(flags &
> RTE_VHOST_USER_NO_RECONNECT);
> +			if (vsocket->reconnect && reconn_tid == 0) {
> +				if (vhost_user_reconnect_init() != 0)
> +					goto out_mutex;
> +			}
> +		} else {
> +			vsocket->is_server = true;
> +		}
> +		ret = create_unix_socket(vsocket);
> +		if (ret < 0)
> +			goto out_mutex;
>  	}
> 
>  	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
> @@ -1068,7 +1073,9 @@ rte_vhost_driver_unregister(const char *path)
>  		if (strcmp(vsocket->path, path))
>  			continue;
> 
> -		if (vsocket->is_server) {
> +		if (vsocket->is_vduse) {
> +			vduse_device_destroy(path);
> +		} else if (vsocket->is_server) {
>  			/*
>  			 * If r/wcb is executing, release vhost_user's
>  			 * mutex lock, and try again since the r/wcb
> @@ -1171,6 +1178,9 @@ rte_vhost_driver_start(const char *path)
>  	if (!vsocket)
>  		return -1;
> 
> +	if (vsocket->is_vduse)
> +		return vduse_device_create(path);
> +
>  	if (fdset_tid == 0) {
>  		/**
>  		 * create a pipe which will be waited by poll and notified to
> diff --git a/lib/vhost/vduse.c b/lib/vhost/vduse.c
> new file mode 100644
> index 0000000000..336761c97a
> --- /dev/null
> +++ b/lib/vhost/vduse.c
> @@ -0,0 +1,184 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (c) 2023 Red Hat, Inc.
> + */
> +
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <fcntl.h>
> +
> +
> +#include <linux/vduse.h>
> +#include <linux/virtio_net.h>
> +
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +
> +#include <rte_common.h>
> +
> +#include "vduse.h"
> +#include "vhost.h"
> +
> +#define VHOST_VDUSE_API_VERSION 0
> +#define VDUSE_CTRL_PATH "/dev/vduse/control"
> +
> +#define VDUSE_NET_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) |
> \
> +				(1ULL << VIRTIO_F_ANY_LAYOUT) | \
> +				(1ULL << VIRTIO_F_VERSION_1)   | \
> +				(1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
> +				(1ULL << VIRTIO_RING_F_EVENT_IDX) | \
> +				(1ULL << VIRTIO_F_IN_ORDER) | \
> +				(1ULL << VIRTIO_F_IOMMU_PLATFORM))
> +
> +static struct vhost_backend_ops vduse_backend_ops = {
> +};
> +
> +int
> +vduse_device_create(const char *path)
> +{
> +	int control_fd, dev_fd, vid, ret;
> +	uint32_t i;
> +	struct virtio_net *dev;
> +	uint64_t ver = VHOST_VDUSE_API_VERSION;
> +	struct vduse_dev_config *dev_config = NULL;
> +	const char *name = path + strlen("/dev/vduse/");
> +
> +	control_fd = open(VDUSE_CTRL_PATH, O_RDWR);
> +	if (control_fd < 0) {
> +		VHOST_LOG_CONFIG(name, ERR, "Failed to open %s: %s\n",
> +				VDUSE_CTRL_PATH, strerror(errno));
> +		return -1;
> +	}
> +
> +	if (ioctl(control_fd, VDUSE_SET_API_VERSION, &ver)) {
> +		VHOST_LOG_CONFIG(name, ERR, "Failed to set API version: %"
> PRIu64 ": %s\n",
> +				ver, strerror(errno));
> +		ret = -1;
> +		goto out_ctrl_close;
> +	}
> +
> +	dev_config = malloc(offsetof(struct vduse_dev_config, config));
> +	if (!dev_config) {
> +		VHOST_LOG_CONFIG(name, ERR, "Failed to allocate VDUSE
> config\n");
> +		ret = -1;
> +		goto out_ctrl_close;
> +	}
> +
> +	memset(dev_config, 0, sizeof(struct vduse_dev_config));
> +
> +	strncpy(dev_config->name, name, VDUSE_NAME_MAX - 1);
> +	dev_config->device_id = VIRTIO_ID_NET;
> +	dev_config->vendor_id = 0;
> +	dev_config->features = VDUSE_NET_SUPPORTED_FEATURES;
> +	dev_config->vq_num = 2;
> +	dev_config->vq_align = sysconf(_SC_PAGE_SIZE);
> +	dev_config->config_size = 0;
> +
> +	ret = ioctl(control_fd, VDUSE_CREATE_DEV, dev_config);
> +	if (ret < 0) {
> +		VHOST_LOG_CONFIG(name, ERR, "Failed to create VDUSE
> device: %s\n",
> +				strerror(errno));
> +		goto out_free;
> +	}
> +
> +	dev_fd = open(path, O_RDWR);
> +	if (dev_fd < 0) {
> +		VHOST_LOG_CONFIG(name, ERR, "Failed to open device %s: %s\n",
> +				path, strerror(errno));
> +		ret = -1;
> +		goto out_dev_close;
> +	}
> +
> +	vid = vhost_new_device(&vduse_backend_ops);
> +	if (vid < 0) {
> +		VHOST_LOG_CONFIG(name, ERR, "Failed to create new Vhost
> device\n");
> +		ret = -1;
> +		goto out_dev_close;
> +	}
> +
> +	dev = get_device(vid);
> +	if (!dev) {
> +		ret = -1;
> +		goto out_dev_close;
> +	}
> +
> +	strncpy(dev->ifname, path, IF_NAME_SZ - 1);
> +	dev->vduse_ctrl_fd = control_fd;
> +	dev->vduse_dev_fd = dev_fd;
> +	vhost_setup_virtio_net(dev->vid, true, true, true, true);
> +
> +	for (i = 0; i < 2; i++) {
> +		struct vduse_vq_config vq_cfg = { 0 };
> +
> +		ret = alloc_vring_queue(dev, i);
> +		if (ret) {
> +			VHOST_LOG_CONFIG(name, ERR, "Failed to alloc vring %d
> metadata\n", i);
> +			goto out_dev_destroy;
> +		}
> +
> +		vq_cfg.index = i;
> +		vq_cfg.max_size = 1024;
> +
> +		ret = ioctl(dev->vduse_dev_fd, VDUSE_VQ_SETUP, &vq_cfg);
> +		if (ret) {
> +			VHOST_LOG_CONFIG(name, ERR, "Failed to set-up VQ %d\n",
> i);
> +			goto out_dev_destroy;
> +		}
> +	}
> +
> +	free(dev_config);
> +
> +	return 0;
> +
> +out_dev_destroy:
> +	vhost_destroy_device(vid);
> +out_dev_close:
> +	if (dev_fd >= 0)
> +		close(dev_fd);
> +	ioctl(control_fd, VDUSE_DESTROY_DEV, name);
> +out_free:
> +	free(dev_config);
> +out_ctrl_close:
> +	close(control_fd);
> +
> +	return ret;
> +}
> +
> +int
> +vduse_device_destroy(const char *path)
> +{
> +	const char *name = path + strlen("/dev/vduse/");
> +	struct virtio_net *dev;
> +	int vid, ret;
> +
> +	for (vid = 0; vid < RTE_MAX_VHOST_DEVICE; vid++) {
> +		dev = vhost_devices[vid];
> +
> +		if (dev == NULL)
> +			continue;
> +
> +		if (!strcmp(path, dev->ifname))
> +			break;
> +	}
> +
> +	if (vid == RTE_MAX_VHOST_DEVICE)
> +		return -1;
> +
> +	if (dev->vduse_dev_fd >= 0) {
> +		close(dev->vduse_dev_fd);
> +		dev->vduse_dev_fd = -1;
> +	}
> +
> +	if (dev->vduse_ctrl_fd >= 0) {
> +		ret = ioctl(dev->vduse_ctrl_fd, VDUSE_DESTROY_DEV, name);
> +		if (ret)
> +			VHOST_LOG_CONFIG(name, ERR, "Failed to destroy VDUSE
> device: %s\n",
> +					strerror(errno));
> +		close(dev->vduse_ctrl_fd);
> +		dev->vduse_ctrl_fd = -1;
> +	}
> +
> +	vhost_destroy_device(vid);
> +
> +	return 0;
> +}
> diff --git a/lib/vhost/vduse.h b/lib/vhost/vduse.h
> new file mode 100644
> index 0000000000..a15e5d4c16
> --- /dev/null
> +++ b/lib/vhost/vduse.h
> @@ -0,0 +1,33 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright (c) 2023 Red Hat, Inc.
> + */
> +
> +#ifndef _VDUSE_H
> +#define _VDUSE_H
> +
> +#include "vhost.h"
> +
> +#ifdef VHOST_HAS_VDUSE
> +
> +int vduse_device_create(const char *path);
> +int vduse_device_destroy(const char *path);
> +
> +#else
> +
> +static inline int
> +vduse_device_create(const char *path)
> +{
> +	VHOST_LOG_CONFIG(path, ERR, "VDUSE support disabled at build
> time\n");
> +	return -1;
> +}
> +
> +static inline int
> +vduse_device_destroy(const char *path)
> +{
> +	VHOST_LOG_CONFIG(path, ERR, "VDUSE support disabled at build
> time\n");
> +	return -1;
> +}
> +
> +#endif /* VHOST_HAS_VDUSE */
> +
> +#endif /* _VDUSE_H */
> diff --git a/lib/vhost/vhost.h b/lib/vhost/vhost.h
> index 76663aed24..c8f2a0d43a 100644
> --- a/lib/vhost/vhost.h
> +++ b/lib/vhost/vhost.h
> @@ -524,6 +524,8 @@ struct virtio_net {
> 
>  	int			postcopy_ufd;
>  	int			postcopy_listening;
> +	int			vduse_ctrl_fd;
> +	int			vduse_dev_fd;
> 
>  	struct vhost_virtqueue	*cvq;
> 
> --
> 2.39.2

Reviewed-by: Chenbo Xia <chenbo.xia@intel.com>
  

Patch

diff --git a/lib/vhost/meson.build b/lib/vhost/meson.build
index cdcd403df3..a57a15937f 100644
--- a/lib/vhost/meson.build
+++ b/lib/vhost/meson.build
@@ -30,6 +30,10 @@  sources = files(
         'virtio_net.c',
         'virtio_net_ctrl.c',
 )
+if cc.has_header('linux/vduse.h')
+    sources += files('vduse.c')
+    cflags += '-DVHOST_HAS_VDUSE'
+endif
 headers = files(
         'rte_vdpa.h',
         'rte_vhost.h',
diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c
index e95c3ffeac..a8a1c4cd2b 100644
--- a/lib/vhost/socket.c
+++ b/lib/vhost/socket.c
@@ -18,6 +18,7 @@ 
 #include <rte_log.h>
 
 #include "fd_man.h"
+#include "vduse.h"
 #include "vhost.h"
 #include "vhost_user.h"
 
@@ -35,6 +36,7 @@  struct vhost_user_socket {
 	int socket_fd;
 	struct sockaddr_un un;
 	bool is_server;
+	bool is_vduse;
 	bool reconnect;
 	bool iommu_support;
 	bool use_builtin_virtio_net;
@@ -992,18 +994,21 @@  rte_vhost_driver_register(const char *path, uint64_t flags)
 #endif
 	}
 
-	if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
-		vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
-		if (vsocket->reconnect && reconn_tid == 0) {
-			if (vhost_user_reconnect_init() != 0)
-				goto out_mutex;
-		}
+	if (!strncmp("/dev/vduse/", path, strlen("/dev/vduse/"))) {
+		vsocket->is_vduse = true;
 	} else {
-		vsocket->is_server = true;
-	}
-	ret = create_unix_socket(vsocket);
-	if (ret < 0) {
-		goto out_mutex;
+		if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
+			vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
+			if (vsocket->reconnect && reconn_tid == 0) {
+				if (vhost_user_reconnect_init() != 0)
+					goto out_mutex;
+			}
+		} else {
+			vsocket->is_server = true;
+		}
+		ret = create_unix_socket(vsocket);
+		if (ret < 0)
+			goto out_mutex;
 	}
 
 	vhost_user.vsockets[vhost_user.vsocket_cnt++] = vsocket;
@@ -1068,7 +1073,9 @@  rte_vhost_driver_unregister(const char *path)
 		if (strcmp(vsocket->path, path))
 			continue;
 
-		if (vsocket->is_server) {
+		if (vsocket->is_vduse) {
+			vduse_device_destroy(path);
+		} else if (vsocket->is_server) {
 			/*
 			 * If r/wcb is executing, release vhost_user's
 			 * mutex lock, and try again since the r/wcb
@@ -1171,6 +1178,9 @@  rte_vhost_driver_start(const char *path)
 	if (!vsocket)
 		return -1;
 
+	if (vsocket->is_vduse)
+		return vduse_device_create(path);
+
 	if (fdset_tid == 0) {
 		/**
 		 * create a pipe which will be waited by poll and notified to
diff --git a/lib/vhost/vduse.c b/lib/vhost/vduse.c
new file mode 100644
index 0000000000..336761c97a
--- /dev/null
+++ b/lib/vhost/vduse.c
@@ -0,0 +1,184 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Red Hat, Inc.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+
+#include <linux/vduse.h>
+#include <linux/virtio_net.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <rte_common.h>
+
+#include "vduse.h"
+#include "vhost.h"
+
+#define VHOST_VDUSE_API_VERSION 0
+#define VDUSE_CTRL_PATH "/dev/vduse/control"
+
+#define VDUSE_NET_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
+				(1ULL << VIRTIO_F_ANY_LAYOUT) | \
+				(1ULL << VIRTIO_F_VERSION_1)   | \
+				(1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
+				(1ULL << VIRTIO_RING_F_EVENT_IDX) | \
+				(1ULL << VIRTIO_F_IN_ORDER) | \
+				(1ULL << VIRTIO_F_IOMMU_PLATFORM))
+
+static struct vhost_backend_ops vduse_backend_ops = {
+};
+
+int
+vduse_device_create(const char *path)
+{
+	int control_fd, dev_fd, vid, ret;
+	uint32_t i;
+	struct virtio_net *dev;
+	uint64_t ver = VHOST_VDUSE_API_VERSION;
+	struct vduse_dev_config *dev_config = NULL;
+	const char *name = path + strlen("/dev/vduse/");
+
+	control_fd = open(VDUSE_CTRL_PATH, O_RDWR);
+	if (control_fd < 0) {
+		VHOST_LOG_CONFIG(name, ERR, "Failed to open %s: %s\n",
+				VDUSE_CTRL_PATH, strerror(errno));
+		return -1;
+	}
+
+	if (ioctl(control_fd, VDUSE_SET_API_VERSION, &ver)) {
+		VHOST_LOG_CONFIG(name, ERR, "Failed to set API version: %" PRIu64 ": %s\n",
+				ver, strerror(errno));
+		ret = -1;
+		goto out_ctrl_close;
+	}
+
+	dev_config = malloc(offsetof(struct vduse_dev_config, config));
+	if (!dev_config) {
+		VHOST_LOG_CONFIG(name, ERR, "Failed to allocate VDUSE config\n");
+		ret = -1;
+		goto out_ctrl_close;
+	}
+
+	memset(dev_config, 0, sizeof(struct vduse_dev_config));
+
+	strncpy(dev_config->name, name, VDUSE_NAME_MAX - 1);
+	dev_config->device_id = VIRTIO_ID_NET;
+	dev_config->vendor_id = 0;
+	dev_config->features = VDUSE_NET_SUPPORTED_FEATURES;
+	dev_config->vq_num = 2;
+	dev_config->vq_align = sysconf(_SC_PAGE_SIZE);
+	dev_config->config_size = 0;
+
+	ret = ioctl(control_fd, VDUSE_CREATE_DEV, dev_config);
+	if (ret < 0) {
+		VHOST_LOG_CONFIG(name, ERR, "Failed to create VDUSE device: %s\n",
+				strerror(errno));
+		goto out_free;
+	}
+
+	dev_fd = open(path, O_RDWR);
+	if (dev_fd < 0) {
+		VHOST_LOG_CONFIG(name, ERR, "Failed to open device %s: %s\n",
+				path, strerror(errno));
+		ret = -1;
+		goto out_dev_close;
+	}
+
+	vid = vhost_new_device(&vduse_backend_ops);
+	if (vid < 0) {
+		VHOST_LOG_CONFIG(name, ERR, "Failed to create new Vhost device\n");
+		ret = -1;
+		goto out_dev_close;
+	}
+
+	dev = get_device(vid);
+	if (!dev) {
+		ret = -1;
+		goto out_dev_close;
+	}
+
+	strncpy(dev->ifname, path, IF_NAME_SZ - 1);
+	dev->vduse_ctrl_fd = control_fd;
+	dev->vduse_dev_fd = dev_fd;
+	vhost_setup_virtio_net(dev->vid, true, true, true, true);
+
+	for (i = 0; i < 2; i++) {
+		struct vduse_vq_config vq_cfg = { 0 };
+
+		ret = alloc_vring_queue(dev, i);
+		if (ret) {
+			VHOST_LOG_CONFIG(name, ERR, "Failed to alloc vring %d metadata\n", i);
+			goto out_dev_destroy;
+		}
+
+		vq_cfg.index = i;
+		vq_cfg.max_size = 1024;
+
+		ret = ioctl(dev->vduse_dev_fd, VDUSE_VQ_SETUP, &vq_cfg);
+		if (ret) {
+			VHOST_LOG_CONFIG(name, ERR, "Failed to set-up VQ %d\n", i);
+			goto out_dev_destroy;
+		}
+	}
+
+	free(dev_config);
+
+	return 0;
+
+out_dev_destroy:
+	vhost_destroy_device(vid);
+out_dev_close:
+	if (dev_fd >= 0)
+		close(dev_fd);
+	ioctl(control_fd, VDUSE_DESTROY_DEV, name);
+out_free:
+	free(dev_config);
+out_ctrl_close:
+	close(control_fd);
+
+	return ret;
+}
+
+int
+vduse_device_destroy(const char *path)
+{
+	const char *name = path + strlen("/dev/vduse/");
+	struct virtio_net *dev;
+	int vid, ret;
+
+	for (vid = 0; vid < RTE_MAX_VHOST_DEVICE; vid++) {
+		dev = vhost_devices[vid];
+
+		if (dev == NULL)
+			continue;
+
+		if (!strcmp(path, dev->ifname))
+			break;
+	}
+
+	if (vid == RTE_MAX_VHOST_DEVICE)
+		return -1;
+
+	if (dev->vduse_dev_fd >= 0) {
+		close(dev->vduse_dev_fd);
+		dev->vduse_dev_fd = -1;
+	}
+
+	if (dev->vduse_ctrl_fd >= 0) {
+		ret = ioctl(dev->vduse_ctrl_fd, VDUSE_DESTROY_DEV, name);
+		if (ret)
+			VHOST_LOG_CONFIG(name, ERR, "Failed to destroy VDUSE device: %s\n",
+					strerror(errno));
+		close(dev->vduse_ctrl_fd);
+		dev->vduse_ctrl_fd = -1;
+	}
+
+	vhost_destroy_device(vid);
+
+	return 0;
+}
diff --git a/lib/vhost/vduse.h b/lib/vhost/vduse.h
new file mode 100644
index 0000000000..a15e5d4c16
--- /dev/null
+++ b/lib/vhost/vduse.h
@@ -0,0 +1,33 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2023 Red Hat, Inc.
+ */
+
+#ifndef _VDUSE_H
+#define _VDUSE_H
+
+#include "vhost.h"
+
+#ifdef VHOST_HAS_VDUSE
+
+int vduse_device_create(const char *path);
+int vduse_device_destroy(const char *path);
+
+#else
+
+static inline int
+vduse_device_create(const char *path)
+{
+	VHOST_LOG_CONFIG(path, ERR, "VDUSE support disabled at build time\n");
+	return -1;
+}
+
+static inline int
+vduse_device_destroy(const char *path)
+{
+	VHOST_LOG_CONFIG(path, ERR, "VDUSE support disabled at build time\n");
+	return -1;
+}
+
+#endif /* VHOST_HAS_VDUSE */
+
+#endif /* _VDUSE_H */
diff --git a/lib/vhost/vhost.h b/lib/vhost/vhost.h
index 76663aed24..c8f2a0d43a 100644
--- a/lib/vhost/vhost.h
+++ b/lib/vhost/vhost.h
@@ -524,6 +524,8 @@  struct virtio_net {
 
 	int			postcopy_ufd;
 	int			postcopy_listening;
+	int			vduse_ctrl_fd;
+	int			vduse_dev_fd;
 
 	struct vhost_virtqueue	*cvq;