[libvirt] [PATCH v2 0/2] Allow usernet to have an address

diff to v1: - moved the <ip/> directly under <interface/> - enhanced the test - tuned some error messages Michal Privoznik (2): conf: Allow usernet to have an address qemu: Implement usernet address docs/formatdomain.html.in | 8 +++- src/qemu/qemu_command.c | 22 +++++++++ src/qemu/qemu_domain.c | 53 +++++++++++++++++++++- .../qemuxml2argv-net-user-addr.args | 26 +++++++++++ .../qemuxml2argv-net-user-addr.xml | 41 +++++++++++++++++ tests/qemuxml2argvtest.c | 1 + .../qemuxml2xmlout-net-user-addr.xml | 1 + tests/qemuxml2xmltest.c | 1 + 8 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml -- 2.13.5

https://bugzilla.redhat.com/show_bug.cgi?id=1075520 Currently, all that users can specify for an interface type of 'user' is the common attributes: PCI address, NIC model (and that's basically it). However, some need to configure other address range than the default one. Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- docs/formatdomain.html.in | 8 ++++- src/qemu/qemu_domain.c | 9 ++++- .../qemuxml2argv-net-user-addr.xml | 41 ++++++++++++++++++++++ .../qemuxml2xmlout-net-user-addr.xml | 1 + tests/qemuxml2xmltest.c | 1 + 5 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 8ca7637a4..2c0afb240 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -4701,7 +4701,11 @@ starting from <code>10.0.2.15</code>. The default router will be <code>10.0.2.2</code> and the DNS server will be <code>10.0.2.3</code>. This networking is the only option for unprivileged users who need their - VMs to have outgoing access. + VMs to have outgoing access. However, <span class="since">since 3.8.0</span> + it is possible to override the default network address by including + <code>ip</code> element. The element has one mandatory attribute + <code>address</code>. Optionally, address <code>family</code> can be + specified as well as <code>prefix</code>. </p> <pre> @@ -4711,6 +4715,8 @@ ... <interface type='user'> <mac address="00:11:22:33:44:55"/> + <ip family='ipv4' address='172.17.2.0' prefix='24'/> + <ip family='ipv6' address='2001:db8:ac10:fd01::' prefix='64'/> </interface> </devices> ...</pre> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 72031893f..bccd30e12 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3342,7 +3342,14 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev, if (dev->type == VIR_DOMAIN_DEVICE_NET) { const virDomainNetDef *net = dev->data.net; - if (net->guestIP.nroutes || net->guestIP.nips) { + if (net->type == VIR_DOMAIN_NET_TYPE_USER) { + if (net->guestIP.nroutes) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Invalid attempt to set network interface " + "guest-side IP route, not supported by QEMU")); + goto cleanup; + } + } else if (net->guestIP.nroutes || net->guestIP.nips) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Invalid attempt to set network interface " "guest-side IP route and/or address info, " diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml new file mode 100644 index 000000000..0b5f15198 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml @@ -0,0 +1,41 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-i686</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <ip address='172.17.2.0' family='ipv4' prefix='24'/> + <ip address='2001:db8:ac10:fd01::' family='ipv6' prefix='64'/> + <model type='rtl8139'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml new file mode 120000 index 000000000..fd909ec24 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/qemuxml2argv-net-user-addr.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 0a87cedf2..efac9e828 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -531,6 +531,7 @@ mymain(void) DO_TEST("misc-uuid", NONE); DO_TEST("net-vhostuser", NONE); DO_TEST("net-user", NONE); + DO_TEST("net-user-addr", QEMU_CAPS_NETDEV); DO_TEST("net-virtio", NONE); DO_TEST("net-virtio-device", NONE); DO_TEST("net-virtio-disable-offloads", NONE); -- 2.13.5

