GNOME Bugzilla – Bug 738590
Invalid route added for DHCP server
Last modified: 2014-10-31 17:52:01 UTC
I have a number of hypervisors set up to run DHCP on a 169.254.169.254 address. Each hypervisor has this IP configured, and the guests all talk to it directly. Importantly, the default gateway has no idea this address exists. Even if it did, it wouldn't work because there are multiple instances of this (link-local) address on the same network. I also provide a route for 169.254.0.0/16 via the 'classless static route' DHCP option. This lets guests communicate with the DHCP server directly (which has some other things running), while bypassing the default gateway. The routing table for this, looks something like this: # ip -4 route default via x.y.z.1 dev eth0 proto static metric 1024 x.y.z.0/23 dev eth0 proto kernel scope link src x.y.z.232 169.254.0.0/16 dev eth0 proto static scope link metric 1 The problem is, NetworkManager sees the DHCP server IP and adds an explicit route for that IP: 169.254.169.254 via x.y.z.1 dev eth0 proto static metric 1 This does not work. The default gateway doesn't know about the DHCP server IP. Also, we already have a route describing how to get to the DHCP server (the 169.254.0.0/16 route shown above). I tracked this down, and it's coming from here: http://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/src/dhcp-manager/nm-dhcp-utils.c#n458 This should probably take into account any other routes received via DHCP, and not just compare the machine's default route. While I understand this setup is a little odd, it works perfectly on everything I've tested (pre-networkmanager Linux, FreeBSD, OpenBSD, Windows). I noticed this in CentOS 7, but the same bug appears to be in the latest HEAD
(In reply to comment #0) > I tracked this down, and it's coming from here: > http://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/src/dhcp-manager/nm-dhcp-utils.c#n458 [For the record] the mentioned lines were originally added by: http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=31fe84e467732463eabc8f70c2a419008e7a227c
Created attachment 288619 [details] [review] core: add nm_utils_ip6_route_metric_normalize() function Kernel treats IPv6 route metrics with value zero (0) special. Add a utility function that helps accounting for that. Signed-off-by: Thomas Haller <thaller@redhat.com>
Created attachment 288620 [details] [review] core: add nm_ipX_config_get_direct_route_for_host() functions add two functions nm_ip4_config_get_direct_route_for_host() and nm_ip6_config_get_direct_route_for_host() to check if we have a direct (non-gw) route to a certain host. Signed-off-by: Thomas Haller <thaller@redhat.com>
Created attachment 288621 [details] [review] dhcp: don't add special route to DHCP server when having direct route When the DHCP server address is not on the same subnet, we used to add a /32 route to the server IP address via the gateway. Do not add this route, if we already got a direct route from DHCP. https://bugzilla.gnome.org/show_bug.cgi?id=738590 Signed-off-by: Thomas Haller <thaller@redhat.com>
How about the above 3 patches? (I pushed the same 3 patches also to: th/bgo738590_dhcp_server_route) (the first two patches were cherry-picked from bug 735512 where they are useful too -- hence they add more then actually needed for this fix).
That fixes it, thanks!
> core: add nm_ipX_config_get_direct_route_for_host() functions > * Note: this function is self assignment save, to update @src inplace, set both > * @dst and @src to the same destination. > */ >-void >+const struct in6_addr * > nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_addr *src, guint8 plen) fix the typo ("save" -> "safe") in the comment above while you're there > dhcp: don't add special route to DHCP server when having direct route >- if ((tmp_addr & mask) != (address.address & mask)) { >+ if ( (tmp_addr & mask) != (address.address & mask) >+ && !nm_ip4_config_get_direct_route_for_host (ip4_config, tmp_addr)) { > /* DHCP server not on assigned subnet, route needed */ Comment is no longer entirely accurate. Maybe just "We need to add a route to the DHCP server". Also, you could rewrite that check using nm_utils_ip4_address_clear_host_address()...
> core: add nm_ipX_config_get_direct_route_for_host() functions + if (memcmp (&network2, &host2, sizeof (network2)) != 0) + continue; IN6_ARE_ADDR_EQUAL() perhaps would be clearer? Rest looks good after danw's comments are fixed.
merged. master: http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=119c0625af2f0ac8e7a4437f8b38ffca584fad17 nm-0-9-10: http://cgit.freedesktop.org/NetworkManager/NetworkManager/commit/?id=76dd38ecc985f2c16cf837c3f6ed66bb42303efd