[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 5/5] vhost-user: Add new option to specify vhost-
From: |
Tetsuya Mukawa |
Subject: |
[Qemu-devel] [PATCH v2 5/5] vhost-user: Add new option to specify vhost-user backend supports |
Date: |
Mon, 22 Jun 2015 12:50:48 +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 | 6 +++++-
hw/net/virtio-net.c | 15 +++++++++++++++
hw/scsi/vhost-scsi.c | 2 +-
hw/virtio/vhost-user.c | 6 ++++++
hw/virtio/vhost.c | 3 ++-
include/hw/virtio/vhost.h | 3 ++-
include/hw/virtio/virtio-net.h | 1 +
include/net/net.h | 3 +++
include/net/vhost_net.h | 1 +
net/net.c | 9 +++++++++
net/tap.c | 1 +
net/vhost-user.c | 19 +++++++++++++++++--
qapi-schema.json | 12 ++++++++++--
qemu-options.hx | 3 ++-
14 files changed, 75 insertions(+), 9 deletions(-)
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 9bd360b..b9425ea 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -162,8 +162,12 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
net->dev.vqs = net->vqs;
net->dev.vq_index = net->nc->queue_index;
+ if (options->backend_features) {
+ net->dev.backend_features = options->backend_features;
+ }
+
r = vhost_dev_init(&net->dev, options->opaque,
- options->backend_type);
+ options->backend_type, options->backend_features);
if (r < 0) {
goto fail;
}
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index d728233..7138f4e 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -363,6 +363,18 @@ static int peer_has_ufo(VirtIONet *n)
return n->has_ufo;
}
+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 version_1)
{
@@ -467,6 +479,9 @@ static uint64_t virtio_net_get_features(VirtIODevice *vdev,
uint64_t features)
if (!get_vhost_net(nc->peer)) {
virtio_add_feature(&features, VIRTIO_F_VERSION_1);
+ if (peer_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 1c389c4..1d7957c 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);
+ VHOST_BACKEND_TYPE_KERNEL, 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 2215c39..3caa1a0 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -315,6 +315,12 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned
long int request,
error_report("Received bad msg size.");
goto close;
}
+ if (dev->backend_features != (dev->backend_features & msg.u64)) {
+ error_report("Lack of backend features. "
+ "Expected 0x%llx, but receives 0x%" PRIx64,
+ 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 a6dcc79..bbfc336 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -901,7 +901,8 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue
*vq)
}
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
- VhostBackendType backend_type)
+ VhostBackendType backend_type,
+ unsigned long long backend_features)
{
uint64_t features;
int i, r;
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index dd51050..074b36b 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -60,7 +60,8 @@ struct vhost_dev {
};
int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
- VhostBackendType backend_type);
+ VhostBackendType backend_type,
+ 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 280dacf..871dc3c 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -70,6 +70,7 @@ typedef struct VirtIONet {
size_t guest_hdr_len;
uint32_t host_features;
uint8_t has_ufo;
+ 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 4306252..d4379d1 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -57,6 +57,7 @@ typedef void (SetOffload)(NetClientState *, int, int, int,
int, int);
typedef void (SetVnetHdrLen)(NetClientState *, int);
typedef int (SetVnetLE)(NetClientState *, bool);
typedef int (SetVnetBE)(NetClientState *, bool);
+typedef unsigned long long (BackendFeatures)(NetClientState *);
typedef struct NetClientInfo {
NetClientOptionsKind type;
@@ -77,6 +78,7 @@ typedef struct NetClientInfo {
SetVnetHdrLen *set_vnet_hdr_len;
SetVnetLE *set_vnet_le;
SetVnetBE *set_vnet_be;
+ BackendFeatures *backend_features;
} NetClientInfo;
struct NetClientState {
@@ -140,6 +142,7 @@ 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);
+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 840d4b1..0b19b4a 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -11,6 +11,7 @@ typedef struct VhostNetOptions {
VhostBackendType backend_type;
NetClientState *net_backend;
void *opaque;
+ 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 6dbd61a..4ad7a69 100644
--- a/net/net.c
+++ b/net/net.c
@@ -528,6 +528,15 @@ int qemu_set_vnet_be(NetClientState *nc, bool is_be)
return nc->info->set_vnet_be(nc, is_be);
}
+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 bd01590..743c168 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -662,6 +662,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap,
NetClientState *peer,
options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
options.net_backend = &s->nc;
+ 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 58cd5dc..fd46e32 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -19,6 +19,7 @@ typedef struct VhostUserState {
NetClientState nc;
CharDriverState *chr;
VHostNetState *vhost_net;
+ unsigned long long backend_features;
int watch;
} VhostUserState;
@@ -53,6 +54,7 @@ static int vhost_user_start(VhostUserState *s)
options.backend_type = VHOST_BACKEND_TYPE_USER;
options.net_backend = &s->nc;
options.opaque = s->chr;
+ options.backend_features = s->backend_features;
s->vhost_net = vhost_net_init(&options);
@@ -90,12 +92,22 @@ static bool vhost_user_has_ufo(NetClientState *nc)
return true;
}
+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,
+ .backend_features = vhost_user_backend_features,
};
static void net_vhost_link_down(VhostUserState *s, bool link_down)
@@ -152,7 +164,8 @@ 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,
- uint32_t queues)
+ uint32_t queues,
+ unsigned long long backend_features)
{
NetClientState *nc;
VhostUserState *s;
@@ -170,6 +183,7 @@ static int net_vhost_user_init(NetClientState *peer, const
char *device,
s->nc.receive_disabled = 1;
s->chr = chr;
s->nc.queue_index = i;
+ s->backend_features = backend_features;
qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
}
@@ -279,5 +293,6 @@ int net_init_vhost_user(const NetClientOptions *opts, const
char *name,
queues = 1;
}
- return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
+ return net_vhost_user_init(peer, "vhost_user", name, chr, queues,
+ vhost_user_opts->backend_features);
}
diff --git a/qapi-schema.json b/qapi-schema.json
index 106008c..88760e5 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2262,6 +2262,9 @@
#
# @queues: #optional number of queues to be created for multiqueue capable tap
#
+# @backend-features: #optional feature flag to support vhost user backend
+# (since 2.4)
+#
# Since 1.2
##
{ 'struct': 'NetdevTapOptions',
@@ -2278,7 +2281,8 @@
'*vhostfd': 'str',
'*vhostfds': 'str',
'*vhostforce': 'bool',
- '*queues': 'uint32'} }
+ '*queues': 'uint32',
+ '*backend-features':'uint64'} }
##
# @NetdevSocketOptions
@@ -2466,13 +2470,17 @@
# @queues: #optional number of queues to be created for multiqueue vhost-user
# (default: 1) (Since 2.4)
#
+# @backend-features: #optional feature flag to support vhost user backend
+# (default: 0) (since 2.4)
+#
# Since 2.1
##
{ 'struct': 'NetdevVhostUserOptions',
'data': {
'chardev': 'str',
'*vhostforce': 'bool',
- '*queues': 'uint32' } }
+ '*queues': 'uint32',
+ '*backend-features': 'uint64' } }
##
# @NetClientOptions
diff --git a/qemu-options.hx b/qemu-options.hx
index 7959dd0..69f13c2 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1473,7 +1473,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
#else
"-netdev
tap,id=str[,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile]\n"
"
[,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off]\n"
- "
[,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n]\n"
+ "
[,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n][,backend-features=n]\n"
" configure a host TAP network backend with ID 'str'\n"
" use network scripts 'file' (default="
DEFAULT_NETWORK_SCRIPT ")\n"
" to configure it and 'dfile' (default="
DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
@@ -1493,6 +1493,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
" 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"
"-netdev bridge,id=str[,br=bridge][,helper=helper]\n"
" configure a host TAP network backend with ID 'str' that
is\n"
" connected to a bridge (default=" DEFAULT_BRIDGE_INTERFACE
")\n"
--
2.1.4
- [Qemu-devel] [PATCH v2 0/5] Add feature to start QEMU without vhost-user backend, Tetsuya Mukawa, 2015/06/21
- [Qemu-devel] [PATCH v2 1/5] vhost-user: Add ability to know vhost-user backend disconnection, Tetsuya Mukawa, 2015/06/21
- [Qemu-devel] [PATCH v2 3/5] vhost-user: Shutdown vhost-user connection when wrong messages are passed, Tetsuya Mukawa, 2015/06/21
- [Qemu-devel] [PATCH v2 2/5] qemu-char: Add qemu_chr_disconnect to close a fd accepted by listen fd, Tetsuya Mukawa, 2015/06/21
- [Qemu-devel] [PATCH v2 4/5] vhost-user: Enable 'nowait' and 'reconnect' option, Tetsuya Mukawa, 2015/06/21
- [Qemu-devel] [PATCH v2 5/5] vhost-user: Add new option to specify vhost-user backend supports,
Tetsuya Mukawa <=
- Re: [Qemu-devel] [PATCH v2 0/5] Add feature to start QEMU without vhost-user backend, Michael S. Tsirkin, 2015/06/22