[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH 4/4] vhost-user: Add new option to specify vhost
From: |
Tetsuya Mukawa |
Subject: |
[Qemu-devel] [RFC PATCH 4/4] vhost-user: Add new option to specify vhost-user backend supports |
Date: |
Mon, 25 May 2015 16:28:28 +0900 |
This patch adds 'backend_features' option for vhost-user backends.
If this option is specified, QEMU assumes vhost-user backends support
the features specified by user, and QEMU can start without vhost-user
backend.
Here are examples.
* QEMU is configured as vhost-user client.
-chardev socket,id=chr0,path=/tmp/sock,reconnect=3 \
-netdev vhost-user,id=net0,chardev=chr0,vhostforce,backend_features=0x68000 \
-device virtio-net-pci,netdev=net0 \
* QEMU is configured as vhost-user server.
-chardev socket,id=chr0,path=/tmp/sock,server,nowait \
-netdev vhost-user,id=net0,chardev=chr0,vhostforce,backend_features=0x68000 \
-device virtio-net-pci,netdev=net0 \
To know vhost-user backend features that the backend expects, please
specify 0xffffffff as backend_features, then invoke QEMU and check error log
like below.
Lack of backend features. Expected 0xffffffff, but receives 0x68000
Above log indicates the backend features QEMU should be passed.
Signed-off-by: Tetsuya Mukawa <address@hidden>
---
hw/net/vhost_net.c | 9 ++++++++-
hw/net/virtio-net.c | 24 ++++++++++++++++++++++++
hw/scsi/vhost-scsi.c | 2 +-
hw/virtio/vhost-user.c | 9 +++++++++
hw/virtio/vhost.c | 8 ++++++--
include/hw/virtio/vhost.h | 5 ++++-
include/hw/virtio/virtio-net.h | 2 ++
include/net/net.h | 6 ++++++
include/net/vhost_net.h | 2 ++
net/net.c | 18 ++++++++++++++++++
net/tap.c | 5 ++++-
net/vhost-user.c | 42 ++++++++++++++++++++++++++++++++++++++++--
qapi-schema.json | 10 ++++++++--
qemu-options.hx | 3 ++-
14 files changed, 134 insertions(+), 11 deletions(-)
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 47f8b89..f974d09 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -158,8 +158,15 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
net->dev.nvqs = 2;
net->dev.vqs = net->vqs;
+ if (options->has_backend_features) {
+ net->dev.has_backend_features = options->has_backend_features;
+ net->dev.backend_features = options->backend_features;
+ }
+
r = vhost_dev_init(&net->dev, options->opaque,
- options->backend_type, options->force);
+ options->backend_type, options->force,
+ options->has_backend_features,
+ options->backend_features);
if (r < 0) {
goto fail;
}
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 3af6faf..ebe5422 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -366,6 +366,28 @@ static int peer_has_ufo(VirtIONet *n)
return n->has_ufo;
}
+static int peer_has_backend_features(VirtIONet *n)
+{
+ if (!peer_has_vnet_hdr(n))
+ return 0;
+
+ n->has_backend_features =
+ qemu_has_backend_features(qemu_get_queue(n->nic)->peer);
+
+ return n->has_backend_features;
+}
+
+static uint64_t peer_backend_features(VirtIONet *n)
+{
+ if (!peer_has_vnet_hdr(n))
+ return 0;
+
+ n->backend_features =
+ qemu_backend_features(qemu_get_queue(n->nic)->peer);
+
+ return n->backend_features;
+}
+
static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs)
{
int i;
@@ -463,6 +485,8 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev,
uint32_t features)
}
if (!get_vhost_net(nc->peer)) {
+ if (peer_has_backend_features(n))
+ features = peer_backend_features(n);
return features;
}
return vhost_net_get_features(get_vhost_net(nc->peer), features);
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 335f442..4998a95 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -246,7 +246,7 @@ static void vhost_scsi_realize(DeviceState *dev, Error
**errp)
s->dev.backend_features = 0;
ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd,
- VHOST_BACKEND_TYPE_KERNEL, true);
+ VHOST_BACKEND_TYPE_KERNEL, true, false, 0);
if (ret < 0) {
error_setg(errp, "vhost-scsi: vhost initialization failed: %s",
strerror(-ret));
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 4d7e3ba..f0dcb97 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -307,6 +307,15 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned
long int request,
error_report("Received bad msg size.");
goto close;
}
+ if (dev->has_backend_features) {
+ if (dev->backend_features != (dev->backend_features &
msg.u64)) {
+ error_report("Lack of backend features. "
+ "Expected 0x%llx, but receives 0x%lx",
+ dev->backend_features, msg.u64);
+ goto close;
+ }
+ }
+
*((__u64 *) arg) = msg.u64;
break;
case VHOST_USER_GET_VRING_BASE:
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 54851b7..20cb116 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -811,7 +811,9 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue
*vq)
}
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
- VhostBackendType backend_type, bool force)
+ VhostBackendType backend_type, bool force,
+ bool has_backend_features,
+ unsigned long long backend_features)
{
uint64_t features;
int i, r;
@@ -833,7 +835,9 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
r = hdev->vhost_ops->vhost_call(hdev, VHOST_GET_FEATURES, &features);
if (r < 0) {
- goto fail;
+ if (!has_backend_features)
+ goto fail;
+ features = backend_features;
}
for (i = 0; i < hdev->nvqs; ++i) {
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 8f04888..60306cb 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -41,6 +41,7 @@ struct vhost_dev {
unsigned long long features;
unsigned long long acked_features;
unsigned long long backend_features;
+ bool has_backend_features;
bool started;
bool log_enabled;
vhost_log_chunk_t *log;
@@ -55,7 +56,9 @@ struct vhost_dev {
};
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
- VhostBackendType backend_type, bool force);
+ VhostBackendType backend_type, bool force,
+ bool has_backend_features,
+ unsigned long long backend_features);
void vhost_dev_cleanup(struct vhost_dev *hdev);
bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev);
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index e0dbb41..528da28 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -70,6 +70,8 @@ typedef struct VirtIONet {
size_t guest_hdr_len;
uint32_t host_features;
uint8_t has_ufo;
+ uint8_t has_backend_features;
+ uint64_t backend_features;
int mergeable_rx_bufs;
uint8_t promisc;
uint8_t allmulti;
diff --git a/include/net/net.h b/include/net/net.h
index e66ca03..e2eab3e 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -55,6 +55,8 @@ typedef bool (HasVnetHdrLen)(NetClientState *, int);
typedef void (UsingVnetHdr)(NetClientState *, bool);
typedef void (SetOffload)(NetClientState *, int, int, int, int, int);
typedef void (SetVnetHdrLen)(NetClientState *, int);
+typedef bool (HasBackendFeatures)(NetClientState *);
+typedef unsigned long long (BackendFeatures)(NetClientState *);
typedef struct NetClientInfo {
NetClientOptionsKind type;
@@ -73,6 +75,8 @@ typedef struct NetClientInfo {
UsingVnetHdr *using_vnet_hdr;
SetOffload *set_offload;
SetVnetHdrLen *set_vnet_hdr_len;
+ HasBackendFeatures *has_backend_features;
+ BackendFeatures *backend_features;
} NetClientInfo;
struct NetClientState {
@@ -136,6 +140,8 @@ bool qemu_has_ufo(NetClientState *nc);
bool qemu_has_vnet_hdr(NetClientState *nc);
bool qemu_has_vnet_hdr_len(NetClientState *nc, int len);
void qemu_using_vnet_hdr(NetClientState *nc, bool enable);
+bool qemu_has_backend_features(NetClientState *nc);
+unsigned long long qemu_backend_features(NetClientState *nc);
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
int ecn, int ufo);
void qemu_set_vnet_hdr_len(NetClientState *nc, int len);
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index b1c18a3..b4ca8e8 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -12,6 +12,8 @@ typedef struct VhostNetOptions {
NetClientState *net_backend;
void *opaque;
bool force;
+ bool has_backend_features;
+ unsigned long long backend_features;
} VhostNetOptions;
struct vhost_net *vhost_net_init(VhostNetOptions *options);
diff --git a/net/net.c b/net/net.c
index 7427f6a..85e41d0 100644
--- a/net/net.c
+++ b/net/net.c
@@ -459,6 +459,24 @@ void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
nc->info->set_vnet_hdr_len(nc, len);
}
+bool qemu_has_backend_features(NetClientState *nc)
+{
+ if (!nc || !nc->info->has_backend_features) {
+ return false;
+ }
+
+ return nc->info->has_backend_features(nc);
+}
+
+unsigned long long qemu_backend_features(NetClientState *nc)
+{
+ if (!nc || !nc->info->backend_features) {
+ return false;
+ }
+
+ return nc->info->backend_features(nc);
+}
+
int qemu_can_send_packet(NetClientState *sender)
{
int vm_running = runstate_is_running();
diff --git a/net/tap.c b/net/tap.c
index 968df46..6d25170 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -636,12 +636,15 @@ static int net_init_tap_one(const NetdevTapOptions *tap,
NetClientState *peer,
}
if (tap->has_vhost ? tap->vhost :
- vhostfdname || (tap->has_vhostforce && tap->vhostforce)) {
+ vhostfdname || tap->has_backend_features ||
+ (tap->has_vhostforce && tap->vhostforce)) {
VhostNetOptions options;
options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
options.net_backend = &s->nc;
options.force = tap->has_vhostforce && tap->vhostforce;
+ options.has_backend_features = tap->has_backend_features;
+ options.backend_features = tap->backend_features;
if (tap->has_vhostfd || tap->has_vhostfds) {
vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
diff --git a/net/vhost-user.c b/net/vhost-user.c
index d31fc41..2705393 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -19,6 +19,8 @@ typedef struct VhostUserState {
NetClientState nc;
CharDriverState *chr;
VHostNetState *vhost_net;
+ bool has_backend_features;
+ unsigned long long backend_features;
int watch;
} VhostUserState;
@@ -54,6 +56,7 @@ static int vhost_user_start(VhostUserState *s)
options.net_backend = &s->nc;
options.opaque = s->chr;
options.force = true;
+ options.backend_features = s->backend_features;
s->vhost_net = vhost_net_init(&options);
@@ -91,12 +94,32 @@ static bool vhost_user_has_ufo(NetClientState *nc)
return true;
}
+static bool vhost_user_has_backend_features(NetClientState *nc)
+{
+ assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
+
+ VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc);
+
+ return s->has_backend_features;
+}
+
+static unsigned long long vhost_user_backend_features(NetClientState *nc)
+{
+ assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
+
+ VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc);
+
+ return s->backend_features;
+}
+
static NetClientInfo net_vhost_user_info = {
.type = NET_CLIENT_OPTIONS_KIND_VHOST_USER,
.size = sizeof(VhostUserState),
.cleanup = vhost_user_cleanup,
.has_vnet_hdr = vhost_user_has_vnet_hdr,
.has_ufo = vhost_user_has_ufo,
+ .has_backend_features = vhost_user_has_backend_features,
+ .backend_features = vhost_user_backend_features,
};
static void net_vhost_link_down(VhostUserState *s, bool link_down)
@@ -148,7 +171,9 @@ static void net_vhost_user_event(void *opaque, int event)
}
static int net_vhost_user_init(NetClientState *peer, const char *device,
- const char *name, CharDriverState *chr)
+ const char *name, CharDriverState *chr,
+ bool has_backend_features,
+ unsigned long long backend_features)
{
NetClientState *nc;
VhostUserState *s;
@@ -163,6 +188,8 @@ static int net_vhost_user_init(NetClientState *peer, const
char *device,
/* We don't provide a receive callback */
s->nc.receive_disabled = 1;
s->chr = chr;
+ s->has_backend_features = has_backend_features;
+ s->backend_features = backend_features;
qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
@@ -247,6 +274,8 @@ int net_init_vhost_user(const NetClientOptions *opts, const
char *name,
{
const NetdevVhostUserOptions *vhost_user_opts;
CharDriverState *chr;
+ bool has_backend_features;;
+ unsigned long long backend_features;
assert(opts->kind == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
vhost_user_opts = opts->vhost_user;
@@ -263,6 +292,15 @@ int net_init_vhost_user(const NetClientOptions *opts,
const char *name,
return -1;
}
+ /* backend features */
+ if (vhost_user_opts->has_backend_features) {
+ has_backend_features = true;
+ backend_features = vhost_user_opts->backend_features;
+ } else {
+ has_backend_features = false;
+ backend_features = 0;
+ }
- return net_vhost_user_init(peer, "vhost_user", name, chr);
+ return net_vhost_user_init(peer, "vhost_user", name, chr,
+ has_backend_features, backend_features);
}
diff --git a/qapi-schema.json b/qapi-schema.json
index f97ffa1..bab4a74 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2243,6 +2243,8 @@
#
# @queues: #optional number of queues to be created for multiqueue capable tap
#
+# @backend_features: #optional feature flag to support vhost user backend
+#
# Since 1.2
##
{ 'struct': 'NetdevTapOptions',
@@ -2259,7 +2261,8 @@
'*vhostfd': 'str',
'*vhostfds': 'str',
'*vhostforce': 'bool',
- '*queues': 'uint32'} }
+ '*queues': 'uint32',
+ '*backend_features':'uint64'} }
##
# @NetdevSocketOptions
@@ -2444,12 +2447,15 @@
#
# @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
#
+# @backend_features: #optional feature flag to support vhost user backend
(default: 0).
+#
# Since 2.1
##
{ 'struct': 'NetdevVhostUserOptions',
'data': {
'chardev': 'str',
- '*vhostforce': 'bool' } }
+ '*vhostforce': 'bool',
+ '*backend_features': 'uint64' } }
##
# @NetClientOptions
diff --git a/qemu-options.hx b/qemu-options.hx
index ec356f6..3ad3486 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1466,7 +1466,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
"-net tap[,vlan=n][,name=str],ifname=name\n"
" connect the host TAP network interface to VLAN 'n'\n"
#else
- "-net
tap[,vlan=n][,name=str][,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n]\n"
+ "-net
tap[,vlan=n][,name=str][,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n][,backend_features=n]\n"
" connect the host TAP network interface to VLAN 'n'\n"
" use network scripts 'file' (default="
DEFAULT_NETWORK_SCRIPT ")\n"
" to configure it and 'dfile' (default="
DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
@@ -1486,6 +1486,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
" use 'vhostfd=h' to connect to an already opened vhost net
device\n"
" use 'vhostfds=x:y:...:z to connect to multiple already
opened vhost net devices\n"
" use 'queues=n' to specify the number of queues to be
created for multiqueue TAP\n"
+ " use 'backend_features=n' to specify the features that
vhost backend supported\n"
"-net bridge[,vlan=n][,name=str][,br=bridge][,helper=helper]\n"
" connects a host TAP network interface to a host bridge
device 'br'\n"
" (default=" DEFAULT_BRIDGE_INTERFACE ") using the program
'helper'\n"
--
2.1.4
- [Qemu-devel] [RFC PATCH 0/4] Add feature to start QEMU without vhost-user backend, Tetsuya Mukawa, 2015/05/25
- [Qemu-devel] [RFC PATCH 1/4] vhost-user: Add ability to know vhost-user backend disconnection, Tetsuya Mukawa, 2015/05/25
- [Qemu-devel] [RFC PATCH 2/4] vhost-user: Shutdown vhost-user connection when wrong messages are passed, Tetsuya Mukawa, 2015/05/25
- [Qemu-devel] [RFC PATCH 3/4] vhost-user: Enable 'nowait' and 'reconnect' option, Tetsuya Mukawa, 2015/05/25
- [Qemu-devel] [RFC PATCH 4/4] vhost-user: Add new option to specify vhost-user backend supports,
Tetsuya Mukawa <=
- Re: [Qemu-devel] [RFC PATCH 4/4] vhost-user: Add new option to specify vhost-user backend supports, Eric Blake, 2015/05/25
- Re: [Qemu-devel] [RFC PATCH 4/4] vhost-user: Add new option to specify vhost-user backend supports, Tetsuya Mukawa, 2015/05/25
- Re: [Qemu-devel] [RFC PATCH 4/4] vhost-user: Add new option to specify vhost-user backend supports, Tetsuya Mukawa, 2015/05/26
- Re: [Qemu-devel] [RFC PATCH 4/4] vhost-user: Add new option to specify vhost-user backend supports, Eric Blake, 2015/05/26
- Re: [Qemu-devel] [RFC PATCH 4/4] vhost-user: Add new option to specify vhost-user backend supports, Tetsuya Mukawa, 2015/05/27
- Re: [Qemu-devel] [RFC PATCH 4/4] vhost-user: Add new option to specify vhost-user backend supports, Tetsuya Mukawa, 2015/05/29
[Qemu-devel] [PATCH v1 0/4] Add feature to start QEMU without vhost-user backend, Tetsuya Mukawa, 2015/05/29