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.
This commit is contained in:
Thomas Haller
2017-08-21 23:17:12 +02:00
parent 538a0dd2dc
commit 10ac675299
8 changed files with 74 additions and 15 deletions

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -2898,6 +2898,16 @@ nm_platform_lookup (NMPlatform *self,
lookup);
}
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));

View File

@@ -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*/
@@ -852,6 +859,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);

View File

@@ -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);
}