On Fri, Jan 31, 2014 at 06:34:40PM +0100, Antonios Motakis wrote: > Add a new QEMU netdev backend that is intended to invoke vhost_net with the > vhost-user backend. > > At runtime the netdev will detect if the vhost backend is up or down. Upon > disconnection it will set link_down accordingly and notify virtio-net. The > virtio-net interface goes down. > > Signed-off-by: Antonios Motakis <a.mota...@virtualopensystems.com> > Signed-off-by: Nikolay Nikolaev <n.nikol...@virtualopensystems.com>
What happens if users try to configure e.g. e1000 with this netdev backend? I would expect some code in the backend checking that frontend is virtio, but I don't see such. > --- > include/net/vhost-user.h | 17 +++++++ > net/Makefile.objs | 2 +- > net/clients.h | 3 ++ > net/vhost-user.c | 130 > +++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 151 insertions(+), 1 deletion(-) > create mode 100644 include/net/vhost-user.h > create mode 100644 net/vhost-user.c > > diff --git a/include/net/vhost-user.h b/include/net/vhost-user.h > new file mode 100644 > index 0000000..85109f6 > --- /dev/null > +++ b/include/net/vhost-user.h > @@ -0,0 +1,17 @@ > +/* > + * vhost-user.h > + * > + * Copyright (c) 2013 Virtual Open Systems Sarl. > + * > + * 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_USER_H_ > +#define VHOST_USER_H_ > + > +struct vhost_net; > +struct vhost_net *vhost_user_get_vhost_net(NetClientState *nc); > + > +#endif /* VHOST_USER_H_ */ > diff --git a/net/Makefile.objs b/net/Makefile.objs > index c25fe69..301f6b6 100644 > --- a/net/Makefile.objs > +++ b/net/Makefile.objs > @@ -2,7 +2,7 @@ common-obj-y = net.o queue.o checksum.o util.o hub.o > common-obj-y += socket.o > common-obj-y += dump.o > common-obj-y += eth.o > -common-obj-$(CONFIG_POSIX) += tap.o > +common-obj-$(CONFIG_POSIX) += tap.o vhost-user.o > common-obj-$(CONFIG_LINUX) += tap-linux.o > common-obj-$(CONFIG_WIN32) += tap-win32.o > common-obj-$(CONFIG_BSD) += tap-bsd.o > diff --git a/net/clients.h b/net/clients.h > index 7322ff5..7f3d4ae 100644 > --- a/net/clients.h > +++ b/net/clients.h > @@ -57,4 +57,7 @@ int net_init_netmap(const NetClientOptions *opts, const > char *name, > NetClientState *peer); > #endif > > +int net_init_vhost_user(const NetClientOptions *opts, const char *name, > + NetClientState *peer); > + > #endif /* QEMU_NET_CLIENTS_H */ > diff --git a/net/vhost-user.c b/net/vhost-user.c > new file mode 100644 > index 0000000..b25722c > --- /dev/null > +++ b/net/vhost-user.c > @@ -0,0 +1,130 @@ > +/* > + * vhost-user.c > + * > + * Copyright (c) 2013 Virtual Open Systems Sarl. > + * > + * 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 "clients.h" > +#include "net/vhost_net.h" > +#include "net/vhost-user.h" > +#include "sysemu/char.h" > +#include "qemu/error-report.h" > + > +typedef struct VhostUserState { > + NetClientState nc; > + CharDriverState *chr; > + VHostNetState *vhost_net; > +} VhostUserState; > + > +VHostNetState *vhost_user_get_vhost_net(NetClientState *nc) > +{ > + VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc); > + return s->vhost_net; > +} > + > +static int vhost_user_running(VhostUserState *s) > +{ > + return (s->vhost_net) ? 1 : 0; > +} > + > +static int vhost_user_start(VhostUserState *s) > +{ > + VhostNetOptions options; > + > + if (vhost_user_running(s)) { > + return 0; > + } > + > + options.backend_type = VHOST_BACKEND_TYPE_USER; > + options.net_backend = &s->nc; > + options.opaque = s->chr; > + options.force = 1; > + > + s->vhost_net = vhost_net_init(&options); > + > + return vhost_user_running(s) ? 0 : -1; > +} > + > +static void vhost_user_stop(VhostUserState *s) > +{ > + if (vhost_user_running(s)) { > + vhost_net_cleanup(s->vhost_net); > + } > + > + s->vhost_net = 0; > +} > + > +static void vhost_user_cleanup(NetClientState *nc) > +{ > + VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc); > + > + vhost_user_stop(s); > + qemu_purge_queued_packets(nc); > +} > + > +static NetClientInfo net_vhost_user_info = { > + .type = 0, > + .size = sizeof(VhostUserState), > + .cleanup = vhost_user_cleanup, > +}; > + > +static void net_vhost_user_event(void *opaque, int event) > +{ > + VhostUserState *s = opaque; > + > + switch (event) { > + case CHR_EVENT_OPENED: > + vhost_user_start(s); > + break; > + case CHR_EVENT_CLOSED: > + s->nc.link_down = 1; > + > + if (s->nc.peer) { > + s->nc.peer->link_down = 1; > + } > + > + if (s->nc.info->link_status_changed) { > + s->nc.info->link_status_changed(&s->nc); > + } > + > + if (s->nc.peer && s->nc.peer->info->link_status_changed) { > + s->nc.peer->info->link_status_changed(s->nc.peer); > + } > + > + vhost_user_stop(s); > + error_report("chardev \"%s\" went down\n", s->chr->label); > + break; > + } > +} > + > +static int net_vhost_user_init(NetClientState *peer, const char *device, > + const char *name, CharDriverState *chr) > +{ > + NetClientState *nc; > + VhostUserState *s; > + > + nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name); > + > + snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s", > + chr->label); > + > + s = DO_UPCAST(VhostUserState, nc, nc); > + > + /* We don't provide a receive callback */ > + s->nc.receive_disabled = 1; > + s->chr = chr; > + > + qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s); > + > + return 0; > +} > + > +int net_init_vhost_user(const NetClientOptions *opts, const char *name, > + NetClientState *peer) > +{ > + return net_vhost_user_init(peer, "vhost_user", 0, 0); > +} > -- > 1.8.3.2 >