From 0c6c193b29f9236e72d0746d1b018bc6ede0323c Mon Sep 17 00:00:00 2001 From: Max Makarov Date: Tue, 31 Mar 2026 12:39:48 +0300 Subject: [PATCH] Fix network config when gateway is outside the address subnet When using L3-only / EVPN networking with /32 host addresses, the gateway (e.g. 169.254.0.1) is outside the address subnet. The WMI MSFT_NetIPAddress.create() call rejects this with: "DefaultGateway X is not on the same network segment (subnet) that is defined by the IP address Y and PrefixLength 32." Fix this by creating routes manually instead of relying on DefaultGateway parameter: 1. Assign the IP address without DefaultGateway 2. Create an on-link route to the gateway (/32 or /128) 3. Create the default route via the gateway This is equivalent to what Linux does with on-link routes: ip route add 169.254.0.1 dev eth0 scope link ip route add default via 169.254.0.1 dev eth0 Also skip gateway route creation when the gateway address family does not match the address being configured (e.g. IPv4 gateway with IPv6 address). Closes: https://github.com/cloudbase/cloudbase-init/issues/166 Signed-off-by: Max Makarov --- cloudbaseinit/osutils/windows.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/cloudbaseinit/osutils/windows.py b/cloudbaseinit/osutils/windows.py index fc7597bc..4fe10a88 100644 --- a/cloudbaseinit/osutils/windows.py +++ b/cloudbaseinit/osutils/windows.py @@ -1020,7 +1020,29 @@ def _set_static_network_config(name, address, prefix_len, gateway): conn.MSFT_NetIPAddress.create( AddressFamily=family, InterfaceAlias=name, IPAddress=address, - PrefixLength=prefix_len, DefaultGateway=gateway) + PrefixLength=prefix_len) + + if gateway: + gw_is_v4 = netaddr.valid_ipv4(gateway) + gw_is_v6 = netaddr.valid_ipv6(gateway) + addr_is_v4 = (family == AF_INET) + + if (gw_is_v4 and addr_is_v4) or (gw_is_v6 and not addr_is_v4): + gw_prefix_len = "32" if gw_is_v4 else "128" + defroute = "0.0.0.0/0" if gw_is_v4 else "::/0" + + # Create on-link route to the gateway so it is reachable + # even when it is outside the address subnet (e.g. /32). + try: + conn.MSFT_NetRoute.create( + AddressFamily=family, InterfaceAlias=name, + DestinationPrefix="%s/%s" % (gateway, gw_prefix_len)) + except Exception: + pass + + conn.MSFT_NetRoute.create( + AddressFamily=family, InterfaceAlias=name, + DestinationPrefix=defroute, NextHop=gateway) def set_static_network_config(self, name, address, prefix_len_or_netmask, gateway, dnsnameservers):