Laszlo Ersek
2021-Dec-23 10:37 UTC
[Libguestfs] [PATCH 3/3] launch-libvirt: add virtio-net via the standard <interface> element
Starting with version 3.8.0, libvirt allows us to specify the network address and network mask (as prefix) for SLIRP directly via the <interface> element in the domain XML: <https://libvirt.org/formatdomain.html#userspace-slirp-stack>. This means we don't need the <qemu:commandline> hack for virtio-net on such versions. Restrict the hack in construct_libvirt_xml_qemu_cmdline() to libvirt<3.8.0, and generate the proper <interface> element in construct_libvirt_xml_devices() on libvirt>=3.8.0. Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2034160 Suggested-by: Richard W.M. Jones <rjones at redhat.com> Signed-off-by: Laszlo Ersek <lersek at redhat.com> --- Notes: v1: - Tested with "virt-rescue --network" and "ping", using the "libvirt" back-end, after setting "net.ipv4.ping_group_range" properly in sysctl on the host. (Libvirt version: libvirt-daemon-7.6.0-3.fc35.x86_64.) - The generated libvirt XML, per "virsh dumpxml", contains <devices> <interface type='user'> <mac address='52:54:00:fe:23:48'/> <ip address='169.254.0.0' family='ipv4' prefix='16'/> <model type='virtio'/> <alias name='net0'/> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> </interface> </devices> <qemu:commandline> <qemu:env name='TMPDIR' value='/home/lacos/src/v2v/guestfs-tools/tmp'/> </qemu:commandline> and the consequent QEMU cmdline has -netdev user,net=169.254.0.0/16,id=hostnet0 \ -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:fe:23:48,bus=pci.0,addr=0x2 \ - The full set of PCI addresses that libvirt assigns to the virtio devices are, per "virsh dumpxml": <controller type='scsi' index='0' model='virtio-scsi'> <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> <controller type='virtio-serial' index='0'> <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> <interface type='user'> <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> <rng model='virtio'> <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/> - The same, verified with virsh -c ... qemu-monitor-command guestfs-... --hmp info qtree is: bus: main-system-bus dev: i440FX-pcihost, id "" bus: pci.0 dev: virtio-rng-pci, id "rng0" addr = 05.0 dev: virtio-net-pci, id "net0" addr = 02.0 dev: virtio-serial-pci, id "virtio-serial0" addr = 04.0 dev: virtio-scsi-pci, id "scsi0" addr = 03.0 lib/guestfs-internal.h | 3 ++- lib/launch-libvirt.c | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/guestfs-internal.h b/lib/guestfs-internal.h index e24d570f5aa7..4a19e5c6bb47 100644 --- a/lib/guestfs-internal.h +++ b/lib/guestfs-internal.h @@ -173,7 +173,8 @@ cleanup_mutex_unlock (pthread_mutex_t **ptr) #endif /* Place the virtio-net controller in slot 0x1e on the root bus, on normal - * hardware with PCI. Refer to RHBZ#2034160. + * hardware with PCI. Necessary only before libvirt 3.8.0. Refer to + * RHBZ#2034160. */ #ifdef HAVE_LIBVIRT_BACKEND #if defined(__arm__) || defined(__s390x__) diff --git a/lib/launch-libvirt.c b/lib/launch-libvirt.c index 266d88824686..cc714c02efbf 100644 --- a/lib/launch-libvirt.c +++ b/lib/launch-libvirt.c @@ -1413,6 +1413,28 @@ construct_libvirt_xml_devices (guestfs_h *g, } end_element (); } end_element (); + /* Virtio-net NIC with SLIRP (= userspace) back-end, if networking is + * enabled. Starting with libvirt 3.8.0, we can specify the network address + * and prefix for SLIRP in the domain XML. Therefore, we can add the NIC + * via the standard <interface> element rather than <qemu:commandline>, and + * so libvirt can manage the PCI address of the virtio-net NIC like the PCI + * addresses of all other devices. Refer to RHBZ#2034160. + */ + if (g->enable_network && + guestfs_int_version_ge (¶ms->data->libvirt_version, 3, 8, 0)) { + start_element ("interface") { + attribute ("type", "user"); + start_element ("model") { + attribute ("type", "virtio"); + } end_element (); + start_element ("ip") { + attribute ("family", "ipv4"); + attribute ("address", NETWORK_ADDRESS); + attribute ("prefix", NETWORK_PREFIX); + } end_element (); + } end_element (); + } + /* Libvirt adds some devices by default. Indicate to libvirt * that we don't want them. */ @@ -1835,9 +1857,10 @@ construct_libvirt_xml_qemu_cmdline (guestfs_h *g, } end_element (); /* Workaround because libvirt user networking cannot specify "net=" - * parameter. + * parameter. Necessary only before libvirt 3.8.0; refer to RHBZ#2034160. */ - if (g->enable_network) { + if (g->enable_network && + !guestfs_int_version_ge (¶ms->data->libvirt_version, 3, 8, 0)) { start_element ("qemu:arg") { attribute ("value", "-netdev"); } end_element (); -- 2.19.1.3.g30247aa5d201
Richard W.M. Jones
2021-Dec-23 11:31 UTC
[Libguestfs] [PATCH 3/3] launch-libvirt: add virtio-net via the standard <interface> element
Yes, this series looks all good to me, thanks for fixing this blocker so quickly. I also tested it on RHEL 9 and it fixes the "regression" (or whatever we want to call it!) there. So for the whole series: Reviewed-by: Richard W.M. Jones <rjones at redhat.com> Tested-by: Richard W.M. Jones <rjones at redhat.com> Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into KVM guests. http://libguestfs.org/virt-v2v