From: Tiwei Bie <tiwei.bie@intel.com>
This patch set introduces a new net client type: vhost-vdpa.
vhost-vdpa net client will set up a vDPA device which is specified
by a "vhostdev" parameter.
Co-authored-by: Lingshan Zhu <lingshan.zhu@intel.com>
Signed-off-by: Cindy Lu <lulu@redhat.com>
---
include/net/vhost-vdpa.h | 19 ++++
include/net/vhost_net.h | 2 +-
net/Makefile.objs | 2 +-
net/clients.h | 2 +
net/net.c | 3 +
net/vhost-vdpa.c | 235 +++++++++++++++++++++++++++++++++++++++
qapi/net.json | 26 ++++-
7 files changed, 285 insertions(+), 4 deletions(-)
create mode 100644 include/net/vhost-vdpa.h
create mode 100644 net/vhost-vdpa.c
diff --git a/include/net/vhost-vdpa.h b/include/net/vhost-vdpa.h
new file mode 100644
index 0000000000..6ce0d04f72
--- /dev/null
+++ b/include/net/vhost-vdpa.h
@@ -0,0 +1,19 @@
+/*
+ * vhost-vdpa.h
+ *
+ * Copyright(c) 2017-2018 Intel Corporation.
+ * Copyright(c) 2020 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef VHOST_VDPA_H
+#define VHOST_VDPA_H
+
+struct vhost_net;
+struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc);
+uint64_t vhost_vdpa_get_acked_features(NetClientState *nc);
+
+#endif /* VHOST_VDPA_H */
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index 56e67fe164..0b87d3c6e9 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -41,4 +41,4 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net);
int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
int vhost_net_get_device_id(struct vhost_net *net, uint32_t *device_id);
-endif
+#endif
diff --git a/net/Makefile.objs b/net/Makefile.objs
index c5d076d19c..5ab45545db 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -26,7 +26,7 @@ tap-obj-$(CONFIG_SOLARIS) = tap-solaris.o
tap-obj-y ?= tap-stub.o
common-obj-$(CONFIG_POSIX) += tap.o $(tap-obj-y)
common-obj-$(CONFIG_WIN32) += tap-win32.o
-
+common-obj-$(CONFIG_VHOST_NET_VDPA) += vhost-vdpa.o
vde.o-libs = $(VDE_LIBS)
common-obj-$(CONFIG_CAN_BUS) += can/
diff --git a/net/clients.h b/net/clients.h
index a6ef267e19..92f9b59aed 100644
--- a/net/clients.h
+++ b/net/clients.h
@@ -61,4 +61,6 @@ int net_init_netmap(const Netdev *netdev, const char *name,
int net_init_vhost_user(const Netdev *netdev, const char *name,
NetClientState *peer, Error **errp);
+int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
+ NetClientState *peer, Error **errp);
#endif /* QEMU_NET_CLIENTS_H */
diff --git a/net/net.c b/net/net.c
index 599fb61028..82624ea9ac 100644
--- a/net/net.c
+++ b/net/net.c
@@ -965,6 +965,9 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
#ifdef CONFIG_VHOST_NET_USER
[NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
#endif
+#ifdef CONFIG_VHOST_NET_VDPA
+ [NET_CLIENT_DRIVER_VHOST_VDPA] = net_init_vhost_vdpa,
+#endif
#ifdef CONFIG_L2TPV3
[NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
#endif
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
new file mode 100644
index 0000000000..7b98c142b5
--- /dev/null
+++ b/net/vhost-vdpa.c
@@ -0,0 +1,235 @@
+/*
+ * vhost-vdpa.c
+ *
+ * Copyright(c) 2017-2018 Intel Corporation.
+ * Copyright(c) 2020 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "clients.h"
+#include "net/vhost_net.h"
+#include "net/vhost-vdpa.h"
+#include "hw/virtio/vhost-vdpa.h"
+#include "qemu/config-file.h"
+#include "qemu/error-report.h"
+#include "qemu/option.h"
+#include "qapi/error.h"
+#include <sys/ioctl.h>
+#include <err.h>
+#include "standard-headers/linux/virtio_net.h"
+#include "monitor/monitor.h"
+#include "hw/virtio/vhost.h"
+
+/* Todo:need to add the multiqueue support here */
+typedef struct VhostVDPAState {
+ NetClientState nc;
+ struct vhost_vdpa vhost_vdpa;
+ VHostNetState *vhost_net;
+ uint64_t acked_features;
+ bool started;
+} VhostVDPAState;
+
+VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc)
+{
+ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+ return s->vhost_net;
+}
+
+uint64_t vhost_vdpa_get_acked_features(NetClientState *nc)
+{
+ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+ return s->acked_features;
+}
+
+static int vhost_vdpa_check_device_id(NetClientState *nc)
+{
+ uint32_t device_id;
+ int ret;
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
+ /* Get the device id from hw*/
+ ret = vhost_net_get_device_id(s->vhost_net, &device_id);
+ if (device_id != VIRTIO_ID_NET) {
+ return -ENOTSUP;
+ }
+ return ret;
+}
+
+static void vhost_vdpa_del(NetClientState *ncs)
+{
+ VhostVDPAState *s;
+
+ assert(ncs->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+
+ s = DO_UPCAST(VhostVDPAState, nc, ncs);
+
+ if (s->vhost_net) {
+ /* save acked features */
+ uint64_t features = vhost_net_get_acked_features(s->vhost_net);
+ if (features) {
+ s->acked_features = features;
+ }
+ vhost_net_cleanup(s->vhost_net);
+ }
+}
+
+static int vhost_vdpa_add(NetClientState *ncs, void *be)
+{
+ VhostNetOptions options;
+ struct vhost_net *net = NULL;
+ VhostVDPAState *s;
+ int ret;
+
+ options.backend_type = VHOST_BACKEND_TYPE_VDPA;
+
+ assert(ncs->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+
+ s = DO_UPCAST(VhostVDPAState, nc, ncs);
+
+ options.net_backend = ncs;
+ options.opaque = be;
+ options.busyloop_timeout = 0;
+ net = vhost_net_init(&options);
+ if (!net) {
+ error_report("failed to init vhost_net for queue");
+ goto err;
+ }
+
+ if (s->vhost_net) {
+ vhost_net_cleanup(s->vhost_net);
+ g_free(s->vhost_net);
+ }
+ s->vhost_net = net;
+ /* check the device id for vdpa */
+ ret = vhost_vdpa_check_device_id(ncs);
+ if (ret) {
+ goto err;
+ }
+ return 0;
+err:
+ if (net) {
+ vhost_net_cleanup(net);
+ }
+ vhost_vdpa_del(ncs);
+ return -1;
+}
+
+static void vhost_vdpa_cleanup(NetClientState *nc)
+{
+ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
+
+ if (s->vhost_net) {
+ vhost_net_cleanup(s->vhost_net);
+ g_free(s->vhost_net);
+ s->vhost_net = NULL;
+ }
+
+ qemu_purge_queued_packets(nc);
+}
+
+static bool vhost_vdpa_has_vnet_hdr(NetClientState *nc)
+{
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+
+ return true;
+}
+
+static bool vhost_vdpa_has_ufo(NetClientState *nc)
+{
+ assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+ VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
+ uint64_t features = 0;
+
+ features |= (1ULL << VIRTIO_NET_F_HOST_UFO);
+ features = vhost_net_get_features(s->vhost_net, features);
+ return !!(features & (1ULL << VIRTIO_NET_F_HOST_UFO));
+
+}
+
+static NetClientInfo net_vhost_vdpa_info = {
+ .type = NET_CLIENT_DRIVER_VHOST_VDPA,
+ .size = sizeof(VhostVDPAState),
+ .cleanup = vhost_vdpa_cleanup,
+ .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
+ .has_ufo = vhost_vdpa_has_ufo,
+};
+
+static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
+ const char *name, const char *vhostdev,
+ bool has_fd, char *fd)
+{
+ NetClientState *nc = NULL;
+ VhostVDPAState *s;
+ int vdpa_device_fd = -1;
+ Error *err = NULL;
+ int ret = 0;
+ assert(name);
+
+ nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name);
+ snprintf(nc->info_str, sizeof(nc->info_str), "vhost-vdpa");
+ nc->queue_index = 0;
+
+ s = DO_UPCAST(VhostVDPAState, nc, nc);
+
+ if (has_fd) {
+ vdpa_device_fd = monitor_fd_param(cur_mon, fd, &err);
+ } else{
+ vdpa_device_fd = open(vhostdev, O_RDWR);
+ }
+
+ if (vdpa_device_fd == -1) {
+ return -errno;
+ }
+ s->vhost_vdpa.device_fd = vdpa_device_fd;
+ ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa);
+ assert(s->vhost_net);
+
+ if (ret) {
+ if (has_fd) {
+ close(vdpa_device_fd);
+ }
+ }
+ return ret;
+}
+
+static int net_vhost_check_net(void *opaque, QemuOpts *opts, Error **errp)
+{
+ const char *name = opaque;
+ const char *driver, *netdev;
+
+ driver = qemu_opt_get(opts, "driver");
+ netdev = qemu_opt_get(opts, "netdev");
+ if (!driver || !netdev) {
+ return 0;
+ }
+
+ if (strcmp(netdev, name) == 0 &&
+ !g_str_has_prefix(driver, "virtio-net-")) {
+ error_setg(errp, "vhost-vdpa requires frontend driver virtio-net-*");
+ return -1;
+ }
+
+ return 0;
+}
+
+int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
+ NetClientState *peer, Error **errp)
+{
+ const NetdevVhostVDPAOptions *opts;
+
+ assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA);
+ opts = &netdev->u.vhost_vdpa;
+ /* verify net frontend */
+ if (qemu_opts_foreach(qemu_find_opts("device"), net_vhost_check_net,
+ (char *)name, errp)) {
+ return -1;
+ }
+ return net_vhost_vdpa_init(peer, "vhost_vdpa", name, opts->vhostdev,
+ opts->has_fd, opts->fd);
+}
diff --git a/qapi/net.json b/qapi/net.json
index cebb1b52e3..37507ce9ba 100644
--- a/qapi/net.json
+++ b/qapi/net.json
@@ -428,6 +428,27 @@
'*vhostforce': 'bool',
'*queues': 'int' } }
+##
+# @NetdevVhostVDPAOptions:
+#
+# Vhost-vdpa network backend
+#
+# @vhostdev: name of a vdpa dev path in sysfs
+# (default path:/dev/vhost-vdpa-$ID)
+#
+# @fd: file descriptor of an already opened vdpa device
+#
+# @queues: number of queues to be created for multiqueue vhost-vdpa
+# (default: 1)
+#
+# Since: 5.1
+##
+{ 'struct': 'NetdevVhostVDPAOptions',
+ 'data': {
+ '*vhostdev': 'str',
+ '*fd': 'str',
+ '*queues': 'int' } }
+
##
# @NetClientDriver:
#
@@ -437,7 +458,7 @@
##
{ 'enum': 'NetClientDriver',
'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
- 'bridge', 'hubport', 'netmap', 'vhost-user' ] }
+ 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa' ] }
##
# @Netdev:
@@ -465,7 +486,8 @@
'bridge': 'NetdevBridgeOptions',
'hubport': 'NetdevHubPortOptions',
'netmap': 'NetdevNetmapOptions',
- 'vhost-user': 'NetdevVhostUserOptions' } }
+ 'vhost-user': 'NetdevVhostUserOptions',
+ 'vhost-vdpa': 'NetdevVhostVDPAOptions' } }
##
# @NetLegacy:
--
2.21.1
On 5/29/20 9:06 AM, Cindy Lu wrote:
> From: Tiwei Bie <tiwei.bie@intel.com>
>
> This patch set introduces a new net client type: vhost-vdpa.
> vhost-vdpa net client will set up a vDPA device which is specified
> by a "vhostdev" parameter.
>
> Co-authored-by: Lingshan Zhu <lingshan.zhu@intel.com>
> Signed-off-by: Cindy Lu <lulu@redhat.com>
> ---
> +static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
> + const char *name, const char *vhostdev,
> + bool has_fd, char *fd)
> +{
fd is usually an int, not a string.
> + NetClientState *nc = NULL;
> + VhostVDPAState *s;
> + int vdpa_device_fd = -1;
> + Error *err = NULL;
> + int ret = 0;
> + assert(name);
> +
> + nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name);
> + snprintf(nc->info_str, sizeof(nc->info_str), "vhost-vdpa");
> + nc->queue_index = 0;
> +
> + s = DO_UPCAST(VhostVDPAState, nc, nc);
> +
> + if (has_fd) {
> + vdpa_device_fd = monitor_fd_param(cur_mon, fd, &err);
> + } else{
> + vdpa_device_fd = open(vhostdev, O_RDWR);
> + }
Oh, you're trying to use the old way for passing in fds. The preferred
way is to use qemu_open(), at which point you can pass in fds via the
add-fd QMP command, and then pass the string "/dev/fdset/NNN" as
vhostdev. Then you don't need a special fd parameter here.
> +++ b/qapi/net.json
> @@ -428,6 +428,27 @@
> '*vhostforce': 'bool',
> '*queues': 'int' } }
>
> +##
> +# @NetdevVhostVDPAOptions:
> +#
> +# Vhost-vdpa network backend
> +#
> +# @vhostdev: name of a vdpa dev path in sysfs
> +# (default path:/dev/vhost-vdpa-$ID)
> +#
> +# @fd: file descriptor of an already opened vdpa device
> +#
> +# @queues: number of queues to be created for multiqueue vhost-vdpa
> +# (default: 1)
> +#
> +# Since: 5.1
> +##
> +{ 'struct': 'NetdevVhostVDPAOptions',
> + 'data': {
> + '*vhostdev': 'str',
> + '*fd': 'str',
> + '*queues': 'int' } }
Instead of having vhostdev and fd both be optional (but where the user
has to specify exactly one of them), you should only have vhostdev be
mandatory, and rely on the /dev/fdset/NNN string as a way to get
vhostdev to point to a previously-passed fd.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3226
Virtualization: qemu.org | libvirt.org
On Fri, May 29, 2020 at 10:23 PM Eric Blake <eblake@redhat.com> wrote:
>
> On 5/29/20 9:06 AM, Cindy Lu wrote:
> > From: Tiwei Bie <tiwei.bie@intel.com>
> >
> > This patch set introduces a new net client type: vhost-vdpa.
> > vhost-vdpa net client will set up a vDPA device which is specified
> > by a "vhostdev" parameter.
> >
> > Co-authored-by: Lingshan Zhu <lingshan.zhu@intel.com>
> > Signed-off-by: Cindy Lu <lulu@redhat.com>
> > ---
>
> > +static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
> > + const char *name, const char *vhostdev,
> > + bool has_fd, char *fd)
> > +{
>
> fd is usually an int, not a string.
>
will fix this
> > + NetClientState *nc = NULL;
> > + VhostVDPAState *s;
> > + int vdpa_device_fd = -1;
> > + Error *err = NULL;
> > + int ret = 0;
> > + assert(name);
> > +
> > + nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name);
> > + snprintf(nc->info_str, sizeof(nc->info_str), "vhost-vdpa");
> > + nc->queue_index = 0;
> > +
> > + s = DO_UPCAST(VhostVDPAState, nc, nc);
> > +
> > + if (has_fd) {
> > + vdpa_device_fd = monitor_fd_param(cur_mon, fd, &err);
> > + } else{
> > + vdpa_device_fd = open(vhostdev, O_RDWR);
> > + }
>
> Oh, you're trying to use the old way for passing in fds. The preferred
> way is to use qemu_open(), at which point you can pass in fds via the
> add-fd QMP command, and then pass the string "/dev/fdset/NNN" as
> vhostdev. Then you don't need a special fd parameter here.
>
Thanks Eric, I will try this.
> > +++ b/qapi/net.json
> > @@ -428,6 +428,27 @@
> > '*vhostforce': 'bool',
> > '*queues': 'int' } }
> >
> > +##
> > +# @NetdevVhostVDPAOptions:
> > +#
> > +# Vhost-vdpa network backend
> > +#
> > +# @vhostdev: name of a vdpa dev path in sysfs
> > +# (default path:/dev/vhost-vdpa-$ID)
> > +#
> > +# @fd: file descriptor of an already opened vdpa device
> > +#
> > +# @queues: number of queues to be created for multiqueue vhost-vdpa
> > +# (default: 1)
> > +#
> > +# Since: 5.1
> > +##
> > +{ 'struct': 'NetdevVhostVDPAOptions',
> > + 'data': {
> > + '*vhostdev': 'str',
> > + '*fd': 'str',
> > + '*queues': 'int' } }
>
> Instead of having vhostdev and fd both be optional (but where the user
> has to specify exactly one of them), you should only have vhostdev be
> mandatory, and rely on the /dev/fdset/NNN string as a way to get
> vhostdev to point to a previously-passed fd.
>
will fix this
> --
> Eric Blake, Principal Software Engineer
> Red Hat, Inc. +1-919-301-3226
> Virtualization: qemu.org | libvirt.org
>
On 2020/5/29 下午10:06, Cindy Lu wrote:
> From: Tiwei Bie <tiwei.bie@intel.com>
Similar for this patch, you can change the git author and keep sobs for
both Tiwei and Ling Shan.
>
> This patch set introduces a new net client type: vhost-vdpa.
> vhost-vdpa net client will set up a vDPA device which is specified
> by a "vhostdev" parameter.
>
> Co-authored-by: Lingshan Zhu <lingshan.zhu@intel.com>
> Signed-off-by: Cindy Lu <lulu@redhat.com>
> ---
> include/net/vhost-vdpa.h | 19 ++++
> include/net/vhost_net.h | 2 +-
> net/Makefile.objs | 2 +-
> net/clients.h | 2 +
> net/net.c | 3 +
> net/vhost-vdpa.c | 235 +++++++++++++++++++++++++++++++++++++++
> qapi/net.json | 26 ++++-
> 7 files changed, 285 insertions(+), 4 deletions(-)
> create mode 100644 include/net/vhost-vdpa.h
> create mode 100644 net/vhost-vdpa.c
>
> diff --git a/include/net/vhost-vdpa.h b/include/net/vhost-vdpa.h
> new file mode 100644
> index 0000000000..6ce0d04f72
> --- /dev/null
> +++ b/include/net/vhost-vdpa.h
> @@ -0,0 +1,19 @@
> +/*
> + * vhost-vdpa.h
> + *
> + * Copyright(c) 2017-2018 Intel Corporation.
> + * Copyright(c) 2020 Red Hat, Inc.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#ifndef VHOST_VDPA_H
> +#define VHOST_VDPA_H
> +
> +struct vhost_net;
> +struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc);
> +uint64_t vhost_vdpa_get_acked_features(NetClientState *nc);
> +
> +#endif /* VHOST_VDPA_H */
> diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
> index 56e67fe164..0b87d3c6e9 100644
> --- a/include/net/vhost_net.h
> +++ b/include/net/vhost_net.h
> @@ -41,4 +41,4 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net);
>
> int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
> int vhost_net_get_device_id(struct vhost_net *net, uint32_t *device_id);
> -endif
> +#endif
> diff --git a/net/Makefile.objs b/net/Makefile.objs
> index c5d076d19c..5ab45545db 100644
> --- a/net/Makefile.objs
> +++ b/net/Makefile.objs
> @@ -26,7 +26,7 @@ tap-obj-$(CONFIG_SOLARIS) = tap-solaris.o
> tap-obj-y ?= tap-stub.o
> common-obj-$(CONFIG_POSIX) += tap.o $(tap-obj-y)
> common-obj-$(CONFIG_WIN32) += tap-win32.o
> -
> +common-obj-$(CONFIG_VHOST_NET_VDPA) += vhost-vdpa.o
> vde.o-libs = $(VDE_LIBS)
>
> common-obj-$(CONFIG_CAN_BUS) += can/
> diff --git a/net/clients.h b/net/clients.h
> index a6ef267e19..92f9b59aed 100644
> --- a/net/clients.h
> +++ b/net/clients.h
> @@ -61,4 +61,6 @@ int net_init_netmap(const Netdev *netdev, const char *name,
> int net_init_vhost_user(const Netdev *netdev, const char *name,
> NetClientState *peer, Error **errp);
>
> +int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
> + NetClientState *peer, Error **errp);
> #endif /* QEMU_NET_CLIENTS_H */
> diff --git a/net/net.c b/net/net.c
> index 599fb61028..82624ea9ac 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -965,6 +965,9 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
> #ifdef CONFIG_VHOST_NET_USER
> [NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
> #endif
> +#ifdef CONFIG_VHOST_NET_VDPA
> + [NET_CLIENT_DRIVER_VHOST_VDPA] = net_init_vhost_vdpa,
> +#endif
> #ifdef CONFIG_L2TPV3
> [NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
> #endif
> diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
> new file mode 100644
> index 0000000000..7b98c142b5
> --- /dev/null
> +++ b/net/vhost-vdpa.c
> @@ -0,0 +1,235 @@
> +/*
> + * vhost-vdpa.c
> + *
> + * Copyright(c) 2017-2018 Intel Corporation.
> + * Copyright(c) 2020 Red Hat, Inc.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "clients.h"
> +#include "net/vhost_net.h"
> +#include "net/vhost-vdpa.h"
> +#include "hw/virtio/vhost-vdpa.h"
> +#include "qemu/config-file.h"
> +#include "qemu/error-report.h"
> +#include "qemu/option.h"
> +#include "qapi/error.h"
> +#include <sys/ioctl.h>
> +#include <err.h>
> +#include "standard-headers/linux/virtio_net.h"
> +#include "monitor/monitor.h"
> +#include "hw/virtio/vhost.h"
> +
> +/* Todo:need to add the multiqueue support here */
> +typedef struct VhostVDPAState {
> + NetClientState nc;
> + struct vhost_vdpa vhost_vdpa;
> + VHostNetState *vhost_net;
> + uint64_t acked_features;
> + bool started;
> +} VhostVDPAState;
> +
> +VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc)
> +{
> + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> + return s->vhost_net;
> +}
> +
> +uint64_t vhost_vdpa_get_acked_features(NetClientState *nc)
> +{
> + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> + return s->acked_features;
> +}
> +
> +static int vhost_vdpa_check_device_id(NetClientState *nc)
A better name is needed, something like "vhost_vdpa_net_check_devie_id"
is better.
> +{
> + uint32_t device_id;
> + int ret;
> + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> + /* Get the device id from hw*/
The code explains itself, so no need for this comment.
> + ret = vhost_net_get_device_id(s->vhost_net, &device_id);
> + if (device_id != VIRTIO_ID_NET) {
> + return -ENOTSUP;
> + }
> + return ret;
> +}
> +
> +static void vhost_vdpa_del(NetClientState *ncs)
> +{
> + VhostVDPAState *s;
> +
> + assert(ncs->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> +
> + s = DO_UPCAST(VhostVDPAState, nc, ncs);
> +
> + if (s->vhost_net) {
> + /* save acked features */
> + uint64_t features = vhost_net_get_acked_features(s->vhost_net);
> + if (features) {
> + s->acked_features = features;
> + }
I'm not sure I get here, is the acked_features used in the
vhost_net_cleanup()?
> + vhost_net_cleanup(s->vhost_net);
> + }
> +}
> +
> +static int vhost_vdpa_add(NetClientState *ncs, void *be)
> +{
> + VhostNetOptions options;
> + struct vhost_net *net = NULL;
> + VhostVDPAState *s;
> + int ret;
> +
> + options.backend_type = VHOST_BACKEND_TYPE_VDPA;
> +
> + assert(ncs->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> +
> + s = DO_UPCAST(VhostVDPAState, nc, ncs);
> +
> + options.net_backend = ncs;
> + options.opaque = be;
> + options.busyloop_timeout = 0;
> + net = vhost_net_init(&options);
> + if (!net) {
> + error_report("failed to init vhost_net for queue");
> + goto err;
> + }
> +
> + if (s->vhost_net) {
> + vhost_net_cleanup(s->vhost_net);
> + g_free(s->vhost_net);
> + }
> + s->vhost_net = net;
> + /* check the device id for vdpa */
The comment could be removed as well.
> + ret = vhost_vdpa_check_device_id(ncs);
> + if (ret) {
> + goto err;
> + }
> + return 0;
> +err:
> + if (net) {
> + vhost_net_cleanup(net);
> + }
> + vhost_vdpa_del(ncs);
> + return -1;
> +}
> +
> +static void vhost_vdpa_cleanup(NetClientState *nc)
> +{
> + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> +
> + if (s->vhost_net) {
> + vhost_net_cleanup(s->vhost_net);
> + g_free(s->vhost_net);
> + s->vhost_net = NULL;
> + }
> +
> + qemu_purge_queued_packets(nc);
Why this is needed?
Thanks
> +}
> +
> +static bool vhost_vdpa_has_vnet_hdr(NetClientState *nc)
> +{
> + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> +
> + return true;
> +}
> +
> +static bool vhost_vdpa_has_ufo(NetClientState *nc)
> +{
> + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> + uint64_t features = 0;
> +
> + features |= (1ULL << VIRTIO_NET_F_HOST_UFO);
> + features = vhost_net_get_features(s->vhost_net, features);
> + return !!(features & (1ULL << VIRTIO_NET_F_HOST_UFO));
> +
> +}
> +
> +static NetClientInfo net_vhost_vdpa_info = {
> + .type = NET_CLIENT_DRIVER_VHOST_VDPA,
> + .size = sizeof(VhostVDPAState),
> + .cleanup = vhost_vdpa_cleanup,
> + .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
> + .has_ufo = vhost_vdpa_has_ufo,
> +};
> +
> +static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
> + const char *name, const char *vhostdev,
> + bool has_fd, char *fd)
> +{
> + NetClientState *nc = NULL;
> + VhostVDPAState *s;
> + int vdpa_device_fd = -1;
> + Error *err = NULL;
> + int ret = 0;
> + assert(name);
> +
> + nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name);
> + snprintf(nc->info_str, sizeof(nc->info_str), "vhost-vdpa");
> + nc->queue_index = 0;
> +
> + s = DO_UPCAST(VhostVDPAState, nc, nc);
> +
> + if (has_fd) {
> + vdpa_device_fd = monitor_fd_param(cur_mon, fd, &err);
> + } else{
> + vdpa_device_fd = open(vhostdev, O_RDWR);
> + }
> +
> + if (vdpa_device_fd == -1) {
> + return -errno;
> + }
> + s->vhost_vdpa.device_fd = vdpa_device_fd;
> + ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa);
> + assert(s->vhost_net);
> +
> + if (ret) {
> + if (has_fd) {
> + close(vdpa_device_fd);
> + }
> + }
> + return ret;
> +}
> +
> +static int net_vhost_check_net(void *opaque, QemuOpts *opts, Error **errp)
> +{
> + const char *name = opaque;
> + const char *driver, *netdev;
> +
> + driver = qemu_opt_get(opts, "driver");
> + netdev = qemu_opt_get(opts, "netdev");
> + if (!driver || !netdev) {
> + return 0;
> + }
> +
> + if (strcmp(netdev, name) == 0 &&
> + !g_str_has_prefix(driver, "virtio-net-")) {
> + error_setg(errp, "vhost-vdpa requires frontend driver virtio-net-*");
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
> + NetClientState *peer, Error **errp)
> +{
> + const NetdevVhostVDPAOptions *opts;
> +
> + assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> + opts = &netdev->u.vhost_vdpa;
> + /* verify net frontend */
> + if (qemu_opts_foreach(qemu_find_opts("device"), net_vhost_check_net,
> + (char *)name, errp)) {
> + return -1;
> + }
> + return net_vhost_vdpa_init(peer, "vhost_vdpa", name, opts->vhostdev,
> + opts->has_fd, opts->fd);
> +}
> diff --git a/qapi/net.json b/qapi/net.json
> index cebb1b52e3..37507ce9ba 100644
> --- a/qapi/net.json
> +++ b/qapi/net.json
> @@ -428,6 +428,27 @@
> '*vhostforce': 'bool',
> '*queues': 'int' } }
>
> +##
> +# @NetdevVhostVDPAOptions:
> +#
> +# Vhost-vdpa network backend
> +#
> +# @vhostdev: name of a vdpa dev path in sysfs
> +# (default path:/dev/vhost-vdpa-$ID)
> +#
> +# @fd: file descriptor of an already opened vdpa device
> +#
> +# @queues: number of queues to be created for multiqueue vhost-vdpa
> +# (default: 1)
> +#
> +# Since: 5.1
> +##
> +{ 'struct': 'NetdevVhostVDPAOptions',
> + 'data': {
> + '*vhostdev': 'str',
> + '*fd': 'str',
> + '*queues': 'int' } }
> +
> ##
> # @NetClientDriver:
> #
> @@ -437,7 +458,7 @@
> ##
> { 'enum': 'NetClientDriver',
> 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
> - 'bridge', 'hubport', 'netmap', 'vhost-user' ] }
> + 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa' ] }
>
> ##
> # @Netdev:
> @@ -465,7 +486,8 @@
> 'bridge': 'NetdevBridgeOptions',
> 'hubport': 'NetdevHubPortOptions',
> 'netmap': 'NetdevNetmapOptions',
> - 'vhost-user': 'NetdevVhostUserOptions' } }
> + 'vhost-user': 'NetdevVhostUserOptions',
> + 'vhost-vdpa': 'NetdevVhostVDPAOptions' } }
>
> ##
> # @NetLegacy:
Hi Jason,
On Wed, Jun 3, 2020 at 2:39 PM Jason Wang <jasowang@redhat.com> wrote:
>
>
> On 2020/5/29 下午10:06, Cindy Lu wrote:
> > From: Tiwei Bie <tiwei.bie@intel.com>
>
>
> Similar for this patch, you can change the git author and keep sobs for
> both Tiwei and Ling Shan.
>
>
Will Fix this
> >
> > This patch set introduces a new net client type: vhost-vdpa.
> > vhost-vdpa net client will set up a vDPA device which is specified
> > by a "vhostdev" parameter.
> >
> > Co-authored-by: Lingshan Zhu <lingshan.zhu@intel.com>
> > Signed-off-by: Cindy Lu <lulu@redhat.com>
> > ---
> > include/net/vhost-vdpa.h | 19 ++++
> > include/net/vhost_net.h | 2 +-
> > net/Makefile.objs | 2 +-
> > net/clients.h | 2 +
> > net/net.c | 3 +
> > net/vhost-vdpa.c | 235 +++++++++++++++++++++++++++++++++++++++
> > qapi/net.json | 26 ++++-
> > 7 files changed, 285 insertions(+), 4 deletions(-)
> > create mode 100644 include/net/vhost-vdpa.h
> > create mode 100644 net/vhost-vdpa.c
> >
> > diff --git a/include/net/vhost-vdpa.h b/include/net/vhost-vdpa.h
> > new file mode 100644
> > index 0000000000..6ce0d04f72
> > --- /dev/null
> > +++ b/include/net/vhost-vdpa.h
> > @@ -0,0 +1,19 @@
> > +/*
> > + * vhost-vdpa.h
> > + *
> > + * Copyright(c) 2017-2018 Intel Corporation.
> > + * Copyright(c) 2020 Red Hat, Inc.
> > + *
> > + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> > + * See the COPYING file in the top-level directory.
> > + *
> > + */
> > +
> > +#ifndef VHOST_VDPA_H
> > +#define VHOST_VDPA_H
> > +
> > +struct vhost_net;
> > +struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc);
> > +uint64_t vhost_vdpa_get_acked_features(NetClientState *nc);
> > +
> > +#endif /* VHOST_VDPA_H */
> > diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
> > index 56e67fe164..0b87d3c6e9 100644
> > --- a/include/net/vhost_net.h
> > +++ b/include/net/vhost_net.h
> > @@ -41,4 +41,4 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net);
> >
> > int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu);
> > int vhost_net_get_device_id(struct vhost_net *net, uint32_t *device_id);
> > -endif
> > +#endif
> > diff --git a/net/Makefile.objs b/net/Makefile.objs
> > index c5d076d19c..5ab45545db 100644
> > --- a/net/Makefile.objs
> > +++ b/net/Makefile.objs
> > @@ -26,7 +26,7 @@ tap-obj-$(CONFIG_SOLARIS) = tap-solaris.o
> > tap-obj-y ?= tap-stub.o
> > common-obj-$(CONFIG_POSIX) += tap.o $(tap-obj-y)
> > common-obj-$(CONFIG_WIN32) += tap-win32.o
> > -
> > +common-obj-$(CONFIG_VHOST_NET_VDPA) += vhost-vdpa.o
> > vde.o-libs = $(VDE_LIBS)
> >
> > common-obj-$(CONFIG_CAN_BUS) += can/
> > diff --git a/net/clients.h b/net/clients.h
> > index a6ef267e19..92f9b59aed 100644
> > --- a/net/clients.h
> > +++ b/net/clients.h
> > @@ -61,4 +61,6 @@ int net_init_netmap(const Netdev *netdev, const char *name,
> > int net_init_vhost_user(const Netdev *netdev, const char *name,
> > NetClientState *peer, Error **errp);
> >
> > +int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
> > + NetClientState *peer, Error **errp);
> > #endif /* QEMU_NET_CLIENTS_H */
> > diff --git a/net/net.c b/net/net.c
> > index 599fb61028..82624ea9ac 100644
> > --- a/net/net.c
> > +++ b/net/net.c
> > @@ -965,6 +965,9 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
> > #ifdef CONFIG_VHOST_NET_USER
> > [NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
> > #endif
> > +#ifdef CONFIG_VHOST_NET_VDPA
> > + [NET_CLIENT_DRIVER_VHOST_VDPA] = net_init_vhost_vdpa,
> > +#endif
> > #ifdef CONFIG_L2TPV3
> > [NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
> > #endif
> > diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
> > new file mode 100644
> > index 0000000000..7b98c142b5
> > --- /dev/null
> > +++ b/net/vhost-vdpa.c
> > @@ -0,0 +1,235 @@
> > +/*
> > + * vhost-vdpa.c
> > + *
> > + * Copyright(c) 2017-2018 Intel Corporation.
> > + * Copyright(c) 2020 Red Hat, Inc.
> > + *
> > + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> > + * See the COPYING file in the top-level directory.
> > + *
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "clients.h"
> > +#include "net/vhost_net.h"
> > +#include "net/vhost-vdpa.h"
> > +#include "hw/virtio/vhost-vdpa.h"
> > +#include "qemu/config-file.h"
> > +#include "qemu/error-report.h"
> > +#include "qemu/option.h"
> > +#include "qapi/error.h"
> > +#include <sys/ioctl.h>
> > +#include <err.h>
> > +#include "standard-headers/linux/virtio_net.h"
> > +#include "monitor/monitor.h"
> > +#include "hw/virtio/vhost.h"
> > +
> > +/* Todo:need to add the multiqueue support here */
> > +typedef struct VhostVDPAState {
> > + NetClientState nc;
> > + struct vhost_vdpa vhost_vdpa;
> > + VHostNetState *vhost_net;
> > + uint64_t acked_features;
> > + bool started;
> > +} VhostVDPAState;
> > +
> > +VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc)
> > +{
> > + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> > + return s->vhost_net;
> > +}
> > +
> > +uint64_t vhost_vdpa_get_acked_features(NetClientState *nc)
> > +{
> > + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> > + return s->acked_features;
> > +}
> > +
> > +static int vhost_vdpa_check_device_id(NetClientState *nc)
>
>
> A better name is needed, something like "vhost_vdpa_net_check_devie_id"
> is better.
>
Sure will fix this
>
> > +{
> > + uint32_t device_id;
> > + int ret;
> > + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> > + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > + /* Get the device id from hw*/
>
>
> The code explains itself, so no need for this comment.
>
will remove this
>
> > + ret = vhost_net_get_device_id(s->vhost_net, &device_id);
> > + if (device_id != VIRTIO_ID_NET) {
> > + return -ENOTSUP;
> > + }
> > + return ret;
> > +}
> > +
> > +static void vhost_vdpa_del(NetClientState *ncs)
> > +{
> > + VhostVDPAState *s;
> > +
> > + assert(ncs->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> > +
> > + s = DO_UPCAST(VhostVDPAState, nc, ncs);
> > +
> > + if (s->vhost_net) {
> > + /* save acked features */
> > + uint64_t features = vhost_net_get_acked_features(s->vhost_net);
> > + if (features) {
> > + s->acked_features = features;
> > + }
>
>
> I'm not sure I get here, is the acked_features used in the
> vhost_net_cleanup()?
>
I think we can remove this part, seems these bit are not using anymore
>
> > + vhost_net_cleanup(s->vhost_net);
> > + }
> > +}
> > +
> > +static int vhost_vdpa_add(NetClientState *ncs, void *be)
> > +{
> > + VhostNetOptions options;
> > + struct vhost_net *net = NULL;
> > + VhostVDPAState *s;
> > + int ret;
> > +
> > + options.backend_type = VHOST_BACKEND_TYPE_VDPA;
> > +
> > + assert(ncs->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> > +
> > + s = DO_UPCAST(VhostVDPAState, nc, ncs);
> > +
> > + options.net_backend = ncs;
> > + options.opaque = be;
> > + options.busyloop_timeout = 0;
> > + net = vhost_net_init(&options);
> > + if (!net) {
> > + error_report("failed to init vhost_net for queue");
> > + goto err;
> > + }
> > +
> > + if (s->vhost_net) {
> > + vhost_net_cleanup(s->vhost_net);
> > + g_free(s->vhost_net);
> > + }
> > + s->vhost_net = net;
> > + /* check the device id for vdpa */
>
>
> The comment could be removed as well.
>
>
Sure will remove this
> > + ret = vhost_vdpa_check_device_id(ncs);
> > + if (ret) {
> > + goto err;
> > + }
> > + return 0;
> > +err:
> > + if (net) {
> > + vhost_net_cleanup(net);
> > + }
> > + vhost_vdpa_del(ncs);
> > + return -1;
> > +}
> > +
> > +static void vhost_vdpa_cleanup(NetClientState *nc)
> > +{
> > + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > +
> > + if (s->vhost_net) {
> > + vhost_net_cleanup(s->vhost_net);
> > + g_free(s->vhost_net);
> > + s->vhost_net = NULL;
> > + }
> > +
> > + qemu_purge_queued_packets(nc);
>
>
> Why this is needed?
>
> Thanks
>
This is to clean the packet in the queue while the vdpa remove, I
will double check this part
>
> > +}
> > +
> > +static bool vhost_vdpa_has_vnet_hdr(NetClientState *nc)
> > +{
> > + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> > +
> > + return true;
> > +}
> > +
> > +static bool vhost_vdpa_has_ufo(NetClientState *nc)
> > +{
> > + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> > + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> > + uint64_t features = 0;
> > +
> > + features |= (1ULL << VIRTIO_NET_F_HOST_UFO);
> > + features = vhost_net_get_features(s->vhost_net, features);
> > + return !!(features & (1ULL << VIRTIO_NET_F_HOST_UFO));
> > +
> > +}
> > +
> > +static NetClientInfo net_vhost_vdpa_info = {
> > + .type = NET_CLIENT_DRIVER_VHOST_VDPA,
> > + .size = sizeof(VhostVDPAState),
> > + .cleanup = vhost_vdpa_cleanup,
> > + .has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
> > + .has_ufo = vhost_vdpa_has_ufo,
> > +};
> > +
> > +static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
> > + const char *name, const char *vhostdev,
> > + bool has_fd, char *fd)
> > +{
> > + NetClientState *nc = NULL;
> > + VhostVDPAState *s;
> > + int vdpa_device_fd = -1;
> > + Error *err = NULL;
> > + int ret = 0;
> > + assert(name);
> > +
> > + nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name);
> > + snprintf(nc->info_str, sizeof(nc->info_str), "vhost-vdpa");
> > + nc->queue_index = 0;
> > +
> > + s = DO_UPCAST(VhostVDPAState, nc, nc);
> > +
> > + if (has_fd) {
> > + vdpa_device_fd = monitor_fd_param(cur_mon, fd, &err);
> > + } else{
> > + vdpa_device_fd = open(vhostdev, O_RDWR);
> > + }
> > +
> > + if (vdpa_device_fd == -1) {
> > + return -errno;
> > + }
> > + s->vhost_vdpa.device_fd = vdpa_device_fd;
> > + ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa);
> > + assert(s->vhost_net);
> > +
> > + if (ret) {
> > + if (has_fd) {
> > + close(vdpa_device_fd);
> > + }
> > + }
> > + return ret;
> > +}
> > +
> > +static int net_vhost_check_net(void *opaque, QemuOpts *opts, Error **errp)
> > +{
> > + const char *name = opaque;
> > + const char *driver, *netdev;
> > +
> > + driver = qemu_opt_get(opts, "driver");
> > + netdev = qemu_opt_get(opts, "netdev");
> > + if (!driver || !netdev) {
> > + return 0;
> > + }
> > +
> > + if (strcmp(netdev, name) == 0 &&
> > + !g_str_has_prefix(driver, "virtio-net-")) {
> > + error_setg(errp, "vhost-vdpa requires frontend driver virtio-net-*");
> > + return -1;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
> > + NetClientState *peer, Error **errp)
> > +{
> > + const NetdevVhostVDPAOptions *opts;
> > +
> > + assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA);
> > + opts = &netdev->u.vhost_vdpa;
> > + /* verify net frontend */
> > + if (qemu_opts_foreach(qemu_find_opts("device"), net_vhost_check_net,
> > + (char *)name, errp)) {
> > + return -1;
> > + }
> > + return net_vhost_vdpa_init(peer, "vhost_vdpa", name, opts->vhostdev,
> > + opts->has_fd, opts->fd);
> > +}
> > diff --git a/qapi/net.json b/qapi/net.json
> > index cebb1b52e3..37507ce9ba 100644
> > --- a/qapi/net.json
> > +++ b/qapi/net.json
> > @@ -428,6 +428,27 @@
> > '*vhostforce': 'bool',
> > '*queues': 'int' } }
> >
> > +##
> > +# @NetdevVhostVDPAOptions:
> > +#
> > +# Vhost-vdpa network backend
> > +#
> > +# @vhostdev: name of a vdpa dev path in sysfs
> > +# (default path:/dev/vhost-vdpa-$ID)
> > +#
> > +# @fd: file descriptor of an already opened vdpa device
> > +#
> > +# @queues: number of queues to be created for multiqueue vhost-vdpa
> > +# (default: 1)
> > +#
> > +# Since: 5.1
> > +##
> > +{ 'struct': 'NetdevVhostVDPAOptions',
> > + 'data': {
> > + '*vhostdev': 'str',
> > + '*fd': 'str',
> > + '*queues': 'int' } }
> > +
> > ##
> > # @NetClientDriver:
> > #
> > @@ -437,7 +458,7 @@
> > ##
> > { 'enum': 'NetClientDriver',
> > 'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
> > - 'bridge', 'hubport', 'netmap', 'vhost-user' ] }
> > + 'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa' ] }
> >
> > ##
> > # @Netdev:
> > @@ -465,7 +486,8 @@
> > 'bridge': 'NetdevBridgeOptions',
> > 'hubport': 'NetdevHubPortOptions',
> > 'netmap': 'NetdevNetmapOptions',
> > - 'vhost-user': 'NetdevVhostUserOptions' } }
> > + 'vhost-user': 'NetdevVhostUserOptions',
> > + 'vhost-vdpa': 'NetdevVhostVDPAOptions' } }
> >
> > ##
> > # @NetLegacy:
>
On 2020/6/3 下午4:19, Cindy Lu wrote:
>>> +static void vhost_vdpa_cleanup(NetClientState *nc)
>>> +{
>>> + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
>>> +
>>> + if (s->vhost_net) {
>>> + vhost_net_cleanup(s->vhost_net);
>>> + g_free(s->vhost_net);
>>> + s->vhost_net = NULL;
>>> + }
>>> +
>>> + qemu_purge_queued_packets(nc);
>> Why this is needed?
>>
>> Thanks
>>
> This is to clean the packet in the queue while the vdpa remove, I
> will double check this part
Note we don't have a software backup driver for qemu currently (we
probably need one in the future).
So we can't fallback into userspace which means the packet can not be
queued by qemu.
Thanks
Hi Jason,
On Wed, Jun 3, 2020 at 4:43 PM Jason Wang <jasowang@redhat.com> wrote:
>
>
> On 2020/6/3 下午4:19, Cindy Lu wrote:
> >>> +static void vhost_vdpa_cleanup(NetClientState *nc)
> >>> +{
> >>> + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
> >>> +
> >>> + if (s->vhost_net) {
> >>> + vhost_net_cleanup(s->vhost_net);
> >>> + g_free(s->vhost_net);
> >>> + s->vhost_net = NULL;
> >>> + }
> >>> +
> >>> + qemu_purge_queued_packets(nc);
> >> Why this is needed?
> >>
> >> Thanks
> >>
> > This is to clean the packet in the queue while the vdpa remove, I
> > will double check this part
>
>
> Note we don't have a software backup driver for qemu currently (we
> probably need one in the future).
>
> So we can't fallback into userspace which means the packet can not be
> queued by qemu.
>
Got it, Thanks Jason, I will remove this part
> Thanks
>
© 2016 - 2026 Red Hat, Inc.