mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-28 11:00:09 +01:00
core: merge branch 'th/local-route-sync'
https://bugzilla.redhat.com/show_bug.cgi?id=1907661 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/790
This commit is contained in:
commit
fbabfa5e36
5 changed files with 138 additions and 74 deletions
|
|
@ -13478,12 +13478,13 @@ nm_device_set_ip_config(NMDevice * self,
|
|||
gboolean commit,
|
||||
GPtrArray * ip4_dev_route_blacklist)
|
||||
{
|
||||
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
NMIPConfig * old_config;
|
||||
gboolean has_changes = FALSE;
|
||||
gboolean success = TRUE;
|
||||
NMSettingsConnection *settings_connection;
|
||||
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||
NMIPConfig * old_config;
|
||||
gboolean has_changes = FALSE;
|
||||
gboolean success = TRUE;
|
||||
NMSettingsConnection * settings_connection;
|
||||
NMIPRouteTableSyncMode route_table_sync_mode;
|
||||
|
||||
nm_assert_addr_family(addr_family);
|
||||
nm_assert(!new_config || nm_ip_config_get_addr_family(new_config) == addr_family);
|
||||
|
|
@ -13495,11 +13496,18 @@ nm_device_set_ip_config(NMDevice * self,
|
|||
})));
|
||||
nm_assert(IS_IPv4 || !ip4_dev_route_blacklist);
|
||||
|
||||
if (commit && new_config)
|
||||
route_table_sync_mode = _get_route_table_sync_mode_stateful(self, addr_family);
|
||||
else
|
||||
route_table_sync_mode = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE;
|
||||
|
||||
_LOGD(LOGD_IPX(IS_IPv4),
|
||||
"ip%c-config: update (commit=%d, new-config=%p)",
|
||||
"ip%c-config: update (commit=%d, new-config=" NM_HASH_OBFUSCATE_PTR_FMT
|
||||
", route-table-sync-mode=%d)",
|
||||
nm_utils_addr_family_to_char(addr_family),
|
||||
commit,
|
||||
new_config);
|
||||
NM_HASH_OBFUSCATE_PTR(new_config),
|
||||
(int) route_table_sync_mode);
|
||||
|
||||
/* Always commit to nm-platform to update lifetimes */
|
||||
if (commit && new_config) {
|
||||
|
|
@ -13508,7 +13516,7 @@ nm_device_set_ip_config(NMDevice * self,
|
|||
if (IS_IPv4) {
|
||||
success = nm_ip4_config_commit(NM_IP4_CONFIG(new_config),
|
||||
nm_device_get_platform(self),
|
||||
_get_route_table_sync_mode_stateful(self, AF_INET));
|
||||
route_table_sync_mode);
|
||||
nm_platform_ip4_dev_route_blacklist_set(nm_device_get_platform(self),
|
||||
nm_ip_config_get_ifindex(new_config),
|
||||
ip4_dev_route_blacklist);
|
||||
|
|
@ -13517,7 +13525,7 @@ nm_device_set_ip_config(NMDevice * self,
|
|||
|
||||
success = nm_ip6_config_commit(NM_IP6_CONFIG(new_config),
|
||||
nm_device_get_platform(self),
|
||||
_get_route_table_sync_mode_stateful(self, AF_INET6),
|
||||
route_table_sync_mode,
|
||||
&temporary_not_available);
|
||||
|
||||
if (!_rt6_temporary_not_available_set(self, temporary_not_available))
|
||||
|
|
|
|||
|
|
@ -649,21 +649,6 @@ nm_ip4_config_add_dependent_routes(NMIP4Config *self,
|
|||
if (my_addr->external)
|
||||
continue;
|
||||
|
||||
/* Pre-generate local route added by kernel */
|
||||
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 = my_addr->address;
|
||||
route->plen = 32;
|
||||
route->pref_src = my_addr->address;
|
||||
route->type_coerced = nm_platform_route_type_coerce(RTN_LOCAL);
|
||||
route->scope_inv = nm_platform_route_scope_inv(RT_SCOPE_HOST);
|
||||
route->table_coerced =
|
||||
nm_platform_route_table_coerce(is_vrf ? route_table : RT_TABLE_LOCAL);
|
||||
_add_route(self, r, NULL, NULL);
|
||||
nm_clear_pointer(&r, nmp_object_unref);
|
||||
|
||||
if (nm_utils_ip4_address_is_zeronet(network)) {
|
||||
/* Kernel doesn't add device-routes for destinations that
|
||||
* start with 0.x.y.z. Skip them. */
|
||||
|
|
|
|||
|
|
@ -396,23 +396,6 @@ nm_ip6_config_add_dependent_routes(NMIP6Config *self,
|
|||
*
|
||||
* For manually added IPv6 routes, add the device routes explicitly. */
|
||||
|
||||
/* Pre-generate multicast route */
|
||||
{
|
||||
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.s6_addr[0] = 0xffu;
|
||||
route->plen = 8;
|
||||
route->table_coerced = nm_platform_route_table_coerce(RT_TABLE_LOCAL);
|
||||
route->type_coerced = nm_platform_route_type_coerce(RTN_UNICAST);
|
||||
route->metric = 256;
|
||||
|
||||
_add_route(self, r, NULL, NULL);
|
||||
}
|
||||
|
||||
nm_ip_config_iter_ip6_address_for_each (&iter, self, &my_addr) {
|
||||
NMPlatformIP6Route *route;
|
||||
gboolean has_peer;
|
||||
|
|
@ -421,22 +404,6 @@ nm_ip6_config_add_dependent_routes(NMIP6Config *self,
|
|||
if (my_addr->external)
|
||||
continue;
|
||||
|
||||
{
|
||||
nm_auto_nmpobj NMPObject *r = NULL;
|
||||
|
||||
/* Pre-generate local route added by kernel */
|
||||
r = nmp_object_new(NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
|
||||
route = NMP_OBJECT_CAST_IP6_ROUTE(r);
|
||||
route->ifindex = ifindex;
|
||||
route->network = my_addr->address;
|
||||
route->plen = 128;
|
||||
route->type_coerced = nm_platform_route_type_coerce(RTN_LOCAL);
|
||||
route->metric = 0;
|
||||
route->table_coerced =
|
||||
nm_platform_route_table_coerce(is_vrf ? route_table : RT_TABLE_LOCAL);
|
||||
_add_route(self, r, NULL, NULL);
|
||||
}
|
||||
|
||||
if (NM_FLAGS_HAS(my_addr->n_ifa_flags, IFA_F_NOPREFIXROUTE))
|
||||
continue;
|
||||
if (my_addr->plen == 0)
|
||||
|
|
|
|||
|
|
@ -4312,34 +4312,134 @@ nm_platform_ip_route_get_prune_list(NMPlatform * self,
|
|||
GPtrArray * routes_prune;
|
||||
const NMDedupMultiHeadEntry *head_entry;
|
||||
CList * iter;
|
||||
NMPlatformIP4Route rt_local4;
|
||||
NMPlatformIP6Route rt_local6;
|
||||
const NMPlatformLink * pllink;
|
||||
const NMPlatformLnkVrf * lnk_vrf;
|
||||
guint32 local_table;
|
||||
|
||||
nm_assert(NM_IS_PLATFORM(self));
|
||||
nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
|
||||
nm_assert(NM_IN_SET(route_table_sync,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_FULL,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL));
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE));
|
||||
|
||||
nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family)), ifindex);
|
||||
head_entry = nm_platform_lookup(self, &lookup);
|
||||
if (!head_entry)
|
||||
return NULL;
|
||||
|
||||
lnk_vrf = nm_platform_link_get_lnk_vrf(self, ifindex, &pllink);
|
||||
if (!lnk_vrf && pllink && pllink->master > 0)
|
||||
lnk_vrf = nm_platform_link_get_lnk_vrf(self, pllink->master, NULL);
|
||||
local_table = lnk_vrf ? lnk_vrf->table : RT_TABLE_LOCAL;
|
||||
|
||||
rt_local4.plen = 0;
|
||||
rt_local6.plen = 0;
|
||||
|
||||
routes_prune = g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nm_dedup_multi_obj_unref);
|
||||
|
||||
c_list_for_each (iter, &head_entry->lst_entries_head) {
|
||||
const NMPObject *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj;
|
||||
const NMPObject * obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj;
|
||||
const NMPlatformIPXRoute *rt = NMP_OBJECT_CAST_IPX_ROUTE(obj);
|
||||
|
||||
if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_FULL) {
|
||||
if (nm_platform_ip_route_get_effective_table(NMP_OBJECT_CAST_IP_ROUTE(obj))
|
||||
== RT_TABLE_LOCAL)
|
||||
switch (route_table_sync) {
|
||||
case NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN:
|
||||
if (!nm_platform_route_table_is_main(nm_platform_ip_route_get_effective_table(&rt->rx)))
|
||||
continue;
|
||||
} else if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN) {
|
||||
if (!nm_platform_route_table_is_main(
|
||||
nm_platform_ip_route_get_effective_table(NMP_OBJECT_CAST_IP_ROUTE(obj))))
|
||||
break;
|
||||
case NM_IP_ROUTE_TABLE_SYNC_MODE_FULL:
|
||||
if (nm_platform_ip_route_get_effective_table(&rt->rx) == RT_TABLE_LOCAL)
|
||||
continue;
|
||||
} else
|
||||
nm_assert(route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_ALL);
|
||||
break;
|
||||
case NM_IP_ROUTE_TABLE_SYNC_MODE_ALL:
|
||||
|
||||
/* FIXME: we should better handle routes that are automatically added by kernel.
|
||||
*
|
||||
* For now, make a good guess which are those routes and exclude them from
|
||||
* pruning them. */
|
||||
|
||||
if (NM_IS_IPv4(addr_family)) {
|
||||
/* for each IPv4 address kernel adds a route like
|
||||
*
|
||||
* local $ADDR dev $IFACE table local proto kernel scope host src $PRIMARY_ADDR
|
||||
*
|
||||
* Check whether route could be of that kind. */
|
||||
if (nm_platform_ip_route_get_effective_table(&rt->rx) == local_table
|
||||
&& rt->rx.plen == 32 && rt->rx.rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL
|
||||
&& rt->rx.metric == 0
|
||||
&& rt->r4.scope_inv == nm_platform_route_scope_inv(RT_SCOPE_HOST)
|
||||
&& rt->r4.gateway == INADDR_ANY) {
|
||||
if (rt_local4.plen == 0) {
|
||||
rt_local4 = (NMPlatformIP4Route){
|
||||
.ifindex = ifindex,
|
||||
.type_coerced = nm_platform_route_type_coerce(RTN_LOCAL),
|
||||
.plen = 32,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_RTPROT_KERNEL,
|
||||
.metric = 0,
|
||||
.table_coerced = nm_platform_route_table_coerce(local_table),
|
||||
.scope_inv = nm_platform_route_scope_inv(RT_SCOPE_HOST),
|
||||
.gateway = INADDR_ANY,
|
||||
};
|
||||
}
|
||||
|
||||
/* the possible "network" depends on the addresses we have. We don't check that
|
||||
* carefully. If the other parameters match, we assume that this route is the one
|
||||
* generated by kernel. */
|
||||
rt_local4.network = rt->r4.network;
|
||||
rt_local4.pref_src = rt->r4.pref_src;
|
||||
|
||||
/* to be more confident about comparing the value, use our nm_platform_ip4_route_cmp()
|
||||
* implementation. That will also consider parameters that we leave unspecified here. */
|
||||
if (nm_platform_ip4_route_cmp(&rt->r4,
|
||||
&rt_local4,
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
|
||||
== 0)
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/* for each IPv6 address (that is no longer tentative) kernel adds a route like
|
||||
*
|
||||
* local $ADDR dev $IFACE table local proto kernel metric 0 pref medium
|
||||
*
|
||||
* Same as for the IPv4 case. */
|
||||
if (nm_platform_ip_route_get_effective_table(&rt->rx) == local_table
|
||||
&& rt->rx.plen == 128 && rt->rx.rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL
|
||||
&& rt->rx.metric == 0 && rt->r6.rt_pref == NM_ICMPV6_ROUTER_PREF_MEDIUM
|
||||
&& IN6_IS_ADDR_UNSPECIFIED(&rt->r6.gateway)) {
|
||||
if (rt_local6.plen == 0) {
|
||||
rt_local6 = (NMPlatformIP6Route){
|
||||
.ifindex = ifindex,
|
||||
.type_coerced = nm_platform_route_type_coerce(RTN_LOCAL),
|
||||
.plen = 128,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_RTPROT_KERNEL,
|
||||
.metric = 0,
|
||||
.table_coerced = nm_platform_route_table_coerce(local_table),
|
||||
.rt_pref = NM_ICMPV6_ROUTER_PREF_MEDIUM,
|
||||
.gateway = IN6ADDR_ANY_INIT,
|
||||
};
|
||||
}
|
||||
|
||||
rt_local6.network = rt->r6.network;
|
||||
|
||||
if (nm_platform_ip6_route_cmp(&rt->r6,
|
||||
&rt_local6,
|
||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
|
||||
== 0)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE:
|
||||
break;
|
||||
|
||||
default:
|
||||
nm_assert_not_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
g_ptr_array_add(routes_prune, (gpointer) nmp_object_ref(obj));
|
||||
}
|
||||
|
|
@ -4634,7 +4734,7 @@ nm_platform_ip_route_flush(NMPlatform *self, int addr_family, int ifindex)
|
|||
routes_prune = nm_platform_ip_route_get_prune_list(self,
|
||||
AF_INET,
|
||||
ifindex,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL);
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE);
|
||||
success &= nm_platform_ip_route_sync(self, AF_INET, ifindex, NULL, routes_prune, NULL);
|
||||
}
|
||||
if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) {
|
||||
|
|
@ -4643,7 +4743,7 @@ nm_platform_ip_route_flush(NMPlatform *self, int addr_family, int ifindex)
|
|||
routes_prune = nm_platform_ip_route_get_prune_list(self,
|
||||
AF_INET6,
|
||||
ifindex,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL);
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE);
|
||||
success &= nm_platform_ip_route_sync(self, AF_INET6, ifindex, NULL, routes_prune, NULL);
|
||||
}
|
||||
return success;
|
||||
|
|
|
|||
|
|
@ -168,12 +168,16 @@ nmp_object_type_to_flags(NMPObjectType obj_type)
|
|||
* local table (255).
|
||||
* @NM_IP_ROUTE_TABLE_SYNC_MODE_ALL: NM will sync all tables, including the
|
||||
* local table (255).
|
||||
* @NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE: NM will sync all tables (including
|
||||
* the local table). It will thereby remove all addresses, that is during
|
||||
* deactivation.
|
||||
*/
|
||||
typedef enum {
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_NONE = 0,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN = 1,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_FULL = 2,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL = 3,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_FULL,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL,
|
||||
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE,
|
||||
} NMIPRouteTableSyncMode;
|
||||
|
||||
#endif /* __NMP_FWD_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue