[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v8 13/17] Add new vhost-user netdev backend
From: |
Antonios Motakis |
Subject: |
[Qemu-devel] [PATCH v8 13/17] Add new vhost-user netdev backend |
Date: |
Thu, 13 Feb 2014 13:03:24 +0100 |
Add a new QEMU netdev backend that is intended to invoke vhost_net with the
vhost-user backend. It uses an Unix socket chardev to establish a
communication with the 'slave' (client and server mode supported).
At runtime the netdev will handle OPEN/CLOSE events from the chardev. Upon
disconnection it will set link_down accordingly and notify virtio-net. The
virtio-net interface will gos down.
On reconnection then a new vhost-net instance will get the saved features
from the previous session from the saved 'mandatory features'. This will
ensure that the newly connected slave is compatible with the first one.
Signed-off-by: Antonios Motakis <address@hidden>
Signed-off-by: Nikolay Nikolaev <address@hidden>
---
include/net/vhost-user.h | 17 ++++++
net/Makefile.objs | 2 +-
net/clients.h | 3 +
net/vhost-user.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 171 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..292be41
--- /dev/null
+++ b/net/vhost-user.c
@@ -0,0 +1,150 @@
+/*
+ * 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;
+ bool vhostforce;
+ VHostNetState *vhost_net;
+ unsigned long long features;
+} 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 = s->vhostforce;
+ if (s->features) {
+ options.mandatory_features = s->features;
+ } else {
+ options.mandatory_features = 0;
+ }
+
+ s->vhost_net = vhost_net_init(&options);
+
+ /* store the negotiated features in case of reconnection */
+ if (vhost_user_running(s) && !s->features) {
+ s->features = vhost_net_features(s->vhost_net);
+ }
+
+ 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_link_down(VhostUserState *s, bool link_down)
+{
+ s->nc.link_down = link_down;
+
+ if (s->nc.peer) {
+ s->nc.peer->link_down = link_down;
+ }
+
+ 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);
+ }
+}
+
+static void net_vhost_user_event(void *opaque, int event)
+{
+ VhostUserState *s = opaque;
+
+ switch (event) {
+ case CHR_EVENT_OPENED:
+ vhost_user_start(s);
+ net_vhost_link_down(s, false);
+ error_report("chardev \"%s\" went up\n", s->chr->label);
+ break;
+ case CHR_EVENT_CLOSED:
+ net_vhost_link_down(s, true);
+ 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,
+ bool vhostforce)
+{
+ 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;
+ s->vhostforce = vhostforce;
+
+ 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, 0);
+}
--
1.8.3.2
- [Qemu-devel] [PATCH v8 03/17] Add chardev API qemu_chr_fe_set_msgfds, (continued)
- [Qemu-devel] [PATCH v8 03/17] Add chardev API qemu_chr_fe_set_msgfds, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 04/17] Add chardev API qemu_chr_fe_get_msgfds, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 05/17] Add G_IO_HUP handler for socket chardev, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 06/17] vhost_net should call the poll callback only when it is set, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 07/17] Refactor virtio-net to use generic get_vhost_net, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 08/17] vhost_net_init will use VhostNetOptions to get all its arguments, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 09/17] Add vhost_ops to vhost_dev struct and replace all relevant ioctls, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 10/17] Add mandatory_features to vhost_dev, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 11/17] Add vhost-backend and VhostBackendType, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 12/17] Add vhost-user as a vhost backend, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 13/17] Add new vhost-user netdev backend,
Antonios Motakis <=
- [Qemu-devel] [PATCH v8 14/17] Add the vhost-user netdev backend to the command line, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 15/17] Add vhost-user protocol documentation, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 16/17] libqemustub: add stubs to be able to use qemu-char.c, Antonios Motakis, 2014/02/13
- [Qemu-devel] [PATCH v8 17/17] Add qtest for vhost-user, Antonios Motakis, 2014/02/13
- Re: [Qemu-devel] [PATCH v8 00/17] Vhost and vhost-net support for userspace based backends, Michael S. Tsirkin, 2014/02/26