summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dhcp/nm-dhcp-utils.c6
-rw-r--r--src/nm-core-utils.h12
-rw-r--r--src/nm-ip4-config.c31
-rw-r--r--src/nm-ip6-config.c22
-rw-r--r--src/nm-manager.c7
-rw-r--r--src/nm-policy.c6
-rw-r--r--src/platform/nm-platform.c24
-rw-r--r--src/platform/nm-platform.h6
-rw-r--r--src/platform/tests/test-route.c16
9 files changed, 66 insertions, 64 deletions
diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c
index d8e5a65328..1c305238fd 100644
--- a/src/dhcp/nm-dhcp-utils.c
+++ b/src/dhcp/nm-dhcp-utils.c
@@ -440,10 +440,10 @@ nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx,
if (gateway_has) {
const NMPlatformIP4Route r = {
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .gateway = gateway,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = gateway,
.table_coerced = nm_platform_route_table_coerce (route_table),
- .metric = route_metric,
+ .metric = route_metric,
};
nm_ip4_config_add_route (ip4_config, &r, NULL);
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
index 1b911894c9..cb6b06208e 100644
--- a/src/nm-core-utils.h
+++ b/src/nm-core-utils.h
@@ -156,8 +156,13 @@ double nm_utils_exp10 (gint16 e);
* nm_utils_ip6_route_metric_normalize:
* @metric: the route metric
*
- * For IPv6 route, kernel treats the value 0 as IP6_RT_PRIO_USER (1024).
- * Thus, when comparing metric (values), we want to treat zero as NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6.
+ * For IPv6 route, when adding a route via netlink, kernel treats the value 0 as IP6_RT_PRIO_USER (1024).
+ * So, user space cannot add routes with such a metric, and 0 gets "normalized"
+ * to NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6.
+ *
+ * Note that kernel itself can add IPv6 routes with metric zero. Also, you can delete
+ * them, but mostly because with `ip -6 route delete ... metric 0` the 0 acts as a wildcard
+ * and kills the first matching route.
*
* Returns: @metric, if @metric is not zero, otherwise 1024.
*/
@@ -174,9 +179,8 @@ nm_utils_ip_route_metric_normalize (int addr_family, guint32 metric)
}
static inline guint32
-nm_utils_ip_route_metric_penalize (int addr_family, guint32 metric, guint32 penalty)
+nm_utils_ip_route_metric_penalize (guint32 metric, guint32 penalty)
{
- metric = nm_utils_ip_route_metric_normalize (addr_family, metric);
if (metric < G_MAXUINT32 - penalty)
return metric + penalty;
return G_MAXUINT32;
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 62b41478f4..8f3ef1f583 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -393,10 +393,6 @@ nm_ip_config_iter_ip4_route_init (NMDedupMultiIter *ipconf_iter, const NMIP4Conf
const NMPObject *
_nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NMPObject *obj_cmp)
{
- int addr_family;
- int c;
- guint metric_cur, metric_cmp;
-
nm_assert ( !obj_cur
|| NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_cur), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
nm_assert ( !obj_cmp
@@ -410,17 +406,20 @@ _nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NM
* @obj_cmp is also a default route and returns the best of both. */
if ( obj_cmp
&& nm_ip_config_best_default_route_is (obj_cmp)) {
+ guint32 metric_cur, metric_cmp;
+
if (!obj_cur)
return obj_cmp;
- addr_family = NMP_OBJECT_GET_CLASS (obj_cmp)->addr_family;
- metric_cur = nm_utils_ip_route_metric_normalize (addr_family, NMP_OBJECT_CAST_IP_ROUTE (obj_cur)->metric);
- metric_cmp = nm_utils_ip_route_metric_normalize (addr_family, NMP_OBJECT_CAST_IP_ROUTE (obj_cmp)->metric);
+ metric_cur = NMP_OBJECT_CAST_IP_ROUTE (obj_cur)->metric;
+ metric_cmp = NMP_OBJECT_CAST_IP_ROUTE (obj_cmp)->metric;
if (metric_cmp < metric_cur)
return obj_cmp;
if (metric_cmp == metric_cur) {
+ int c;
+
/* Routes have the same metric. We still want to deterministically
* prefer one or the other. It's important to consistently choose one
* or the other, so that the order doesn't matter how routes are added
@@ -1002,6 +1001,7 @@ nm_ip4_config_merge_setting (NMIP4Config *self,
for (i = 0; i < nroutes; i++) {
NMIPRoute *s_route = nm_setting_ip_config_get_route (setting, i);
NMPlatformIP4Route route;
+ gint64 m;
if (nm_ip_route_get_family (s_route) != AF_INET) {
nm_assert_not_reached ();
@@ -1015,10 +1015,11 @@ nm_ip4_config_merge_setting (NMIP4Config *self,
nm_assert (route.plen <= 32);
nm_ip_route_get_next_hop_binary (s_route, &route.gateway);
- if (nm_ip_route_get_metric (s_route) == -1)
+ m = nm_ip_route_get_metric (s_route);
+ if (m < 0)
route.metric = route_metric;
else
- route.metric = nm_ip_route_get_metric (s_route);
+ route.metric = m;
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
route.network = nm_utils_ip4_address_clear_host_address (route.network, route.plen);
@@ -1141,8 +1142,10 @@ nm_ip4_config_create_setting (const NMIP4Config *self)
continue;
s_route = nm_ip_route_new_binary (AF_INET,
- &route->network, route->plen,
- &route->gateway, route->metric,
+ &route->network,
+ route->plen,
+ &route->gateway,
+ route->metric,
NULL);
nm_setting_ip_config_add_route (s_ip4, s_route);
nm_ip_route_unref (s_route);
@@ -1227,7 +1230,7 @@ nm_ip4_config_merge (NMIP4Config *dst,
if (default_route_metric_penalty) {
NMPlatformIP4Route r = *r_src;
- r.metric = nm_utils_ip_route_metric_penalize (AF_INET, r.metric, default_route_metric_penalty);
+ r.metric = nm_utils_ip_route_metric_penalize (r.metric, default_route_metric_penalty);
_add_route (dst, NULL, &r, NULL);
continue;
}
@@ -1459,7 +1462,7 @@ nm_ip4_config_subtract (NMIP4Config *dst,
* the routes. */
o_lookup = nmp_object_stackinit_obj (&o_lookup_copy, o_src);
rr = NMP_OBJECT_CAST_IP4_ROUTE (&o_lookup_copy);
- rr->metric = nm_utils_ip_route_metric_penalize (AF_INET, rr->metric, default_route_metric_penalty);
+ rr->metric = nm_utils_ip_route_metric_penalize (rr->metric, default_route_metric_penalty);
} else
o_lookup = o_src;
@@ -1610,7 +1613,7 @@ _nm_ip4_config_intersect_helper (NMIP4Config *dst,
* the routes. */
o_lookup = nmp_object_stackinit_obj (&o_lookup_copy, o_dst);
rr = NMP_OBJECT_CAST_IP4_ROUTE (&o_lookup_copy);
- rr->metric = nm_utils_ip_route_metric_penalize (AF_INET, rr->metric, default_route_metric_penalty);
+ rr->metric = nm_utils_ip_route_metric_penalize (rr->metric, default_route_metric_penalty);
} else
o_lookup = o_dst;
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index b60e8057cb..d772d6a255 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -650,6 +650,7 @@ nm_ip6_config_merge_setting (NMIP6Config *self,
for (i = 0; i < nroutes; i++) {
NMIPRoute *s_route = nm_setting_ip_config_get_route (setting, i);
NMPlatformIP6Route route;
+ gint64 m;
if (nm_ip_route_get_family (s_route) != AF_INET6) {
nm_assert_not_reached ();
@@ -663,10 +664,11 @@ nm_ip6_config_merge_setting (NMIP6Config *self,
nm_assert (route.plen <= 128);
nm_ip_route_get_next_hop_binary (s_route, &route.gateway);
- if (nm_ip_route_get_metric (s_route) == -1)
+ m = nm_ip_route_get_metric (s_route);
+ if (m < 0)
route.metric = route_metric;
else
- route.metric = nm_ip_route_get_metric (s_route);
+ route.metric = nm_utils_ip6_route_metric_normalize (m);
route.rt_source = NM_IP_CONFIG_SOURCE_USER;
nm_utils_ip6_address_clear_host_address (&route.network, &route.network, route.plen);
@@ -797,8 +799,10 @@ nm_ip6_config_create_setting (const NMIP6Config *self)
continue;
s_route = nm_ip_route_new_binary (AF_INET6,
- &route->network, route->plen,
- &route->gateway, route->metric,
+ &route->network,
+ route->plen,
+ &route->gateway,
+ route->metric,
NULL);
nm_setting_ip_config_add_route (s_ip6, s_route);
nm_ip_route_unref (s_route);
@@ -882,7 +886,7 @@ nm_ip6_config_merge (NMIP6Config *dst,
if (default_route_metric_penalty) {
NMPlatformIP6Route r = *r_src;
- r.metric = nm_utils_ip_route_metric_penalize (AF_INET6, r.metric, default_route_metric_penalty);
+ r.metric = nm_utils_ip_route_metric_penalize (r.metric, default_route_metric_penalty);
_add_route (dst, NULL, &r, NULL);
continue;
}
@@ -1052,7 +1056,7 @@ nm_ip6_config_subtract (NMIP6Config *dst,
* the routes. */
o_lookup = nmp_object_stackinit_obj (&o_lookup_copy, o_src);
rr = NMP_OBJECT_CAST_IP6_ROUTE (&o_lookup_copy);
- rr->metric = nm_utils_ip_route_metric_penalize (AF_INET6, rr->metric, default_route_metric_penalty);
+ rr->metric = nm_utils_ip_route_metric_penalize (rr->metric, default_route_metric_penalty);
} else
o_lookup = o_src;
@@ -1173,7 +1177,7 @@ _nm_ip6_config_intersect_helper (NMIP6Config *dst,
* the routes. */
o_lookup = nmp_object_stackinit_obj (&o_lookup_copy, o_dst);
rr = NMP_OBJECT_CAST_IP6_ROUTE (&o_lookup_copy);
- rr->metric = nm_utils_ip_route_metric_penalize (AF_INET6, rr->metric, default_route_metric_penalty);
+ rr->metric = nm_utils_ip_route_metric_penalize (rr->metric, default_route_metric_penalty);
} else
o_lookup = o_dst;
@@ -2052,8 +2056,8 @@ nm_ip6_config_get_direct_route_for_host (const NMIP6Config *self,
if (!nm_utils_ip6_address_same_prefix (host, &item->network, item->plen))
continue;
- if (best_route &&
- nm_utils_ip6_route_metric_normalize (best_route->metric) <= nm_utils_ip6_route_metric_normalize (item->metric))
+ if ( best_route
+ && best_route->metric <= item->metric)
continue;
best_route = item;
diff --git a/src/nm-manager.c b/src/nm-manager.c
index c69922648d..286c9ef35b 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -3044,10 +3044,9 @@ _get_best_connectivity (NMManager *self, int addr_family)
gint64 metric;
r = nm_device_get_best_default_route (dev, addr_family);
- if (r) {
- metric = nm_utils_ip_route_metric_normalize (addr_family,
- NMP_OBJECT_CAST_IP_ROUTE (r)->metric);
- } else {
+ if (r)
+ metric = NMP_OBJECT_CAST_IP_ROUTE (r)->metric;
+ else {
/* if all devices have no default-route, we still include the best
* of all connectivity state of all the devices. */
metric = G_MAXINT64;
diff --git a/src/nm-policy.c b/src/nm-policy.c
index 5912b8f257..148f5618ba 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -442,14 +442,12 @@ get_best_active_connection (NMPolicy *self,
*
* In this case, is it really the best device? Why do we even need the best
* device?? */
- metric = nm_utils_ip_route_metric_normalize (addr_family,
- NMP_OBJECT_CAST_IP_ROUTE (r)->metric);
+ metric = NMP_OBJECT_CAST_IP_ROUTE (r)->metric;
is_fully_activated = TRUE;
} else if ( !fully_activated
&& (connection = nm_device_get_applied_connection (device))
&& nm_utils_connection_has_default_route (connection, addr_family, NULL)) {
- metric = nm_utils_ip_route_metric_normalize (addr_family,
- nm_device_get_route_metric (device, addr_family));
+ metric = nm_device_get_route_metric (device, addr_family);
is_fully_activated = FALSE;
} else
continue;
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 26e1f1e282..880e7b5d27 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -4571,7 +4571,6 @@ nm_platform_ip_route_normalize (int addr_family,
r6->table_coerced = nm_platform_route_table_coerce (nm_platform_route_table_uncoerce (r6->table_coerced, TRUE));
nm_utils_ip6_address_clear_host_address (&r6->network, &r6->network, r6->plen);
r6->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r6->rt_source),
- r6->metric = nm_utils_ip6_route_metric_normalize (r6->metric);
nm_utils_ip6_address_clear_host_address (&r6->src, &r6->src, r6->src_plen);
break;
default:
@@ -7463,7 +7462,7 @@ nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRo
nm_platform_route_table_uncoerce (obj->table_coerced, TRUE),
*nm_utils_ip6_address_clear_host_address (&a1, &obj->network, obj->plen),
obj->plen,
- nm_utils_ip6_route_metric_normalize (obj->metric),
+ obj->metric,
*nm_utils_ip6_address_clear_host_address (&a2, &obj->src, obj->src_plen),
obj->src_plen);
break;
@@ -7473,7 +7472,7 @@ nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRo
nm_platform_route_table_uncoerce (obj->table_coerced, TRUE),
*nm_utils_ip6_address_clear_host_address (&a1, &obj->network, obj->plen),
obj->plen,
- nm_utils_ip6_route_metric_normalize (obj->metric),
+ obj->metric,
*nm_utils_ip6_address_clear_host_address (&a2, &obj->src, obj->src_plen),
obj->src_plen,
/* on top of WEAK_ID: */
@@ -7487,7 +7486,7 @@ nm_platform_ip6_route_hash_update (const NMPlatformIP6Route *obj, NMPlatformIPRo
obj->ifindex,
*nm_utils_ip6_address_clear_host_address (&a1, &obj->network, obj->plen),
obj->plen,
- nm_utils_ip6_route_metric_normalize (obj->metric),
+ obj->metric,
obj->gateway,
obj->pref_src,
*nm_utils_ip6_address_clear_host_address (&a2, &obj->src, obj->src_plen),
@@ -7550,7 +7549,7 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
nm_platform_route_table_uncoerce (b->table_coerced, TRUE));
NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX (&a->network, &b->network, MIN (a->plen, b->plen));
NM_CMP_FIELD (a, b, plen);
- NM_CMP_DIRECT (nm_utils_ip6_route_metric_normalize (a->metric), nm_utils_ip6_route_metric_normalize (b->metric));
+ NM_CMP_FIELD (a, b, metric);
NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX (&a->src, &b->src, MIN (a->src_plen, b->src_plen));
NM_CMP_FIELD (a, b, src_plen);
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) {
@@ -7573,10 +7572,7 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
else
NM_CMP_FIELD_IN6ADDR (a, b, network);
NM_CMP_FIELD (a, b, plen);
- if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
- NM_CMP_DIRECT (nm_utils_ip6_route_metric_normalize (a->metric), nm_utils_ip6_route_metric_normalize (b->metric));
- else
- NM_CMP_FIELD (a, b, metric);
+ NM_CMP_FIELD (a, b, metric);
NM_CMP_FIELD_IN6ADDR (a, b, gateway);
NM_CMP_FIELD_IN6ADDR (a, b, pref_src);
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) {
@@ -8054,14 +8050,6 @@ nm_platform_netns_push (NMPlatform *self, NMPNetns **netns)
/*****************************************************************************/
-static guint32
-_vtr_v4_metric_normalize (guint32 metric)
-{
- return metric;
-}
-
-/*****************************************************************************/
-
const _NMPlatformVTableRouteUnion nm_platform_vtable_route = {
.v4 = {
.is_ip4 = TRUE,
@@ -8070,7 +8058,6 @@ const _NMPlatformVTableRouteUnion nm_platform_vtable_route = {
.sizeof_route = sizeof (NMPlatformIP4Route),
.route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip4_route_cmp,
.route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip4_route_to_string,
- .metric_normalize = _vtr_v4_metric_normalize,
},
.v6 = {
.is_ip4 = FALSE,
@@ -8079,7 +8066,6 @@ const _NMPlatformVTableRouteUnion nm_platform_vtable_route = {
.sizeof_route = sizeof (NMPlatformIP6Route),
.route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip6_route_cmp,
.route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip6_route_to_string,
- .metric_normalize = nm_utils_ip6_route_metric_normalize,
},
};
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 145401d19d..339ef5ba3b 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -382,7 +382,10 @@ typedef union {
#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 0
/* Default value for adding an IPv6 route. This is also what iproute2 does.
- * Adding an IPv6 route with metric 0, kernel translates to IP6_RT_PRIO_USER (1024). */
+ * Adding an IPv6 route with metric 0, kernel translates to IP6_RT_PRIO_USER (1024).
+ *
+ * Note that kernel doesn't allow adding IPv6 routes with metric zero via netlink.
+ * It however can itself add routes with metric zero. */
#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 1024
/* For IPv4, kernel adds a device route (subnet routes) with metric 0 when user
@@ -720,7 +723,6 @@ typedef struct {
gsize sizeof_route;
int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type);
const char *(*route_to_string) (const NMPlatformIPXRoute *route, char *buf, gsize len);
- guint32 (*metric_normalize) (guint32 metric);
} NMPlatformVTableRoute;
typedef union {
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index b37446e3bf..531c61dbdc 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -319,7 +319,7 @@ test_ip6_route (void)
guint8 plen = 64;
struct in6_addr gateway, pref_src;
/* Choose a high metric so that we hopefully don't conflict. */
- int metric = 22987;
+ const int metric = 22987;
int mss = 1000;
inet_pton (AF_INET6, "2001:db8:a:b:0:0:0:0", &network);
@@ -365,7 +365,7 @@ test_ip6_route (void)
rts[0].ifindex = ifindex;
rts[0].gateway = in6addr_any;
rts[0].pref_src = in6addr_any;
- rts[0].metric = nm_utils_ip6_route_metric_normalize (metric);
+ rts[0].metric = metric;
rts[0].mss = mss;
rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[1].network = network;
@@ -373,7 +373,7 @@ test_ip6_route (void)
rts[1].ifindex = ifindex;
rts[1].gateway = gateway;
rts[1].pref_src = pref_src;
- rts[1].metric = nm_utils_ip6_route_metric_normalize (metric);
+ rts[1].metric = metric;
rts[1].mss = mss;
rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[2].network = in6addr_any;
@@ -381,7 +381,7 @@ test_ip6_route (void)
rts[2].ifindex = ifindex;
rts[2].gateway = gateway;
rts[2].pref_src = in6addr_any;
- rts[2].metric = nm_utils_ip6_route_metric_normalize (metric);
+ rts[2].metric = metric;
rts[2].mss = mss;
g_assert_cmpint (routes->len, ==, 3);
nmtst_platform_ip6_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts, routes->len, TRUE);
@@ -586,7 +586,13 @@ test_ip6_route_get (void)
NMTST_WAIT_ASSERT (100, {
nmtstp_wait_for_signal (NM_PLATFORM_GET, 10);
- if (nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet6_from_string ("fd01:abcd::"), 64, 0, NULL, 0))
+ if (nmtstp_ip6_route_get (NM_PLATFORM_GET,
+ ifindex,
+ nmtst_inet6_from_string ("fd01:abcd::"),
+ 64,
+ NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6,
+ NULL,
+ 0))
break;
});