On Fri, Jan 31, 2014 at 06:34:41PM +0100, Antonios Motakis wrote: > 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 <a.mota...@virtualopensystems.com> > Signed-off-by: Nikolay Nikolaev <n.nikol...@virtualopensystems.com> > --- > 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, > }; > >
Please align other options at =. > @@ -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. > > +@item -netdev vhost-user,chardev=@var{id} > + > +Establish a vhost-user netdev, backedb by a chardev @var{id}. The chardev > should typo > +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: > +@example > +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 > +@end example > + > @item -net dump[,vlan=@var{n}][,file=@var{file}][,len=@var{len}] > 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 >