]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Implement usernet address
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 13 Sep 2017 09:16:04 +0000 (11:16 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Mon, 18 Sep 2017 11:54:27 +0000 (13:54 +0200)
https://bugzilla.redhat.com/show_bug.cgi?id=1075520

Apart from generic checks, we need to constrain netmask/prefix
length a bit. Thing is, with current implementation QEMU needs to
be able to 'assign' some IP addresses to the virtual network. For
instance, the default gateway is at x.x.x.2, dns is at x.x.x.3,
the default DHCP range is x.x.x.15-x.x.x.30. Since we don't
expose these settings yet, it's safer to require shorter prefix
to have room for the defaults.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: laine@laine.org
src/qemu/qemu_command.c
src/qemu/qemu_domain.c
tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.args [new file with mode: 0644]
tests/qemuxml2argvtest.c

index d553df57f496cade202a3fb006e94e6083103adf..d7f7fa9b16ef96852d6b15c8c9949e82dc9d0f58 100644 (file)
@@ -3805,6 +3805,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
     virDomainNetType netType = virDomainNetGetActualType(net);
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     size_t i;
+    char *addr = NULL;
     char *ret = NULL;
 
     if (net->script && netType != VIR_DOMAIN_NET_TYPE_ETHERNET) {
@@ -3873,6 +3874,26 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
         break;
 
     case VIR_DOMAIN_NET_TYPE_USER:
+        virBufferAsprintf(&buf, "user%c", type_sep);
+        for (i = 0; i < net->guestIP.nips; i++) {
+            const virNetDevIPAddr *ip = net->guestIP.ips[i];
+            const char *prefix = "";
+
+            if (!(addr = virSocketAddrFormat(&ip->address)))
+                goto cleanup;
+
+            if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET))
+                prefix = "net=";
+            if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET6))
+                prefix = "ipv6-net=";
+
+            virBufferAsprintf(&buf, "%s%s", prefix, addr);
+            if (ip->prefix)
+                virBufferAsprintf(&buf, "/%u", ip->prefix);
+            virBufferAddChar(&buf, ',');
+        }
+        break;
+
     case VIR_DOMAIN_NET_TYPE_INTERNAL:
         virBufferAsprintf(&buf, "user%c", type_sep);
         break;
@@ -3928,6 +3949,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
  cleanup:
     virBufferFreeAndReset(&buf);
     virObjectUnref(cfg);
+    VIR_FREE(addr);
     return ret;
 }
 
index 305019b66cf6216ab2c6869a413c01f331e685f3..50b536eec7b1d8e12c83eceef94ace0a61d968d7 100644 (file)
@@ -3338,9 +3338,11 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
                             void *opaque ATTRIBUTE_UNUSED)
 {
     int ret = -1;
+    size_t i;
 
     if (dev->type == VIR_DOMAIN_DEVICE_NET) {
         const virDomainNetDef *net = dev->data.net;
+        bool hasIPv4 = false, hasIPv6 = false;
 
         if (net->type == VIR_DOMAIN_NET_TYPE_USER) {
             if (net->guestIP.nroutes) {
@@ -3349,6 +3351,48 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
                                  "guest-side IP route, not supported by QEMU"));
                 goto cleanup;
             }
+
+            for (i = 0; i < net->guestIP.nips; i++) {
+                const virNetDevIPAddr *ip = net->guestIP.ips[i];
+
+                if (VIR_SOCKET_ADDR_VALID(&net->guestIP.ips[i]->peer)) {
+                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                                   _("Invalid attempt to set peer IP for guest"));
+                    goto cleanup;
+                }
+
+                if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET)) {
+                    if (hasIPv4) {
+                        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                                       _("Only one IPv4 address per "
+                                         "interface is allowed"));
+                        goto cleanup;
+                    }
+                    hasIPv4 = true;
+
+                    if (ip->prefix > 27) {
+                        virReportError(VIR_ERR_XML_ERROR, "%s",
+                                       _("prefix too long"));
+                        goto cleanup;
+                    }
+                }
+
+                if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET6)) {
+                    if (hasIPv6) {
+                        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                                       _("Only one IPv6 address per "
+                                         "interface is allowed"));
+                        goto cleanup;
+                    }
+                    hasIPv6 = true;
+
+                    if (ip->prefix > 120) {
+                        virReportError(VIR_ERR_XML_ERROR, "%s",
+                                       _("prefix too long"));
+                        goto cleanup;
+                    }
+                }
+            }
         } else if (net->guestIP.nroutes || net->guestIP.nips) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("Invalid attempt to set network interface "
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.args b/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.args
new file mode 100644 (file)
index 0000000..632d2ec
--- /dev/null
@@ -0,0 +1,26 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-i686 \
+-name QEMUGuest1 \
+-S \
+-M pc \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-netdev user,net=172.17.2.0/24,ipv6-net=2001:db8:ac10:fd01::/64,id=hostnet0 \
+-device rtl8139,netdev=hostnet0,id=net0,mac=00:11:22:33:44:55,bus=pci.0,\
+addr=0x3
index c8c479cbd4379099c09030313e3e1252662e6850..579cdb6f083cdf91cda3e008685a10d47e7ca4de 100644 (file)
@@ -1161,6 +1161,7 @@ mymain(void)
                     QEMU_CAPS_NETDEV,
                     QEMU_CAPS_VHOSTUSER_MULTIQUEUE);
     DO_TEST("net-user", NONE);
+    DO_TEST("net-user-addr", QEMU_CAPS_NETDEV);
     DO_TEST("net-virtio", NONE);
     DO_TEST("net-virtio-device",
             QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_VIRTIO_TX_ALG);