[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v9 16/20] Add new vhost-user netdev backend
From: |
Antonios Motakis |
Subject: |
[Qemu-devel] [PATCH v9 16/20] Add new vhost-user netdev backend |
Date: |
Tue, 4 Mar 2014 19:22:59 +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 go down.
On reconnection 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
- Re: [Qemu-devel] [PATCH v9 10/20] Gracefully handle ioctl failure in vhost_virtqueue_stop, (continued)
- [Qemu-devel] [PATCH v9 05/20] Add chardev API qemu_chr_fe_get_msgfds, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 03/20] Add chardev API qemu_chr_fe_read_all, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 17/20] Add the vhost-user netdev backend to the command line, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 19/20] libqemustub: add stubs to be able to use qemu-char.c, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 20/20] Add qtest for vhost-user, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 02/20] Add kvm_eventfds_enabled function, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 09/20] Add new virtio API virtio_queue_get_avail_idx, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 16/20] Add new vhost-user netdev backend,
Antonios Motakis <=
- [Qemu-devel] [PATCH v9 15/20] Add vhost-user as a vhost backend., Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 11/20] vhost_net_init will use VhostNetOptions to get all its arguments, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 13/20] Add mandatory_features to vhost_dev, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 18/20] Add vhost-user protocol documentation, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 04/20] Add chardev API qemu_chr_fe_set_msgfds, Antonios Motakis, 2014/03/04
- [Qemu-devel] [PATCH v9 14/20] Add vhost-backend and VhostBackendType, Antonios Motakis, 2014/03/04