import NetworkManager-1.48.10-5.el9_5

c9 imports/c9/NetworkManager-1.48.10-5.el9_5
MSVSphere Packaging Team 1 week ago
parent b158ab6af1
commit 65e37c4e2f
Signed by: sys_gitsync
GPG Key ID: B2B0B9F29E528FE8

@ -0,0 +1,541 @@
From 9628d71b541635047807e3344b871f701bddf77e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
Date: Wed, 4 Dec 2024 14:24:38 +0100
Subject: [PATCH 1/4] libnmc: fix bug checking VersionInfo's capabilities
Remove the `+ 31u` that was making that it would search for bit 1 at
array's element 1, instead of element 0. Fixed comparison >len that
shoudl be >=len. Fix a few typos.
Fixes: bc6098d44106 ('libnm: add internal nmc_client_has_{version_info_v,version_info_capability,capability}() helper')
(cherry picked from commit 5a65170b49d38f5195da900f63710c847ce3364e)
---
src/libnm-client-aux-extern/nm-libnm-aux.c | 11 ++++-------
src/libnm-client-impl/nm-client.c | 4 ++--
2 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/src/libnm-client-aux-extern/nm-libnm-aux.c b/src/libnm-client-aux-extern/nm-libnm-aux.c
index 5855bc299b..77f4a19559 100644
--- a/src/libnm-client-aux-extern/nm-libnm-aux.c
+++ b/src/libnm-client-aux-extern/nm-libnm-aux.c
@@ -169,14 +169,11 @@ nmc_client_has_version_info_capability(NMClient *nmc, NMVersionInfoCapability ca
len--;
ver++;
- idx = (gsize) capability;
- if (idx >= G_MAXSIZE - 31u)
- return FALSE;
-
- idx_hi = ((idx + 31u) / 32u);
- idx_lo = (idx % 32u);
+ idx = (gsize) capability;
+ idx_hi = idx / 32u;
+ idx_lo = idx % 32u;
- if (idx_hi > len)
+ if (idx_hi >= len)
return FALSE;
return NM_FLAGS_ANY(ver[idx_hi], (1ull << idx_lo));
diff --git a/src/libnm-client-impl/nm-client.c b/src/libnm-client-impl/nm-client.c
index 4ecc83899c..677f9aacab 100644
--- a/src/libnm-client-impl/nm-client.c
+++ b/src/libnm-client-impl/nm-client.c
@@ -6315,7 +6315,7 @@ nm_client_get_capabilities(NMClient *client, gsize *length)
*
* If available, the first element in the array is NM_VERSION which
* encodes the daemon version as "(major << 16 | minor << 8 | micro)".
- * The following elements are a bitfield of %NMVersionInfoCapabilities
+ * The following elements are a bitfield of %NMVersionInfoCapability
* that indicate that the daemon supports a certain capability.
*
* Returns: (transfer none) (array length=length): the
@@ -8312,7 +8312,7 @@ nm_client_class_init(NMClientClass *client_class)
* Expose version info and capabilities of NetworkManager. If non-empty,
* the first element is NM_VERSION, which encodes the version of the
* daemon as "(major << 16 | minor << 8 | micro)". The following elements
- * is a bitfields of %NMVersionInfoCapabilities. If a bit is set, then
+ * is a bitfields of %NMVersionInfoCapability. If a bit is set, then
* the running NetworkManager has the respective capability.
*
* Since: 1.42
--
2.47.1
From 2498b7aa0b0e654d97c6ded907c20341b866af21 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
Date: Wed, 27 Nov 2024 08:48:50 +0100
Subject: [PATCH 2/4] platform: rename NM_IP_ROUTE_TABLE_SYNC_MODE_FULL ->
ALL_EXCEPT_LOCAL
The difference between FULL and ALL was not obvious without reading the
documentation. Moreover, a new mode is going to be introduced so the
confusion could grow. Rename to a more explicit name.
(cherry picked from commit e1840ad5fbe4684cb8fce4a638617729969255e5)
---
src/libnm-platform/nm-platform.c | 4 ++--
src/libnm-platform/nmp-base.h | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index af04f29fad..ac2ecb421c 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -4890,7 +4890,7 @@ nm_platform_ip_route_get_prune_list(NMPlatform *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_EXCEPT_LOCAL,
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL,
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE));
@@ -4915,7 +4915,7 @@ nm_platform_ip_route_get_prune_list(NMPlatform *self,
if (!nm_platform_route_table_is_main(nm_platform_ip_route_get_effective_table(&rt->rx)))
continue;
break;
- case NM_IP_ROUTE_TABLE_SYNC_MODE_FULL:
+ case NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_EXCEPT_LOCAL:
if (nm_platform_ip_route_get_effective_table(&rt->rx) == RT_TABLE_LOCAL)
continue;
break;
diff --git a/src/libnm-platform/nmp-base.h b/src/libnm-platform/nmp-base.h
index c7d487e23c..9e2e1063a1 100644
--- a/src/libnm-platform/nmp-base.h
+++ b/src/libnm-platform/nmp-base.h
@@ -211,8 +211,8 @@ nmp_object_type_to_flags(NMPObjectType obj_type)
* @NM_IP_ROUTE_TABLE_SYNC_MODE_NONE: indicate an invalid setting.
* @NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN: only the main table is synced. For all
* other tables, NM won't delete any extra routes.
- * @NM_IP_ROUTE_TABLE_SYNC_MODE_FULL: NM will sync all tables, except the
- * local table (255).
+ * @NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_EXCEPT_LOCAL: NM will sync all tables, except
+ * the 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
@@ -222,7 +222,7 @@ nmp_object_type_to_flags(NMPObjectType obj_type)
typedef enum {
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_EXCEPT_LOCAL,
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL,
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE,
} NMIPRouteTableSyncMode;
--
2.47.1
From f970d505e9f5cfdc6b699105e404cd06c51439ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
Date: Wed, 27 Nov 2024 13:53:02 +0100
Subject: [PATCH 3/4] l3cfg: remove routes added by NM on reapply
By default, on reapply we were only syncing the main routes table. This
causes that routes added by NM to other tables are not removed on
reapply. This was done to preserve routes added externally, but routes
added by NM itself should be removed.
Add a new route table syncing mode "main + NM routes". This mode
maintains the normal behaviour of syncing completely the main table,
and for other tables removes only routes that were added by us, leaving
the rest untouched. Use this mode by default, as this is what a user
would expect on reapply.
Note: this might not work if NM is restarted between the profile being
modified and the reapply, because NM forgets what routes were added by
itself because of the restart. This is a rare corner case, though.
Use the D-Bus property "VersionInfo" to expose a capability flag
indicating that this bug is fixed. It is the first capability that we
expose in this way. However, it is convenient to do it this way as it's
something that clients like nmstate needs to know, so they can decide
whether a conn down is needed or not. It is not enough to decide that by
version number because it might be fixed via a downstream patch in distros
like RHEL.
https://issues.redhat.com/browse/RHEL-67324
https://issues.redhat.com/browse/RHEL-66262
Fixes: e9c17fcc9b33 ('l3cfg: default to 'main' route table sync mode')
(cherry picked from commit e330eb9c4a721d158641701cb48cd8094246d258)
---
src/core/nm-l3cfg.c | 22 ++++++-
src/core/nm-manager.c | 29 +++++----
src/libnm-core-public/nm-dbus-interface.h | 13 ++--
src/libnm-platform/nm-platform.c | 78 ++++++++++++++++++++++-
src/libnm-platform/nm-platform.h | 5 +-
src/libnm-platform/nmp-base.h | 4 ++
6 files changed, 127 insertions(+), 24 deletions(-)
diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c
index 57baeac25d..9dd8275b1f 100644
--- a/src/core/nm-l3cfg.c
+++ b/src/core/nm-l3cfg.c
@@ -4997,7 +4997,7 @@ _l3_commit_one(NML3Cfg *self,
}
if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_NONE)
- route_table_sync = NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN;
+ route_table_sync = NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN_AND_NM_ROUTES;
if (any_dirty)
_obj_states_track_prune_dirty(self, TRUE);
@@ -5026,6 +5026,8 @@ _l3_commit_one(NML3Cfg *self,
}
if (c_list_is_empty(&self->priv.p->blocked_lst_head_x[IS_IPv4])) {
+ gs_unref_ptrarray GPtrArray *routes_old = NULL;
+
addresses_prune =
nm_platform_ip_address_get_prune_list(self->priv.platform,
addr_family,
@@ -5033,10 +5035,26 @@ _l3_commit_one(NML3Cfg *self,
nm_g_array_data(ipv6_temp_addrs_keep),
nm_g_array_len(ipv6_temp_addrs_keep));
+ if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN_AND_NM_ROUTES) {
+ NMDedupMultiIter iter;
+ const NMPObject *rt_obj;
+
+ routes_old = g_ptr_array_new();
+ nm_l3_config_data_iter_obj_for_each (&iter,
+ l3cd_old,
+ &rt_obj,
+ NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))
+ g_ptr_array_add(routes_old, (gpointer) rt_obj);
+
+ nm_platform_route_objs_sort(routes_old, NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY);
+ }
+
routes_prune = nm_platform_ip_route_get_prune_list(self->priv.platform,
addr_family,
self->priv.ifindex,
- route_table_sync);
+ route_table_sync,
+ routes_old);
+
_obj_state_zombie_lst_prune_all(self, addr_family);
}
} else {
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index 0a7e7b2e4a..a673279712 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -462,21 +462,24 @@ static GVariant *
_version_info_get(void)
{
const guint32 arr[] = {
+ /* The array contains as first element NM_VERSION, which can be
+ * used to numerically compare the version (see also NM_ENCODE_VERSION,
+ * nm_utils_version(), nm_encode_version() and nm_decode_version(). */
NM_VERSION,
- };
- /* The array contains as first element NM_VERSION, which can be
- * used to numerically compare the version (see also NM_ENCODE_VERSION,
- * nm_utils_version(), nm_encode_version() and nm_decode_version().
- *
- * The following elements of the array are a bitfield of capabilities.
- * These capabilities should only depend on compile-time abilities
- * (unlike NM_MANAGER_CAPABILITIES, NMCapability). The supported values
- * are from NMVersionInfoCapability enum. This way to expose capabilities
- * is more cumbersome but more efficient compared to NM_MANAGER_CAPABILITIES.
- * As such, it is cheap to add capabilities for something, where you would
- * avoid it as NM_MANAGER_CAPABILITIES due to the overhead.
- */
+ /* The following elements of the array are a bitfield of capabilities.
+ * These capabilities should only depend on compile-time abilities
+ * (unlike NM_MANAGER_CAPABILITIES, NMCapability). The supported values
+ * are from NMVersionInfoCapability enum. This way to expose capabilities
+ * is more cumbersome but more efficient compared to NM_MANAGER_CAPABILITIES.
+ * As such, it is cheap to add capabilities for something, where you would
+ * avoid it as NM_MANAGER_CAPABILITIES due to the overhead.
+ *
+ * Each of the array's elements has 32 bits. This means that capabilities
+ * with index 0-31 goes to element #1, with index 32-63 to element #2,
+ * with index 64-95 to element #3 and so on. */
+ 1 << NM_VERSION_INFO_CAPABILITY_SYNC_ROUTE_WITH_TABLE,
+ };
return nm_g_variant_new_au(arr, G_N_ELEMENTS(arr));
}
diff --git a/src/libnm-core-public/nm-dbus-interface.h b/src/libnm-core-public/nm-dbus-interface.h
index 5eedd7da3a..9c737dbea5 100644
--- a/src/libnm-core-public/nm-dbus-interface.h
+++ b/src/libnm-core-public/nm-dbus-interface.h
@@ -93,16 +93,19 @@
/**
* NMVersionInfoCapability:
- * %_NM_VERSION_INFO_CAPABILITY_UNUSED: a dummy capability. It has no meaning,
- * don't use it.
+ * @NM_VERSION_INFO_CAPABILITY_SYNC_ROUTE_WITH_TABLE: Contains the fix to a bug that
+ * caused that routes in table other than main were not removed on reapply nor
+ * on connection down.
+ * https://issues.redhat.com/browse/RHEL-66262
+ * https://issues.redhat.com/browse/RHEL-67324
*
- * Currently no enum values are defined. These capabilities are exposed
- * on D-Bus in the "VersionInfo" bit field.
+ * The numeric values represent the bit index of the capability. These capabilities
+ * can be queried in the "VersionInfo" D-Bus property.
*
* Since: 1.42
*/
typedef enum {
- _NM_VERSION_INFO_CAPABILITY_UNUSED = 0x7FFFFFFFu,
+ NM_VERSION_INFO_CAPABILITY_SYNC_ROUTE_WITH_TABLE = 0,
} NMVersionInfoCapability;
/**
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index ac2ecb421c..6523fb8a98 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -61,6 +61,8 @@ G_STATIC_ASSERT(sizeof(((NMPlatformLink *) NULL)->l_address.data) == _NM_UTILS_H
G_STATIC_ASSERT(sizeof(((NMPlatformLink *) NULL)->l_perm_address.data) == _NM_UTILS_HWADDR_LEN_MAX);
G_STATIC_ASSERT(sizeof(((NMPlatformLink *) NULL)->l_broadcast.data) == _NM_UTILS_HWADDR_LEN_MAX);
+static int _route_objs_cmp_values(gconstpointer a, gconstpointer b, gpointer user_data);
+
static const char *
_nmp_link_port_data_to_string(NMPortKind port_kind,
const NMPlatformLinkPortData *port_data,
@@ -4872,11 +4874,24 @@ nm_platform_ip_address_get_prune_list(NMPlatform *self,
return result;
}
+static gboolean
+_route_obj_find_bsearch(GPtrArray *sorted_routes_objs, const NMPObject *route_obj)
+{
+ gssize pos =
+ nm_ptrarray_find_bsearch((gconstpointer *) sorted_routes_objs->pdata,
+ sorted_routes_objs->len,
+ route_obj,
+ _route_objs_cmp_values,
+ GINT_TO_POINTER((int) NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY));
+ return pos >= 0;
+}
+
GPtrArray *
nm_platform_ip_route_get_prune_list(NMPlatform *self,
int addr_family,
int ifindex,
- NMIPRouteTableSyncMode route_table_sync)
+ NMIPRouteTableSyncMode route_table_sync,
+ GPtrArray *sorted_old_routes_objs)
{
NMPLookup lookup;
GPtrArray *routes_prune = NULL;
@@ -4891,9 +4906,20 @@ nm_platform_ip_route_get_prune_list(NMPlatform *self,
nm_assert(NM_IN_SET(route_table_sync,
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN,
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_EXCEPT_LOCAL,
+ NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN_AND_NM_ROUTES,
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL,
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE));
+ if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN_AND_NM_ROUTES) {
+ nm_assert(sorted_old_routes_objs);
+ nm_assert(nm_utils_ptrarray_is_sorted(
+ (gconstpointer *) sorted_old_routes_objs->pdata,
+ sorted_old_routes_objs->len,
+ FALSE,
+ _route_objs_cmp_values,
+ GINT_TO_POINTER((int) NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)));
+ }
+
nmp_lookup_init_object_by_ifindex(&lookup,
NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family)),
ifindex);
@@ -4915,6 +4941,11 @@ nm_platform_ip_route_get_prune_list(NMPlatform *self,
if (!nm_platform_route_table_is_main(nm_platform_ip_route_get_effective_table(&rt->rx)))
continue;
break;
+ case NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN_AND_NM_ROUTES:
+ if (!nm_platform_route_table_is_main(nm_platform_ip_route_get_effective_table(&rt->rx))
+ && !_route_obj_find_bsearch(sorted_old_routes_objs, obj))
+ continue;
+ break;
case NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_EXCEPT_LOCAL:
if (nm_platform_ip_route_get_effective_table(&rt->rx) == RT_TABLE_LOCAL)
continue;
@@ -5284,7 +5315,8 @@ 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_PRUNE);
+ NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE,
+ NULL);
success &= nm_platform_ip_route_sync(self, AF_INET, ifindex, NULL, routes_prune, NULL);
}
if (NM_IN_SET(addr_family, AF_UNSPEC, AF_INET6)) {
@@ -5293,7 +5325,8 @@ 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_PRUNE);
+ NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE,
+ NULL);
success &= nm_platform_ip_route_sync(self, AF_INET6, ifindex, NULL, routes_prune, NULL);
}
return success;
@@ -8767,6 +8800,45 @@ nm_platform_lnk_wireguard_cmp(const NMPlatformLnkWireGuard *a, const NMPlatformL
return 0;
}
+static int
+_route_objs_cmp_values(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ const NMPObject *a_obj = a;
+ const NMPObject *b_obj = b;
+ NMPlatformIPRouteCmpType cmp_type = GPOINTER_TO_INT(user_data);
+
+ nm_assert(a_obj && b_obj);
+ nm_assert(NMP_OBJECT_CAST_IP_ROUTE(a_obj) && NMP_OBJECT_CAST_IP_ROUTE(b_obj));
+
+ if (NMP_OBJECT_GET_ADDR_FAMILY(a_obj) != NMP_OBJECT_GET_ADDR_FAMILY(b_obj)) {
+ return NMP_OBJECT_GET_ADDR_FAMILY(a_obj) == AF_INET ? 1 : -1;
+ } else if (NMP_OBJECT_GET_ADDR_FAMILY(a_obj) == AF_INET) {
+ return nm_platform_ip4_route_cmp(NMP_OBJECT_CAST_IP4_ROUTE(a_obj),
+ NMP_OBJECT_CAST_IP4_ROUTE(b_obj),
+ cmp_type);
+ } else {
+ return nm_platform_ip6_route_cmp(NMP_OBJECT_CAST_IP6_ROUTE(a_obj),
+ NMP_OBJECT_CAST_IP6_ROUTE(b_obj),
+ cmp_type);
+ }
+}
+
+static int
+_route_objs_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ nm_assert(a && b);
+
+ return _route_objs_cmp_values(*((const NMPObject **) a), *((const NMPObject **) b), user_data);
+}
+
+void
+nm_platform_route_objs_sort(GPtrArray *routes_objs, NMPlatformIPRouteCmpType cmp_type)
+{
+ nm_assert(routes_objs);
+
+ g_ptr_array_sort_with_data(routes_objs, _route_objs_cmp, GINT_TO_POINTER((int) cmp_type));
+}
+
void
nm_platform_ip4_rt_nexthop_hash_update(const NMPlatformIP4RtNextHop *obj,
gboolean for_id,
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index e33be81356..22bf0fdbec 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -2389,7 +2389,8 @@ int nm_platform_ip6_route_add(NMPlatform *self, NMPNlmFlags flags, const NMPlatf
GPtrArray *nm_platform_ip_route_get_prune_list(NMPlatform *self,
int addr_family,
int ifindex,
- NMIPRouteTableSyncMode route_table_sync);
+ NMIPRouteTableSyncMode route_table_sync,
+ GPtrArray *old_routes_objs);
gboolean nm_platform_ip_route_sync(NMPlatform *self,
int addr_family,
@@ -2495,6 +2496,8 @@ int nm_platform_lnk_wireguard_cmp(const NMPlatformLnkWireGuard *a, const NMPlatf
GHashTable *nm_platform_ip4_address_addr_to_hash(NMPlatform *self, int ifindex);
+void nm_platform_route_objs_sort(GPtrArray *routes_objs, NMPlatformIPRouteCmpType cmp_type);
+
int nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a,
const NMPlatformIP4Route *b,
NMPlatformIPRouteCmpType cmp_type);
diff --git a/src/libnm-platform/nmp-base.h b/src/libnm-platform/nmp-base.h
index 9e2e1063a1..3784a78e9d 100644
--- a/src/libnm-platform/nmp-base.h
+++ b/src/libnm-platform/nmp-base.h
@@ -211,6 +211,9 @@ nmp_object_type_to_flags(NMPObjectType obj_type)
* @NM_IP_ROUTE_TABLE_SYNC_MODE_NONE: indicate an invalid setting.
* @NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN: only the main table is synced. For all
* other tables, NM won't delete any extra routes.
+ * @NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN_AND_NM_ROUTES: only the main table is synced,
+ * plus individual routes in other tables added by NM, leaving routes that
+ * were not added by NM untouched.
* @NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_EXCEPT_LOCAL: NM will sync all tables, except
* the local table (255).
* @NM_IP_ROUTE_TABLE_SYNC_MODE_ALL: NM will sync all tables, including the
@@ -222,6 +225,7 @@ nmp_object_type_to_flags(NMPObjectType obj_type)
typedef enum {
NM_IP_ROUTE_TABLE_SYNC_MODE_NONE,
NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN,
+ NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN_AND_NM_ROUTES,
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_EXCEPT_LOCAL,
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL,
NM_IP_ROUTE_TABLE_SYNC_MODE_ALL_PRUNE,
--
2.47.1
From 2ac691360f265d655b1e2e1caf9344ae0ec6a802 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
Date: Tue, 10 Dec 2024 10:15:52 +0100
Subject: [PATCH 4/4] l3cfg: get routes to prune from the list of routes
configured by NM
We always sync routes in the main table, but routes in tables other
than main are only pruned if were added by NM, by default. Get the list
of routes to prune from other tables using obj_state->os_nm_configured,
as this tracks what routes were effectively added by NM.
The list should be the same that the one obtained from l3cfg_old. It
could be different if we commited the l3cfg with an NMIPRouteTableSyncMode
of NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, thus not deleting some routes at
commit time. However, since the previous commit, we never do it.
What all this shows is that starting to use different NMIPRouteTableSyncModes
is probably a bad idea: it will be a source of bugs of routes not being
always synced as users expect, and the use case for them is still to be
known.
(cherry picked from commit c06d130c38a4d4238e18c06f0152f8f1a6bafa7f)
---
src/core/nm-l3cfg.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c
index 9dd8275b1f..f29cfa1baf 100644
--- a/src/core/nm-l3cfg.c
+++ b/src/core/nm-l3cfg.c
@@ -5036,15 +5036,17 @@ _l3_commit_one(NML3Cfg *self,
nm_g_array_len(ipv6_temp_addrs_keep));
if (route_table_sync == NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN_AND_NM_ROUTES) {
- NMDedupMultiIter iter;
- const NMPObject *rt_obj;
-
- routes_old = g_ptr_array_new();
- nm_l3_config_data_iter_obj_for_each (&iter,
- l3cd_old,
- &rt_obj,
- NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))
- g_ptr_array_add(routes_old, (gpointer) rt_obj);
+ GHashTableIter h_iter;
+ ObjStateData *obj_state;
+
+ /* Get list of all the routes that were configured by us */
+ routes_old = g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
+ g_hash_table_iter_init(&h_iter, self->priv.p->obj_state_hash);
+ while (g_hash_table_iter_next(&h_iter, (gpointer *) &obj_state, NULL)) {
+ if (NMP_OBJECT_GET_TYPE(obj_state->obj) == NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)
+ && obj_state->os_nm_configured)
+ g_ptr_array_add(routes_old, (gpointer) nmp_object_ref(obj_state->obj));
+ }
nm_platform_route_objs_sort(routes_old, NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY);
}
--
2.47.1

