[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v7 12/13] Add the vhost-user netdev backend to comma
From: |
Antonios Motakis |
Subject: |
[Qemu-devel] [PATCH v7 12/13] Add the vhost-user netdev backend to command line |
Date: |
Fri, 31 Jan 2014 18:34:41 +0100 |
The supplied chardev id will be inspected for supported options. Only
a socket backend, with a set path (i.e. a unix socket) and optionally
the server parameter set, will be allowed. Other options (nowait, telnet)
will make the chardev unusable and the netdev will not be initialised.
Signed-off-by: Antonios Motakis <address@hidden>
Signed-off-by: Nikolay Nikolaev <address@hidden>
---
hmp-commands.hx | 4 +--
hw/net/vhost_net.c | 4 +++
hw/net/virtio-net.c | 3 ++
net/hub.c | 1 +
net/net.c | 2 ++
net/vhost-user.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++--
qapi-schema.json | 18 ++++++++++-
qemu-options.hx | 16 ++++++++++
8 files changed, 134 insertions(+), 5 deletions(-)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index f3fc514..68128c1 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1195,7 +1195,7 @@ ETEXI
{
.name = "host_net_add",
.args_type = "device:s,opts:s?",
- .params = "tap|user|socket|vde|netmap|dump [options]",
+ .params = "tap|user|socket|vde|netmap|vhost-user|dump [options]",
.help = "add host VLAN client",
.mhandler.cmd = net_host_device_add,
},
@@ -1223,7 +1223,7 @@ ETEXI
{
.name = "netdev_add",
.args_type = "netdev:O",
- .params =
"[user|tap|socket|hubport|netmap],id=str[,prop=value][,...]",
+ .params =
"[user|tap|socket|hubport|netmap|vhost-user],id=str[,prop=value][,...]",
.help = "add host network device",
.mhandler.cmd = hmp_netdev_add,
},
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 6b6268b..e630407 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -15,6 +15,7 @@
#include "net/net.h"
#include "net/tap.h"
+#include "net/vhost-user.h"
#include "hw/virtio/virtio-net.h"
#include "net/vhost_net.h"
@@ -322,6 +323,9 @@ VHostNetState *get_vhost_net(NetClientState *nc)
case NET_CLIENT_OPTIONS_KIND_TAP:
vhost_net = tap_get_vhost_net(nc);
break;
+ case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
+ vhost_net = vhost_user_get_vhost_net(nc);
+ break;
default:
break;
}
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 72acd15..d49ee82 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -322,6 +322,9 @@ static void peer_test_vnet_hdr(VirtIONet *n)
case NET_CLIENT_OPTIONS_KIND_TAP:
n->has_vnet_hdr = tap_has_vnet_hdr(nc->peer);
break;
+ case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
+ n->has_vnet_hdr = 0;
+ break;
default:
break;
}
diff --git a/net/hub.c b/net/hub.c
index 33a99c9..7e0f2d6 100644
--- a/net/hub.c
+++ b/net/hub.c
@@ -322,6 +322,7 @@ void net_hub_check_clients(void)
case NET_CLIENT_OPTIONS_KIND_TAP:
case NET_CLIENT_OPTIONS_KIND_SOCKET:
case NET_CLIENT_OPTIONS_KIND_VDE:
+ case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
has_host_dev = 1;
break;
default:
diff --git a/net/net.c b/net/net.c
index 2c3af20..30f1273 100644
--- a/net/net.c
+++ b/net/net.c
@@ -731,6 +731,7 @@ static int (* const
net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
[NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge,
#endif
[NET_CLIENT_OPTIONS_KIND_HUBPORT] = net_init_hubport,
+ [NET_CLIENT_OPTIONS_KIND_VHOST_USER] = net_init_vhost_user,
};
@@ -764,6 +765,7 @@ static int net_client_init1(const void *object, int
is_netdev, Error **errp)
case NET_CLIENT_OPTIONS_KIND_BRIDGE:
#endif
case NET_CLIENT_OPTIONS_KIND_HUBPORT:
+ case NET_CLIENT_OPTIONS_KIND_VHOST_USER:
break;
default:
diff --git a/net/vhost-user.c b/net/vhost-user.c
index b25722c..f5bd211 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -12,6 +12,7 @@
#include "net/vhost_net.h"
#include "net/vhost-user.h"
#include "sysemu/char.h"
+#include "qemu/config-file.h"
#include "qemu/error-report.h"
typedef struct VhostUserState {
@@ -20,9 +21,17 @@ typedef struct VhostUserState {
VHostNetState *vhost_net;
} VhostUserState;
+typedef struct VhostUserChardevProps {
+ bool is_socket;
+ bool is_unix;
+ bool is_server;
+ bool has_unsupported;
+} VhostUserChardevProps;
+
VHostNetState *vhost_user_get_vhost_net(NetClientState *nc)
{
VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc);
+ assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
return s->vhost_net;
}
@@ -67,7 +76,7 @@ static void vhost_user_cleanup(NetClientState *nc)
}
static NetClientInfo net_vhost_user_info = {
- .type = 0,
+ .type = NET_CLIENT_OPTIONS_KIND_VHOST_USER,
.size = sizeof(VhostUserState),
.cleanup = vhost_user_cleanup,
};
@@ -123,8 +132,86 @@ static int net_vhost_user_init(NetClientState *peer, const
char *device,
return 0;
}
+static int net_vhost_chardev_opts(const char *name, const char *value,
+ void *opaque)
+{
+ VhostUserChardevProps *props = opaque;
+
+ if (strcmp(name, "backend") == 0 && strcmp(value, "socket") == 0) {
+ props->is_socket = 1;
+ } else if (strcmp(name, "path") == 0) {
+ props->is_unix = 1;
+ } else if (strcmp(name, "server") == 0) {
+ props->is_server = 1;
+ } else {
+ error_report("vhost-user does not support a chardev"
+ " with the following option:\n %s = %s",
+ name, value);
+ props->has_unsupported = 1;
+ return -1;
+ }
+ return 0;
+}
+
+static CharDriverState *net_vhost_parse_chardev(
+ const NetdevVhostUserOptions *opts)
+{
+ CharDriverState *chr = qemu_chr_find(opts->chardev);
+ VhostUserChardevProps props;
+
+ if (chr == NULL) {
+ error_report("chardev \"%s\" not found\n", opts->chardev);
+ return 0;
+ }
+
+ /* inspect chardev opts */
+ memset(&props, 0, sizeof(props));
+ qemu_opt_foreach(chr->opts, net_vhost_chardev_opts, &props, false);
+
+ if (!props.is_socket || !props.is_unix) {
+ error_report("chardev \"%s\" is not a unix socket\n",
+ opts->chardev);
+ return 0;
+ }
+
+ if (props.has_unsupported) {
+ error_report("chardev \"%s\" has an unsupported option\n",
+ opts->chardev);
+ return 0;
+ }
+
+ qemu_chr_fe_claim_no_fail(chr);
+
+ return chr;
+}
+
int net_init_vhost_user(const NetClientOptions *opts, const char *name,
NetClientState *peer)
{
- return net_vhost_user_init(peer, "vhost_user", 0, 0);
+ const NetdevVhostUserOptions *vhost_user_opts;
+ CharDriverState *chr;
+ QemuOpts *mem_opts;
+ unsigned int mem_share = 0;
+
+ assert(opts->kind == NET_CLIENT_OPTIONS_KIND_VHOST_USER);
+ vhost_user_opts = opts->vhost_user;
+
+ chr = net_vhost_parse_chardev(vhost_user_opts);
+ if (!chr) {
+ error_report("No suitable chardev found\n");
+ return -1;
+ }
+
+ /* verify mem-path is set and shared */
+ mem_opts = qemu_opts_find(qemu_find_opts("mem-path"), NULL);
+ if (mem_opts) {
+ mem_share = qemu_opt_get_bool(mem_opts, "share", 0);
+ }
+
+ if (!mem_share) {
+ error_report("vhost-user requires -mem-path /path,share=on");
+ return -1;
+ }
+
+ return net_vhost_user_init(peer, "vhost_user", name, chr);
}
diff --git a/qapi-schema.json b/qapi-schema.json
index 05ced9d..51609a4 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3104,6 +3104,21 @@
'*devname': 'str' } }
##
+# @NetdevVhostUserOptions
+#
+# Vhost-user network backend
+#
+# @path: control socket path
+#
+# Since 2.0
+##
+{ 'type': 'NetdevVhostUserOptions',
+ 'data': {
+ 'chardev': 'str' } }
+
+##
+
+##
# @NetClientOptions
#
# A discriminated record of network device traits.
@@ -3121,7 +3136,8 @@
'dump': 'NetdevDumpOptions',
'bridge': 'NetdevBridgeOptions',
'hubport': 'NetdevHubPortOptions',
- 'netmap': 'NetdevNetmapOptions' } }
+ 'netmap': 'NetdevNetmapOptions',
+ 'vhost-user': 'NetdevVhostUserOptions' } }
##
# @NetLegacy
diff --git a/qemu-options.hx b/qemu-options.hx
index 60ecc95..2c59164 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1435,6 +1435,7 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
#ifdef CONFIG_NETMAP
"netmap|"
#endif
+ "vhost-user|"
"socket|"
"hubport],id=str[,option][,option][,...]\n", QEMU_ARCH_ALL)
STEXI
@@ -1766,6 +1767,21 @@ The hubport netdev lets you connect a NIC to a QEMU
"vlan" instead of a single
netdev. @code{-net} and @code{-device} with parameter @option{vlan} create the
required hub automatically.
address@hidden -netdev vhost-user,address@hidden
+
+Establish a vhost-user netdev, backedb by a chardev @var{id}. The chardev
should
+be a unix domain socket backed one. The vhost-user uses a specifically defined
+protocol to pass vhost ioctl replacement messages to an application on the
other
+end of the socket.
+
+Example:
address@hidden
+qemu -m 1024 -mem-path /hugetlbfs,prealloc=on,share=on \
+ -chardev socket,path=/path/to/socket \
+ -netdev type=vhost-user,id=net0,chardev=chr0 \
+ -device virtio-net-pci,netdev=net0
address@hidden example
+
@item -net dump[,address@hidden,address@hidden,address@hidden
Dump network traffic on VLAN @var{n} to file @var{file}
(@file{qemu-vlan0.pcap} by default).
At most @var{len} bytes (64k by default) per packet are stored. The file
format is
--
1.8.3.2
- [Qemu-devel] [PATCH v7 02/13] Add chardev API qemu_chr_fe_read_all, (continued)
- [Qemu-devel] [PATCH v7 02/13] Add chardev API qemu_chr_fe_read_all, Antonios Motakis, 2014/01/31
- [Qemu-devel] [PATCH v7 03/13] Add chardev API qemu_chr_fe_set_msgfds, Antonios Motakis, 2014/01/31
- [Qemu-devel] [PATCH v7 04/13] Add G_IO_HUP handler for socket chardev, Antonios Motakis, 2014/01/31
- [Qemu-devel] [PATCH v7 05/13] vhost_net should call the poll callback only when it is set, Antonios Motakis, 2014/01/31
- [Qemu-devel] [PATCH v7 07/13] vhost_net_init will use VhostNetOptions to get all its arguments, Antonios Motakis, 2014/01/31
- [Qemu-devel] [PATCH v7 06/13] Refactor virtio-net to use a generic get_vhost_net, Antonios Motakis, 2014/01/31
- [Qemu-devel] [PATCH v7 08/13] Add vhost_ops to the vhost_dev struct and replace all relevant ioctls, Antonios Motakis, 2014/01/31
- [Qemu-devel] [PATCH v7 09/13] Add vhost-backend and VhostBackendType, Antonios Motakis, 2014/01/31
- [Qemu-devel] [PATCH v7 10/13] Add vhost-user as a vhost backend., Antonios Motakis, 2014/01/31
- [Qemu-devel] [PATCH v7 11/13] Add new vhost-user netdev backend, Antonios Motakis, 2014/01/31
- [Qemu-devel] [PATCH v7 12/13] Add the vhost-user netdev backend to command line,
Antonios Motakis <=
- [Qemu-devel] [PATCH v7 13/13] Add vhost-user protocol documentation, Antonios Motakis, 2014/01/31