From patchwork Tue Sep 29 16:34:47 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 524553 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 3295A140D57 for ; Thu, 1 Oct 2015 06:34:02 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=x/nGsC4j; dkim-atps=neutral Received: from localhost ([::1]:32836 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZhO4e-0002y3-26 for incoming@patchwork.ozlabs.org; Wed, 30 Sep 2015 16:34:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51431) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zgxsc-0002Fp-6V for qemu-devel@nongnu.org; Tue, 29 Sep 2015 12:35:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zgxsa-0004My-L3 for qemu-devel@nongnu.org; Tue, 29 Sep 2015 12:35:50 -0400 Received: from mail-qg0-x22d.google.com ([2607:f8b0:400d:c04::22d]:35897) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zgxsa-0004Mt-Gn for qemu-devel@nongnu.org; Tue, 29 Sep 2015 12:35:48 -0400 Received: by qgx61 with SMTP id 61so11011698qgx.3 for ; Tue, 29 Sep 2015 09:35:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=j3TUhtq6RdwDORzVYK4iV3MpaBp4HZpSKrOa8TpovKQ=; b=x/nGsC4jrgAsqxJzUmD3UjEsv38HFTTCvgoCFCBfgwlgP9wEXoVQTVsoHBX68s1S/L 8aDhTd8Gp8rpUZpIqWaa1Q5Se8+QzJ7t7Rn16wHnewFhgg6tOPEFwq6ZcH1hC7z5By2K 8HNG2tAU2eVIKZ80i2C+ftCpXE7JsbOdBjKmXcPHumlL8fPSHL2Q9g9sSircfeuAlBp4 3/S20gbPn9iTMhXM2+mcwszwuVlQgxcLtAwHzHgKdqzsoblh82OeDnbU0q1f2FIFkiQq 5XeHbx1iOAl8ArlGrgkF+s6hymvldKDP2eD9GYLarN656PRD028sPruf81PSYhGRv+M3 fdKQ== X-Received: by 10.140.235.16 with SMTP id g16mr32055408qhc.33.1443544548329; Tue, 29 Sep 2015 09:35:48 -0700 (PDT) Received: from localhost (bne75-h02-31-39-163-232.dsl.sta.abo.bbox.fr. [31.39.163.232]) by smtp.gmail.com with ESMTPSA id f71sm4120116qkf.38.2015.09.29.09.35.47 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 29 Sep 2015 09:35:47 -0700 (PDT) From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Date: Tue, 29 Sep 2015 18:34:47 +0200 Message-Id: <1443544494-28737-18-git-send-email-marcandre.lureau@redhat.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1443544494-28737-1-git-send-email-marcandre.lureau@redhat.com> References: <1443544494-28737-1-git-send-email-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400d:c04::22d Cc: haifeng.lin@huawei.com, mst@redhat.com, thibaut.collet@6wind.com, jasowang@redhat.com, pbonzini@redhat.com, =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Subject: [Qemu-devel] [PATCH v6 17/24] vhost user: add rarp sending after live migration for legacy guest 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 From: Thibaut Collet A new vhost user message is added to allow QEMU to ask to vhost user backend to broadcast a fake RARP after live migration for guest without GUEST_ANNOUNCE capability. This new message is sent only if the backend supports the new VHOST_USER_PROTOCOL_F_RARP protocol feature. The payload of this new message is the MAC address of the guest (not known by the backend). The MAC address is copied in the first 6 bytes of a u64 to avoid to create a new payload message type. This new message has no equivalent ioctl so a new callback is added in the userOps structure to send the request. Upon reception of this new message the vhost user backend must generate and broadcast a fake RARP request to notify the migration is terminated. Signed-off-by: Thibaut Collet [Rebased and fixed checkpatch errors - Marc-André] Signed-off-by: Marc-André Lureau --- docs/specs/vhost-user.txt | 15 +++++++++++++++ hw/net/vhost_net.c | 17 +++++++++++++++++ hw/virtio/vhost-user.c | 32 +++++++++++++++++++++++++++++++- include/hw/virtio/vhost-backend.h | 3 +++ include/net/vhost_net.h | 1 + net/vhost-user.c | 24 ++++++++++++++++++++++-- 6 files changed, 89 insertions(+), 3 deletions(-) diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt index e0292a0..e0d71e2 100644 --- a/docs/specs/vhost-user.txt +++ b/docs/specs/vhost-user.txt @@ -194,6 +194,7 @@ Protocol features #define VHOST_USER_PROTOCOL_F_MQ 0 #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1 +#define VHOST_USER_PROTOCOL_F_RARP 2 Message types ------------- @@ -381,3 +382,17 @@ Message types Master payload: vring state description Signal slave to enable or disable corresponding vring. + + * VHOST_USER_SEND_RARP + + Id: 19 + Equivalent ioctl: N/A + Master payload: u64 + + Ask vhost user backend to broadcast a fake RARP to notify the migration + is terminated for guest that does not support GUEST_ANNOUNCE. + Only legal if feature bit VHOST_USER_F_PROTOCOL_FEATURES is present in + VHOST_USER_GET_FEATURES and protocol feature bit VHOST_USER_PROTOCOL_F_RARP + is present in VHOST_USER_GET_PROTOCOL_FEATURES. + The first 6 bytes of the payload contain the mac address of the guest to + allow the vhost user backend to construct and broadcast the fake RARP. diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 840f443..da66b64 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -388,6 +388,18 @@ void vhost_net_cleanup(struct vhost_net *net) g_free(net); } +int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr) +{ + const VhostOps *vhost_ops = net->dev.vhost_ops; + int r = -1; + + if (vhost_ops->vhost_migration_done) { + r = vhost_ops->vhost_migration_done(&net->dev, mac_addr); + } + + return r; +} + bool vhost_net_virtqueue_pending(VHostNetState *net, int idx) { return vhost_virtqueue_pending(&net->dev, idx); @@ -479,6 +491,11 @@ void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, { } +int vhost_net_notify_migration_done(struct vhost_net *net) +{ + return -1; +} + VHostNetState *get_vhost_net(NetClientState *nc) { return 0; diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 455caba..1716e4f 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -10,6 +10,7 @@ #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-backend.h" +#include "hw/virtio/virtio-net.h" #include "sysemu/char.h" #include "sysemu/kvm.h" #include "qemu/error-report.h" @@ -27,9 +28,10 @@ #define VHOST_MEMORY_MAX_NREGIONS 8 #define VHOST_USER_F_PROTOCOL_FEATURES 30 -#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x3ULL +#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x7ULL #define VHOST_USER_PROTOCOL_F_MQ 0 #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1 +#define VHOST_USER_PROTOCOL_F_RARP 2 typedef enum VhostUserRequest { VHOST_USER_NONE = 0, @@ -51,6 +53,7 @@ typedef enum VhostUserRequest { VHOST_USER_SET_PROTOCOL_FEATURES = 16, VHOST_USER_GET_QUEUE_NUM = 17, VHOST_USER_SET_VRING_ENABLE = 18, + VHOST_USER_SEND_RARP = 19, VHOST_USER_MAX } VhostUserRequest; @@ -561,6 +564,32 @@ static bool vhost_user_requires_shm_log(struct vhost_dev *dev) VHOST_USER_PROTOCOL_F_LOG_SHMFD); } +static int vhost_user_migration_done(struct vhost_dev *dev, char* mac_addr) +{ + VhostUserMsg msg = { 0 }; + int err; + + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); + + /* If guest supports GUEST_ANNOUNCE do nothing */ + if (virtio_has_feature(dev->acked_features, VIRTIO_NET_F_GUEST_ANNOUNCE)) { + return 0; + } + + /* if backend supports VHOST_USER_PROTOCOL_F_RARP ask it to send the RARP */ + if (virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_RARP)) { + msg.request = VHOST_USER_SEND_RARP; + msg.flags = VHOST_USER_VERSION; + memcpy((char *)&msg.u64, mac_addr, 6); + msg.size = sizeof(m.u64); + + err = vhost_user_write(dev, &msg, NULL, 0); + return err; + } + return -1; +} + const VhostOps user_ops = { .backend_type = VHOST_BACKEND_TYPE_USER, .vhost_backend_init = vhost_user_init, @@ -582,4 +611,5 @@ const VhostOps user_ops = { .vhost_get_vq_index = vhost_user_get_vq_index, .vhost_set_vring_enable = vhost_user_set_vring_enable, .vhost_requires_shm_log = vhost_user_requires_shm_log, + .vhost_migration_done = vhost_user_migration_done, }; diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h index e07118c..5918c01 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -67,6 +67,8 @@ typedef int (*vhost_get_vq_index_op)(struct vhost_dev *dev, int idx); typedef int (*vhost_set_vring_enable_op)(struct vhost_dev *dev, int enable); typedef bool (*vhost_requires_shm_log_op)(struct vhost_dev *dev); +typedef int (*vhost_migration_done_op)(struct vhost_dev *dev, + char *mac_addr); typedef struct VhostOps { VhostBackendType backend_type; @@ -94,6 +96,7 @@ typedef struct VhostOps { vhost_get_vq_index_op vhost_get_vq_index; vhost_set_vring_enable_op vhost_set_vring_enable; vhost_requires_shm_log_op vhost_requires_shm_log; + vhost_migration_done_op vhost_migration_done; } VhostOps; extern const VhostOps user_ops; diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index 0188c4d..3389b41 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -27,6 +27,7 @@ void vhost_net_ack_features(VHostNetState *net, uint64_t features); bool vhost_net_virtqueue_pending(VHostNetState *net, int n); void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, int idx, bool mask); +int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr); VHostNetState *get_vhost_net(NetClientState *nc); int vhost_set_vring_enable(NetClientState * nc, int enable); diff --git a/net/vhost-user.c b/net/vhost-user.c index 87917a5..cfe11b8 100644 --- a/net/vhost-user.c +++ b/net/vhost-user.c @@ -106,9 +106,29 @@ err: static ssize_t vhost_user_receive(NetClientState *nc, const uint8_t *buf, size_t size) { - /* Discard the request that is received and managed by backend - * by an other way. + /* In case of RARP (message size is 60) notify backup to send a fake RARP. + This fake RARP will be sent by backend only for guest + without GUEST_ANNOUNCE capability. */ + if (size == 60) { + VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc); + int r; + static int display_rarp_failure = 1; + char mac_addr[6]; + + /* extract guest mac address from the RARP message */ + memcpy(mac_addr, &buf[6], 6); + + r = vhost_net_notify_migration_done(s->vhost_net, mac_addr); + + if ((r != 0) && (display_rarp_failure)) { + fprintf(stderr, + "Vhost user backend fails to broadcast fake RARP\n"); + fflush(stderr); + display_rarp_failure = 0; + } + } + return size; }