From patchwork Thu Feb 13 12:03:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonios Motakis X-Patchwork-Id: 319997 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 853642C00B0 for ; Thu, 13 Feb 2014 23:12:21 +1100 (EST) Received: from localhost ([::1]:45787 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WDv9O-0003IO-LN for incoming@patchwork.ozlabs.org; Thu, 13 Feb 2014 07:12:18 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39861) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WDv1q-00089j-U9 for qemu-devel@nongnu.org; Thu, 13 Feb 2014 07:04:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WDv1k-0001AL-TX for qemu-devel@nongnu.org; Thu, 13 Feb 2014 07:04:30 -0500 Received: from mail-we0-f169.google.com ([74.125.82.169]:42605) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WDv1k-0001A4-Kb for qemu-devel@nongnu.org; Thu, 13 Feb 2014 07:04:24 -0500 Received: by mail-we0-f169.google.com with SMTP id t61so7448128wes.28 for ; Thu, 13 Feb 2014 04:04:24 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=w5ZnbcxaC9nmKRrd14/8GDsW1fyWabqWeWMYAZ1cGt0=; b=RUxypPtdEr5xaOuXXiQ7Rgj5Day40XPa+45MQrDwYUo/WZ3WX2VaYQHd+so87+/J3a /JBE4F4F/Pi8E4/+wvGolsM4wnPQWqUtiFGQi0/JyLD3+Ojj//niaKSptkvd+HKuth8u Jj801w0qfWCBVbpth62gb1jQLbaHn6c8fNE/8icTA7673HcwPtykmT+wYMiF//wvAaHs 0/JdlOfEXcDdDdRRH8psNcwqM0pKu/MVY36EwP4VMsYwIeoAizBksM03/e7iWAsewlJf 2f9naPWn88owJyzIBxoNk1jeJbHU/llpRhzvp6B5d8q6Uy0nb5kariW6twaCHCqDpHqf 9R8g== X-Gm-Message-State: ALoCoQniszeFRyDCbTW8egoLa3R/8v+KYz2UAWRjB7e/s3dCJTVYnhN2RiA91ZXWRa2Qo8MzpPCh X-Received: by 10.194.236.9 with SMTP id uq9mr953796wjc.31.1392293063864; Thu, 13 Feb 2014 04:04:23 -0800 (PST) Received: from localhost.localdomain (home.tvelocity.eu. [82.67.68.96]) by mx.google.com with ESMTPSA id bj3sm4039419wjb.14.2014.02.13.04.04.21 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 13 Feb 2014 04:04:22 -0800 (PST) From: Antonios Motakis To: qemu-devel@nongnu.org, snabb-devel@googlegroups.com Date: Thu, 13 Feb 2014 13:03:24 +0100 Message-Id: <1392293009-13812-14-git-send-email-a.motakis@virtualopensystems.com> X-Mailer: git-send-email 1.8.3.2 In-Reply-To: <1392293009-13812-1-git-send-email-a.motakis@virtualopensystems.com> References: <1392293009-13812-1-git-send-email-a.motakis@virtualopensystems.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 74.125.82.169 Cc: Stefan Hajnoczi , mst@redhat.com, n.nikolaev@virtualopensystems.com, Anthony Liguori , lukego@gmail.com, Antonios Motakis , tech@virtualopensystems.com Subject: [Qemu-devel] [PATCH v8 13/17] Add new vhost-user netdev backend X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 Signed-off-by: Nikolay Nikolaev --- 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); +}