}
virBufferAsprintf(&buf, ",host_mtu=%u", net->mtu);
}
+ if (usingVirtio && net->teaming.type == VIR_DOMAIN_NET_TEAMING_TYPE_PERSISTENT)
+ virBufferAddLit(&buf, ",failover=on");
virBufferAsprintf(&buf, ",netdev=host%s", net->info.alias);
virBufferAsprintf(&buf, ",id=%s", net->info.alias);
if (qemuBuildRomStr(&buf, dev->info) < 0)
return NULL;
+ if (dev->parentnet &&
+ dev->parentnet->teaming.type == VIR_DOMAIN_NET_TEAMING_TYPE_TRANSIENT &&
+ dev->parentnet->teaming.persistent) {
+ virBufferAsprintf(&buf, ",failover_pair_id=%s",
+ dev->parentnet->teaming.persistent);
+ }
+
return virBufferContentAndReset(&buf);
}
return -1;
}
+ if (net->teaming.type == VIR_DOMAIN_NET_TEAMING_TYPE_TRANSIENT &&
+ actualType != VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("interface %s - teaming transient device must be type='hostdev', not '%s'"),
+ macstr, virDomainNetTypeToString(actualType));
+ return -1;
+ }
return 0;
}
static int
-qemuDomainDeviceDefValidateNetwork(const virDomainNetDef *net)
+qemuDomainDeviceDefValidateNetwork(const virDomainNetDef *net,
+ virQEMUCapsPtr qemuCaps)
{
bool hasIPv4 = false;
bool hasIPv6 = false;
return -1;
}
- if (net->coalesce && !qemuDomainNetSupportsCoalesce(net->type)) {
+ if (net->teaming.type != 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 with this QEMU binary"));
+ return -1;
+ }
+ if (net->teaming.type == VIR_DOMAIN_NET_TEAMING_TYPE_PERSISTENT
+ && !virDomainNetIsVirtioModel(net)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("virtio-net teaming persistent interface must be <model type='virtio'/>, not '%s'"),
+ virDomainNetGetModelString(net));
+ return -1;
+ }
+ if (net->teaming.type == VIR_DOMAIN_NET_TEAMING_TYPE_TRANSIENT &&
+ net->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
+ net->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("virtio-net teaming transient interface must be type='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 supported"),
virDomainNetTypeToString(net->type));
switch ((virDomainDeviceType)dev->type) {
case VIR_DOMAIN_DEVICE_NET:
- ret = qemuDomainDeviceDefValidateNetwork(dev->data.net);
+ ret = qemuDomainDeviceDefValidateNetwork(dev->data.net, qemuCaps);
break;
case VIR_DOMAIN_DEVICE_CHR:
--- /dev/null
+LC_ALL=C \
+PATH=/bin \
+HOME=/tmp/lib/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/tmp/lib/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/tmp/lib/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-i386 \
+-name QEMUGuest1 \
+-S \
+-machine pc,accel=tcg,usb=off,dump-guest-core=off \
+-m 214 \
+-realtime mlock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 \
+-netdev user,id=hostua-backup0 \
+-device virtio-net-pci,failover=on,netdev=hostua-backup0,id=ua-backup0,\
+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 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
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);