diff --git a/SOURCES/1012-ovs-don-t-remove-unrelated-external-ports-rhel-121102.patch b/SOURCES/1012-ovs-don-t-remove-unrelated-external-ports-rhel-121102.patch new file mode 100644 index 0000000..f9c16df --- /dev/null +++ b/SOURCES/1012-ovs-don-t-remove-unrelated-external-ports-rhel-121102.patch @@ -0,0 +1,93 @@ +From 589556437b65dba2a1630d923fd7ff877ed8d6cd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= +Date: Thu, 9 Oct 2025 12:24:11 +0200 +Subject: [PATCH] ovs: don't remove unrelated external ports + +The commit linked below introduced a bug that caused that OVS ports +added externally to NM are always deleted when we delete any OVS +interface. It affects to all externally added ports, including those +that are not related to the deleted interface and even those in +different OVS bridges. + +Fix it by only modifying ports and bridges that are ascendants of the +deleted interface, leaving everything else untouched. + +Note that bridges and ports still need to have at least one NM-managed +interface, otherwise they will also be purged. For example, an NM-owned +OVS bridge with 2 ports+iface, one NM-owned and one external: if we +delete the NM-owned iface, both ports and the bridge will be deleted. +For now, this is a known limitation that is not being fixed here. + +Fixes: 476c89b6f2cd ('ovs: only keep bridges and ports with NM interfaces attached') +(cherry picked from commit 93491d76ecf75c202ff82369e3eb72e7e6d37c8a) +(cherry picked from commit 8326cc32d64441dd993b5b1e73ded21d548efa6d) +(cherry picked from commit a2cad8cb1027d14dd7239b44468de8feeaab8b28) +--- + src/core/devices/ovs/nm-ovsdb.c | 32 +++++++++++++++++--------------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c +index 84467896d5..42b19c8090 100644 +--- a/src/core/devices/ovs/nm-ovsdb.c ++++ b/src/core/devices/ovs/nm-ovsdb.c +@@ -1447,40 +1447,42 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) + json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid)); + } + +- if (num_nm_interfaces == 0) { +- /* The port no longer has any NM interface. Don't add it to "new_ports" and set +- * ports_changed=TRUE, so that it will be deleted. */ ++ if (interfaces_changed && num_nm_interfaces == 0) { ++ /* We are deleting the last nm-interface of this port. Don't add it to "new_ports" ++ * and set ports_changed=TRUE, so that it will be deleted. */ + ports_changed = TRUE; + } else { ++ /* Keep this port: it's still alive, or it's unrelated to the deleted interface */ ++ json_array_append_new(new_ports, json_pack("[s,s]", "uuid", port_uuid)); ++ if (ovs_port->connection_uuid) ++ num_nm_ports++; ++ + if (interfaces_changed) { +- /* An interface needs to be deleted from this port */ ++ /* This port is still alive, but an interface needs to be deleted from it */ + _expect_port_interfaces(params, ovs_port->name, interfaces); + _set_port_interfaces(params, ovs_port->name, new_interfaces); + } +- /* The port is still alive */ +- json_array_append_new(new_ports, json_pack("[s,s]", "uuid", port_uuid)); +- if (ovs_port->connection_uuid) +- num_nm_ports++; + } + } + +- if (num_nm_ports == 0) { +- /* The bridge no longer has any NM port. Don't add it to "new_bridges" and set +- * bridges_changed=TRUE, so that it will be deleted. */ ++ if (ports_changed && num_nm_ports == 0) { ++ /* We are deleting the last nm-port of this bridge. Don't add it to "new_bridges" ++ * and set bridges_changed=TRUE, so that it will be deleted. */ + bridges_changed = TRUE; + } else { ++ /* Keep this bridge: it's still alive, or it's unrelated to the deleted interface */ ++ json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); ++ + if (ports_changed) { +- /* A port needs to be deleted from this bridge */ ++ /* This bridge is still alive, but a port needs to be deleted from it */ + _expect_bridge_ports(params, ovs_bridge->name, ports); + _set_bridge_ports(params, ovs_bridge->name, new_ports); + } +- /* The bridge is still alive */ +- json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); + } + } + + if (bridges_changed) { +- /* A port needs to be deleted from this bridge */ ++ /* A bridge needs to be deleted */ + _expect_ovs_bridges(params, priv->db_uuid, bridges); + _set_ovs_bridges(params, priv->db_uuid, new_bridges); + } +-- +2.50.1 + diff --git a/SOURCES/1013-support-reapplying-sriov-vfs-rhel-113952.patch b/SOURCES/1013-support-reapplying-sriov-vfs-rhel-113952.patch new file mode 100644 index 0000000..42cc43a --- /dev/null +++ b/SOURCES/1013-support-reapplying-sriov-vfs-rhel-113952.patch @@ -0,0 +1,184 @@ +From d2c3ea6166cf3ada470ee0caf652470e645445af Mon Sep 17 00:00:00 2001 +From: Jan Vaclav +Date: Thu, 14 Aug 2025 12:52:09 +0200 +Subject: [PATCH 1/2] device: extract sriov platform vf generation to separate + function + +(cherry picked from commit 588a69cd1b0e5bab7371f297c6450d17f5de9ab2) +(cherry picked from commit b2d8f60c4970401b4e981604eceaa37520052fcf) +(cherry picked from commit 8676995903564a526f882dbb05126885c3272129) +--- + src/core/devices/nm-device.c | 61 +++++++++++++++++++++++++----------- + 1 file changed, 43 insertions(+), 18 deletions(-) + +diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c +index e4249dc4e8..631f978bed 100644 +--- a/src/core/devices/nm-device.c ++++ b/src/core/devices/nm-device.c +@@ -10329,6 +10329,43 @@ sriov_params_cb(GError *error, gpointer user_data) + nm_device_activate_schedule_stage1_device_prepare(self, FALSE); + } + ++static gboolean ++sriov_gen_platform_vfs(NMDevice *self, ++ NMSettingSriov *s_sriov, ++ NMPlatformVF ***plat_vfs_out, ++ GError **error) ++{ ++ nm_auto_freev NMPlatformVF **plat_vfs = NULL; ++ guint num; ++ ++ nm_assert(s_sriov); ++ nm_assert(plat_vfs_out && !*plat_vfs_out); ++ ++ num = nm_setting_sriov_get_num_vfs(s_sriov); ++ plat_vfs = g_new0(NMPlatformVF *, num + 1); ++ ++ for (int i = 0; i < num; i++) { ++ NMSriovVF *vf = nm_setting_sriov_get_vf(s_sriov, i); ++ gs_free_error GError *local = NULL; ++ ++ plat_vfs[i] = sriov_vf_config_to_platform(self, vf, &local); ++ ++ if (!plat_vfs[i]) { ++ g_set_error(error, ++ local->domain, ++ local->code, ++ "VF '%s' is invalid: %s", ++ nm_utils_sriov_vf_to_str(vf, FALSE, NULL), ++ local->message); ++ return FALSE; ++ } ++ } ++ ++ *plat_vfs_out = g_steal_pointer(&plat_vfs); ++ ++ return TRUE; ++} ++ + /* + * activate_stage1_device_prepare + * +@@ -10375,10 +10412,7 @@ activate_stage1_device_prepare(NMDevice *self) + if (s_sriov && nm_device_has_capability(self, NM_DEVICE_CAP_SRIOV)) { + nm_auto_freev NMPlatformVF **plat_vfs = NULL; + gs_free_error GError *error = NULL; +- NMSriovVF *vf; + NMTernary autoprobe; +- guint num; +- guint i; + + autoprobe = nm_setting_sriov_get_autoprobe_drivers(s_sriov); + if (autoprobe == NM_TERNARY_DEFAULT) { +@@ -10391,21 +10425,12 @@ activate_stage1_device_prepare(NMDevice *self) + NM_OPTION_BOOL_TRUE); + } + +- num = nm_setting_sriov_get_num_vfs(s_sriov); +- plat_vfs = g_new0(NMPlatformVF *, num + 1); +- for (i = 0; i < num; i++) { +- vf = nm_setting_sriov_get_vf(s_sriov, i); +- plat_vfs[i] = sriov_vf_config_to_platform(self, vf, &error); +- if (!plat_vfs[i]) { +- _LOGE(LOGD_DEVICE, +- "failed to apply SR-IOV VF '%s': %s", +- nm_utils_sriov_vf_to_str(vf, FALSE, NULL), +- error->message); +- nm_device_state_changed(self, +- NM_DEVICE_STATE_FAILED, +- NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED); +- return; +- } ++ if (!sriov_gen_platform_vfs(self, s_sriov, &plat_vfs, &error)) { ++ _LOGE(LOGD_DEVICE, "cannot parse the VF list: %s", error->message); ++ nm_device_state_changed(self, ++ NM_DEVICE_STATE_FAILED, ++ NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED); ++ return; + } + + /* When changing the number of VFs the kernel can block +-- +2.50.1 + + +From a92341d549de435e69c3b66d5569d2bd98d37908 Mon Sep 17 00:00:00 2001 +From: Jan Vaclav +Date: Thu, 14 Aug 2025 13:00:53 +0200 +Subject: [PATCH 2/2] device: add support for reapplying the `sriov.vfs` + property + +Adds support for reapplying the `sriov.vfs` property. Note this +does not include `num_vfs`, as the configuration needs to be reset +and reconfigured from scratch in that case. + +Previously, if an existing VF is modified (e.g. if we change the `trust` +flag), we reset all VF configurations, and started from scratch. But in +some cases, this is unnecessarily disruptive. + +Resolves: https://issues.redhat.com/browse/RHEL-95844 +(cherry picked from commit 4ba3ffee6788e6d8b75aff6c7aa21f92e45d5b9c) +(cherry picked from commit 6f454c98a98818e96ecd4f228f1e42febd2b2b32) +(cherry picked from commit 737000860ee9efcc15e8eec8d85f47afd4eca8c5) +--- + src/core/devices/nm-device.c | 35 ++++++++++++++++++++++++++++++++++- + 1 file changed, 34 insertions(+), 1 deletion(-) + +diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c +index 631f978bed..b9bd3492e4 100644 +--- a/src/core/devices/nm-device.c ++++ b/src/core/devices/nm-device.c +@@ -14028,6 +14028,13 @@ can_reapply_change(NMDevice *self, + NM_SETTING_BRIDGE_PORT_VLANS); + } + ++ if (nm_streq(setting_name, NM_SETTING_SRIOV_SETTING_NAME)) { ++ return nm_device_hash_check_invalid_keys(diffs, ++ NM_SETTING_SRIOV_SETTING_NAME, ++ error, ++ NM_SETTING_SRIOV_VFS); ++ } ++ + out_fail: + g_set_error(error, + NM_DEVICE_ERROR, +@@ -14203,9 +14210,35 @@ check_and_reapply_connection(NMDevice *self, + + nm_device_link_properties_set(self, TRUE); + +- if (priv->state >= NM_DEVICE_STATE_CONFIG) ++ if (priv->state >= NM_DEVICE_STATE_CONFIG) { ++ GHashTable *sriov_diff; ++ + lldp_setup(self, NM_TERNARY_DEFAULT); + ++ sriov_diff = nm_g_hash_table_lookup(diffs, NM_SETTING_SRIOV_SETTING_NAME); ++ ++ if (sriov_diff && nm_g_hash_table_lookup(sriov_diff, NM_SETTING_SRIOV_VFS)) { ++ nm_auto_freev NMPlatformVF **plat_vfs = NULL; ++ NMSettingSriov *s_sriov; ++ ++ s_sriov = (NMSettingSriov *) nm_connection_get_setting(applied, NM_TYPE_SETTING_SRIOV); ++ ++ if (s_sriov) { ++ gs_free_error GError *local = NULL; ++ ++ if (!sriov_gen_platform_vfs(self, s_sriov, &plat_vfs, &local) ++ || !nm_platform_link_set_sriov_vfs(nm_device_get_platform(self), ++ priv->ifindex, ++ (const NMPlatformVF *const *) plat_vfs)) { ++ _LOGE(LOGD_DEVICE, ++ "failed to reapply SRIOV VFs%s%s", ++ local ? ": " : "", ++ local ? local->message : ""); ++ } ++ } ++ } ++ } ++ + if (priv->state >= NM_DEVICE_STATE_IP_CONFIG) { + /* Allow reapply of MTU */ + priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE; +-- +2.50.1 + diff --git a/SPECS/NetworkManager.spec b/SPECS/NetworkManager.spec index 12b9d54..45a7733 100644 --- a/SPECS/NetworkManager.spec +++ b/SPECS/NetworkManager.spec @@ -7,7 +7,7 @@ %global real_version 1.52.0 %global git_tag_version_suffix %{nil} %global rpm_version %{real_version} -%global release_version 7 +%global release_version 9 %global snapshot %{nil} %global git_sha %{nil} %global bcond_default_debug 0 @@ -201,6 +201,8 @@ Patch1008: 1008-device-update-the-external-down-unmanaged-flag-on-port-attach-re Patch1009: 1009-ovs-set-the-tun-interface-up-before-stage3-98550.patch Patch1010: 1010-bridge-fix-reapplying-port-VLANs-102742.patch Patch1011: 1011-device-dont-disable-IPv6-in-stage3-on-reapply-102771.patch +Patch1012: 1012-ovs-don-t-remove-unrelated-external-ports-rhel-121102.patch +Patch1013: 1013-support-reapplying-sriov-vfs-rhel-113952.patch Requires(post): systemd Requires(post): systemd-udev @@ -1092,6 +1094,13 @@ fi %changelog +* Mon Oct 20 2025 Íñigo Huguet - 1:1.52.0-9 +- Rebuild due to wrong buildroot picked in last build + +* Wed Oct 15 2025 Íñigo Huguet - 1:1.52.0-8 +- Support reapplying sriov.vfs (RHEL-113952) +- Fix removing unrelated OVS ports (RHEL-121102) + * Wed Aug 13 2025 Vladimír Beneš - 1:1.52.0-7 - ovs: only keep bridges and ports with NM interfaces attached #2 (RHEL-87167)