[libvirt] [PATCH v2 2/2] qemu: Implement usernet address
Laine Stump
laine at laine.org
Wed Sep 13 17:34:14 UTC 2017
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 at 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);
More information about the libvir-list
mailing list