@ -0,0 +1,60 @@
From d9addb0ded2da8b86fa4b6e1cdc4b96f83729afd Mon Sep 17 00:00:00 2001
From: Gris Ge <fge@redhat.com>
Date: Wed, 11 Dec 2024 22:22:59 +0800
Subject: [PATCH 1/1] vpn: Place gateway route to table defined in
ipvx.route-table
Previously, NM create direct route to gateway to main(254) route table
regardless `ipvx.route-table` value.
Fixed by setting `NMPlatformIP4Route.table_any` to `TRUE`.
Resolves: https://issues.redhat.com/browse/RHEL-69901
Signed-off-by: Gris Ge <fge@redhat.com>
(cherry picked from commit 6d06286f1db7421bef1c4dab5fada918c59daf87)
(cherry picked from commit 29f23d3519dbb4dcffc9682fbdfb721cfc0b851c)
(cherry picked from commit 0dc07c5ca4d32b5ea8e104cbad106da9bb5b096d)
---
src/core/vpn/nm-vpn-connection.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c
index b5a7fc4c29..88c5703a69 100644
--- a/src/core/vpn/nm-vpn-connection.c
+++ b/src/core/vpn/nm-vpn-connection.c
@@ -1242,6 +1242,7 @@ _parent_device_l3cd_add_gateway_route(NML3ConfigData *l3cd,
.gateway = parent_gw.addr4,
.rt_source = NM_IP_CONFIG_SOURCE_VPN,
.metric_any = TRUE,
+ .table_any = TRUE,
};
} else {
route.r6 = (NMPlatformIP6Route){
@@ -1251,6 +1252,7 @@ _parent_device_l3cd_add_gateway_route(NML3ConfigData *l3cd,
.gateway = parent_gw.addr6,
.rt_source = NM_IP_CONFIG_SOURCE_VPN,
.metric_any = TRUE,
+ .table_any = TRUE,
};
}
nm_l3_config_data_add_route(l3cd, addr_family, NULL, &route.rx);
@@ -1267,6 +1269,7 @@ _parent_device_l3cd_add_gateway_route(NML3ConfigData *l3cd,
.plen = 32,
.rt_source = NM_IP_CONFIG_SOURCE_VPN,
.metric_any = TRUE,
+ .table_any = TRUE,
};
} else {
route.r6 = (NMPlatformIP6Route){
@@ -1274,6 +1277,7 @@ _parent_device_l3cd_add_gateway_route(NML3ConfigData *l3cd,
.plen = 128,
.rt_source = NM_IP_CONFIG_SOURCE_VPN,
.metric_any = TRUE,
+ .table_any = TRUE,
};
}
nm_l3_config_data_add_route(l3cd, addr_family, NULL, &route.rx);
--
2.45.0

@ -0,0 +1,238 @@
From 50331402dae72990a268704e4047d6c762572755 Mon Sep 17 00:00:00 2001
From: Wen Liang <wenliang@redhat.com>
Date: Fri, 20 Dec 2024 10:10:25 -0500
Subject: [PATCH 1/1] vpn: fix routing rules support in vpn conenctions
This commit introduces the ability to manage routing rules specifically
for VPN connections. These rules allow finer control over traffic
routing by enabling the specification of policy-based routing for
traffic over the VPN.
- Updated the connection backend to apply rules during VPN activation.
- Ensured proper cleanup of routing rules upon VPN deactivation.
This enhancement improves VPN usability in scenarios requiring advanced
routing configurations, such as split tunneling and traffic
prioritization.
Resolves: https://issues.redhat.com/browse/RHEL-70160
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2092
https://gitlab.freedesktop.org/NetworkManager/NetworkManager-ci/-/merge_requests/1842
(cherry picked from commit 308e34a501482d01c1cc6c87c38791ad9f34dc1f)
(cherry picked from commit a24b347e93e37b04aa0f5698efcb462c02517c09)
(cherry picked from commit b5c46f8a8d644e1c5a6dc07e06d5dab3338e9a91)
---
src/core/devices/nm-device.c | 62 +++++++++++++++++++-------------
src/core/devices/nm-device.h | 6 ++++
src/core/vpn/nm-vpn-connection.c | 7 +++-
3 files changed, 50 insertions(+), 25 deletions(-)
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index f9a2e7e8fe..070ba46495 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -10327,31 +10327,34 @@ lldp_setup(NMDevice *self, NMTernary enabled)
* as externally added ones. Don't restart NetworkManager if
* you care about that.
*/
-static void
-_routing_rules_sync(NMDevice *self, NMTernary set_mode)
+void
+nm_routing_rules_sync(NMConnection *applied_connection,
+ NMTernary set_mode,
+ GPtrArray *(*get_extra_rules)(NMDevice *self),
+ NMDevice *self,
+ NMNetns *netns)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMPGlobalTracker *global_tracker = nm_netns_get_global_tracker(nm_device_get_netns(self));
- NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self);
+ NMPGlobalTracker *global_tracker = nm_netns_get_global_tracker(netns);
gboolean untrack_only_dirty = FALSE;
gboolean keep_deleted_rules;
gpointer user_tag_1;
gpointer user_tag_2;
- /* take two arbitrary user-tag pointers that belong to @self. */
- user_tag_1 = &priv->v4_route_table;
- user_tag_2 = &priv->v6_route_table;
+ if (self) {
+ user_tag_1 = ((guint32 *) self) + 1;
+ user_tag_2 = ((guint32 *) self) + 2;
+ } else {
+ user_tag_1 = ((guint32 *) applied_connection) + 1;
+ user_tag_2 = ((guint32 *) applied_connection) + 2;
+ }
if (set_mode == NM_TERNARY_TRUE) {
- NMConnection *applied_connection;
NMSettingIPConfig *s_ip;
guint i, num;
int is_ipv4;
untrack_only_dirty = TRUE;
- applied_connection = nm_device_get_applied_connection(self);
-
for (is_ipv4 = 0; applied_connection && is_ipv4 < 2; is_ipv4++) {
int addr_family = is_ipv4 ? AF_INET : AF_INET6;
@@ -10390,10 +10393,10 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode)
}
}
- if (klass->get_extra_rules) {
+ if (get_extra_rules) {
gs_unref_ptrarray GPtrArray *extra_rules = NULL;
- extra_rules = klass->get_extra_rules(self);
+ extra_rules = get_extra_rules(self);
if (extra_rules) {
for (i = 0; i < extra_rules->len; i++) {
nmp_global_tracker_track_rule(
@@ -10408,7 +10411,7 @@ _routing_rules_sync(NMDevice *self, NMTernary set_mode)
}
nmp_global_tracker_untrack_all(global_tracker, user_tag_1, !untrack_only_dirty, TRUE);
- if (klass->get_extra_rules)
+ if (get_extra_rules)
nmp_global_tracker_untrack_all(global_tracker, user_tag_2, !untrack_only_dirty, TRUE);
keep_deleted_rules = FALSE;
@@ -10468,8 +10471,8 @@ tc_commit(NMDevice *self)
static void
activate_stage2_device_config(NMDevice *self)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMDeviceClass *klass;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self);
NMActStageReturn ret;
NMSettingWired *s_wired;
gboolean no_firmware = FALSE;
@@ -10494,7 +10497,11 @@ activate_stage2_device_config(NMDevice *self)
priv->tc_committed = TRUE;
}
- _routing_rules_sync(self, NM_TERNARY_TRUE);
+ nm_routing_rules_sync(nm_device_get_applied_connection(self),
+ NM_TERNARY_TRUE,
+ klass->get_extra_rules,
+ self,
+ nm_device_get_netns(self));
if (!nm_device_sys_iface_state_is_external_or_assume(self)) {
if (!nm_device_bring_up_full(self, FALSE, TRUE, &no_firmware)) {
@@ -10506,7 +10513,6 @@ activate_stage2_device_config(NMDevice *self)
}
}
- klass = NM_DEVICE_GET_CLASS(self);
if (klass->act_stage2_config_also_for_external_or_assume
|| !nm_device_sys_iface_state_is_external_or_assume(self)) {
NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
@@ -13881,7 +13887,11 @@ check_and_reapply_connection(NMDevice *self,
nm_device_activate_schedule_stage3_ip_config(self, FALSE);
- _routing_rules_sync(self, NM_TERNARY_TRUE);
+ nm_routing_rules_sync(nm_device_get_applied_connection(self),
+ NM_TERNARY_TRUE,
+ klass->get_extra_rules,
+ self,
+ nm_device_get_netns(self));
reactivate_proxy_config(self);
@@ -16444,6 +16454,7 @@ static void
nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanup_type)
{
NMDevicePrivate *priv;
+ NMDeviceClass *klass = NM_DEVICE_GET_CLASS(self);
int ifindex;
g_return_if_fail(NM_IS_DEVICE(self));
@@ -16468,8 +16479,8 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
}
/* Call device type-specific deactivation */
- if (NM_DEVICE_GET_CLASS(self)->deactivate)
- NM_DEVICE_GET_CLASS(self)->deactivate(self);
+ if (klass->deactivate)
+ klass->deactivate(self);
ifindex = nm_device_get_ip_ifindex(self);
@@ -16491,8 +16502,11 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
priv->tc_committed = FALSE;
- _routing_rules_sync(self,
- cleanup_type == CLEANUP_TYPE_KEEP ? NM_TERNARY_DEFAULT : NM_TERNARY_FALSE);
+ nm_routing_rules_sync(nm_device_get_applied_connection(self),
+ cleanup_type == CLEANUP_TYPE_KEEP ? NM_TERNARY_DEFAULT : NM_TERNARY_FALSE,
+ klass->get_extra_rules,
+ self,
+ nm_device_get_netns(self));
if (ifindex > 0)
nm_platform_ip4_dev_route_blacklist_set(nm_device_get_platform(self), ifindex, NULL);
@@ -16521,7 +16535,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu
/* for other device states (UNAVAILABLE, DISCONNECTED), allow the
* device to overwrite the reset behavior, so that Wi-Fi can set
* a randomized MAC address used during scanning. */
- NM_DEVICE_GET_CLASS(self)->deactivate_reset_hw_addr(self);
+ klass->deactivate_reset_hw_addr(self);
}
}
diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h
index 37eda5c0c8..c3a06c12e6 100644
--- a/src/core/devices/nm-device.h
+++ b/src/core/devices/nm-device.h
@@ -848,4 +848,10 @@ void nm_device_clear_dns_lookup_data(NMDevice *self, const char *reason);
gboolean nm_device_get_allow_autoconnect_on_external(NMDevice *self);
+void nm_routing_rules_sync(NMConnection *applied_connection,
+ NMTernary set_mode,
+ GPtrArray *(*get_extra_rules)(NMDevice *self),
+ NMDevice *self,
+ NMNetns *netns);
+
#endif /* __NETWORKMANAGER_DEVICE_H__ */
diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c
index 88c5703a69..c14682b8cc 100644
--- a/src/core/vpn/nm-vpn-connection.c
+++ b/src/core/vpn/nm-vpn-connection.c
@@ -905,7 +905,8 @@ fw_call_cleanup(NMVpnConnection *self)
static void
vpn_cleanup(NMVpnConnection *self, NMDevice *parent_dev)
{
- const char *iface;
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
+ const char *iface;
/* Remove zone from firewall */
iface = nm_vpn_connection_get_ip_iface(self, FALSE);
@@ -917,6 +918,8 @@ vpn_cleanup(NMVpnConnection *self, NMDevice *parent_dev)
fw_call_cleanup(self);
_l3cfg_l3cd_clear_all(self);
+
+ nm_routing_rules_sync(_get_applied_connection(self), NM_TERNARY_FALSE, NULL, NULL, priv->netns);
}
static void
@@ -2278,6 +2281,8 @@ _dbus_signal_ip_config_cb(NMVpnConnection *self, int addr_family, GVariant *dict
_l3cfg_l3cd_set(self, L3CD_TYPE_IP_X(IS_IPv4), l3cd);
+ nm_routing_rules_sync(_get_applied_connection(self), NM_TERNARY_TRUE, NULL, NULL, priv->netns);
+
_check_complete(self, TRUE);
}
--
2.45.0

@ -6,7 +6,7 @@
%global epoch_version 1
%global real_version 1.48.10
%global rpm_version %{real_version}
%global release_version 3
%global release_version 5
%global snapshot %{nil}
%global git_sha %{nil}
%global bcond_default_debug 0
@ -216,6 +216,9 @@ Patch1002: 1002-cloud-setup-ensure-azure-places-primary-address-first-rhel-56387
Patch1003: 1003-only-validate-sriov-capability-when-enabled-rhel-58397.patch
Patch1004: 1004-fix-bug-when-deactivating-port-connections-rhel-50747.patch
Patch1005: 1005-fix-validation-of-ovs-dpdk-interface-name-rhel-60022.patch
Patch1006: 1006-remove-routes-added-by-nm-on-reapply-rhel-73013.patch
Patch1007: 1007-vpn-place-gateway-route-to-table-defined-in-ipvx-route-table-rhel-73166.patch
Patch1008: 1008-vpn-support-routing-rules-in-vpn-conenctions-rhel-73167.patch
Requires(post): systemd
%if 0%{?fedora} || 0%{?rhel} >= 8
@ -1272,6 +1275,13 @@ fi
%changelog
* Thu Jan 09 2025 Wen Liang <wenliang@redhat.com> - 1:1.48.10-5
- vpn: Support routing rules in vpn conenctions (RHEL-73167)
- vpn: Place gateway route to table defined in ipvx.route-table (RHEL-73166)
* Wed Jan 08 2025 Íñigo Huguet <ihuguet@redhat.com> - 1:1.48.10-4
- Remove routes added by NetworkManager when doing reapply, also those not in main table (RHEL-73013)
* Tue Nov 12 2024 Beniamino Galvani <bgalvani@redhat.com> - 1:1.48.10-3
- Only validate the SR-IOV device capability when SR-IOV is enabled (RHEL-58397)
- Fix bug when deactivating port connections (RHEL-50747)

Loading…
Cancel
Save