On Mon, Feb 10, 2014 at 9:42 AM, Michael S. Tsirkin <m...@redhat.com> wrote: > 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.
Good point, we are looking into it. Thanks. > >> --- >> 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 >> -- Antonios Motakis Virtual Open Systems