core: add dependent local routes configured by kernel

Pre-generate routes in the local table that are configured
by kernel when an ip-address is assigned to an interface.

This helps NM taking into account routes that are not to be deleted
when a connection is reapplied (or deactivated) on an interface instead of only
ignoring (when pruning) IPv6 routes having metric 0 and routes belonging
to the local table having 'kernel' as proto.

https://bugzilla.redhat.com/show_bug.cgi?id=1821787
This commit is contained in:
Antonio Cardace
2020-07-08 18:01:55 +02:00
parent a83622f7d0
commit 3e5fc04df3
3 changed files with 47 additions and 10 deletions

View File

@@ -671,6 +671,28 @@ nm_ip4_config_update_routes_metric (NMIP4Config *self, gint64 metric)
g_object_thaw_notify (G_OBJECT (self));
}
static void
_add_local_route_from_addr4 (NMIP4Config *self,
const NMPlatformIP4Address *addr,
int ifindex)
{
nm_auto_nmpobj NMPObject *r = NULL;
NMPlatformIP4Route *route;
r = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
route = NMP_OBJECT_CAST_IP4_ROUTE (r);
route->ifindex = ifindex;
route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
route->network = addr->address;
route->plen = 32;
route->pref_src = addr->address;
route->table_coerced = nm_platform_route_table_coerce (RT_TABLE_LOCAL);
route->type_coerced = nm_platform_route_type_coerce (RTN_LOCAL);
route->scope_inv = nm_platform_route_scope_inv (RT_SCOPE_HOST);
_add_route (self, r, NULL, NULL);
}
void
nm_ip4_config_add_dependent_routes (NMIP4Config *self,
guint32 route_table,
@@ -707,6 +729,8 @@ nm_ip4_config_add_dependent_routes (NMIP4Config *self,
if (my_addr->external)
continue;
_add_local_route_from_addr4 (self, my_addr, ifindex);
if (_ipv4_is_zeronet (network)) {
/* Kernel doesn't add device-routes for destinations that
* start with 0.x.y.z. Skip them. */

View File

@@ -474,6 +474,24 @@ _add_multicast_route6 (NMIP6Config *self, int ifindex)
_add_route (self, r, NULL, NULL);
}
static void
_add_local_route_from_addr6 (NMIP6Config *self, const NMPlatformIP6Address *addr, int ifindex)
{
nm_auto_nmpobj NMPObject *r = NULL;
NMPlatformIP6Route *route;
r = nmp_object_new (NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
route = NMP_OBJECT_CAST_IP6_ROUTE (r);
route->ifindex = ifindex;
route->network = addr->address;
route->plen = 128;
route->table_coerced = nm_platform_route_table_coerce (RT_TABLE_LOCAL);
route->type_coerced = nm_platform_route_type_coerce (RTN_LOCAL);
route->metric = 0;
_add_route (self, r, NULL, NULL);
}
void
nm_ip6_config_add_dependent_routes (NMIP6Config *self,
guint32 route_table,
@@ -504,6 +522,10 @@ nm_ip6_config_add_dependent_routes (NMIP6Config *self,
if (my_addr->external)
continue;
/* Pre-generate local route added by kernel */
_add_local_route_from_addr6 (self, my_addr, ifindex);
if (NM_FLAGS_HAS (my_addr->n_ifa_flags, IFA_F_NOPREFIXROUTE))
continue;
if (my_addr->plen == 0)

View File

@@ -4230,18 +4230,9 @@ nm_platform_ip_route_get_prune_list (NMPlatform *self,
} else if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN) {
if (!nm_platform_route_table_is_main (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced))
continue;
} else {
} else
nm_assert (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_ALL);
/* IPv6 routes having metric 0 and routes having rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL
* are entirely managed by kernel, let's not touch them */
if (addr_family == AF_INET6 && NMP_OBJECT_CAST_IP6_ROUTE (obj)->metric == 0)
continue;
if ( nm_platform_route_table_uncoerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced, TRUE) == RT_TABLE_LOCAL
&& NMP_OBJECT_CAST_IP_ROUTE (obj)->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
continue;
}
g_ptr_array_add (routes_prune, (gpointer) nmp_object_ref (obj));
}