diff --git a/SOURCES/1008-manager-fix-active_connection_find.patch b/SOURCES/1008-manager-fix-active_connection_find.patch new file mode 100644 index 0000000..e73bb74 --- /dev/null +++ b/SOURCES/1008-manager-fix-active_connection_find.patch @@ -0,0 +1,176 @@ +From 602f73a2e838ea1055ef5e6913aec3d8a87ed610 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Thu, 13 May 2021 10:49:39 +0200 +Subject: [PATCH 1/2] manager: fix active_connection_find() + +Commit 33b9fa3a3caf ("manager: Keep volatile/external connections +while referenced by async_op_lst") changed active_connection_find() to +also return active connections that are not yet activating but are +waiting authorization. + +This has side effect for other callers of the function. In particular, +_get_activatable_connections_filter() should exclude only ACs that are +really active, not those waiting for authorization. + +Otherwise, in ensure_master_active_connection() all the ACs waiting +authorization are missed and we might fail to find the right master +AC. + +Add an argument to active_connection_find to select whether include +ACs waiting authorization. + +Fixes: 33b9fa3a3caf ('manager: Keep volatile/external connections while referenced by async_op_lst') + +https://bugzilla.redhat.com/show_bug.cgi?id=1955101 +(cherry picked from commit e694f2cec1a0e7bc188776c8573e07a4d57851dc) +(cherry picked from commit fc611f60470160fe98512c405d6785f2b24b98a1) +--- + src/core/nm-manager.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c +index 5a6e05a934..c751b2db50 100644 +--- a/src/core/nm-manager.c ++++ b/src/core/nm-manager.c +@@ -363,6 +363,7 @@ static NMActiveConnection *active_connection_find(NMManager * self, + NMSettingsConnection * sett_conn, + const char * uuid, + NMActiveConnectionState max_state, ++ gboolean also_waiting_auth, + GPtrArray ** out_all_matching); + + static NMConnectivity *concheck_get_mgr(NMManager *self); +@@ -833,6 +834,7 @@ _delete_volatile_connection_do(NMManager *self, NMSettingsConnection *connection + connection, + NULL, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, ++ TRUE, + NULL)) + return; + +@@ -978,6 +980,7 @@ active_connection_find( + NMSettingsConnection * sett_conn, + const char * uuid, + NMActiveConnectionState max_state /* candidates in state @max_state will be found */, ++ gboolean also_waiting_auth /* return also ACs waiting authorization */, + GPtrArray ** out_all_matching) + { + NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); +@@ -1017,6 +1020,9 @@ active_connection_find( + if (!best_ac) { + AsyncOpData *async_op_data; + ++ if (!also_waiting_auth) ++ return NULL; ++ + c_list_for_each_entry (async_op_data, &priv->async_op_lst_head, async_op_lst) { + NMSettingsConnection *ac_conn; + +@@ -1078,6 +1084,7 @@ active_connection_find_by_connection(NMManager * self, + sett_conn, + sett_conn ? NULL : nm_connection_get_uuid(connection), + max_state, ++ FALSE, + out_all_matching); + } + +@@ -1112,6 +1119,7 @@ _get_activatable_connections_filter(NMSettings * settings, + sett_conn, + NULL, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED, ++ FALSE, + NULL); + } + +@@ -2245,6 +2253,7 @@ connection_flags_changed(NMSettings *settings, NMSettingsConnection *connection, + connection, + NULL, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, ++ FALSE, + NULL)) { + /* the connection still has an active-connection. It will be purged + * when the active connection(s) get(s) removed. */ +@@ -2564,6 +2573,7 @@ new_activation_allowed_for_connection(NMManager *self, NMSettingsConnection *con + connection, + NULL, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED, ++ FALSE, + NULL); + } + +@@ -4134,6 +4144,7 @@ find_master(NMManager * self, + master_connection, + NULL, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, ++ FALSE, + NULL); + } + +@@ -4985,6 +4996,7 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError ** + sett_conn, + NULL, + NM_ACTIVE_CONNECTION_STATE_ACTIVATED, ++ FALSE, + &all_ac_arr); + if (ac) { + n_all = all_ac_arr ? all_ac_arr->len : ((guint) 1); +-- +2.26.3 + + +From cf2f0e5a5180d2333ce33b925d54c8b7b925e094 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Fri, 30 Apr 2021 22:35:20 +0200 +Subject: [PATCH 2/2] manager: fix assertion failure in + active_connection_find() + +Active-connections in the async_op_lst are not guaranteed to have a +settings-connection. In particular, the settings-connection for an +AddAndActivate() AC is set only after the authorization succeeds. Use +the non-asserting variant of the function to fix the following +failure: + + nm_active_connection_get_settings_connection: assertion 'sett_conn' failed + + 1 _g_log_abort() + 2 g_logv() + 3 g_log() + 4 _nm_g_return_if_fail_warning.constprop.14() + 5 nm_active_connection_get_settings_connection() + 6 active_connection_find() + 7 _get_activatable_connections_filter() + 8 nm_settings_get_connections_clone() + 9 nm_manager_get_activatable_connections() + 10 auto_activate_device_cb() + 11 g_idle_dispatch() + 12 g_main_context_dispatch() + 13 g_main_context_iterate.isra.21() + 14 g_main_loop_run() + 15 main() + +Fixes: 33b9fa3a3caf ('manager: Keep volatile/external connections while referenced by async_op_lst') + +https://bugzilla.redhat.com/show_bug.cgi?id=1933719 +https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/834 +(cherry picked from commit 23cc0bf3353ea43d95a906e27c9881b1b68e2bbe) +(cherry picked from commit d0b0c65905ae19145d1c1f2912aa580a3b0a36e0) +--- + src/core/nm-manager.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c +index c751b2db50..3405de86ee 100644 +--- a/src/core/nm-manager.c ++++ b/src/core/nm-manager.c +@@ -1027,7 +1027,7 @@ active_connection_find( + NMSettingsConnection *ac_conn; + + ac = async_op_data->ac_auth.active; +- ac_conn = nm_active_connection_get_settings_connection(ac); ++ ac_conn = _nm_active_connection_get_settings_connection(ac); + if (sett_conn && sett_conn != ac_conn) + continue; + if (uuid && !nm_streq0(uuid, nm_settings_connection_get_uuid(ac_conn))) +-- +2.26.3 + diff --git a/SOURCES/1009-bond-support-tlb_dynamic_lb-in-balance-alb-mode.patch b/SOURCES/1009-bond-support-tlb_dynamic_lb-in-balance-alb-mode.patch new file mode 100644 index 0000000..4da291f --- /dev/null +++ b/SOURCES/1009-bond-support-tlb_dynamic_lb-in-balance-alb-mode.patch @@ -0,0 +1,53 @@ +From ba9dbfa4e5aaef9aa646a7718f302433ecf1a001 Mon Sep 17 00:00:00 2001 +From: Wen Liang +Date: Tue, 25 May 2021 08:45:46 -0400 +Subject: [PATCH] bond: support `tlb_dynamic_lb` in `balance-alb` mode + +In kernel, `tlb_dynamic_lb` is supported to configure in bonding mode +`balance-alb`. Therefore, add the support in NetworkManager to avoid +undesirable limitation. + +Kernel previously had such limitation and it was removed in +https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e79c1055749e3183a2beee04a24da378623329c5. + +Signed-off-by: Wen Liang + +https://bugzilla.redhat.com/show_bug.cgi?id=1959934 + +https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/868 +(cherry picked from commit 18839361aca42d5c9f470268c28063a6e7578851) +(cherry picked from commit 2f42c781edebac329c8031561c4b210118c0b3ab) +--- + libnm-core/nm-setting-bond.c | 2 +- + libnm-core/tests/test-setting.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c +index 68d4ca88f6..ea82d838c7 100644 +--- a/libnm-core/nm-setting-bond.c ++++ b/libnm-core/nm-setting-bond.c +@@ -225,7 +225,7 @@ static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( + {NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE, ~(BIT(NM_BOND_MODE_ROUNDROBIN))}, + {NM_SETTING_BOND_OPTION_PRIMARY, + ~(BIT(NM_BOND_MODE_ACTIVEBACKUP) | BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, +- {NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, ~(BIT(NM_BOND_MODE_TLB))}, ); ++ {NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB, ~(BIT(NM_BOND_MODE_TLB) | BIT(NM_BOND_MODE_ALB))}, ); + + gboolean + _nm_setting_bond_option_supported(const char *option, NMBondMode mode) +diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c +index 01cdb41cb2..56ba31541a 100644 +--- a/libnm-core/tests/test-setting.c ++++ b/libnm-core/tests/test-setting.c +@@ -687,7 +687,7 @@ test_bond_normalize(void) + ((const char *[]){"mode", "active-backup", "miimon", "1", NULL})); + test_bond_normalize_options( + ((const char *[]){"mode", "balance-alb", "tlb_dynamic_lb", "1", NULL}), +- ((const char *[]){"mode", "balance-alb", NULL})); ++ ((const char *[]){"mode", "balance-alb", "tlb_dynamic_lb", "1", NULL})); + test_bond_normalize_options( + ((const char *[]){"mode", "balance-tlb", "tlb_dynamic_lb", "1", NULL}), + ((const char *[]){"mode", "balance-tlb", "tlb_dynamic_lb", "1", NULL})); +-- +2.26.3 + diff --git a/SOURCES/1010-manager-delete-default-connection-when-veth-removed.patch b/SOURCES/1010-manager-delete-default-connection-when-veth-removed.patch new file mode 100644 index 0000000..5b35c7e --- /dev/null +++ b/SOURCES/1010-manager-delete-default-connection-when-veth-removed.patch @@ -0,0 +1,213 @@ +From a2cd778f7d54de1cf9f173fff5f09fededf5f49e Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Wed, 21 Apr 2021 13:42:45 +0200 +Subject: [PATCH 1/2] device: take reference to device object before + 'delete_on_deactivate' + +It's not clear why currently a weak reference is needed. + +(cherry picked from commit a42682d44fe2220412574fb13128814e643ed775) +(cherry picked from commit 8cfbb73294e9eaa475d28a6eada2c5ab14f1d74a) +--- + src/core/devices/nm-device.c | 44 ++++++++++++------------------------ + 1 file changed, 15 insertions(+), 29 deletions(-) + +diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c +index 5eaf8c23e7..7c2a6d3250 100644 +--- a/src/core/devices/nm-device.c ++++ b/src/core/devices/nm-device.c +@@ -125,7 +125,6 @@ typedef struct { + typedef struct { + NMDevice *device; + guint idle_add_id; +- int ifindex; + } DeleteOnDeactivateData; + + typedef struct { +@@ -12141,28 +12140,19 @@ nm_device_is_nm_owned(NMDevice *self) + static gboolean + delete_on_deactivate_link_delete(gpointer user_data) + { +- DeleteOnDeactivateData *data = user_data; +- NMDevice * self = data->device; ++ DeleteOnDeactivateData *data = user_data; ++ nm_auto_unref_object NMDevice *self = data->device; ++ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); ++ gs_free_error GError *error = NULL; + + _LOGD(LOGD_DEVICE, +- "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)", +- data->ifindex, ++ "delete_on_deactivate: cleanup and delete virtual link (id=%u)", + data->idle_add_id); + +- if (data->device) { +- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(data->device); +- gs_free_error GError *error = NULL; ++ priv->delete_on_deactivate_data = NULL; + +- g_object_remove_weak_pointer(G_OBJECT(data->device), (void **) &data->device); +- priv->delete_on_deactivate_data = NULL; +- +- if (!nm_device_unrealize(data->device, TRUE, &error)) +- _LOGD(LOGD_DEVICE, +- "delete_on_deactivate: unrealizing %d failed (%s)", +- data->ifindex, +- error->message); +- } else if (data->ifindex > 0) +- nm_platform_link_delete(nm_device_get_platform(self), data->ifindex); ++ if (!nm_device_unrealize(self, TRUE, &error)) ++ _LOGD(LOGD_DEVICE, "delete_on_deactivate: unrealizing failed (%s)", error->message); + + nm_device_emit_recheck_auto_activate(self); + +@@ -12181,17 +12171,16 @@ delete_on_deactivate_unschedule(NMDevice *self) + priv->delete_on_deactivate_data = NULL; + + g_source_remove(data->idle_add_id); +- g_object_remove_weak_pointer(G_OBJECT(self), (void **) &data->device); + _LOGD(LOGD_DEVICE, +- "delete_on_deactivate: cancel cleanup and delete virtual link #%d (id=%u)", +- data->ifindex, ++ "delete_on_deactivate: cancel cleanup and delete virtual link (id=%u)", + data->idle_add_id); ++ g_object_unref(data->device); + g_free(data); + } + } + + static void +-delete_on_deactivate_check_and_schedule(NMDevice *self, int ifindex) ++delete_on_deactivate_check_and_schedule(NMDevice *self) + { + NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + DeleteOnDeactivateData *data; +@@ -12208,16 +12197,13 @@ delete_on_deactivate_check_and_schedule(NMDevice *self, int ifindex) + return; + delete_on_deactivate_unschedule(self); /* always cancel and reschedule */ + +- data = g_new(DeleteOnDeactivateData, 1); +- g_object_add_weak_pointer(G_OBJECT(self), (void **) &data->device); +- data->device = self; +- data->ifindex = ifindex; ++ data = g_new(DeleteOnDeactivateData, 1); ++ data->device = g_object_ref(self); + data->idle_add_id = g_idle_add(delete_on_deactivate_link_delete, data); + priv->delete_on_deactivate_data = data; + + _LOGD(LOGD_DEVICE, +- "delete_on_deactivate: schedule cleanup and delete virtual link #%d (id=%u)", +- ifindex, ++ "delete_on_deactivate: schedule cleanup and delete virtual link (id=%u)", + data->idle_add_id); + } + +@@ -15854,7 +15840,7 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type) + /* Check if the device was deactivated, and if so, delete_link. + * Don't call delete_link synchronously because we are currently + * handling a state change -- which is not reentrant. */ +- delete_on_deactivate_check_and_schedule(self, nm_device_get_ip_ifindex(self)); ++ delete_on_deactivate_check_and_schedule(self); + } + + /* ip_iface should be cleared after flushing all routes and addresses, since +-- +2.26.3 + + +From a8eac46cc6a0579cd1b17634c50d9a54518cb53e Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Wed, 31 Mar 2021 21:32:43 +0200 +Subject: [PATCH 2/2] manager: ensure auto default connection is deleted when a + veth goes away + +When the link goes away the manager keeps software devices alive as +unrealized because there is still a connection for them. + +If the device is software and has a NM-generated connection, keeping +the device alive means that also the generated connection stays +alive. The result is that both stick around forever even if there is +no longer a kernel link. + +Add a check to avoid this situation. + +https://bugzilla.redhat.com/show_bug.cgi?id=1945282 + +Fixes: cd0cf9229d49 ('veth: add support to configure veth interfaces') +(cherry picked from commit d19773ecd4bee36f11749085a15d70a49168c0b7) +(cherry picked from commit 5279b85e02341d24a18fc8dd9238f9f68b733bff) +--- + src/core/nm-manager.c | 45 +++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 43 insertions(+), 2 deletions(-) + +diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c +index c751b2db50..804e8db0f0 100644 +--- a/src/core/nm-manager.c ++++ b/src/core/nm-manager.c +@@ -3519,6 +3519,45 @@ typedef struct { + guint idle_id; + } PlatformLinkCbData; + ++static gboolean ++_check_remove_dev_on_link_deleted(NMManager *self, NMDevice *device) ++{ ++ NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self); ++ NMSettingsConnection *const *scons = NULL; ++ NMConnection * con; ++ guint i; ++ ++ nm_assert(nm_device_is_software(device)); ++ ++ /* In general, software devices stick around as unrealized ++ * until their connection is removed. However, we don't want ++ * that a NM-generated connection keeps the device alive. ++ * If there are no other compatible connections, the device ++ * should be also removed. ++ */ ++ ++ scons = nm_settings_get_connections(priv->settings, NULL); ++ ++ for (i = 0; scons[i]; i++) { ++ con = nm_settings_connection_get_connection(scons[i]); ++ if (!nm_connection_is_virtual(con)) ++ continue; ++ ++ if (NM_FLAGS_HAS(nm_settings_connection_get_flags(scons[i]), ++ NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) ++ continue; ++ ++ if (!nm_device_check_connection_compatible(device, con, NULL)) ++ continue; ++ ++ /* Found a virtual connection compatible, the device must ++ * stay around unrealized. */ ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ + static gboolean + _platform_link_cb_idle(PlatformLinkCbData *data) + { +@@ -3544,13 +3583,15 @@ _platform_link_cb_idle(PlatformLinkCbData *data) + if (device) { + if (nm_device_is_software(device)) { + nm_device_sys_iface_state_set(device, NM_DEVICE_SYS_IFACE_STATE_REMOVED); +- /* Our software devices stick around until their connection is removed */ + if (!nm_device_unrealize(device, FALSE, &error)) { + _LOG2W(LOGD_DEVICE, device, "failed to unrealize: %s", error->message); + g_clear_error(&error); + remove_device(self, device, FALSE); + } else { +- nm_device_update_from_platform_link(device, NULL); ++ if (_check_remove_dev_on_link_deleted(self, device)) ++ remove_device(self, device, FALSE); ++ else ++ nm_device_update_from_platform_link(device, NULL); + } + } else { + /* Hardware and external devices always get removed when their kernel link is gone */ +-- +2.26.3 + diff --git a/SOURCES/1011-don-t-touch-device-tc-config-by-default-rh1928078.patch b/SOURCES/1011-don-t-touch-device-tc-config-by-default-rh1928078.patch new file mode 100644 index 0000000..a3476dc --- /dev/null +++ b/SOURCES/1011-don-t-touch-device-tc-config-by-default-rh1928078.patch @@ -0,0 +1,482 @@ +From 78e4c3d3d06b411a1bc9e60ee8bf0c460d4453b2 Mon Sep 17 00:00:00 2001 +From: Beniamino Galvani +Date: Tue, 25 May 2021 16:58:28 +0200 +Subject: [PATCH 1/2] core,libnm: don't touch device TC configuration by + default + +NetworkManager supports a very limited set of qdiscs. If users want to +configure a unsupported qdisc, they need to do it outside of +NetworkManager using tc. + +The problem is that NM also removes all qdiscs and filters during +activation if the connection doesn't contain a TC setting. Therefore, +setting TC configuration outside of NM is hard because users need to +do it *after* the connection is up (for example through a dispatcher +script). + +Let NM consider the presence (or absence) of a TC setting in the +connection to determine whether NM should configure (or not) qdiscs +and filters on the interface. We already do something similar for +SR-IOV configuration. + +Since new connections don't have the TC setting, the new behavior +(ignore existing configuration) will be the default. The impact of +this change in different scenarios is: + + - the user previously configured TC settings via NM. This continues + to work as before; + + - the user didn't set any qdiscs or filters in the connection, and + expected NM to clear them from the interface during activation. + Here there is a change in behavior, but it seems unlikely that + anybody relied on the old one; + + - the user didn't care about qdiscs and filters; NM removed all + qdiscs upon activation, and so the default qdisc from kernel was + used. After this change, NM will not touch qdiscs and the default + qdisc will be used, as before; + + - the user set a different qdisc via tc and NM cleared it during + activation. Now this will work as expected. + +So, the new default behavior seems better than the previous one. + +https://bugzilla.redhat.com/show_bug.cgi?id=1928078 +(cherry picked from commit a48edd0410c878d65fc5adcd5192b116ab6f8afc) +(cherry picked from commit 2a8181bcd78d055b7cb9e6c0e026bc3b08231b5a) +--- + .../generate-docs-nm-settings-nmcli.xml.in | 4 +-- + clients/common/settings-docs.h.in | 4 +-- + libnm-core/nm-setting-tc-config.c | 16 ++++++++++++ + src/core/devices/nm-device.c | 26 +++++++++---------- + 4 files changed, 33 insertions(+), 17 deletions(-) + +diff --git a/clients/cli/generate-docs-nm-settings-nmcli.xml.in b/clients/cli/generate-docs-nm-settings-nmcli.xml.in +index 1044ae0d38..0a75a0e681 100644 +--- a/clients/cli/generate-docs-nm-settings-nmcli.xml.in ++++ b/clients/cli/generate-docs-nm-settings-nmcli.xml.in +@@ -914,9 +914,9 @@ + + + ++ description="Array of TC queueing disciplines. When the "tc" setting is present, qdiscs from this property are applied upon activation. If the property is empty, all qdiscs are removed and the device will only have the default qdisc assigned by kernel according to the "net.core.default_qdisc" sysctl. If the "tc" setting is not present, NetworkManager doesn't touch the qdiscs present on the interface." /> + ++ description="Array of TC traffic filters. When the "tc" setting is present, filters from this property are applied upon activation. If the property is empty, NetworkManager removes all the filters. If the "tc" setting is not present, NetworkManager doesn't touch the filters present on the interface." /> + + + +Date: Tue, 25 May 2021 18:00:27 +0200 +Subject: [PATCH 2/2] ifcfg-rh: preserve an empty tc configuration + +If the TC setting contains no qdiscs and filters, it is lost after a +write-read cycle. Fix this by adding a new property to indicate the +presence of the (empty) setting. + +(cherry picked from commit 6a88d4e55cf031da2b5a8458d21487a011357da4) +(cherry picked from commit acf0c4df2b0fb0dc332aa929131953390998828f) +--- + Makefile.am | 1 + + libnm-core/nm-setting-tc-config.c | 14 +++- + .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 3 +- + .../plugins/ifcfg-rh/nms-ifcfg-rh-utils.c | 1 + + .../plugins/ifcfg-rh/nms-ifcfg-rh-utils.h | 2 +- + .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 38 +++++---- + .../ifcfg-test-tc-write-empty.cexpected | 15 ++++ + .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 80 +++++++++++++++++++ + 8 files changed, 128 insertions(+), 26 deletions(-) + create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected + +diff --git a/Makefile.am b/Makefile.am +index 9279672c1f..c8e417729b 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3300,6 +3300,7 @@ EXTRA_DIST += \ + src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected \ + src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc \ + src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected \ ++ src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected \ + src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 \ + src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 \ + src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-invalid \ +diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c +index 2fad98b1e8..31e829c1d2 100644 +--- a/libnm-core/nm-setting-tc-config.c ++++ b/libnm-core/nm-setting-tc-config.c +@@ -1822,8 +1822,11 @@ nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) + **/ + /* ---ifcfg-rh--- + * property: qdiscs +- * variable: QDISC1(+), QDISC2(+), ... +- * description: Queueing disciplines ++ * variable: QDISC1(+), QDISC2(+), ..., TC_COMMIT(+) ++ * description: Queueing disciplines to set on the interface. When no ++ * QDISC1, QDISC2, ..., FILTER1, FILTER2, ... keys are present, ++ * NetworkManager doesn't touch qdiscs and filters present on the ++ * interface, unless TC_COMMIT is set to 'yes'. + * example: QDISC1=ingress, QDISC2="root handle 1234: fq_codel" + * ---end--- + */ +@@ -1853,8 +1856,11 @@ nm_setting_tc_config_class_init(NMSettingTCConfigClass *klass) + **/ + /* ---ifcfg-rh--- + * property: qdiscs +- * variable: FILTER1(+), FILTER2(+), ... +- * description: Traffic filters ++ * variable: FILTER1(+), FILTER2(+), ..., TC_COMMIT(+) ++ * description: Traffic filters to set on the interface. When no ++ * QDISC1, QDISC2, ..., FILTER1, FILTER2, ... keys are present, ++ * NetworkManager doesn't touch qdiscs and filters present on the ++ * interface, unless TC_COMMIT is set to 'yes'. + * example: FILTER1="parent ffff: matchall action simple sdata Input", ... + * ---end--- + */ +diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +index 209957d9b8..a42c418884 100644 +--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c ++++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +@@ -2707,7 +2707,8 @@ make_tc_setting(shvarFile *ifcfg) + } + + if (nm_setting_tc_config_get_num_qdiscs(s_tc) > 0 +- || nm_setting_tc_config_get_num_tfilters(s_tc) > 0) ++ || nm_setting_tc_config_get_num_tfilters(s_tc) > 0 ++ || svGetValueBoolean(ifcfg, "TC_COMMIT", FALSE)) + return NM_SETTING(s_tc); + + g_object_unref(s_tc); +diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +index 8da5de473b..ada1942acb 100644 +--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c ++++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +@@ -1026,6 +1026,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { + _KEY_TYPE("STABLE_ID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("STP", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("SUBCHANNELS", NMS_IFCFG_KEY_TYPE_IS_PLAIN), ++ _KEY_TYPE("TC_COMMIT", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("TEAM_CONFIG", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("TEAM_MASTER", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("TEAM_MASTER_UUID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), +diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +index 36ec922514..04a1b63d3e 100644 +--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h ++++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +@@ -33,7 +33,7 @@ typedef struct { + NMSIfcfgKeyTypeFlags key_flags; + } NMSIfcfgKeyTypeInfo; + +-extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[247]; ++extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[248]; + + const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info(const char *key, gssize *out_idx); + +diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +index a968fce0ba..65bacb293a 100644 +--- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c ++++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +@@ -2511,46 +2511,46 @@ write_sriov_setting(NMConnection *connection, shvarFile *ifcfg) + } + } + +-static gboolean +-write_tc_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) ++static void ++write_tc_setting(NMConnection *connection, shvarFile *ifcfg) + { + NMSettingTCConfig *s_tc; +- guint i, num, n; ++ guint num_qdiscs; ++ guint num_filters; ++ guint i; ++ guint n; + char tag[64]; + + s_tc = nm_connection_get_setting_tc_config(connection); + if (!s_tc) +- return TRUE; ++ return; + +- num = nm_setting_tc_config_get_num_qdiscs(s_tc); +- for (n = 1, i = 0; i < num; i++) { ++ num_qdiscs = nm_setting_tc_config_get_num_qdiscs(s_tc); ++ for (n = 1, i = 0; i < num_qdiscs; i++) { + NMTCQdisc * qdisc; + gs_free char *str = NULL; + + qdisc = nm_setting_tc_config_get_qdisc(s_tc, i); +- str = nm_utils_tc_qdisc_to_str(qdisc, error); +- if (!str) +- return FALSE; +- ++ str = nm_utils_tc_qdisc_to_str(qdisc, NULL); ++ nm_assert(str); + svSetValueStr(ifcfg, numbered_tag(tag, "QDISC", n), str); + n++; + } + +- num = nm_setting_tc_config_get_num_tfilters(s_tc); +- for (n = 1, i = 0; i < num; i++) { ++ num_filters = nm_setting_tc_config_get_num_tfilters(s_tc); ++ for (n = 1, i = 0; i < num_filters; i++) { + NMTCTfilter * tfilter; + gs_free char *str = NULL; + + tfilter = nm_setting_tc_config_get_tfilter(s_tc, i); +- str = nm_utils_tc_tfilter_to_str(tfilter, error); +- if (!str) +- return FALSE; +- ++ str = nm_utils_tc_tfilter_to_str(tfilter, NULL); ++ nm_assert(str); + svSetValueStr(ifcfg, numbered_tag(tag, "FILTER", n), str); + n++; + } + +- return TRUE; ++ if (num_qdiscs == 0 && num_filters == 0) ++ svSetValueBoolean(ifcfg, "TC_COMMIT", TRUE); + } + + static void +@@ -3373,9 +3373,7 @@ do_write_construct(NMConnection * connection, + write_match_setting(connection, ifcfg); + write_hostname_setting(connection, ifcfg); + write_sriov_setting(connection, ifcfg); +- +- if (!write_tc_setting(connection, ifcfg, error)) +- return FALSE; ++ write_tc_setting(connection, ifcfg); + + route_path_is_svformat = utils_has_route_file_new_syntax(route_path); + +diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected +new file mode 100644 +index 0000000000..4df768b463 +--- /dev/null ++++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write-empty.cexpected +@@ -0,0 +1,15 @@ ++TYPE=Ethernet ++PROXY_METHOD=none ++BROWSER_ONLY=no ++TC_COMMIT=yes ++BOOTPROTO=none ++IPADDR=1.1.1.3 ++PREFIX=24 ++GATEWAY=1.1.1.1 ++DEFROUTE=yes ++IPV4_FAILURE_FATAL=no ++IPV6INIT=no ++NAME="Test Write TC config" ++UUID=${UUID} ++DEVICE=eth0 ++ONBOOT=yes +diff --git a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +index 59127d0103..9d9ed62653 100644 +--- a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c ++++ b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +@@ -11108,6 +11108,85 @@ test_tc_read(void) + g_object_unref(connection); + } + ++static void ++test_tc_write_empty(void) ++{ ++ nmtst_auto_unlinkfile char *testfile = NULL; ++ gs_unref_object NMConnection *connection = NULL; ++ gs_unref_object NMConnection *reread = NULL; ++ NMSettingConnection * s_con; ++ NMSettingIPConfig * s_ip4; ++ NMSettingIPConfig * s_ip6; ++ NMSettingWired * s_wired; ++ NMSettingTCConfig * s_tc; ++ NMIPAddress * addr; ++ GError * error = NULL; ++ ++ connection = nm_simple_connection_new(); ++ ++ /* Connection setting */ ++ s_con = (NMSettingConnection *) nm_setting_connection_new(); ++ nm_connection_add_setting(connection, NM_SETTING(s_con)); ++ ++ g_object_set(s_con, ++ NM_SETTING_CONNECTION_ID, ++ "Test Write TC config", ++ NM_SETTING_CONNECTION_UUID, ++ nm_utils_uuid_generate_a(), ++ NM_SETTING_CONNECTION_AUTOCONNECT, ++ TRUE, ++ NM_SETTING_CONNECTION_INTERFACE_NAME, ++ "eth0", ++ NM_SETTING_CONNECTION_TYPE, ++ NM_SETTING_WIRED_SETTING_NAME, ++ NULL); ++ ++ /* Wired setting */ ++ s_wired = (NMSettingWired *) nm_setting_wired_new(); ++ nm_connection_add_setting(connection, NM_SETTING(s_wired)); ++ ++ /* IP4 setting */ ++ s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new(); ++ nm_connection_add_setting(connection, NM_SETTING(s_ip4)); ++ ++ g_object_set(s_ip4, ++ NM_SETTING_IP_CONFIG_METHOD, ++ NM_SETTING_IP4_CONFIG_METHOD_MANUAL, ++ NM_SETTING_IP_CONFIG_GATEWAY, ++ "1.1.1.1", ++ NM_SETTING_IP_CONFIG_MAY_FAIL, ++ TRUE, ++ NULL); ++ ++ addr = nm_ip_address_new(AF_INET, "1.1.1.3", 24, &error); ++ g_assert_no_error(error); ++ nm_setting_ip_config_add_address(s_ip4, addr); ++ nm_ip_address_unref(addr); ++ ++ /* IP6 setting */ ++ s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new(); ++ nm_connection_add_setting(connection, NM_SETTING(s_ip6)); ++ ++ g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL); ++ ++ /* TC setting */ ++ s_tc = (NMSettingTCConfig *) nm_setting_tc_config_new(); ++ nm_connection_add_setting(connection, NM_SETTING(s_tc)); ++ ++ nm_connection_add_setting(connection, nm_setting_proxy_new()); ++ ++ nmtst_assert_connection_verifies_without_normalization(connection); ++ ++ _writer_new_connec_exp(connection, ++ TEST_SCRATCH_DIR, ++ TEST_IFCFG_DIR "/ifcfg-test-tc-write-empty.cexpected", ++ &testfile); ++ ++ reread = _connection_from_file(testfile, NULL, TYPE_BOND, NULL); ++ ++ nmtst_assert_connection_equals(connection, FALSE, reread, FALSE); ++} ++ + static void + test_tc_write(void) + { +@@ -11848,6 +11927,7 @@ main(int argc, char **argv) + + g_test_add_func(TPATH "tc/read", test_tc_read); + g_test_add_func(TPATH "tc/write", test_tc_write); ++ g_test_add_func(TPATH "tc/write_empty", test_tc_write_empty); + g_test_add_func(TPATH "utils/test_well_known_keys", test_well_known_keys); + g_test_add_func(TPATH "utils/test_utils_has_route_file_new_syntax", + test_utils_has_route_file_new_syntax); +-- +2.31.1 + diff --git a/SPECS/NetworkManager.spec b/SPECS/NetworkManager.spec index f018107..555162f 100644 --- a/SPECS/NetworkManager.spec +++ b/SPECS/NetworkManager.spec @@ -7,7 +7,7 @@ %global epoch_version 1 %global rpm_version 1.30.0 %global real_version 1.30.0 -%global release_version 7 +%global release_version 9 %global snapshot %{nil} %global git_sha %{nil} @@ -194,6 +194,10 @@ Patch1004: 1004-fix-handling-generated-local-routes-rh1907661.patch Patch1005: 1005-initrd-fix-crash-parsing-empty-rd.znet-argument.patch Patch1006: 1006-core-fix-crash-in-nm_wildcard_match_check.patch Patch1007: 1007-initrd-multiconnect-single-for-manual-ip-rh1915493.patch +Patch1008: 1008-manager-fix-active_connection_find.patch +Patch1009: 1009-bond-support-tlb_dynamic_lb-in-balance-alb-mode.patch +Patch1010: 1010-manager-delete-default-connection-when-veth-removed.patch +Patch1011: 1011-don-t-touch-device-tc-config-by-default-rh1928078.patch # The pregenerated docs contain default values and paths that depend # on the configure options when creating the source tarball. @@ -1158,6 +1162,14 @@ fi %changelog +* Fri Jun 18 2021 Beniamino Galvani - 1:1.30.0-9 +- core: don't touch device traffic control (TC) configuration by default (rh #1928078) + +* Fri Jun 4 2021 Wen Liang - 1:1.30.0-8 +- core: fix finding active connection for controller (rh #1965337) +- bond: support 'tlb_dynamic_lb' in 'balance-alb' mode (rh #1965948) +- manager: delete default connection when veth removed (rh #1965336) + * Fri Mar 26 2021 Beniamino Galvani - 1:1.30.0-7 - initrd: set multi-connect=single for connections with static IP (rh #1915493)