On 09/13/2017 06:47 AM, Michal Privoznik wrote:
https://bugzilla.redhat.com/show_bug.cgi?id=1075520
Currently, all that users can specify for an interface type of 'user' is the common attributes: PCI address, NIC model (and that's basically it). However, some need to configure other address range than the default one.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- docs/formatdomain.html.in | 8 ++++- src/qemu/qemu_domain.c | 9 ++++- .../qemuxml2argv-net-user-addr.xml | 41 ++++++++++++++++++++++ .../qemuxml2xmlout-net-user-addr.xml | 1 + tests/qemuxml2xmltest.c | 1 + 5 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 8ca7637a4..2c0afb240 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -4701,7 +4701,11 @@ starting from <code>10.0.2.15</code>. The default router will be <code>10.0.2.2</code> and the DNS server will be <code>10.0.2.3</code>. This networking is the only option for unprivileged users who need their - VMs to have outgoing access. + VMs to have outgoing access. However, <span class="since">since 3.8.0</span>
I think this sounds better without the "However".
+ it is possible to override the default network address by including + <code>ip</code> element. The element has one mandatory attribute + <code>address</code>. Optionally, address <code>family</code> can be + specified as well as <code>prefix</code>. </p>
".. by including *an* <ip> element specifying an IPv4 address in its one mandatory attribute, <code>address</code>. Optionally, a second <ip> element with a <code>family</code> attribute set to "ipv6" can be specified to add an IPv6 address to the interface." Or something like that.
<pre> @@ -4711,6 +4715,8 @@ ... <interface type='user'> <mac address="00:11:22:33:44:55"/> + <ip family='ipv4' address='172.17.2.0' prefix='24'/> + <ip family='ipv6' address='2001:db8:ac10:fd01::' prefix='64'/> </interface> </devices> ...</pre> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 72031893f..bccd30e12 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3342,7 +3342,14 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev, if (dev->type == VIR_DOMAIN_DEVICE_NET) { const virDomainNetDef *net = dev->data.net;
- if (net->guestIP.nroutes || net->guestIP.nips) { + if (net->type == VIR_DOMAIN_NET_TYPE_USER) { + if (net->guestIP.nroutes) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Invalid attempt to set network interface " + "guest-side IP route, not supported by QEMU")); + goto cleanup; + } + } else if (net->guestIP.nroutes || net->guestIP.nips) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Invalid attempt to set network interface " "guest-side IP route and/or address info, " diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml new file mode 100644 index 000000000..0b5f15198 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.xml @@ -0,0 +1,41 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-i686</emulator> + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/> + </controller> + <controller type='ide' index='0'> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/> + </controller> + <controller type='pci' index='0' model='pci-root'/> + <interface type='user'> + <mac address='00:11:22:33:44:55'/> + <ip address='172.17.2.0' family='ipv4' prefix='24'/> + <ip address='2001:db8:ac10:fd01::' family='ipv6' prefix='64'/> + <model type='rtl8139'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </interface> + <input type='mouse' bus='ps2'/> + <input type='keyboard' bus='ps2'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml new file mode 120000 index 000000000..fd909ec24 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-user-addr.xml @@ -0,0 +1 @@ +../qemuxml2argvdata/qemuxml2argv-net-user-addr.xml \ No newline at end of file diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 0a87cedf2..efac9e828 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -531,6 +531,7 @@ mymain(void) DO_TEST("misc-uuid", NONE); DO_TEST("net-vhostuser", NONE); DO_TEST("net-user", NONE); + DO_TEST("net-user-addr", QEMU_CAPS_NETDEV); DO_TEST("net-virtio", NONE); DO_TEST("net-virtio-device", NONE); DO_TEST("net-virtio-disable-offloads", NONE);
ACK.

https://bugzilla.redhat.com/show_bug.cgi?id=1075520 Apart from generic checks, we need to constrain netmask/prefix lenght 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> --- src/qemu/qemu_command.c | 22 +++++++++++ src/qemu/qemu_domain.c | 44 ++++++++++++++++++++++ .../qemuxml2argv-net-user-addr.args | 26 +++++++++++++ tests/qemuxml2argvtest.c | 1 + 4 files changed, 93 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.args diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d553df57f..d7f7fa9b1 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -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; } diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index bccd30e12..849173fd1 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -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 index 000000000..632d2ecf5 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.args @@ -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 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 2c040e4c0..d4a3b7738 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1159,6 +1159,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); -- 2.13.5

On 09/13/2017 06:47 AM, Michal Privoznik wrote:
https://bugzilla.redhat.com/show_bug.cgi?id=1075520
Apart from generic checks, we need to constrain netmask/prefix lenght a bit. Thing is, with current implementation QEMU needs to
s/lenght/length/
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>
ACK/Reviewed-by/etc.
--- src/qemu/qemu_command.c | 22 +++++++++++ src/qemu/qemu_domain.c | 44 ++++++++++++++++++++++ .../qemuxml2argv-net-user-addr.args | 26 +++++++++++++ tests/qemuxml2argvtest.c | 1 + 4 files changed, 93 insertions(+) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.args
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index d553df57f..d7f7fa9b1 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -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; }
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index bccd30e12..849173fd1 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -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 index 000000000..632d2ecf5 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-user-addr.args @@ -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 diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 2c040e4c0..d4a3b7738 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1159,6 +1159,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);
participants (2)
-
Laine Stump
-
Michal Privoznik