After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 738590 - Invalid route added for DHCP server
Invalid route added for DHCP server
Status: RESOLVED FIXED
Product: NetworkManager
Classification: Platform
Component: general
git master
Other Linux
: Normal major
: ---
Assigned To: NetworkManager maintainer(s)
NetworkManager maintainer(s)
Depends on:
Blocks:
 
 
Reported: 2014-10-15 19:58 UTC by Brian Rak
Modified: 2014-10-31 17:52 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
core: add nm_utils_ip6_route_metric_normalize() function (2.12 KB, patch)
2014-10-15 21:25 UTC, Thomas Haller
none Details | Review
core: add nm_ipX_config_get_direct_route_for_host() functions (6.22 KB, patch)
2014-10-15 21:25 UTC, Thomas Haller
none Details | Review
dhcp: don't add special route to DHCP server when having direct route (1.33 KB, patch)
2014-10-15 21:25 UTC, Thomas Haller
none Details | Review

Description Brian Rak 2014-10-15 19:58:33 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
Comment 1 Thomas Haller 2014-10-15 21:20:39 UTC
(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
Comment 2 Thomas Haller 2014-10-15 21:25:35 UTC
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>
Comment 3 Thomas Haller 2014-10-15 21:25:42 UTC
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>
Comment 4 Thomas Haller 2014-10-15 21:25:48 UTC
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>
Comment 5 Thomas Haller 2014-10-15 21:28:10 UTC
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).
Comment 6 Brian Rak 2014-10-20 23:50:49 UTC
That fixes it, thanks!
Comment 7 Dan Winship 2014-10-23 13:30:31 UTC
> 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()...
Comment 8 Dan Williams 2014-10-31 14:14:43 UTC
> 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.