From nobody Mon Feb 9 17:35:06 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) client-ip=207.211.31.120; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1579880742; cv=none; d=zohomail.com; s=zohoarc; b=Svou1N4Gadh6avsaguk+W1UUa7pQBUtLw5CXBTg9k993yiKdnUXrUZ0CfhRfpJLiMrAdZbqYCIaq75kmOEK9P6jCuANcL/rxiGN7Uozuo8p0o4Ia+DfShstAB/N3tp1BmMykDpuSjLxKJE/mQETlX6m+QpXKXq6Cc97mxPzfvVM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1579880742; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=ExvrS/EE4Yt5l1guyBiKTLsS/EJqGRfSDj5O+7qlha8=; b=Bn5lMfiWrEZqcTXXalFcy5zRYOI7lZPkw6ucuJu8e1++b3xy6TbJTXbupb47xka85aTACEAe23FTS5GyinGUGDrev61ELNqoi7t1BvSwOeFVkBZ5XVC5dxoukuvwfgwY3KvNEISRt+1csUpeUxBlTay3IzNPgdrxOeWZL98c/G0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [207.211.31.120]) by mx.zohomail.com with SMTPS id 1579880742676337.5726356613794; Fri, 24 Jan 2020 07:45:42 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-125-4yB0YgGfOR-RqigzLowu7w-1; Fri, 24 Jan 2020 10:45:19 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5CACD90DE3B; Fri, 24 Jan 2020 15:39:37 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 372E986808; Fri, 24 Jan 2020 15:39:37 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id EC54485966; Fri, 24 Jan 2020 15:39:36 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 00OFdUiC010320 for ; Fri, 24 Jan 2020 10:39:30 -0500 Received: by smtp.corp.redhat.com (Postfix) id 7F0AE5C1BB; Fri, 24 Jan 2020 15:39:30 +0000 (UTC) Received: from vhost2.router.laine.org (ovpn-116-187.phx2.redhat.com [10.3.116.187]) by smtp.corp.redhat.com (Postfix) with ESMTP id EF6985C1B0; Fri, 24 Jan 2020 15:39:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1579880741; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=ExvrS/EE4Yt5l1guyBiKTLsS/EJqGRfSDj5O+7qlha8=; b=UjIlUM/obLSa6za9MpaFBGVmK3bc0XBsK/kOmtypjITKU+6n2xpEdZ4o/hEK4L3slq8tOu MfjOMhouOWbfE/uyR5dQ/tdAd1lMW/mHZN24arPrMgfKsJXV13DqwrQ0wmnxawkRwMnV9V D8xYDkcXuEdTjjtLkAIry3UI8wQIABU= From: Laine Stump To: libvir-list@redhat.com Subject: [libvirt PATCH v2 3/6] qemu: support interface functionality Date: Fri, 24 Jan 2020 10:39:18 -0500 Message-Id: <20200124153922.3883568-4-laine@redhat.com> In-Reply-To: <20200124153922.3883568-1-laine@redhat.com> References: <20200124153922.3883568-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-loop: libvir-list@redhat.com Cc: Jens Freimann X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-MC-Unique: 4yB0YgGfOR-RqigzLowu7w-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" The QEMU driver uses the element to setup a "failover" pair of devices - the persistent device must be a virtio emulated NIC, with the only extra configuration being the addition of ",failover=3Don" to the device commandline, and the transient device must be a hostdev NIC ( or with a network that is a pool of SRIOV VFs) where the extra configuration is the addition of ",failover_pair_id=3D$aliasOfVirtio" to the device commandline. These new options are supported in QEMU 4.2.0 and later. Extra qemu-specific validation is added to ensure that the device type/model is appropriate and that the qemu binary supports these commandline options. The result of this will be: 1) The virtio device presented to the guest will have an extra bit set in its PCI capabilities indicating that it can be used as a failover backup device. The virtio guest driver will need to be equipped to do something with this information. Unfortunately there is no way for libvirt to learn whether or not the guest driver supports failover - if it doesn't then the extra PCI capability will be ignored and the guest OS will just see two independent devices. (NB: the current virtio guest driver also requires that the MAC addresses of the two NICs match in order to pair them into a bond). 2) When a migration is requested, QEMu will automatically unplug the transient/hostdev NIC from the guest on the source host before starting migration, and automatically re-plug a similar device after restarting the guest CPUs on the destination host. While the transient NIC is unplugged, all network traffic will go through the persistent/virtio device, but when the hostdev NIC is plugged in, it will get all the traffic. This means that in normal circumstances the guest gets the performance advantage of vfio-assigned "real hardware" networking, but it can still be migrated with the only downside being a performance penalty (due to using an emulated NIC) during the migration. Signed-off-by: Laine Stump Reviewed-by: Daniel P. Berrang=C3=A9 --- src/qemu/qemu_command.c | 9 +++++ src/qemu/qemu_domain.c | 36 +++++++++++++++-- .../qemuxml2argvdata/net-virtio-teaming.args | 40 +++++++++++++++++++ tests/qemuxml2argvtest.c | 4 ++ 4 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 tests/qemuxml2argvdata/net-virtio-teaming.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index c66b60fd21..63aa10d3af 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -3833,6 +3833,8 @@ qemuBuildNicDevStr(virDomainDefPtr def, } virBufferAsprintf(&buf, ",host_mtu=3D%u", net->mtu); } + if (usingVirtio && net->teaming.type =3D=3D VIR_DOMAIN_NET_TEAMING_TYP= E_PERSISTENT) + virBufferAddLit(&buf, ",failover=3Don"); =20 virBufferAsprintf(&buf, ",netdev=3Dhost%s", net->info.alias); virBufferAsprintf(&buf, ",id=3D%s", net->info.alias); @@ -4704,6 +4706,13 @@ qemuBuildPCIHostdevDevStr(const virDomainDef *def, if (qemuBuildRomStr(&buf, dev->info) < 0) return NULL; =20 + if (dev->parentnet && + dev->parentnet->teaming.type =3D=3D VIR_DOMAIN_NET_TEAMING_TYPE_TR= ANSIENT && + dev->parentnet->teaming.persistent) { + virBufferAsprintf(&buf, ",failover_pair_id=3D%s", + dev->parentnet->teaming.persistent); + } + return virBufferContentAndReset(&buf); } =20 diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index ce0c5b78cd..6bd5d10f09 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -6391,12 +6391,20 @@ qemuDomainValidateActualNetDef(const virDomainNetDe= f *net, return -1; } =20 + if (net->teaming.type =3D=3D VIR_DOMAIN_NET_TEAMING_TYPE_TRANSIENT && + actualType !=3D VIR_DOMAIN_NET_TYPE_HOSTDEV) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("interface %s - teaming transient device must be = type=3D'hostdev', not '%s'"), + macstr, virDomainNetTypeToString(actualType)); + return -1; + } return 0; } =20 =20 static int -qemuDomainDeviceDefValidateNetwork(const virDomainNetDef *net) +qemuDomainDeviceDefValidateNetwork(const virDomainNetDef *net, + virQEMUCapsPtr qemuCaps) { bool hasIPv4 =3D false; bool hasIPv6 =3D false; @@ -6481,7 +6489,29 @@ qemuDomainDeviceDefValidateNetwork(const virDomainNe= tDef *net) return -1; } =20 - if (net->coalesce && !qemuDomainNetSupportsCoalesce(net->type)) { + if (net->teaming.type !=3D VIR_DOMAIN_NET_TEAMING_TYPE_NONE && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_FAILOVER)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("virtio-net failover (teaming) is not supported w= ith this QEMU binary")); + return -1; + } + if (net->teaming.type =3D=3D VIR_DOMAIN_NET_TEAMING_TYPE_PERSISTENT + && !virDomainNetIsVirtioModel(net)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("virtio-net teaming persistent interface must be = , not '%s'"), + virDomainNetGetModelString(net)); + return -1; + } + if (net->teaming.type =3D=3D VIR_DOMAIN_NET_TEAMING_TYPE_TRANSIENT && + net->type !=3D VIR_DOMAIN_NET_TYPE_HOSTDEV && + net->type !=3D VIR_DOMAIN_NET_TYPE_NETWORK) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("virtio-net teaming transient interface must be t= ype=3D'hostdev', not '%s'"), + virDomainNetTypeToString(net->type)); + return -1; + } + + if (net->coalesce && !qemuDomainNetSupportsCoalesce(net->type)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("coalesce settings on interface type %s are not s= upported"), virDomainNetTypeToString(net->type)); @@ -8377,7 +8407,7 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef = *dev, =20 switch ((virDomainDeviceType)dev->type) { case VIR_DOMAIN_DEVICE_NET: - ret =3D qemuDomainDeviceDefValidateNetwork(dev->data.net); + ret =3D qemuDomainDeviceDefValidateNetwork(dev->data.net, qemuCaps= ); break; =20 case VIR_DOMAIN_DEVICE_CHR: diff --git a/tests/qemuxml2argvdata/net-virtio-teaming.args b/tests/qemuxml= 2argvdata/net-virtio-teaming.args new file mode 100644 index 0000000000..19e7260843 --- /dev/null +++ b/tests/qemuxml2argvdata/net-virtio-teaming.args @@ -0,0 +1,40 @@ +LC_ALL=3DC \ +PATH=3D/bin \ +HOME=3D/tmp/lib/domain--1-QEMUGuest1 \ +USER=3Dtest \ +LOGNAME=3Dtest \ +XDG_DATA_HOME=3D/tmp/lib/domain--1-QEMUGuest1/.local/share \ +XDG_CACHE_HOME=3D/tmp/lib/domain--1-QEMUGuest1/.cache \ +XDG_CONFIG_HOME=3D/tmp/lib/domain--1-QEMUGuest1/.config \ +QEMU_AUDIO_DRV=3Dnone \ +/usr/bin/qemu-system-i386 \ +-name QEMUGuest1 \ +-S \ +-machine pc,accel=3Dtcg,usb=3Doff,dump-guest-core=3Doff \ +-m 214 \ +-realtime mlock=3Doff \ +-smp 1,sockets=3D1,cores=3D1,threads=3D1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=3Dcharmonitor,path=3D/tmp/lib/domain--1-QEMUGuest1/moni= tor.sock,\ +server,nowait \ +-mon chardev=3Dcharmonitor,id=3Dmonitor,mode=3Dcontrol \ +-rtc base=3Dutc \ +-no-shutdown \ +-no-acpi \ +-usb \ +-drive file=3D/dev/HostVG/QEMUGuest1,format=3Draw,if=3Dnone,id=3Ddrive-ide= 0-0-0 \ +-device ide-hd,bus=3Dide.0,unit=3D0,drive=3Ddrive-ide0-0-0,id=3Dide0-0-0,b= ootindex=3D1 \ +-netdev user,id=3Dhostua-backup0 \ +-device virtio-net-pci,failover=3Don,netdev=3Dhostua-backup0,id=3Dua-backu= p0,\ +mac=3D00:11:22:33:44:55,bus=3Dpci.0,addr=3D0x3 \ +-netdev user,id=3Dhostua-backup1 \ +-device virtio-net-pci,failover=3Don,netdev=3Dhostua-backup1,id=3Dua-backu= p1,\ +mac=3D66:44:33:22:11:00,bus=3Dpci.0,addr=3D0x4 \ +-device vfio-pci,host=3D0000:03:07.1,id=3Dhostdev0,bus=3Dpci.0,addr=3D0x5,\ +failover_pair_id=3Dua-backup0 \ +-device vfio-pci,host=3D0000:03:07.2,id=3Dhostdev1,bus=3Dpci.0,addr=3D0x6,\ +failover_pair_id=3Dua-backup1 \ +-device virtio-balloon-pci,id=3Dballoon0,bus=3Dpci.0,addr=3D0x7 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index b923590930..4d26fe0b55 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1308,6 +1308,10 @@ mymain(void) QEMU_CAPS_VIRTIO_NET_RX_QUEUE_SIZE, QEMU_CAPS_VIRTIO_NET_TX_QUEUE_SIZE); DO_TEST_PARSE_ERROR("net-virtio-rxqueuesize-invalid-size", NONE); + DO_TEST("net-virtio-teaming", + QEMU_CAPS_VIRTIO_NET_FAILOVER, + QEMU_CAPS_DEVICE_VFIO_PCI); + DO_TEST_PARSE_ERROR("net-virtio-teaming", NONE); DO_TEST("net-eth", NONE); DO_TEST("net-eth-ifname", NONE); DO_TEST("net-eth-names", NONE); --=20 2.24.1