The new <driver> attribute backupAlias gives the alias name ("id" in
QEMU parlance) of the virtio-net device that will be paired in the
guest with a vfio-pci device for "failover" when the vfio-pci device
is unplugged (e.g. during migration).
This patch adds backupAlias for <interface type='hostdev'> (which has
its <driver> stored in the child virDomainHostdevDef); an upcoming
patch will handle the case of <interface type='network'> when the
network is a pool of SRIOV VFs (in that case the <driver> subelement
is stored in the virDomainNetDef).
Since a MAC address must be set for the hostdev in order for the
failover to work (a current guest driver limitation is that the MAC
addresses of the two devices must match), and that isn't possible with
plain <hostdev>, backupAlias is prohibited by validation in the case
of a plain <hostdev>.
An example usage:
<interface type='network'>
<source network='mybridge'/>
<mac address='00:11:22:33:44:55'/>
<model type='virtio'/>
<alias name='ua-backup0'/>
<driver failover='on'/>
</interface>
<interface type='hostdev' managed='yes'>
<source>
<address type='pci' domain='0x0000' bus='0x03'
slot='0x07' function='0x1'/>
</source>
<mac address='00:11:22:33:44:55'/>
<driver backupAlias='ua-backup0'/>
</interface>
QEMU will internally associate these two devices, and will
automatically unplug the hostdev at the start of any migration, and
re-plug a new device on the destination when migration is complete (it
is up to the guest virtio driver to handle bonding the two devices).
Signed-off-by: Laine Stump <laine(a)redhat.com>
---
docs/schemas/domaincommon.rng | 5 +++++
src/conf/domain_conf.c | 16 ++++++++++++++--
src/conf/domain_conf.h | 1 +
src/qemu/qemu_command.c | 2 ++
src/qemu/qemu_domain.c | 6 ++++++
.../qemuxml2argvdata/net-virtio-failover.args | 6 +++++-
tests/qemuxml2argvdata/net-virtio-failover.xml | 14 ++++++++++++++
tests/qemuxml2argvtest.c | 3 ++-
.../qemuxml2xmloutdata/net-virtio-failover.xml | 18 +++++++++++++++++-
tests/qemuxml2xmltest.c | 3 ++-
10 files changed, 68 insertions(+), 6 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 80aea47e36..e0977d28d3 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3002,6 +3002,11 @@
</optional>
<optional>
<element name="driver">
+ <optional>
+ <attribute name="backupAlias">
+ <ref name='aliasName'/>
+ </attribute>
+ </optional>
<choice>
<group>
<attribute name="name">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 29636617a2..e0e47415ed 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2941,8 +2941,10 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
VIR_FREE(def->source.subsys.u.scsi_host.wwpn);
break;
- case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ VIR_FREE(def->source.subsys.u.pci.backupAlias);
+ break;
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
break;
@@ -6360,6 +6362,12 @@ virDomainHostdevDefValidate(const virDomainHostdevDef *hostdev)
"'unassigned' address type"));
return -1;
}
+ if (hostdev->source.subsys.u.pci.backupAlias &&
+ !hostdev->parentnet) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("backupAlias is not supported for plain
<hostdev> - <interface type='hostdev'> is required"));
+ return -1;
+ }
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
if (hostdev->info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE
&&
@@ -8410,6 +8418,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
}
pcisrc->backend = backend;
+ pcisrc->backupAlias =
virXPathString("string(./driver/@backupAlias)", ctxt);
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
@@ -25037,7 +25046,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
- pcisrc->backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
+ (pcisrc->backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT ||
+ pcisrc->backupAlias)) {
virBufferAddLit(buf, "<driver");
@@ -25054,6 +25064,8 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
virBufferAsprintf(buf, " name='%s'", backend);
}
+ virBufferEscapeString(buf, " backupAlias='%s'",
pcisrc->backupAlias);
+
virBufferAddLit(buf, "/>\n");
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index af9691d62b..0bf1d2b6bf 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -235,6 +235,7 @@ struct _virDomainHostdevSubsysUSB {
struct _virDomainHostdevSubsysPCI {
virPCIDeviceAddress addr; /* host address */
int backend; /* enum virDomainHostdevSubsysPCIBackendType */
+ char *backupAlias; /* alias id of backup virtio device for failover */
};
struct _virDomainHostdevSubsysSCSIHost {
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d3c0cc0506..82a95e2474 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4706,6 +4706,8 @@ qemuBuildPCIHostdevDevStr(const virDomainDef *def,
return NULL;
if (qemuBuildRomStr(&buf, dev->info) < 0)
return NULL;
+ if (pcisrc->backupAlias)
+ virBufferAsprintf(&buf, ",failover_pair_id=%s",
pcisrc->backupAlias);
return virBufferContentAndReset(&buf);
}
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 6f45d74bde..d32a3c0935 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -6664,6 +6664,12 @@ qemuDomainDeviceDefValidateHostdev(const virDomainHostdevDef
*hostdev,
return -1;
}
}
+ if (hostdev->source.subsys.u.pci.backupAlias &&
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_FAILOVER)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("virtio-net failover / hostdev backupAlias is not
supported with this QEMU binary"));
+ return -1;
+ }
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
diff --git a/tests/qemuxml2argvdata/net-virtio-failover.args
b/tests/qemuxml2argvdata/net-virtio-failover.args
index da41e19628..19e7260843 100644
--- a/tests/qemuxml2argvdata/net-virtio-failover.args
+++ b/tests/qemuxml2argvdata/net-virtio-failover.args
@@ -33,4 +33,8 @@ mac=00:11:22:33:44:55,bus=pci.0,addr=0x3 \
-netdev user,id=hostua-backup1 \
-device virtio-net-pci,failover=on,netdev=hostua-backup1,id=ua-backup1,\
mac=66:44:33:22:11:00,bus=pci.0,addr=0x4 \
--device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
+-device vfio-pci,host=0000:03:07.1,id=hostdev0,bus=pci.0,addr=0x5,\
+failover_pair_id=ua-backup0 \
+-device vfio-pci,host=0000:03:07.2,id=hostdev1,bus=pci.0,addr=0x6,\
+failover_pair_id=ua-backup1 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x7
diff --git a/tests/qemuxml2argvdata/net-virtio-failover.xml
b/tests/qemuxml2argvdata/net-virtio-failover.xml
index 1f545b8d73..99ac37013a 100644
--- a/tests/qemuxml2argvdata/net-virtio-failover.xml
+++ b/tests/qemuxml2argvdata/net-virtio-failover.xml
@@ -31,6 +31,20 @@
<driver failover='on'/>
<alias name='ua-backup1'/>
</interface>
+ <interface type='hostdev' managed='yes'>
+ <mac address='00:11:22:33:44:55'/>
+ <driver backupAlias='ua-backup0'/>
+ <source>
+ <address type='pci' domain='0x0000' bus='0x03'
slot='0x07' function='0x1'/>
+ </source>
+ </interface>
+ <interface type='hostdev' managed='yes'>
+ <mac address='66:44:33:22:11:00'/>
+ <driver backupAlias='ua-backup1'/>
+ <source>
+ <address type='pci' domain='0x0000' bus='0x03'
slot='0x07' function='0x2'/>
+ </source>
+ </interface>
<memballoon model='virtio'/>
</devices>
</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index c4fbe321d8..411393a55a 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1309,7 +1309,8 @@ mymain(void)
QEMU_CAPS_VIRTIO_NET_TX_QUEUE_SIZE);
DO_TEST_PARSE_ERROR("net-virtio-rxqueuesize-invalid-size", NONE);
DO_TEST("net-virtio-failover",
- QEMU_CAPS_VIRTIO_NET_FAILOVER);
+ QEMU_CAPS_VIRTIO_NET_FAILOVER,
+ QEMU_CAPS_DEVICE_VFIO_PCI);
DO_TEST_PARSE_ERROR("net-virtio-failover", NONE);
DO_TEST("net-eth", NONE);
DO_TEST("net-eth-ifname", NONE);
diff --git a/tests/qemuxml2xmloutdata/net-virtio-failover.xml
b/tests/qemuxml2xmloutdata/net-virtio-failover.xml
index 7895c03dd7..9c73a3bee7 100644
--- a/tests/qemuxml2xmloutdata/net-virtio-failover.xml
+++ b/tests/qemuxml2xmloutdata/net-virtio-failover.xml
@@ -41,10 +41,26 @@
<alias name='ua-backup1'/>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x04' function='0x0'/>
</interface>
+ <interface type='hostdev' managed='yes'>
+ <mac address='00:11:22:33:44:55'/>
+ <driver backupAlias='ua-backup0'/>
+ <source>
+ <address type='pci' domain='0x0000' bus='0x03'
slot='0x07' function='0x1'/>
+ </source>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x05' function='0x0'/>
+ </interface>
+ <interface type='hostdev' managed='yes'>
+ <mac address='66:44:33:22:11:00'/>
+ <driver backupAlias='ua-backup1'/>
+ <source>
+ <address type='pci' domain='0x0000' bus='0x03'
slot='0x07' function='0x2'/>
+ </source>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x06' function='0x0'/>
+ </interface>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<memballoon model='virtio'>
- <address type='pci' domain='0x0000' bus='0x00'
slot='0x05' function='0x0'/>
+ <address type='pci' domain='0x0000' bus='0x00'
slot='0x07' function='0x0'/>
</memballoon>
</devices>
</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 326e49fbcd..c91690a030 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -452,7 +452,8 @@ mymain(void)
DO_TEST("net-virtio-network-portgroup", NONE);
DO_TEST("net-virtio-rxtxqueuesize", NONE);
DO_TEST("net-virtio-failover",
- QEMU_CAPS_VIRTIO_NET_FAILOVER);
+ QEMU_CAPS_VIRTIO_NET_FAILOVER,
+ QEMU_CAPS_DEVICE_VFIO_PCI);
DO_TEST("net-hostdev", NONE);
DO_TEST("net-hostdev-bootorder", NONE);
DO_TEST("net-hostdev-vfio", QEMU_CAPS_DEVICE_VFIO_PCI);
--
2.24.1