core/platform: preserve external and static route metrics

Two issues:

1) routes added by external programs or by users with /sbin/ip should not
be modified, but NetworkManager was always changing those routes' metrics
to match the device priority.  This caused the nm_platform_ipX_route_sync()
functions to remove the original, external route (due to mismatched metric)
and re-add the route with the NetworkManager specified metric.  Fix that
by not touching routes which came from the kernel.

2) Static routes (from persistent connections) that specified a metric were
getting their metric overwritten with the NetworkManager device priority.
Stop doing that.

Since the platform no longer defaults the metric to 1024, callers of
nm_platform_ip4_route_add() (like NMPolicy's default route handling)
must do that themselves, if they desire this behavior.
This commit is contained in:
Dan Williams 2014-01-06 15:15:55 -06:00
parent 067db6f8d7
commit 4c16f3c7e2
5 changed files with 24 additions and 20 deletions

View file

@ -265,7 +265,6 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, int priority)
for (i = 0; i < count; i++) {
memcpy (&route, nm_ip4_config_get_route (config, i), sizeof (route));
route.metric = priority;
/* Don't add the route if it's more specific than one of the subnets
* the device already has an IP address on.
@ -279,6 +278,11 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, int priority)
if (nm_ip4_config_get_never_default (config) && route.network == 0)
continue;
/* Use the default metric only if the route was created by NM and
* didn't already specify a metric.
*/
if (route.source != NM_PLATFORM_SOURCE_KERNEL && !route.metric)
route.metric = priority ? priority : NM_PLATFORM_ROUTE_METRIC_DEFAULT;
g_array_append_val (routes, route);
}

View file

@ -266,7 +266,6 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex, int priority)
for (i = 0; i < count; i++) {
memcpy (&route, nm_ip6_config_get_route (config, i), sizeof (route));
route.metric = priority;
/* Don't add the route if it's more specific than one of the subnets
* the device already has an IP address on.
@ -280,6 +279,11 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex, int priority)
if (nm_ip6_config_get_never_default (config) && IN6_IS_ADDR_UNSPECIFIED (&route.network))
continue;
/* Use the default metric only if the route was created by NM and
* didn't already specify a metric.
*/
if (route.source != NM_PLATFORM_SOURCE_KERNEL && !route.metric)
route.metric = priority ? priority : NM_PLATFORM_ROUTE_METRIC_DEFAULT;
g_array_append_val (routes, route);
}

View file

@ -659,9 +659,9 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update)
if (ip_ifindex <= 0)
ip_ifindex = parent_ifindex;
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, int_gw, 0, mss)) {
(void) nm_platform_ip4_route_add (parent_ifindex, gw_addr, 32, 0, 0, parent_mss);
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, int_gw, 0, mss))
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, int_gw, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip4_route_add (parent_ifindex, gw_addr, 32, 0, NM_PLATFORM_ROUTE_METRIC_DEFAULT, parent_mss);
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, int_gw, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss))
nm_log_err (LOGD_IP4 | LOGD_VPN, "Failed to set default route.");
}
@ -670,9 +670,9 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update)
int mss = nm_ip4_config_get_mss (ip4_config);
g_assert (ip_iface);
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, gw_addr, 0, mss)) {
(void) nm_platform_ip4_route_add (ip_ifindex, gw_addr, 32, 0, 0, mss);
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, gw_addr, 0, mss)) {
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, gw_addr, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip4_route_add (ip_ifindex, gw_addr, 32, 0, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss);
if (!nm_platform_ip4_route_add (ip_ifindex, 0, 0, gw_addr, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
nm_log_err (LOGD_IP4, "Failed to set default route.");
}
}
@ -853,9 +853,9 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update)
if (ip_ifindex <= 0)
ip_ifindex = parent_ifindex;
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *int_gw, 0, mss)) {
(void) nm_platform_ip6_route_add (parent_ifindex, *gw_addr, 128, in6addr_any, 0, parent_mss);
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *int_gw, 0, mss)) {
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *int_gw, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip6_route_add (parent_ifindex, *gw_addr, 128, in6addr_any, NM_PLATFORM_ROUTE_METRIC_DEFAULT, parent_mss);
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *int_gw, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
nm_log_err (LOGD_IP6 | LOGD_VPN, "Failed to set default route.");
}
}
@ -864,9 +864,9 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update)
} else {
int mss = nm_ip6_config_get_mss (ip6_config);
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *gw_addr, 0, mss)) {
(void) nm_platform_ip6_route_add (ip_ifindex, *gw_addr, 128, in6addr_any, 0, mss);
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *gw_addr, 0, mss))
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *gw_addr, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss)) {
(void) nm_platform_ip6_route_add (ip_ifindex, *gw_addr, 128, in6addr_any, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss);
if (!nm_platform_ip6_route_add (ip_ifindex, in6addr_any, 0, *gw_addr, NM_PLATFORM_ROUTE_METRIC_DEFAULT, mss))
nm_log_err (LOGD_IP6, "Failed to set default route.");
}

View file

@ -1478,9 +1478,6 @@ nm_platform_ip4_route_add (int ifindex,
g_return_val_if_fail (mss >= 0, FALSE);
g_return_val_if_fail (klass->ip4_route_add, FALSE);
if (!metric)
metric = 1024;
return klass->ip4_route_add (platform, ifindex, network, plen, gateway, metric, mss);
}
@ -1494,9 +1491,6 @@ nm_platform_ip6_route_add (int ifindex,
g_return_val_if_fail (mss >= 0, FALSE);
g_return_val_if_fail (klass->ip6_route_add, FALSE);
if (!metric)
metric = 1024;
return klass->ip6_route_add (platform, ifindex, network, plen, gateway, metric, mss);
}

View file

@ -156,6 +156,8 @@ typedef struct {
guint flags; /* ifa_flags from <linux/if_addr.h>, field type "unsigned int" is as used in rtnl_addr_get_flags. */
} NMPlatformIP6Address;
#define NM_PLATFORM_ROUTE_METRIC_DEFAULT 1024
typedef struct {
int ifindex;
NMPlatformSource source;