From nobody Mon Feb 9 11:31:55 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1553262709384959.0136990629978; Fri, 22 Mar 2019 06:51:49 -0700 (PDT) Received: from localhost ([127.0.0.1]:57729 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h7KaI-0001cE-27 for importer@patchew.org; Fri, 22 Mar 2019 09:51:46 -0400 Received: from eggs.gnu.org ([209.51.188.92]:33019) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h7KTn-0004Vm-MV for qemu-devel@nongnu.org; Fri, 22 Mar 2019 09:45:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h7KTm-0003Vg-6J for qemu-devel@nongnu.org; Fri, 22 Mar 2019 09:45:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54426) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1h7KTl-0003Rz-Mh for qemu-devel@nongnu.org; Fri, 22 Mar 2019 09:45:02 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CAC5018DF6C; Fri, 22 Mar 2019 13:45:00 +0000 (UTC) Received: from localhost (ovpn-117-44.ams2.redhat.com [10.36.117.44]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 534B0600C4; Fri, 22 Mar 2019 13:45:00 +0000 (UTC) From: Jens Freimann To: qemu-devel@nongnu.org Date: Fri, 22 Mar 2019 14:44:47 +0100 Message-Id: <20190322134447.14831-3-jfreimann@redhat.com> In-Reply-To: <20190322134447.14831-1-jfreimann@redhat.com> References: <20190322134447.14831-1-jfreimann@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Fri, 22 Mar 2019 13:45:00 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC PATCH 2/2] net/virtio: add failover support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pkrempa@redhat.com, ehabkost@redhat.com, mst@redhat.com, mdroth@linux.vnet.ibm.com, liran.alon@oracle.com, laine@redhat.com, ogerlitz@mellanox.com, ailan@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" From: Sameeh Jubran --- hw/net/virtio-net.c | 95 ++++++++++++++++++++++++++++++++++ include/hw/virtio/virtio-net.h | 7 +++ 2 files changed, 102 insertions(+) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 7e2c2a6f6a..880420a673 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -12,6 +12,7 @@ */ =20 #include "qemu/osdep.h" +#include "qemu/atomic.h" #include "qemu/iov.h" #include "hw/virtio/virtio.h" #include "net/net.h" @@ -19,6 +20,7 @@ #include "net/tap.h" #include "qemu/error-report.h" #include "qemu/timer.h" +#include "qemu/option.h" #include "hw/virtio/virtio-net.h" #include "net/vhost_net.h" #include "net/announce.h" @@ -29,6 +31,8 @@ #include "migration/misc.h" #include "standard-headers/linux/ethtool.h" #include "trace.h" +#include "monitor/qdev.h" +#include "hw/pci/pci.h" =20 #define VIRTIO_NET_VM_VERSION 11 =20 @@ -364,6 +368,9 @@ static void virtio_net_set_status(struct VirtIODevice *= vdev, uint8_t status) } } =20 + +static void virtio_net_primary_plug_timer(void *opaque); + static void virtio_net_set_link_status(NetClientState *nc) { VirtIONet *n =3D qemu_get_nic_opaque(nc); @@ -786,6 +793,14 @@ static void virtio_net_set_features(VirtIODevice *vdev= , uint64_t features) } else { memset(n->vlans, 0xff, MAX_VLAN >> 3); } + + if (virtio_has_feature(features, VIRTIO_NET_F_STANDBY)) { + atomic_set(&n->primary_should_be_hidden, false); + if (n->primary_device_timer) + timer_mod(n->primary_device_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + 4000); + } } =20 static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, @@ -2626,6 +2641,74 @@ void virtio_net_set_netclient_name(VirtIONet *n, con= st char *name, n->netclient_type =3D g_strdup(type); } =20 +static void virtio_net_primary_plug_timer(void *opaque) +{ + VirtIONet *n =3D opaque; + Error *err =3D NULL; + + n->primary_dev =3D qdev_device_add(n->primary_device_opts, &err); + if (!n->primary_dev && err) + { + if (n->primary_device_timer) + timer_mod(n->primary_device_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + + 100); + } +} + +static void virtio_net_handle_migration_primary(VirtIONet *n, MigrationSta= te * s) +{ + Error *err =3D NULL; + bool should_be_hidden =3D atomic_read(&n->primary_should_be_hidden); + + if (migration_in_setup(s) && !should_be_hidden && n->primary_dev) { + /* Request unplug + * + * + */ + qdev_unplug(n->primary_dev, &err); + if (!err) + { + atomic_set(&n->primary_should_be_hidden, true); + n->primary_dev =3D NULL; + } + } else if (migration_has_failed(s)) { + if (should_be_hidden && !n->primary_dev) + { + /* We already unplugged the device let's plugged it back */ + n->primary_dev =3D qdev_device_add(n->primary_device_opts, &er= r); + } + else + { + } + } +} + +static void migration_state_notifier(Notifier *notifier, void *data) +{ + MigrationState *s =3D data; + VirtIONet *n =3D container_of(notifier, VirtIONet, migration_state); + virtio_net_handle_migration_primary(n,s); +} + +static void virtio_net_primary_should_be_hidden(DeviceListener *listener, = QemuOpts *device_opts, + bool *match_found, bool *res) +{ + VirtIONet *n =3D container_of(listener, VirtIONet, primary_listener); + const char * dev_id =3D qemu_opts_id(device_opts); + + *match_found =3D !strcmp(n->net_conf.primary_id_str ,dev_id); + if (atomic_read(&n->primary_should_be_hidden) && !strcmp(qemu_opt_get(= device_opts, "driver"), "vfio-pci") + && *match_found) + { + n->primary_device_opts =3D device_opts; + *res =3D true; + return; + } + + *res =3D false; +} + static void virtio_net_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); @@ -2656,6 +2739,17 @@ static void virtio_net_device_realize(DeviceState *d= ev, Error **errp) n->host_features |=3D (1ULL << VIRTIO_NET_F_SPEED_DUPLEX); } =20 + if (n->net_conf.primary_id_str) { + n->primary_listener.should_be_hidden =3D virtio_net_primary_should= _be_hidden; + atomic_set(&n->primary_should_be_hidden, true); + device_listener_register(&n->primary_listener); + n->migration_state.notify =3D migration_state_notifier; + add_migration_state_change_notifier(&n->migration_state); + n->host_features |=3D (1ULL << VIRTIO_NET_F_STANDBY); + n->primary_device_timer =3D timer_new_ms(QEMU_CLOCK_VIRTUAL, + virtio_net_primary_plug_timer, n); + } + virtio_net_set_config_size(n, n->host_features); virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size); =20 @@ -2885,6 +2979,7 @@ static Property virtio_net_properties[] =3D { true), DEFINE_PROP_INT32("speed", VirtIONet, net_conf.speed, SPEED_UNKNOWN), DEFINE_PROP_STRING("duplex", VirtIONet, net_conf.duplex_str), + DEFINE_PROP_STRING("primary", VirtIONet, net_conf.primary_id_str), DEFINE_PROP_END_OF_LIST(), }; =20 diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index b96f0c643f..ec5f387aa9 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -43,6 +43,7 @@ typedef struct virtio_net_conf int32_t speed; char *duplex_str; uint8_t duplex; + char *primary_id_str; } virtio_net_conf; =20 /* Coalesced packets type & status */ @@ -185,6 +186,12 @@ struct VirtIONet { AnnounceTimer announce_timer; bool needs_vnet_hdr_swap; bool mtu_bypass_backend; + QemuOpts *primary_device_opts; + DeviceState *primary_dev; + bool primary_should_be_hidden; + DeviceListener primary_listener; + QEMUTimer *primary_device_timer; + Notifier migration_state; }; =20 void virtio_net_set_netclient_name(VirtIONet *n, const char *name, --=20 2.20.1