mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-08 06:00:18 +01:00
core: fix handling IPv6 device-route and use correct route metric
Before commit6698bf58bb, we would rely on kernel to add the device-route for manual IPv6 routes. We broke that and now kernel would still add the device-route, however nm_platform_ip_route_sync() would delete it immediately after. That is because previously nm_platform_ip_route_sync() would ignore routes with rtm_protocol RTPRO_KERNEL. Now, it will sync and delete those too. Fix that by adding the device-route like we do it for IPv4. This also fixes an actual issue where the automatically added route always had route-metric 256. Instead, we now use the metric from ipv6.route-metric setting. Fixes:6698bf58bb
This commit is contained in:
parent
39d30a170d
commit
03e1cc96a5
7 changed files with 134 additions and 13 deletions
|
|
@ -6290,6 +6290,7 @@ ip6_config_merge_and_apply (NMDevice *self,
|
|||
NMConnection *connection;
|
||||
gboolean success;
|
||||
NMIP6Config *composite;
|
||||
const guint32 default_route_metric = nm_device_get_ip6_route_metric (self);
|
||||
const struct in6_addr *gateway;
|
||||
gboolean connection_has_default_route, connection_is_never_default;
|
||||
gboolean ignore_auto_routes = FALSE;
|
||||
|
|
@ -6423,8 +6424,7 @@ ip6_config_merge_and_apply (NMDevice *self,
|
|||
memset (&default_route, 0, sizeof (default_route));
|
||||
default_route.rt_source = NM_IP_CONFIG_SOURCE_USER;
|
||||
default_route.gateway = *gateway;
|
||||
default_route.metric = route_metric_with_penalty (self,
|
||||
nm_device_get_ip6_route_metric (self));
|
||||
default_route.metric = route_metric_with_penalty (self, default_route_metric);
|
||||
default_route.mss = nm_ip6_config_get_mss (composite);
|
||||
nm_clear_nmp_object (&priv->default_route6);
|
||||
nm_ip6_config_add_route (composite, &default_route, &priv->default_route6);
|
||||
|
|
@ -6447,6 +6447,11 @@ END_ADD_DEFAULT_ROUTE:
|
|||
nm_ip6_config_add_route (composite, NMP_OBJECT_CAST_IP6_ROUTE (priv->default_routegw6), NULL);
|
||||
}
|
||||
|
||||
if (commit) {
|
||||
nm_ip6_config_add_device_routes (composite,
|
||||
default_route_metric);
|
||||
}
|
||||
|
||||
/* Allow setting MTU etc */
|
||||
if (commit) {
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
|
|
|
|||
|
|
@ -226,6 +226,8 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||
}
|
||||
|
||||
nm_ip6_config_merge (existing, ndisc_config, NM_IP_CONFIG_MERGE_DEFAULT);
|
||||
nm_ip6_config_add_device_routes (existing,
|
||||
global_opt.priority_v6);
|
||||
if (!nm_ip6_config_commit (existing, NM_PLATFORM_GET, NULL))
|
||||
_LOGW (LOGD_IP6, "failed to apply IPv6 config");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,13 +245,23 @@ _nm_ip_config_lookup_ip_route (const NMDedupMultiIndex *multi_idx,
|
|||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)
|
||||
nm_assert (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj), NMP_OBJECT_CAST_IP4_ROUTE (needle), cmp_type) == 0);
|
||||
else {
|
||||
if (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj),
|
||||
NMP_OBJECT_CAST_IP4_ROUTE (needle),
|
||||
cmp_type) != 0)
|
||||
return NULL;
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) {
|
||||
nm_assert ( ( NMP_OBJECT_GET_TYPE (needle) == NMP_OBJECT_TYPE_IP4_ROUTE
|
||||
&& nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj), NMP_OBJECT_CAST_IP4_ROUTE (needle), cmp_type) == 0)
|
||||
|| ( NMP_OBJECT_GET_TYPE (needle) == NMP_OBJECT_TYPE_IP6_ROUTE
|
||||
&& nm_platform_ip6_route_cmp (NMP_OBJECT_CAST_IP6_ROUTE (entry->obj), NMP_OBJECT_CAST_IP6_ROUTE (needle), cmp_type) == 0));
|
||||
} else {
|
||||
if (NMP_OBJECT_GET_TYPE (needle) == NMP_OBJECT_TYPE_IP4_ROUTE) {
|
||||
if (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj),
|
||||
NMP_OBJECT_CAST_IP4_ROUTE (needle),
|
||||
cmp_type) != 0)
|
||||
return NULL;
|
||||
} else {
|
||||
if (nm_platform_ip6_route_cmp (NMP_OBJECT_CAST_IP6_ROUTE (entry->obj),
|
||||
NMP_OBJECT_CAST_IP6_ROUTE (needle),
|
||||
cmp_type) != 0)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
|
@ -740,9 +750,8 @@ nm_ip4_config_add_device_routes (NMIP4Config *self,
|
|||
ifindex = nm_ip4_config_get_ifindex (self);
|
||||
g_return_if_fail (ifindex > 0);
|
||||
|
||||
/* For IPv6, we explicitly add the device-routes (onlink) to NMIP6Config.
|
||||
* As we don't do that for IPv4, add it here shortly before syncing
|
||||
* the routes. */
|
||||
/* For IPv6 slaac, we explicitly add the device-routes (onlink) to NMIP6Config.
|
||||
* As we don't do that for IPv4 (and manual IPv6 addresses), add them explicitly. */
|
||||
|
||||
nm_ip_config_iter_ip4_address_for_each (&iter, self, &addr) {
|
||||
nm_auto_nmpobj NMPObject *r = NULL;
|
||||
|
|
|
|||
|
|
@ -115,6 +115,9 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMIP6Config,
|
|||
|
||||
static void _add_address (NMIP6Config *self, const NMPObject *obj_new, const NMPlatformIP6Address *new);
|
||||
static void _add_route (NMIP6Config *self, const NMPObject *obj_new, const NMPlatformIP6Route *new, const NMPObject **out_obj_new);
|
||||
static const NMDedupMultiEntry *_lookup_route (const NMIP6Config *self,
|
||||
const NMPObject *needle,
|
||||
NMPlatformIPRouteCmpType cmp_type);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -527,6 +530,77 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
|
|||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
nm_ip6_config_add_device_routes (NMIP6Config *self,
|
||||
guint32 default_route_metric)
|
||||
{
|
||||
const NMIP6ConfigPrivate *priv;
|
||||
const NMPlatformIP6Address *addr;
|
||||
int ifindex;
|
||||
NMDedupMultiIter iter;
|
||||
|
||||
g_return_if_fail (NM_IS_IP6_CONFIG (self));
|
||||
|
||||
priv = NM_IP6_CONFIG_GET_PRIVATE (self);
|
||||
|
||||
ifindex = nm_ip6_config_get_ifindex (self);
|
||||
g_return_if_fail (ifindex > 0);
|
||||
|
||||
/* For IPv6 addresses received via SLAAC/autoconf, we explicitly add the
|
||||
* device-routes (onlink) to NMIP6Config.
|
||||
*
|
||||
* For manually added IPv6 routes, add the device routes explicitly. */
|
||||
|
||||
nm_ip_config_iter_ip6_address_for_each (&iter, self, &addr) {
|
||||
NMPObject *r;
|
||||
NMPlatformIP6Route *route;
|
||||
gboolean has_peer;
|
||||
int routes_n, routes_i;
|
||||
|
||||
if (NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_NOPREFIXROUTE))
|
||||
continue;
|
||||
|
||||
has_peer = !IN6_IS_ADDR_UNSPECIFIED (&addr->peer_address);
|
||||
|
||||
/* If we have an IPv6 peer, we add two /128 routes
|
||||
* (unless, both addresses are identical). */
|
||||
routes_n = ( has_peer
|
||||
&& !IN6_ARE_ADDR_EQUAL (&addr->address, &addr->peer_address))
|
||||
? 2 : 1;
|
||||
|
||||
for (routes_i = 0; routes_i < routes_n; routes_i++) {
|
||||
|
||||
r = nmp_object_new (NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
|
||||
route = NMP_OBJECT_CAST_IP6_ROUTE (r);
|
||||
|
||||
route->ifindex = ifindex;
|
||||
route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
|
||||
route->metric = default_route_metric;
|
||||
|
||||
if (has_peer) {
|
||||
if (routes_i == 0)
|
||||
route->network = addr->address;
|
||||
else
|
||||
route->network = addr->peer_address;
|
||||
route->plen = 128;
|
||||
} else {
|
||||
nm_utils_ip6_address_clear_host_address (&route->network, &addr->address, addr->plen);
|
||||
route->plen = addr->plen;
|
||||
}
|
||||
|
||||
nm_platform_ip_route_normalize (AF_INET6, (NMPlatformIPRoute *) route);
|
||||
|
||||
if (_lookup_route (self,
|
||||
r,
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
|
||||
/* we already track this route. Don't add it again. */
|
||||
nmp_object_unref (r);
|
||||
} else
|
||||
_add_route (self, r, NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_ip6_config_commit (const NMIP6Config *self,
|
||||
NMPlatform *platform,
|
||||
|
|
@ -1801,6 +1875,24 @@ nm_ip6_config_has_any_dad_pending (const NMIP6Config *self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const NMDedupMultiEntry *
|
||||
_lookup_route (const NMIP6Config *self,
|
||||
const NMPObject *needle,
|
||||
NMPlatformIPRouteCmpType cmp_type)
|
||||
{
|
||||
const NMIP6ConfigPrivate *priv;
|
||||
|
||||
nm_assert (NM_IS_IP6_CONFIG (self));
|
||||
nm_assert (NMP_OBJECT_GET_TYPE (needle) == NMP_OBJECT_TYPE_IP6_ROUTE);
|
||||
|
||||
priv = NM_IP6_CONFIG_GET_PRIVATE (self);
|
||||
|
||||
return _nm_ip_config_lookup_ip_route (priv->multi_idx,
|
||||
&priv->idx_ip6_routes_,
|
||||
needle,
|
||||
cmp_type);
|
||||
}
|
||||
|
||||
void
|
||||
nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
|
||||
const NMNDiscRoute *routes,
|
||||
|
|
|
|||
|
|
@ -107,6 +107,10 @@ struct _NMDedupMultiIndex *nm_ip6_config_get_multi_idx (const NMIP6Config *self)
|
|||
|
||||
NMIP6Config *nm_ip6_config_capture (struct _NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex,
|
||||
gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary);
|
||||
|
||||
void nm_ip6_config_add_device_routes (NMIP6Config *self,
|
||||
guint32 default_route_metric);
|
||||
|
||||
gboolean nm_ip6_config_commit (const NMIP6Config *self,
|
||||
NMPlatform *platform,
|
||||
GPtrArray **out_temporary_not_available);
|
||||
|
|
|
|||
|
|
@ -3479,6 +3479,7 @@ nm_platform_ip6_address_sync (NMPlatform *self,
|
|||
gint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
guint i;
|
||||
NMPLookup lookup;
|
||||
guint32 ifa_flags;
|
||||
|
||||
/* Delete unknown addresses */
|
||||
plat_addresses = nm_platform_lookup_clone (self,
|
||||
|
|
@ -3502,6 +3503,10 @@ nm_platform_ip6_address_sync (NMPlatform *self,
|
|||
if (!known_addresses)
|
||||
return TRUE;
|
||||
|
||||
ifa_flags = nm_platform_check_support_kernel_extended_ifa_flags (self)
|
||||
? IFA_F_NOPREFIXROUTE
|
||||
: 0;
|
||||
|
||||
/* Add missing addresses */
|
||||
for (i = 0; i < known_addresses->len; i++) {
|
||||
const NMPlatformIP6Address *known_address = NMP_OBJECT_CAST_IP6_ADDRESS (known_addresses->pdata[i]);
|
||||
|
|
@ -3518,7 +3523,8 @@ nm_platform_ip6_address_sync (NMPlatform *self,
|
|||
|
||||
if (!nm_platform_ip6_address_add (self, ifindex, known_address->address,
|
||||
known_address->plen, known_address->peer_address,
|
||||
lifetime, preferred, known_address->n_ifa_flags))
|
||||
lifetime, preferred,
|
||||
ifa_flags | known_address->n_ifa_flags))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1786,6 +1786,9 @@ next:
|
|||
nm_ip6_config_add_route (config, &r, NULL);
|
||||
}
|
||||
|
||||
nm_ip6_config_add_device_routes (config,
|
||||
nm_vpn_connection_get_ip6_route_metric (self));
|
||||
|
||||
if (priv->ip6_config) {
|
||||
nm_ip6_config_replace (priv->ip6_config, config, NULL);
|
||||
g_object_unref (config);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue