Message ID | 1391189683-1602-12-git-send-email-a.motakis@virtualopensystems.com |
---|---|
State | New |
Headers | show |
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.motakis@virtualopensystems.com> > Signed-off-by: Nikolay Nikolaev <n.nikolaev@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 >
On Mon, Feb 10, 2014 at 9:42 AM, Michael S. Tsirkin <mst@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.motakis@virtualopensystems.com> >> Signed-off-by: Nikolay Nikolaev <n.nikolaev@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 >>
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); +}