From 105ef857c381fc58fe81dfd58b1897999632a618 Mon Sep 17 00:00:00 2001 From: Omer Tuchfeld Date: Tue, 27 Dec 2022 02:40:57 +0100 Subject: [PATCH] Fix IPv6 subnet size regression (#983) b0489a5cb128b6acae1976e0383e22bf3d870277 introduced a regression where the calculation for the number of IPv6 IP addresses always yields a negative or 0 value, causing users to *always* encounter the following error when creating IPv6 libvirt networks: `netmask seems to be too strict: only <0 or negative> IPs available (ipv6)` That commit attempted to fix the wrong use of the `^` operator in the calculation, which was truely wrong. But it was just wrong in a relatively "harmless" way, as it wasn't completely blocking users. The fix in that commit had its own bug - a `1` shifted by `128` always gives `0`, and not the desired `2 to the power of 128`, because the latter doesn't fit in a primitive integer type. To fix this, I've changed the calculation to simply consider the number of bits available for the subnet, rather than the number of IP addresses available for the subnet, as that is obviously a much smaller number, one that the primitive Go integer types can handle --- libvirt/network.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libvirt/network.go b/libvirt/network.go index 9b836354f..2c731251d 100644 --- a/libvirt/network.go +++ b/libvirt/network.go @@ -115,9 +115,15 @@ func getNetworkIPConfig(address string) (*libvirtxml.NetworkIP, *libvirtxml.Netw if bits == (net.IPv6len * 8) { family = "ipv6" } - ipsRange := (1 << bits) - (1 << ones) - if ipsRange < 4 { - return nil, nil, fmt.Errorf("netmask seems to be too strict: only %d IPs available (%s)", ipsRange-3, family) + + const minimumSubnetBits = 3 + if subnetBits := bits - ones; subnetBits < minimumSubnetBits { + // Reserved IPs are 0, broadcast, and 1 for the host + const reservedIPs = 3 + subnetIPCount := 1 << subnetBits + availableSubnetIPCount := subnetIPCount - reservedIPs + + return nil, nil, fmt.Errorf("netmask seems to be too strict: only %d IPs available (%s)", availableSubnetIPCount, family) } // we should calculate the range served by DHCP. For example, for