summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-08-21 23:17:12 +0200
committerThomas Haller <thaller@redhat.com>2017-08-24 10:55:51 +0200
commit10ac675299cb3d734ae9bb720919dff1d4f1abbf (patch)
treefc5188d452942369fc6fd5fa6182715ef2248cf5
parent538a0dd2dc6da24bf068ea36aa95455ecb787d30 (diff)
downloadNetworkManager-10ac675299cb3d734ae9bb720919dff1d4f1abbf.tar.gz
platform: add support for routing tables to platform cache
The upper layers still ignore all routes outside the main table. For now, just add support to NMPlatform.
-rw-r--r--src/devices/nm-device.c12
-rw-r--r--src/nm-default-route-manager.c4
-rw-r--r--src/nm-ip4-config.c2
-rw-r--r--src/nm-ip6-config.c2
-rw-r--r--src/platform/nm-linux-platform.c9
-rw-r--r--src/platform/nm-platform.c26
-rw-r--r--src/platform/nm-platform.h30
-rw-r--r--src/platform/tests/test-common.h4
8 files changed, 74 insertions, 15 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 79738891b9..b7ff53d406 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -2825,7 +2825,8 @@ _v4_has_shadowed_routes_detect (NMDevice *self)
nm_assert (r->ifindex == ifindex);
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r))
+ if ( NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
+ || r->table_coerced)
continue;
d = &data_arr[data_len++];
@@ -2845,7 +2846,8 @@ _v4_has_shadowed_routes_detect (NMDevice *self)
IP4RPFilterData d;
if ( r->ifindex == ifindex
- || NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r))
+ || NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r)
+ || r->table_coerced)
continue;
d.network = nm_utils_ip4_address_clear_host_address (r->network, r->plen);
@@ -5537,9 +5539,9 @@ _device_get_default_route_from_platform (NMDevice *self, int addr_family, NMPlat
guint32 m;
const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE (plobj);
- if (r->ifindex != ifindex)
- continue;
- if (r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
+ if ( r->ifindex != ifindex
+ || r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL
+ || r->table_coerced)
continue;
/* if there are several default routes, find the one with the best metric */
diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c
index 1f6342ccce..ea0eeeaa63 100644
--- a/src/nm-default-route-manager.c
+++ b/src/nm-default-route-manager.c
@@ -334,7 +334,7 @@ _platform_route_sync_flush (const VTableIP *vtable, NMDefaultRouteManager *self,
routes = nm_platform_lookup_route_default_clone (priv->platform,
vtable->vt->obj_type,
- nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
+ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
NULL);
if (!routes)
return FALSE;
@@ -515,7 +515,7 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c
routes = nm_platform_lookup_route_default_clone (priv->platform,
vtable->vt->obj_type,
- nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
+ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
NULL);
assumed_metrics = _get_assumed_interface_metrics (vtable, self, routes);
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 606bb342fc..cd3b9a8c14 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -820,7 +820,7 @@ nm_ip4_config_commit (const NMIP4Config *self,
AF_INET,
ifindex,
routes,
- nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
+ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
NULL))
success = FALSE;
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 9f9e345637..d95398f6bb 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -538,7 +538,7 @@ nm_ip6_config_commit (const NMIP6Config *self,
AF_INET6,
ifindex,
routes,
- nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
+ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
NULL))
success = FALSE;
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 03585ab0d6..4ca3d94580 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -2030,8 +2030,6 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
table = tb[RTA_TABLE]
? nla_get_u32 (tb[RTA_TABLE])
: (guint32) rtm->rtm_table;
- if (table != RT_TABLE_MAIN)
- goto errout;
/*****************************************************************/
@@ -2148,6 +2146,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
obj = nmp_object_new (is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
+ obj->ip_route.table_coerced = nm_platform_route_table_coerce (table);
obj->ip_route.ifindex = nh.ifindex;
if (_check_addr_or_errout (tb, RTA_DST, addr_len))
@@ -2592,12 +2591,13 @@ _nl_msg_new_route (int nlmsg_type,
const NMPClass *klass = NMP_OBJECT_GET_CLASS (obj);
gboolean is_v4 = klass->addr_family == AF_INET;
const guint32 lock = ip_route_get_lock_flag (NMP_OBJECT_CAST_IP_ROUTE (obj));
+ const guint32 table = nm_platform_route_table_coerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced);
struct rtmsg rtmsg = {
.rtm_family = klass->addr_family,
.rtm_tos = is_v4
? obj->ip4_route.tos
: 0,
- .rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
+ .rtm_table = table <= 0xFF ? table : RT_TABLE_UNSPEC,
.rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (obj->ip_route.rt_source),
.rtm_scope = is_v4
? nm_platform_route_scope_inv (obj->ip4_route.scope_inv)
@@ -2638,6 +2638,9 @@ _nl_msg_new_route (int nlmsg_type,
NLA_PUT_U32 (msg, RTA_PRIORITY, obj->ip_route.metric);
+ if (table > 0xFF)
+ NLA_PUT_U32 (msg, RTA_TABLE, table);
+
if (is_v4) {
if (NMP_OBJECT_CAST_IP4_ROUTE (obj)->pref_src)
NLA_PUT (msg, RTA_PREFSRC, addr_len, &obj->ip4_route.pref_src);
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 665c5576a0..ba2cf7a76b 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2899,6 +2899,16 @@ nm_platform_lookup (NMPlatform *self,
}
gboolean
+nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *obj,
+ gpointer user_data)
+{
+ nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE));
+ return !obj->ip_route.table_coerced
+ && obj->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
+}
+
+gboolean
nm_platform_lookup_predicate_routes_skip_rtprot_kernel (const NMPObject *obj,
gpointer user_data)
{
@@ -3547,7 +3557,7 @@ nm_platform_ip_address_flush (NMPlatform *self,
* @kernel_delete_predicate: (allow-none): if not %NULL, previously
* existing routes already configured will only be deleted if the
* predicate returns TRUE. This allows to preserve/ignore some
- * routes. For example by passing @nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
+ * routes. For example by passing @nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
* routes with "proto kernel" will be left untouched.
* @kernel_delete_userdata: user data for @kernel_delete_predicate.
*
@@ -4858,6 +4868,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN];
char s_pref_src[INET_ADDRSTRLEN];
char str_dev[TO_STRING_DEV_BUF_SIZE];
+ char str_table[30];
char str_scope[30], s_source[50];
char str_tos[32], str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32];
@@ -4871,6 +4882,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
g_snprintf (buf, len,
+ "%s" /* table */
"%s/%d"
" via %s"
"%s"
@@ -4887,6 +4899,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
"%s" /* initrwnd */
"%s" /* mtu */
"",
+ route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_coerce (route->table_coerced)) : "",
s_network,
route->plen,
s_gateway,
@@ -4925,6 +4938,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
{
char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN], s_pref_src[INET6_ADDRSTRLEN];
char s_src_all[INET6_ADDRSTRLEN + 40], s_src[INET6_ADDRSTRLEN];
+ char str_table[30];
char str_dev[TO_STRING_DEV_BUF_SIZE], s_source[50];
char str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32];
@@ -4942,6 +4956,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
_to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev));
g_snprintf (buf, len,
+ "%s" /* table */
"%s/%d"
" via %s"
"%s"
@@ -4957,6 +4972,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
"%s" /* initrwnd */
"%s" /* mtu */
"",
+ route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_coerce (route->table_coerced)) : "",
s_network,
route->plen,
s_gateway,
@@ -5403,6 +5419,7 @@ nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpT
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
+ h = NM_HASH_COMBINE (h, obj->table_coerced);
h = NM_HASH_COMBINE (h, nm_utils_ip4_address_clear_host_address (obj->network, obj->plen));
h = NM_HASH_COMBINE (h, obj->plen);
h = NM_HASH_COMBINE (h, obj->metric);
@@ -5428,6 +5445,7 @@ nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj, NMPlatformIPRouteCmpT
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
+ h = NM_HASH_COMBINE (h, obj->table_coerced);
h = NM_HASH_COMBINE (h, obj->ifindex);
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
h = NM_HASH_COMBINE (h, nm_utils_ip4_address_clear_host_address (obj->network, obj->plen));
@@ -5474,6 +5492,7 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
+ NM_CMP_FIELD (a, b, table_coerced);
NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX (a->network, b->network, MIN (a->plen, b->plen));
NM_CMP_FIELD (a, b, plen);
NM_CMP_FIELD (a, b, metric);
@@ -5501,6 +5520,7 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
+ NM_CMP_FIELD (a, b, table_coerced);
NM_CMP_FIELD (a, b, ifindex);
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX (a->network, b->network, MIN (a->plen, b->plen));
@@ -5550,6 +5570,7 @@ nm_platform_ip6_route_hash (const NMPlatformIP6Route *obj, NMPlatformIPRouteCmpT
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
+ h = NM_HASH_COMBINE (h, obj->table_coerced);
h = NM_HASH_COMBINE_IN6ADDR_PREFIX (h, &obj->network, obj->plen);
h = NM_HASH_COMBINE (h, obj->plen);
h = NM_HASH_COMBINE (h, nm_utils_ip6_route_metric_normalize (obj->metric));
@@ -5562,6 +5583,7 @@ nm_platform_ip6_route_hash (const NMPlatformIP6Route *obj, NMPlatformIPRouteCmpT
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
+ h = NM_HASH_COMBINE (h, obj->table_coerced);
h = NM_HASH_COMBINE (h, obj->ifindex);
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
h = NM_HASH_COMBINE_IN6ADDR_PREFIX (h, &obj->network, obj->plen);
@@ -5612,6 +5634,7 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:
+ NM_CMP_FIELD (a, b, table_coerced);
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));
@@ -5624,6 +5647,7 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
break;
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL:
+ NM_CMP_FIELD (a, b, table_coerced);
NM_CMP_FIELD (a, b, ifindex);
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX (&a->network, &b->network, MIN (a->plen, b->plen));
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index d75b9143c0..e14c71512d 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -424,6 +424,13 @@ typedef union {
/* RTA_PRIORITY (iproute2: metric) */ \
guint32 metric; \
\
+ /* rtm_table, RTA_TABLE.
+ *
+ * This is not the original table ID. Instead, 254 (RT_TABLE_MAIN) and
+ * zero (RT_TABLE_UNSPEC) are swapped, so that the default is the main
+ * table. Use nm_platform_route_table_coerce(). */ \
+ guint32 table_coerced; \
+ \
/*end*/
@@ -853,6 +860,27 @@ NMPlatform *nm_platform_get (void);
/*****************************************************************************/
/**
+ * nm_platform_route_table_coerce:
+ * @table: the route table, either its original value, or its coerced.
+ *
+ * Returns: returns the coerced table id. If the table id is like
+ * RTA_TABLE, it returns a value for NMPlatformIPRoute.table_coerced
+ * and vice versa.
+ */
+static inline guint32
+nm_platform_route_table_coerce (guint32 table)
+{
+ switch (table) {
+ case 0 /* RT_TABLE_UNSPEC */:
+ return 254;
+ case 254 /* RT_TABLE_MAIN */:
+ return 0;
+ default:
+ return table;
+ }
+}
+
+/**
* nm_platform_route_scope_inv:
* @scope: the route scope, either its original value, or its inverse.
*
@@ -930,6 +958,8 @@ struct _NMPLookup;
const struct _NMDedupMultiHeadEntry *nm_platform_lookup (NMPlatform *platform,
const struct _NMPLookup *lookup);
+gboolean nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *obj,
+ gpointer user_data);
gboolean nm_platform_lookup_predicate_routes_skip_rtprot_kernel (const NMPObject *obj,
gpointer user_data);
diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h
index ad58e141a9..4010aa2f83 100644
--- a/src/platform/tests/test-common.h
+++ b/src/platform/tests/test-common.h
@@ -230,7 +230,7 @@ nmtstp_ip4_route_get_all (NMPlatform *platform,
return nm_platform_lookup_addrroute_clone (platform,
NMP_OBJECT_TYPE_IP4_ROUTE,
ifindex,
- nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
+ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
NULL);
}
@@ -241,7 +241,7 @@ nmtstp_ip6_route_get_all (NMPlatform *platform,
return nm_platform_lookup_addrroute_clone (platform,
NMP_OBJECT_TYPE_IP6_ROUTE,
ifindex,
- nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
+ nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
NULL);
}