import UBI NetworkManager-1.54.0-1.el10

This commit is contained in:
eabdullin 2025-11-11 21:32:39 +00:00
parent 239fc057c1
commit 32afd6e3be
16 changed files with 53 additions and 9927 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
NetworkManager-1.52.0.tar.xz
NetworkManager-1.54.0.tar.xz

View File

@ -1,85 +0,0 @@
From 3199dbc5cd688e8b9239a17ba6602779e7b1ba01 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
Date: Thu, 3 Apr 2025 09:20:58 +0200
Subject: [PATCH 1/2] core: fail early if we cannot get current FEC value
If we cannot get current FEC value probably we won't be able to set it a
few lines later. Also, if it fails to set, we try to use the value of
the old one that we tried to retrieve without success. In that case, the
variable old_fec_mode would be uninitialized. Fix it by returning early
if we cannot get the current value.
Fixes: 19bed3121fb6 ('ethtool: support Forward Error Correction(fec)')
(cherry picked from commit cbdd0d9cca34f4e1cbd177e347e14265e1afaf6c)
(cherry picked from commit b7e34f225a57b5374d39e095284d6ad03da59097)
---
src/core/devices/nm-device.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 801dc7cd76..8d7eaa5676 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -2768,13 +2768,16 @@ _ethtool_fec_set(NMDevice *self,
fec_mode = g_variant_get_uint32(variant);
}
- nm_platform_ethtool_get_fec_mode(platform, ethtool_state->ifindex, &old_fec_mode);
-
/* The NM_SETTING_ETHTOOL_FEC_MODE_NONE is query only value, hence do nothing. */
if (!fec_mode || fec_mode == NM_SETTING_ETHTOOL_FEC_MODE_NONE) {
return;
}
+ if (!nm_platform_ethtool_get_fec_mode(platform, ethtool_state->ifindex, &old_fec_mode)) {
+ _LOGW(LOGD_DEVICE, "ethtool: failure setting FEC %d: cannot get current value", fec_mode);
+ return;
+ }
+
if (!nm_platform_ethtool_set_fec_mode(platform, ethtool_state->ifindex, fec_mode))
_LOGW(LOGD_DEVICE, "ethtool: failure setting FEC %d", fec_mode);
else {
--
2.49.0
From 85e98d98e5511e3b4faa5248b51c32d650a098af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
Date: Thu, 3 Apr 2025 09:32:26 +0200
Subject: [PATCH 2/2] core: optimize hash table search in _ethtool_fec_set
Break the loop as soon as we've found the value.
Fixes: 19bed3121fb6 ('ethtool: support Forward Error Correction(fec)')
(cherry picked from commit 245f0e0b35d385e966289080dbd2594e74a189b2)
(cherry picked from commit 094a542546b158038473cc59f3f8ab03851e63eb)
---
src/core/devices/nm-device.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 8d7eaa5676..c777d934d6 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -2759,13 +2759,11 @@ _ethtool_fec_set(NMDevice *self,
g_hash_table_iter_init(&iter, hash);
while (g_hash_table_iter_next(&iter, (gpointer *) &name, (gpointer *) &variant)) {
- NMEthtoolID ethtool_id = nm_ethtool_id_get_by_name(name);
-
- if (!nm_ethtool_id_is_fec(ethtool_id))
- continue;
-
- nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32));
- fec_mode = g_variant_get_uint32(variant);
+ if (nm_ethtool_id_is_fec(nm_ethtool_id_get_by_name(name))) {
+ nm_assert(g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32));
+ fec_mode = g_variant_get_uint32(variant);
+ break;
+ }
}
/* The NM_SETTING_ETHTOOL_FEC_MODE_NONE is query only value, hence do nothing. */
--
2.49.0

File diff suppressed because it is too large Load Diff

View File

@ -1,195 +0,0 @@
From de4f4e870dae3aae3dd77953b9e47a7cef7f5f90 Mon Sep 17 00:00:00 2001
From: Tomas Korbar <tkorbar@redhat.com>
Date: Thu, 13 Mar 2025 12:31:14 +0100
Subject: [PATCH 1/2] dns: Fix invalid memory access on Dnsconfd DBUS error
DBus errors were not properly handled after DBus calls and
that caused SIGSEGV. Now they are checked.
Fixes #1738
Fixes: b8714e86e4e7 ('dns: introduce configuration_serial support to the dnsconfd plugin')
(cherry picked from commit 4ad20787bbeb53559e96bdd74e06b8267a9d287b)
---
src/core/dns/nm-dns-dnsconfd.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/src/core/dns/nm-dns-dnsconfd.c b/src/core/dns/nm-dns-dnsconfd.c
index 63b3060f3d..c994ec8bc9 100644
--- a/src/core/dns/nm-dns-dnsconfd.c
+++ b/src/core/dns/nm-dns-dnsconfd.c
@@ -132,6 +132,13 @@ dnsconfd_serial_retrieval_done(GObject *source_object, GAsyncResult *res, gpoint
self = user_data;
priv = NM_DNS_DNSCONFD_GET_PRIVATE(self);
+ if (!response) {
+ _LOGW("dnsconfd serial retrieval failed: %s", error->message);
+ priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
+ _nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
+ return;
+ }
+
nm_clear_g_cancellable(&priv->serial_cancellable);
g_variant_get(response, "(v)", &new_serial_variant);
@@ -201,8 +208,12 @@ dnsconfd_update_done(GObject *source_object, GAsyncResult *res, gpointer user_da
nm_clear_g_cancellable(&priv->update_cancellable);
- if (!response)
+ if (!response) {
_LOGW("dnsconfd update failed: %s", error->message);
+ priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
+ _nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
+ return;
+ }
/* By using &s we will get pointer to char data contained
* in variant and thus no freing of dnsconfd_message is required */
--
2.49.0
From 873adc4dc04088542b107ebd6aa2289a4c4f6df9 Mon Sep 17 00:00:00 2001
From: Tomas Korbar <tkorbar@redhat.com>
Date: Thu, 13 Mar 2025 12:34:09 +0100
Subject: [PATCH 2/2] dns: Refactor changing of Dnsconfd plugin state
(cherry picked from commit 7ba27f7a13afaa8a55e662cd1857d480c52a3a85)
---
src/core/dns/nm-dns-dnsconfd.c | 45 ++++++++++++++++------------------
1 file changed, 21 insertions(+), 24 deletions(-)
diff --git a/src/core/dns/nm-dns-dnsconfd.c b/src/core/dns/nm-dns-dnsconfd.c
index c994ec8bc9..c17fb9cf44 100644
--- a/src/core/dns/nm-dns-dnsconfd.c
+++ b/src/core/dns/nm-dns-dnsconfd.c
@@ -71,6 +71,15 @@ typedef enum {
/*****************************************************************************/
+static void
+dnsconfd_change_plugin_state(NMDnsDnsconfd *self, DnsconfdPluginState new_state)
+{
+ NMDnsDnsconfdPrivate *priv = NM_DNS_DNSCONFD_GET_PRIVATE(self);
+
+ priv->plugin_state = new_state;
+ _nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
+}
+
static void
dnsconfd_serial_changed(NMDnsDnsconfd *self, guint new_serial)
{
@@ -78,12 +87,10 @@ dnsconfd_serial_changed(NMDnsDnsconfd *self, guint new_serial)
priv->present_configuration_serial = new_serial;
if (priv->plugin_state == DNSCONFD_PLUGIN_WAIT_SERIAL
&& priv->awaited_configuration_serial == new_serial) {
- priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
/* Update finished, serials match */
_LOGT("serials match, update finished");
}
-
- _nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
}
static void
@@ -134,8 +141,7 @@ dnsconfd_serial_retrieval_done(GObject *source_object, GAsyncResult *res, gpoint
if (!response) {
_LOGW("dnsconfd serial retrieval failed: %s", error->message);
- priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
- _nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
return;
}
@@ -210,8 +216,7 @@ dnsconfd_update_done(GObject *source_object, GAsyncResult *res, gpointer user_da
if (!response) {
_LOGW("dnsconfd update failed: %s", error->message);
- priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
- _nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
return;
}
@@ -221,8 +226,7 @@ dnsconfd_update_done(GObject *source_object, GAsyncResult *res, gpointer user_da
if (!awaited_serial) {
_LOGW("dnsconfd refused update: %s", dnsconfd_message);
- priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
- _nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
return;
}
@@ -231,14 +235,12 @@ dnsconfd_update_done(GObject *source_object, GAsyncResult *res, gpointer user_da
if (priv->awaited_configuration_serial == priv->present_configuration_serial) {
/* Serials match, update finished */
- priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
_LOGT("after update serials match");
} else {
- priv->plugin_state = DNSCONFD_PLUGIN_WAIT_SERIAL;
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_SERIAL);
_LOGT("after update serials don't match, waiting");
}
-
- _nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
}
static gboolean
@@ -489,8 +491,7 @@ name_owner_changed(NMDnsDnsconfd *self, const char *name_owner)
|| priv->plugin_state == DNSCONFD_PLUGIN_WAIT_SERIAL) {
/* We were waiting for either serial or confirmation of update and name
* disappeared, thus we need to retransmit */
- priv->plugin_state = DNSCONFD_PLUGIN_WAIT_CONNECT;
- _nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_CONNECT);
}
return;
}
@@ -501,15 +502,13 @@ name_owner_changed(NMDnsDnsconfd *self, const char *name_owner)
if (!subscribe_serial(self)) {
/* This means that in time between new name and subscribe serial call
* we lost the name again thus wait again */
- priv->plugin_state = DNSCONFD_PLUGIN_WAIT_CONNECT;
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_CONNECT);
_LOGT("subscription failed, waiting to connect");
} else {
- priv->plugin_state = DNSCONFD_PLUGIN_WAIT_UPDATE_DONE;
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_UPDATE_DONE);
_LOGT("sending update and waiting for its finish");
send_dnsconfd_update(self);
}
-
- _nm_dns_plugin_update_pending_maybe_changed(NM_DNS_PLUGIN(self));
}
static void
@@ -706,18 +705,16 @@ update(NMDnsPlugin *plugin,
/* We need to consider only whether we are connected, because newer update call
* overrides the old one */
if (all_connected == CONNECTION_FAIL) {
- priv->plugin_state = DNSCONFD_PLUGIN_IDLE;
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_IDLE);
_LOGT("failed to connect");
} else if (all_connected == CONNECTION_WAIT) {
- priv->plugin_state = DNSCONFD_PLUGIN_WAIT_CONNECT;
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_CONNECT);
_LOGT("not connected, waiting to connect");
} else {
- priv->plugin_state = DNSCONFD_PLUGIN_WAIT_UPDATE_DONE;
+ dnsconfd_change_plugin_state(self, DNSCONFD_PLUGIN_WAIT_UPDATE_DONE);
_LOGT("connected, waiting for update to finish");
}
- _nm_dns_plugin_update_pending_maybe_changed(plugin);
-
if (all_connected == CONNECTION_FAIL) {
nm_utils_error_set(error,
NM_UTILS_ERROR_UNKNOWN,
--
2.49.0

View File

@ -1,560 +0,0 @@
From c423bf7631f199edf5dfedeb19212c1eb1dad76a Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Thu, 10 Apr 2025 10:43:30 +0200
Subject: [PATCH 1/1] ovs: allow reapplying ovs-bridge and ovs-port properties
Allow reapplying the following properties:
- ovs-bridge.fail-mode
- ovs-bridge.mcast-snooping-enable
- ovs-bridge.rstp-enable
- ovs-bridge.stp-enable
- ovs-port.bond-downdelay
- ovs-port.bond-mode
- ovs-port.bond-updelay
- ovs-port.lacp
- ovs-port.tag
- ovs-port.trunks
- ovs-port.vlan-mode
(cherry picked from commit 4f577d677f2aed8f2ac1eec16349a09e7fb032c6)
(cherry picked from commit 6f480d949427af07360a9111ef408c72e02d4e39)
---
src/core/devices/ovs/nm-device-ovs-bridge.c | 26 +-
src/core/devices/ovs/nm-device-ovs-port.c | 27 ++
src/core/devices/ovs/nm-ovsdb.c | 298 ++++++++++++--------
src/core/devices/ovs/nm-ovsdb.h | 2 +-
4 files changed, 233 insertions(+), 120 deletions(-)
diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c
index 0977766939..c9b1f4c6af 100644
--- a/src/core/devices/ovs/nm-device-ovs-bridge.c
+++ b/src/core/devices/ovs/nm-device-ovs-bridge.c
@@ -135,13 +135,36 @@ nm_device_ovs_reapply_connection(NMDevice *self, NMConnection *con_old, NMConnec
nm_ovsdb_set_reapply(nm_ovsdb_get(),
device_type,
nm_device_get_ip_iface(self),
- nm_connection_get_uuid(con_new),
+ nm_simple_connection_new_clone(con_new),
_nm_connection_get_setting(con_old, NM_TYPE_SETTING_OVS_EXTERNAL_IDS),
_nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_EXTERNAL_IDS),
_nm_connection_get_setting(con_old, NM_TYPE_SETTING_OVS_OTHER_CONFIG),
_nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_OTHER_CONFIG));
}
+static gboolean
+can_reapply_change(NMDevice *device,
+ const char *setting_name,
+ NMSetting *s_old,
+ NMSetting *s_new,
+ GHashTable *diffs,
+ GError **error)
+{
+ NMDeviceClass *device_class = NM_DEVICE_CLASS(nm_device_ovs_bridge_parent_class);
+
+ if (nm_streq(setting_name, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) {
+ return nm_device_hash_check_invalid_keys(diffs,
+ NM_SETTING_OVS_BRIDGE_SETTING_NAME,
+ error,
+ NM_SETTING_OVS_BRIDGE_FAIL_MODE,
+ NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE,
+ NM_SETTING_OVS_BRIDGE_RSTP_ENABLE,
+ NM_SETTING_OVS_BRIDGE_STP_ENABLE);
+ }
+
+ return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
+}
+
/*****************************************************************************/
static void
@@ -180,6 +203,7 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass)
device_class->ready_for_ip_config = ready_for_ip_config;
device_class->attach_port = attach_port;
device_class->detach_port = detach_port;
+ device_class->can_reapply_change = can_reapply_change;
device_class->can_reapply_change_ovs_external_ids = TRUE;
device_class->reapply_connection = nm_device_ovs_reapply_connection;
}
diff --git a/src/core/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c
index 7eacedb847..e9928548ff 100644
--- a/src/core/devices/ovs/nm-device-ovs-port.c
+++ b/src/core/devices/ovs/nm-device-ovs-port.c
@@ -256,6 +256,32 @@ detach_port(NMDevice *device,
return ret;
}
+static gboolean
+can_reapply_change(NMDevice *device,
+ const char *setting_name,
+ NMSetting *s_old,
+ NMSetting *s_new,
+ GHashTable *diffs,
+ GError **error)
+{
+ NMDeviceClass *device_class = NM_DEVICE_CLASS(nm_device_ovs_port_parent_class);
+
+ if (nm_streq(setting_name, NM_SETTING_OVS_PORT_SETTING_NAME)) {
+ return nm_device_hash_check_invalid_keys(diffs,
+ NM_SETTING_OVS_PORT_SETTING_NAME,
+ error,
+ NM_SETTING_OVS_PORT_TAG,
+ NM_SETTING_OVS_PORT_VLAN_MODE,
+ NM_SETTING_OVS_PORT_BOND_UPDELAY,
+ NM_SETTING_OVS_PORT_BOND_DOWNDELAY,
+ NM_SETTING_OVS_PORT_LACP,
+ NM_SETTING_OVS_PORT_BOND_MODE,
+ NM_SETTING_OVS_PORT_TRUNKS);
+ }
+
+ return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
+}
+
/*****************************************************************************/
static void
@@ -293,6 +319,7 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass)
device_class->ready_for_ip_config = ready_for_ip_config;
device_class->attach_port = attach_port;
device_class->detach_port = detach_port;
+ device_class->can_reapply_change = can_reapply_change;
device_class->can_reapply_change_ovs_external_ids = TRUE;
device_class->reapply_connection = nm_device_ovs_reapply_connection;
}
diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c
index 528d44d8f1..e6d37d270c 100644
--- a/src/core/devices/ovs/nm-ovsdb.c
+++ b/src/core/devices/ovs/nm-ovsdb.c
@@ -101,13 +101,13 @@ typedef union {
guint32 mtu;
} set_interface_mtu;
struct {
- NMDeviceType device_type;
- char *ifname;
- char *connection_uuid;
- GHashTable *external_ids_old;
- GHashTable *external_ids_new;
- GHashTable *other_config_old;
- GHashTable *other_config_new;
+ NMDeviceType device_type;
+ char *ifname;
+ NMConnection *connection;
+ GHashTable *external_ids_old;
+ GHashTable *external_ids_new;
+ GHashTable *other_config_old;
+ GHashTable *other_config_new;
} set_reapply;
} OvsdbMethodPayload;
@@ -242,24 +242,21 @@ static void cleanup_check_ready(NMOvsdb *self);
}, \
}))
-#define OVSDB_METHOD_PAYLOAD_SET_REAPPLY(xdevice_type, \
- xifname, \
- xconnection_uuid, \
- xexternal_ids_old, \
- xexternal_ids_new, \
- xother_config_old, \
- xother_config_new) \
- (&((const OvsdbMethodPayload) { \
- .set_reapply = \
- { \
- .device_type = xdevice_type, \
- .ifname = (char *) NM_CONSTCAST(char, (xifname)), \
- .connection_uuid = (char *) NM_CONSTCAST(char, (xconnection_uuid)), \
- .external_ids_old = (xexternal_ids_old), \
- .external_ids_new = (xexternal_ids_new), \
- .other_config_old = (xother_config_old), \
- .other_config_new = (xother_config_new), \
- }, \
+#define OVSDB_METHOD_PAYLOAD_SET_REAPPLY(xdevice_type, \
+ xifname, \
+ xconnection, \
+ xexternal_ids_old, \
+ xexternal_ids_new, \
+ xother_config_old, \
+ xother_config_new) \
+ (&((const OvsdbMethodPayload) { \
+ .set_reapply = {.device_type = xdevice_type, \
+ .ifname = (char *) NM_CONSTCAST(char, (xifname)), \
+ .connection = (xconnection), \
+ .external_ids_old = (xexternal_ids_old), \
+ .external_ids_new = (xexternal_ids_new), \
+ .other_config_old = (xother_config_old), \
+ .other_config_new = (xother_config_new)}, \
}))
/*****************************************************************************/
@@ -316,7 +313,7 @@ _call_complete(OvsdbMethodCall *call, json_t *response, GError *error)
break;
case OVSDB_SET_REAPPLY:
nm_clear_g_free(&call->payload.set_reapply.ifname);
- nm_clear_g_free(&call->payload.set_reapply.connection_uuid);
+ nm_clear_g_object(&call->payload.set_reapply.connection);
nm_clear_pointer(&call->payload.set_reapply.external_ids_old, g_hash_table_destroy);
nm_clear_pointer(&call->payload.set_reapply.external_ids_new, g_hash_table_destroy);
nm_clear_pointer(&call->payload.set_reapply.other_config_old, g_hash_table_destroy);
@@ -476,9 +473,9 @@ ovsdb_call_method(NMOvsdb *self,
call->payload.set_interface_mtu.mtu);
break;
case OVSDB_SET_REAPPLY:
- call->payload.set_reapply.device_type = payload->set_reapply.device_type;
- call->payload.set_reapply.ifname = g_strdup(payload->set_reapply.ifname);
- call->payload.set_reapply.connection_uuid = g_strdup(payload->set_reapply.connection_uuid);
+ call->payload.set_reapply.device_type = payload->set_reapply.device_type;
+ call->payload.set_reapply.ifname = g_strdup(payload->set_reapply.ifname);
+ call->payload.set_reapply.connection = payload->set_reapply.connection;
call->payload.set_reapply.external_ids_old =
nm_g_hash_table_ref(payload->set_reapply.external_ids_old);
call->payload.set_reapply.external_ids_new =
@@ -488,8 +485,8 @@ ovsdb_call_method(NMOvsdb *self,
call->payload.set_reapply.other_config_new =
nm_g_hash_table_ref(payload->set_reapply.other_config_new);
_LOGT_call(call,
- "new: set external-ids/other-config con-uuid=%s, interface=%s",
- call->payload.set_reapply.connection_uuid,
+ "new: reapply con-uuid=%s, interface=%s",
+ nm_connection_get_uuid(payload->set_reapply.connection),
call->payload.set_reapply.ifname);
break;
}
@@ -976,65 +973,79 @@ _insert_interface(json_t *params,
"rowInterface"));
}
-/**
- * _insert_port:
- *
- * Returns an commands that adds new port from a given connection.
- */
static void
-_insert_port(json_t *params, NMConnection *port, json_t *new_interfaces)
+ovsdb_row_set_string_or_null(json_t *row, const char *key, const char *str)
+{
+ /* ovsdb represents a NULL string (no value) as an empty set */
+ if (str) {
+ json_object_set_new(row, key, json_string(str));
+ } else {
+ json_object_set_new(row, key, json_pack("[s, []]", "set"));
+ }
+}
+
+static json_t *
+create_port_row_object(NMConnection *connection)
{
NMSettingOvsPort *s_ovs_port;
- const char *vlan_mode = NULL;
- json_t *trunks = NULL;
- guint tag = 0;
- const char *lacp = NULL;
- const char *bond_mode = NULL;
- guint bond_updelay = 0;
- guint bond_downdelay = 0;
json_t *row;
+ const char *s;
+ guint u;
- s_ovs_port = nm_connection_get_setting_ovs_port(port);
+ s_ovs_port = nm_connection_get_setting_ovs_port(connection);
+ nm_assert(s_ovs_port);
row = json_object();
- if (s_ovs_port) {
+ s = nm_setting_ovs_port_get_vlan_mode(s_ovs_port);
+ ovsdb_row_set_string_or_null(row, "vlan_mode", s);
+
+ u = nm_setting_ovs_port_get_tag(s_ovs_port);
+ json_object_set_new(row, "tag", u != 0 ? json_integer(u) : json_pack("[s, []]", "set"));
+
+ u = nm_setting_ovs_port_get_bond_updelay(s_ovs_port);
+ json_object_set_new(row, "bond_updelay", json_integer(u));
+
+ u = nm_setting_ovs_port_get_bond_downdelay(s_ovs_port);
+ json_object_set_new(row, "bond_downdelay", json_integer(u));
+
+ s = nm_setting_ovs_port_get_lacp(s_ovs_port);
+ ovsdb_row_set_string_or_null(row, "lacp", s);
+
+ s = nm_setting_ovs_port_get_bond_mode(s_ovs_port);
+ ovsdb_row_set_string_or_null(row, "bond_mode", s);
+
+ {
const GPtrArray *ranges;
- guint i;
+ json_t *trunks = json_array();
guint64 start;
guint64 end;
-
- vlan_mode = nm_setting_ovs_port_get_vlan_mode(s_ovs_port);
- tag = nm_setting_ovs_port_get_tag(s_ovs_port);
- lacp = nm_setting_ovs_port_get_lacp(s_ovs_port);
- bond_mode = nm_setting_ovs_port_get_bond_mode(s_ovs_port);
- bond_updelay = nm_setting_ovs_port_get_bond_updelay(s_ovs_port);
- bond_downdelay = nm_setting_ovs_port_get_bond_downdelay(s_ovs_port);
+ guint i;
ranges = _nm_setting_ovs_port_get_trunks_arr(s_ovs_port);
for (i = 0; i < ranges->len; i++) {
- if (!trunks)
- trunks = json_array();
nm_range_get_range(ranges->pdata[i], &start, &end);
for (; start <= end; start++)
json_array_append_new(trunks, json_integer(start));
}
- }
- if (vlan_mode)
- json_object_set_new(row, "vlan_mode", json_string(vlan_mode));
- if (tag)
- json_object_set_new(row, "tag", json_integer(tag));
- if (trunks)
json_object_set_new(row, "trunks", json_pack("[s, o]", "set", trunks));
- if (lacp)
- json_object_set_new(row, "lacp", json_string(lacp));
- if (bond_mode)
- json_object_set_new(row, "bond_mode", json_string(bond_mode));
- if (bond_updelay)
- json_object_set_new(row, "bond_updelay", json_integer(bond_updelay));
- if (bond_downdelay)
- json_object_set_new(row, "bond_downdelay", json_integer(bond_downdelay));
+ }
+
+ return row;
+}
+
+/**
+ * _insert_port:
+ *
+ * Returns a command that adds new port from a given connection.
+ */
+static void
+_insert_port(json_t *params, NMConnection *port, json_t *new_interfaces)
+{
+ json_t *row;
+
+ row = create_port_row_object(port);
json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(port)));
json_object_set_new(row, "interfaces", json_pack("[s, O]", "set", new_interfaces));
@@ -1058,10 +1069,50 @@ _insert_port(json_t *params, NMConnection *port, json_t *new_interfaces)
"rowPort"));
}
+static json_t *
+create_bridge_row_object(NMConnection *connection, gboolean is_reapply)
+{
+ NMSettingOvsBridge *s_ovs_bridge;
+ json_t *row;
+ gboolean b;
+ const char *s;
+
+ s_ovs_bridge = nm_connection_get_setting_ovs_bridge(connection);
+ nm_assert(s_ovs_bridge);
+
+ row = json_object();
+
+ b = nm_setting_ovs_bridge_get_mcast_snooping_enable(s_ovs_bridge);
+ json_object_set_new(row, "mcast_snooping_enable", json_boolean(b));
+
+ b = nm_setting_ovs_bridge_get_rstp_enable(s_ovs_bridge);
+ json_object_set_new(row, "rstp_enable", json_boolean(b));
+
+ b = nm_setting_ovs_bridge_get_stp_enable(s_ovs_bridge);
+ json_object_set_new(row, "stp_enable", json_boolean(b));
+
+ s = nm_setting_ovs_bridge_get_fail_mode(s_ovs_bridge);
+ ovsdb_row_set_string_or_null(row, "fail_mode", s);
+
+ if (!is_reapply) {
+ /* The datapath type can't be reapplied because after changing it,
+ * ovs removes the existing ovs-interface and creates a tun one (or
+ * vice-versa). */
+ s = nm_setting_ovs_bridge_get_datapath_type(s_ovs_bridge);
+ if (s) {
+ /* Cannot use ovsdb_row_set_string_or_null() here as the column
+ * is a set and must not be empty. */
+ json_object_set_new(row, "datapath_type", json_string(s));
+ }
+ }
+
+ return row;
+}
+
/**
* _insert_bridge:
*
- * Returns an commands that adds new bridge from a given connection.
+ * Returns a command that adds new bridge from a given connection.
*/
static void
_insert_bridge(json_t *params,
@@ -1070,36 +1121,9 @@ _insert_bridge(json_t *params,
json_t *new_ports,
const char *cloned_mac)
{
- NMSettingOvsBridge *s_ovs_bridge;
- const char *fail_mode = NULL;
- gboolean mcast_snooping_enable = FALSE;
- gboolean rstp_enable = FALSE;
- gboolean stp_enable = FALSE;
- const char *datapath_type = NULL;
- json_t *row;
-
- s_ovs_bridge = nm_connection_get_setting_ovs_bridge(bridge);
-
- row = json_object();
-
- if (s_ovs_bridge) {
- fail_mode = nm_setting_ovs_bridge_get_fail_mode(s_ovs_bridge);
- mcast_snooping_enable = nm_setting_ovs_bridge_get_mcast_snooping_enable(s_ovs_bridge);
- rstp_enable = nm_setting_ovs_bridge_get_rstp_enable(s_ovs_bridge);
- stp_enable = nm_setting_ovs_bridge_get_stp_enable(s_ovs_bridge);
- datapath_type = nm_setting_ovs_bridge_get_datapath_type(s_ovs_bridge);
- }
+ json_t *row;
- if (fail_mode)
- json_object_set_new(row, "fail_mode", json_string(fail_mode));
- if (mcast_snooping_enable)
- json_object_set_new(row, "mcast_snooping_enable", json_boolean(mcast_snooping_enable));
- if (rstp_enable)
- json_object_set_new(row, "rstp_enable", json_boolean(rstp_enable));
- if (stp_enable)
- json_object_set_new(row, "stp_enable", json_boolean(stp_enable));
- if (datapath_type)
- json_object_set_new(row, "datapath_type", json_string(datapath_type));
+ row = create_bridge_row_object(bridge, FALSE);
json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(bridge)));
json_object_set_new(row, "ports", json_pack("[s, O]", "set", new_ports));
@@ -1541,13 +1565,47 @@ ovsdb_next_command(NMOvsdb *self)
break;
case OVSDB_SET_REAPPLY:
{
- json_t *mutations;
+ NMConnection *connection;
+ json_t *mutations;
+ json_t *row;
+ const char *table;
+
+ connection = call->payload.set_reapply.connection;
+ table = _device_type_to_table(call->payload.set_reapply.device_type);
+
+ /* Reapply device properties */
+ switch (call->payload.set_reapply.device_type) {
+ case NM_DEVICE_TYPE_OVS_BRIDGE:
+ row = create_bridge_row_object(connection, TRUE);
+ break;
+ case NM_DEVICE_TYPE_OVS_PORT:
+ row = create_port_row_object(connection);
+ break;
+ default:
+ row = NULL;
+ break;
+ }
- mutations = json_array();
+ if (row) {
+ json_array_append_new(params,
+ json_pack("{s:s, s:s, s:o, s:[[s, s, s]]}",
+ "op",
+ "update",
+ "table",
+ table,
+ "row",
+ row,
+ "where",
+ "name",
+ "==",
+ call->payload.set_reapply.ifname));
+ }
+ /* Reapply external-ids and other-config */
+ mutations = json_array();
_j_create_strv_array_update(mutations,
STRDICT_TYPE_EXTERNAL_IDS,
- call->payload.set_reapply.connection_uuid,
+ nm_connection_get_uuid(connection),
call->payload.set_reapply.external_ids_old,
call->payload.set_reapply.external_ids_new);
_j_create_strv_array_update(mutations,
@@ -1556,19 +1614,18 @@ ovsdb_next_command(NMOvsdb *self)
call->payload.set_reapply.other_config_old,
call->payload.set_reapply.other_config_new);
- json_array_append_new(
- params,
- json_pack("{s:s, s:s, s:o, s:[[s, s, s]]}",
- "op",
- "mutate",
- "table",
- _device_type_to_table(call->payload.set_reapply.device_type),
- "mutations",
- mutations,
- "where",
- "name",
- "==",
- call->payload.set_reapply.ifname));
+ json_array_append_new(params,
+ json_pack("{s:s, s:s, s:o, s:[[s, s, s]]}",
+ "op",
+ "mutate",
+ "table",
+ table,
+ "mutations",
+ mutations,
+ "where",
+ "name",
+ "==",
+ call->payload.set_reapply.ifname));
break;
}
@@ -2975,7 +3032,7 @@ void
nm_ovsdb_set_reapply(NMOvsdb *self,
NMDeviceType device_type,
const char *ifname,
- const char *connection_uuid,
+ NMConnection *connection_take,
NMSettingOvsExternalIDs *s_external_ids_old,
NMSettingOvsExternalIDs *s_external_ids_new,
NMSettingOvsOtherConfig *s_other_config_old,
@@ -2986,6 +3043,11 @@ nm_ovsdb_set_reapply(NMOvsdb *self,
gs_unref_hashtable GHashTable *other_config_old = NULL;
gs_unref_hashtable GHashTable *other_config_new = NULL;
+ nm_assert(NM_IN_SET(device_type,
+ NM_DEVICE_TYPE_OVS_BRIDGE,
+ NM_DEVICE_TYPE_OVS_PORT,
+ NM_DEVICE_TYPE_OVS_INTERFACE));
+
external_ids_old =
s_external_ids_old
? nm_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_external_ids_old))
@@ -3011,7 +3073,7 @@ nm_ovsdb_set_reapply(NMOvsdb *self,
OVSDB_SET_REAPPLY,
OVSDB_METHOD_PAYLOAD_SET_REAPPLY(device_type,
ifname,
- connection_uuid,
+ connection_take,
external_ids_old,
external_ids_new,
other_config_old,
diff --git a/src/core/devices/ovs/nm-ovsdb.h b/src/core/devices/ovs/nm-ovsdb.h
index a022ff00ad..9b3fb8f941 100644
--- a/src/core/devices/ovs/nm-ovsdb.h
+++ b/src/core/devices/ovs/nm-ovsdb.h
@@ -50,7 +50,7 @@ void nm_ovsdb_set_interface_mtu(NMOvsdb *self,
void nm_ovsdb_set_reapply(NMOvsdb *self,
NMDeviceType device_type,
const char *ifname,
- const char *connection_uuid,
+ NMConnection *connection_take,
NMSettingOvsExternalIDs *s_external_ids_old,
NMSettingOvsExternalIDs *s_external_ids_new,
NMSettingOvsOtherConfig *s_other_config_old,
--
2.49.0

View File

@ -1,29 +0,0 @@
From 72df36f945042b85386ea514a2affac71aec2e96 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@redhat.com>
Date: Tue, 1 Apr 2025 08:43:24 +0200
Subject: [PATCH 1/1] core: ovs: fix NULL pointer dereference in ovsdb read
timeout callback
Fixes: f7d321c6d6ab ('ovsdb: add watchdog for unparsable JSON data in socket')
(cherry picked from commit dc9bf255eeb4d21452227a590486deef78aac4f8)
(cherry picked from commit 9ec498f3210cbf51e2f02068046630aa524f152e)
---
src/core/devices/ovs/nm-ovsdb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c
index e6d37d270c..2dbc842a73 100644
--- a/src/core/devices/ovs/nm-ovsdb.c
+++ b/src/core/devices/ovs/nm-ovsdb.c
@@ -2468,7 +2468,7 @@ again:
* content is broken (_json_read_msg() cannot extract any data) and
* we disconnect. */
priv->input_timeout_source =
- nm_g_timeout_add_seconds_source(5, _ovsdb_read_input_timeout_cb, NULL);
+ nm_g_timeout_add_seconds_source(5, _ovsdb_read_input_timeout_cb, self);
}
return;
}
--
2.49.0

View File

@ -1,28 +0,0 @@
From bf3494ceb989bc8fefb89d2366fe4024a1f055b5 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Fri, 16 May 2025 09:40:31 +0200
Subject: [PATCH] ip-config: fix crash in DNS options evaluation
Fixes: 58287cbcc0c8 ('core: rework IP configuration in NetworkManager using layer 3 configuration')
(cherry picked from commit c1350f40bdc769514f637b4b6754c4ff3ef67b66)
(cherry picked from commit 35f11cd6e130299cd554bb97e2c165031ed91a72)
---
src/core/nm-ip-config.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/nm-ip-config.c b/src/core/nm-ip-config.c
index eb0ec9aa03..975ae20d45 100644
--- a/src/core/nm-ip-config.c
+++ b/src/core/nm-ip-config.c
@@ -826,7 +826,7 @@ _handle_l3cd_changed(NMIPConfig *self, const NML3ConfigData *l3cd)
if (v_i != v_i_old)
changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DNS_PRIORITY];
- strarr_old = nm_l3_config_data_get_dns_options(l3cd_old, addr_family, &len);
+ strarr_old = nm_l3_config_data_get_dns_options(l3cd_old, addr_family, &len_old);
strarr = nm_l3_config_data_get_dns_options(priv->l3cd, addr_family, &len);
if (!nm_strv_equal_n(strarr, len, strarr_old, len_old))
changed_params[n_changed_params++] = obj_properties_ip[PROP_IP_DNS_OPTIONS];
--
2.49.0

View File

@ -1,223 +0,0 @@
From 78a4e5cf3bd2b8cba19c22826c1a4b99d3d7ef0e Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Wed, 16 Apr 2025 14:45:41 +0200
Subject: [PATCH 1/2] ovs: slightly improve _delete_interface()
Add comments, and move variables inside the block where they are used.
---
src/core/devices/ovs/nm-ovsdb.c | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c
index 60f6209521..39acf1da46 100644
--- a/src/core/devices/ovs/nm-ovsdb.c
+++ b/src/core/devices/ovs/nm-ovsdb.c
@@ -1363,54 +1363,57 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname)
nm_auto_decref_json json_t *bridges = NULL;
nm_auto_decref_json json_t *new_bridges = NULL;
gboolean bridges_changed;
- gboolean ports_changed;
- gboolean interfaces_changed;
- int pi;
- int ii;
bridges = json_array();
new_bridges = json_array();
bridges_changed = FALSE;
+ /* Loop over all bridges */
g_hash_table_iter_init(&iter, priv->bridges);
while (g_hash_table_iter_next(&iter, (gpointer) &ovs_bridge, NULL)) {
- nm_auto_decref_json json_t *ports = NULL;
- nm_auto_decref_json json_t *new_ports = NULL;
+ nm_auto_decref_json json_t *ports = NULL;
+ nm_auto_decref_json json_t *new_ports = NULL;
+ gboolean ports_changed = FALSE;
+ int pi;
ports = json_array();
new_ports = json_array();
- ports_changed = FALSE;
+ /* Add the bridge UUID to the list of known bridges for the "expect" condition */
json_array_append_new(bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
+ /* Loop over all bridge's ports */
for (pi = 0; pi < ovs_bridge->ports->len; pi++) {
nm_auto_decref_json json_t *interfaces = NULL;
nm_auto_decref_json json_t *new_interfaces = NULL;
+ gboolean interfaces_changed = FALSE;
+ int ii;
interfaces = json_array();
new_interfaces = json_array();
port_uuid = g_ptr_array_index(ovs_bridge->ports, pi);
ovs_port = g_hash_table_lookup(priv->ports, &port_uuid);
+ /* Add the port UUID to the list of known bridge port for the "expect" condition */
json_array_append_new(ports, json_pack("[s,s]", "uuid", port_uuid));
- interfaces_changed = FALSE;
-
if (!ovs_port) {
/* This would be a violation of ovsdb's reference integrity (a bug). */
_LOGW("Unknown port '%s' in bridge '%s'", port_uuid, ovs_bridge->bridge_uuid);
continue;
}
+ /* Loop over all port's interfaces */
for (ii = 0; ii < ovs_port->interfaces->len; ii++) {
interface_uuid = g_ptr_array_index(ovs_port->interfaces, ii);
ovs_interface = g_hash_table_lookup(priv->interfaces, &interface_uuid);
+ /* Add the interface UUID to the list of known port interfaces for the "expect" condition */
json_array_append_new(interfaces, json_pack("[s,s]", "uuid", interface_uuid));
if (ovs_interface) {
if (nm_streq(ovs_interface->name, ifname)) {
- /* skip the interface */
+ /* We are deleting this interface, don't count it */
interfaces_changed = TRUE;
continue;
}
@@ -1419,32 +1422,42 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname)
_LOGW("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid);
}
+ /* Add the interface to the list of new interfaces to set on the port */
json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid));
}
if (json_array_size(new_interfaces) == 0) {
+ /* The port no longer has any interface. Don't add it to "new_ports" and set
+ * ports_changed=TRUE, so that it will be deleted. */
ports_changed = TRUE;
} else {
if (interfaces_changed) {
+ /* An interface needs to be deleted from this port */
_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 (json_array_size(new_ports) == 0) {
+ /* The bridge no longer has any port. Don't add it to "new_bridges" and set
+ * bridges_changed=TRUE, so that it will be deleted. */
bridges_changed = TRUE;
} else {
if (ports_changed) {
+ /* A port needs to be deleted from this bridge */
_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 */
_expect_ovs_bridges(params, priv->db_uuid, bridges);
_set_ovs_bridges(params, priv->db_uuid, new_bridges);
}
--
2.50.1
From 476c89b6f2cd514fca8797bdc503eff60dc3db18 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Wed, 16 Apr 2025 15:16:13 +0200
Subject: [PATCH 2/2] ovs: only keep bridges and ports with NM interfaces
attached
If a OVS bridge created via NM has a port created externally, when the
bridge connections goes down then NM detaches the NM-created
port. However, it finds that the bridge still has a port (the external
one) and so it doesn't remove the bridge from ovsdb.
This is a problem, because it means that an explicity deactivation of
the bridge leaves the bridge up. To fix this, only track the number of
port in the bridge actually created by NM. Also, leave alone bridges
not created by NM.
---
src/core/devices/ovs/nm-ovsdb.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c
index 39acf1da46..b36d4bb09b 100644
--- a/src/core/devices/ovs/nm-ovsdb.c
+++ b/src/core/devices/ovs/nm-ovsdb.c
@@ -1373,19 +1373,27 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname)
while (g_hash_table_iter_next(&iter, (gpointer) &ovs_bridge, NULL)) {
nm_auto_decref_json json_t *ports = NULL;
nm_auto_decref_json json_t *new_ports = NULL;
+ guint num_nm_ports = 0;
gboolean ports_changed = FALSE;
int pi;
- ports = json_array();
- new_ports = json_array();
+ ports = json_array();
+ new_ports = json_array();
/* Add the bridge UUID to the list of known bridges for the "expect" condition */
json_array_append_new(bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
+ if (!ovs_bridge->connection_uuid) {
+ /* Externally created, don't touch it */
+ json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid));
+ continue;
+ }
+
/* Loop over all bridge's ports */
for (pi = 0; pi < ovs_bridge->ports->len; pi++) {
- nm_auto_decref_json json_t *interfaces = NULL;
- nm_auto_decref_json json_t *new_interfaces = NULL;
+ nm_auto_decref_json json_t *interfaces = NULL;
+ nm_auto_decref_json json_t *new_interfaces = NULL;
+ guint num_nm_interfaces = 0;
gboolean interfaces_changed = FALSE;
int ii;
@@ -1417,6 +1425,8 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname)
interfaces_changed = TRUE;
continue;
}
+ if (ovs_interface->connection_uuid)
+ num_nm_interfaces++;
} else {
/* This would be a violation of ovsdb's reference integrity (a bug). */
_LOGW("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid);
@@ -1426,8 +1436,8 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname)
json_array_append_new(new_interfaces, json_pack("[s,s]", "uuid", interface_uuid));
}
- if (json_array_size(new_interfaces) == 0) {
- /* The port no longer has any interface. Don't add it to "new_ports" and set
+ 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. */
ports_changed = TRUE;
} else {
@@ -1438,11 +1448,13 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname)
}
/* 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 (json_array_size(new_ports) == 0) {
- /* The bridge no longer has any port. Don't add it to "new_bridges" and set
+ 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. */
bridges_changed = TRUE;
} else {
--
2.50.1

View File

@ -1,64 +0,0 @@
From fd3eccfb1612a3bac87232e1cbaabc10da80c302 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Wed, 7 May 2025 15:19:03 +0200
Subject: [PATCH] device: update the external-down unmanaged flag on port
attach/release
A device has the "external-down" unmanaged flag when:
!is-created-by-nm AND (!is-up OR (!has-address AND !is-controller))
When the "is-up" or the "has-address" conditions change, we properly update
the unmanaged flag by calling _dev_unmanaged_check_external_down() in
_dev_l3_cfg_notify_cb(PLATFORM_CHANGE_ON_IDLE).
The "is-controller" condition changes when another link indicates the
current device as controller. We currently don't update the unmanaged flag
when that happens and so it's possible that the device stays unmanaged even
if it has a port. This can be easily reproduced by running this commands:
ip link add veth0 type veth peer name veth1
ip link add vrf0 type vrf table 10
ip link set vrf0 up
ip link set veth0 master vrf0
Sometimes, the device shows as "unmanaged" instead of "connected
(externally)".
Fix this by re-evaluating the "external-down" unmanaged flags on the
controller when a port is attached or detached.
Fixes: c3586ce01a5b ('device: consider a device with slaves configured')
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2209
---
src/core/devices/nm-device.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index fc6efb2b3c..793378be88 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -7158,6 +7158,9 @@ nm_device_controller_release_port(NMDevice *self,
NM_UNMANAGED_IS_PORT,
NM_UNMAN_FLAG_OP_FORGET,
NM_DEVICE_STATE_REASON_REMOVED);
+
+ /* Once the port is detached, unmanaged-external-down might change */
+ _dev_unmanaged_check_external_down(self, FALSE, FALSE);
}
/*****************************************************************************/
@@ -8852,6 +8855,9 @@ nm_device_controller_add_port(NMDevice *self, NMDevice *port, gboolean configure
} else
g_return_val_if_fail(port_priv->controller == self, FALSE);
+ /* Once the port is attached, unmanaged-external-down might change */
+ _dev_unmanaged_check_external_down(self, TRUE, FALSE);
+
nm_device_queue_recheck_assume(self);
nm_device_queue_recheck_assume(port);
--
2.50.1

View File

@ -1,217 +0,0 @@
From 46e0d2b4e4eb5948db12186a3c60d3fd98ae8cd4 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Wed, 4 Jun 2025 10:57:51 +0200
Subject: [PATCH] ovs: set the tun interface up before stage3
When using the netdev datapath, we wait that the tun link appears, we
call nm_device_set_ip_ifindex() (which also brings the link up) and
then we check that the link is ready, i.e. that udev has announced the
link and the MAC address is correct. After that, we schedule stage3
(ip-config).
In this, there is a race condition that occurs sometimes in NMCI test
ovs_datapath_type_netdev_with_cloned_mac. In rare conditions,
nm_device_set_ip_ifindex() bring the interface up but then ovs-vswitch
changes again the flags of the interface without IFF_UP. The result is
that the interface stays down, breaking communications.
To fix this, we need to always call nm_device_bring_up() after the tun
device is ready. The problem is that we can't do it in
_netdev_tun_link_cb() because that function is already invoked
synchronously from platform code.
Instead, simplify the handling of the netdev datapath. Every
"link-changed" event from platform is handled by
_netdev_tun_link_cb(), which always schedule a delayed function
_netdev_tun_link_cb_in_idle(). This function just assigns the
ip-ifindex to the device if missing, and starts stage3 if the link is
ready. While doing so, it also bring the interface up.
Fixes: 99a6c6eda6e1 ('ovs, dpdk: fix creating ovs-interface when the ovs-bridge is netdev')
https://issues.redhat.com/browse/RHEL-17358
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2218
---
.../devices/ovs/nm-device-ovs-interface.c | 100 ++++++++----------
1 file changed, 42 insertions(+), 58 deletions(-)
diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c
index 271dedeab3..922ed34571 100644
--- a/src/core/devices/ovs/nm-device-ovs-interface.c
+++ b/src/core/devices/ovs/nm-device-ovs-interface.c
@@ -28,16 +28,18 @@ typedef struct {
NMOvsdb *ovsdb;
struct {
- /* The source for the idle handler to set the TUN ifindex */
- GSource *tun_set_ifindex_idle_source;
- /* The cloned MAC to set */
- char *cloned_mac;
- /* The id for the signal watching the TUN link to appear/change */
+ /* The signal id for the TUN link-changed event */
gulong tun_link_signal_id;
- /* The TUN ifindex to set in the idle handler */
+ /* The idle handler source for the TUN link-changed event */
+ GSource *tun_link_idle_source;
+ /* The ifindex for the TUN link-changed event */
int tun_ifindex;
+
+ /* The cloned MAC to set */
+ char *cloned_mac;
/* Whether we have determined the cloned MAC */
bool cloned_mac_evaluated : 1;
+
/* Whether we are waiting for the kernel link */
bool waiting : 1;
} wait_link;
@@ -263,39 +265,33 @@ ready_for_ip_config(NMDevice *device, gboolean is_manual)
}
static gboolean
-_set_ip_ifindex_tun(gpointer user_data)
+_netdev_tun_link_cb_in_idle(gpointer user_data)
{
NMDevice *device = user_data;
NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device);
NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
- _LOGT(LOGD_CORE,
- "ovs-wait-link: setting ip-ifindex %d from tun interface",
- priv->wait_link.tun_ifindex);
-
- nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
-
- nm_device_set_ip_ifindex(device, priv->wait_link.tun_ifindex);
-
- if (check_waiting_for_link(device, "set-ip-ifindex-tun")) {
- /* If the link is not ready, it means the MAC is not set yet. We don't have
- * a convenient way to monitor for ip-ifindex changes other than listening
- * for platform events again.*/
- nm_assert(!priv->wait_link.tun_link_signal_id);
- priv->wait_link.tun_link_signal_id = g_signal_connect(nm_device_get_platform(device),
- NM_PLATFORM_SIGNAL_LINK_CHANGED,
- G_CALLBACK(_netdev_tun_link_cb),
- self);
- return G_SOURCE_CONTINUE;
+ if (nm_device_get_ip_ifindex(device) <= 0) {
+ _LOGT(LOGD_CORE,
+ "ovs-wait-link: setting ip-ifindex %d from tun link",
+ priv->wait_link.tun_ifindex);
+ nm_device_set_ip_ifindex(device, priv->wait_link.tun_ifindex);
}
- _LOGT(LOGD_CORE, "tun link is ready");
+ if (check_waiting_for_link(device, "tun-link-changed")) {
+ nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
+ return G_SOURCE_CONTINUE;
+ }
+ _LOGT(LOGD_CORE, "ovs-wait-link: tun link is ready");
nm_device_link_properties_set(device, FALSE);
+ nm_device_bring_up(device);
nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL);
nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL);
nm_device_activate_schedule_stage3_ip_config(device, FALSE);
+ nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
+ nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
return G_SOURCE_CONTINUE;
}
@@ -311,40 +307,28 @@ _netdev_tun_link_cb(NMPlatform *platform,
const NMPlatformSignalChangeType change_type = change_type_i;
NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device);
NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self);
- int ip_ifindex;
- if (pllink->type != NM_LINK_TYPE_TUN || !nm_streq0(pllink->name, nm_device_get_iface(device)))
+ /* This is the handler for the link-changed platform events. It is triggered for all
+ * link changes. Keep only the ones matching our device. */
+ if (!NM_IN_SET(change_type, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_SIGNAL_CHANGED))
return;
-
- ip_ifindex = nm_device_get_ip_ifindex(device);
- if (ip_ifindex > 0) {
- /* When we have an ifindex, we are only waiting for the MAC to settle */
- if (change_type != NM_PLATFORM_SIGNAL_CHANGED)
- return;
-
- if (!check_waiting_for_link(device, "tun-link-changed")) {
- _LOGT(LOGD_CORE, "ovs-wait-link: tun link is ready, cloned MAC is set");
-
- nm_clear_g_signal_handler(platform, &priv->wait_link.tun_link_signal_id);
- nm_device_link_properties_set(device, FALSE);
-
- nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL);
- nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL);
- nm_device_activate_schedule_stage3_ip_config(device, FALSE);
- }
- return;
- }
-
- /* No ip-ifindex on the device, set it when the link appears */
- if (change_type != NM_PLATFORM_SIGNAL_ADDED)
+ if (pllink->type != NM_LINK_TYPE_TUN || !nm_streq0(pllink->name, nm_device_get_iface(device)))
return;
_LOGT(LOGD_CORE,
- "ovs-wait-link: found matching tun interface, schedule set-ip-ifindex(%d)",
+ "ovs-wait-link: got platform event \'%s\' for ifindex %d, scheduling idle handler",
+ change_type == NM_PLATFORM_SIGNAL_ADDED ? "added" : "changed",
ifindex);
- nm_clear_g_signal_handler(platform, &priv->wait_link.tun_link_signal_id);
- priv->wait_link.tun_ifindex = ifindex;
- priv->wait_link.tun_set_ifindex_idle_source = nm_g_idle_add_source(_set_ip_ifindex_tun, device);
+
+ /* The handler is invoked by the platform synchronously in the netlink receive loop.
+ * We can't perform other platform operations (like bringing the interface up) since
+ * the code there is not re-entrant. Schedule an idle handler. */
+ nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
+ priv->wait_link.tun_link_idle_source =
+ nm_g_idle_add_source(_netdev_tun_link_cb_in_idle, device);
+ priv->wait_link.tun_ifindex = ifindex;
+
+ return;
}
static gboolean
@@ -466,7 +450,7 @@ act_stage3_ip_config(NMDevice *device, int addr_family)
nm_device_activate_schedule_stage3_ip_config(device, TRUE);
return;
}
- nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
+ nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
nm_device_link_properties_set(device, FALSE);
@@ -490,7 +474,7 @@ deactivate(NMDevice *device)
priv->wait_link.cloned_mac_evaluated = FALSE;
nm_clear_g_free(&priv->wait_link.cloned_mac);
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
- nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
+ nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
}
typedef struct {
@@ -583,7 +567,7 @@ deactivate_async(NMDevice *device,
_LOGT(LOGD_CORE, "deactivate: start async");
nm_clear_g_signal_handler(nm_device_get_platform(device), &priv->wait_link.tun_link_signal_id);
- nm_clear_g_source_inst(&priv->wait_link.tun_set_ifindex_idle_source);
+ nm_clear_g_source_inst(&priv->wait_link.tun_link_idle_source);
priv->wait_link.tun_ifindex = -1;
priv->wait_link.cloned_mac_evaluated = FALSE;
nm_clear_g_free(&priv->wait_link.cloned_mac);
@@ -706,7 +690,7 @@ dispose(GObject *object)
nm_assert(!priv->wait_link.waiting);
nm_assert(priv->wait_link.tun_link_signal_id == 0);
- nm_assert(!priv->wait_link.tun_set_ifindex_idle_source);
+ nm_assert(!priv->wait_link.tun_link_idle_source);
if (priv->ovsdb) {
g_signal_handlers_disconnect_by_func(priv->ovsdb, G_CALLBACK(ovsdb_ready), self);
--
2.50.1

View File

@ -1,82 +0,0 @@
From 1489f9d0e32ac1e9f5f86f5fc940a3c8ed6fc17e Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Tue, 8 Jul 2025 15:09:25 +0200
Subject: [PATCH 1/2] bridge: fix reapplying port VLANs
If the bridge default-pvid is zero, it means that the default PVID is
disabled. That is, the bridge PVID is not propagated to ports.
Currently NM tries to merge the existing bridge VLANs on the port with
the default PVID from the bridge, even when the PVID is zero. This
causes an error when setting the new VLAN list in the kernel, because
it rejects VLAN zero.
Skip the merge of the default PVID when zero.
Fixes: c5d1e35f993e ('device: support reapplying bridge-port VLANs')
(cherry picked from commit bf79fbd6780fd38ca29c12a137951c8729379767)
(cherry picked from commit 956f9ba365c18bf00d91ffd0842c09932dd9a5ec)
---
src/core/devices/nm-device-bridge.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/core/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c
index 7c34fde07f..45cdd83f07 100644
--- a/src/core/devices/nm-device-bridge.c
+++ b/src/core/devices/nm-device-bridge.c
@@ -735,6 +735,11 @@ merge_bridge_vlan_default_pvid(NMPlatformBridgeVlan *vlans, guint *num_vlans, gu
gboolean has_pvid = FALSE;
guint i;
+ if (default_pvid == 0) {
+ /* default_pvid=0 means that the default PVID is disabled. No need to merge it. */
+ return vlans;
+ }
+
for (i = 0; i < *num_vlans; i++) {
if (vlans[i].pvid) {
has_pvid = TRUE;
--
2.50.1
From 0135379ac48b71f5029c72f368b44d9e1244ef80 Mon Sep 17 00:00:00 2001
From: Beniamino Galvani <bgalvani@redhat.com>
Date: Tue, 8 Jul 2025 17:16:25 +0200
Subject: [PATCH 2/2] device: accept changes to the bond-port.vlans during
reapply
Commit c5d1e35f993e ('device: support reapplying bridge-port VLANs')
didn't update can_reapply_change() to accept the "bridge-port.vlans"
property during a reapply. So, it was only possible to change the
bridge port VLANs by updating the "bridge.vlan-default-pvid" property
and doing a reapply. Fix that.
Fixes: c5d1e35f993e ('device: support reapplying bridge-port VLANs')
(cherry picked from commit 261fa8db336e0571479567e2bda10dbf5d171b0a)
(cherry picked from commit c647c060d6dabefeb05f6be6c4af8778437d9a1e)
---
src/core/devices/nm-device.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 2f2f25a5b8..dee160ed90 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -14003,6 +14003,13 @@ can_reapply_change(NMDevice *self,
return TRUE;
}
+ if (nm_streq(setting_name, NM_SETTING_BRIDGE_PORT_SETTING_NAME)) {
+ return nm_device_hash_check_invalid_keys(diffs,
+ NM_SETTING_BRIDGE_PORT_SETTING_NAME,
+ error,
+ NM_SETTING_BRIDGE_PORT_VLANS);
+ }
+
out_fail:
g_set_error(error,
NM_DEVICE_ERROR,
--
2.50.1

View File

@ -1,54 +0,0 @@
From 9bbb1139872b6a3cb21e1c08c7853057b4ee2674 Mon Sep 17 00:00:00 2001
From: Lubomir Rintel <lkundrak@v3.sk>
Date: Mon, 30 Jun 2025 15:50:44 +0200
Subject: [PATCH] device: don't disable IPv6 in stage3 on reapply
Currently, when a call to Reapply() results in stage3 being re-run, IPv6
ends up messed up. Like this:
$ nmcli device modify eth0 ipv4.address ''
$ nmcli device modify eth0 ipv4.address 172.31.13.37/24
$
NetworkManager[666]: <debug> [1751286095.2070] device[c95ca04a69467d81] (eth0): ip4: reapply...
...
NetworkManager[666]: <debug> [1751286095.2104] device[c95ca04a69467d81] (eth0): ip6: addrgenmode6: set none (already set)
NetworkManager[666]: <debug> [1751286095.2105] device[c95ca04a69467d81] (eth0): ip6: addrgenmode6: toggle disable_ipv6 sysctl after disabling addr-gen-mode
NetworkManager[666]: <debug> [1751286095.2105] platform-linux: sysctl: setting '/proc/sys/net/ipv6/conf/eth0/disable_ipv6' to '1' (current value is '0')
NetworkManager[666]: <debug> [1751286095.2106] platform-linux: sysctl: setting '/proc/sys/net/ipv6/conf/eth0/disable_ipv6' to '0' (current value is '1')
NetworkManager[666]: <debug> [1751286095.2106] platform-linux: sysctl: setting '/proc/sys/net/ipv6/conf/eth0/accept_ra' to '0' (current value is identical)
NetworkManager[666]: <debug> [1751286095.2106] platform-linux: sysctl: setting '/proc/sys/net/ipv6/conf/eth0/disable_ipv6' to '0' (current value is identical)
Not only is this unnecessary because addr-gen-mode already has the
desired value (as is logged), but also wipes off all IPv6 configuration.
This is fine on initial configuration, but not on Reapply().
Let's look at the device state first: if we've progressed past ip-config
state, then we can't possibly ever touch the offending sysctls. It's
okay -- we don't need to: addr-gen-mode is going to be set right if we
went through ip-config before.
Resolves: https://issues.redhat.com/browse/NMT-1681
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2232
---
src/core/devices/nm-device.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 7aaf4d78ed..9e0a53cd32 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -13437,7 +13437,8 @@ activate_stage3_ip_config(NMDevice *self)
* IPv6LL if this is not an assumed connection, since assumed connections
* will already have IPv6 set up.
*/
- if (!nm_device_managed_type_is_external_or_assume(self))
+ if ((priv->state <= NM_DEVICE_STATE_IP_CONFIG || priv->ip_data_6.do_reapply)
+ && !nm_device_managed_type_is_external_or_assume(self))
_dev_addrgenmode6_set(self, NM_IN6_ADDR_GEN_MODE_NONE);
/* Re-enable IPv6 on the interface */
--
2.50.1

View File

@ -1,93 +0,0 @@
From 589556437b65dba2a1630d923fd7ff877ed8d6cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= <ihuguet@riseup.net>
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

View File

@ -1,184 +0,0 @@
From d2c3ea6166cf3ada470ee0caf652470e645445af Mon Sep 17 00:00:00 2001
From: Jan Vaclav <jvaclav@redhat.com>
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 <jvaclav@redhat.com>
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

View File

@ -4,10 +4,10 @@
%global glib2_version %(pkg-config --modversion glib-2.0 2>/dev/null || echo bad)
%global epoch_version 1
%global real_version 1.52.0
%global git_tag_version_suffix %{nil}
%global real_version 1.54.0
%global git_tag_version 1.54.0
%global rpm_version %{real_version}
%global release_version 8
%global release_version 1
%global snapshot %{nil}
%global git_sha %{nil}
%global bcond_default_debug 0
@ -172,7 +172,7 @@ Group: System Environment/Base
License: GPL-2.0-or-later AND LGPL-2.1-or-later
URL: https://networkmanager.dev/
Source: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/releases/%{real_version}%{git_tag_version_suffix}/downloads/%{name}-%{real_version}.tar.xz
Source: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/releases/%{git_tag_version}/downloads/%{name}-%{real_version}.tar.xz
Source1: NetworkManager.conf
Source2: 00-server.conf
Source4: 20-connectivity-fedora.conf
@ -189,19 +189,6 @@ Source9: readme-ifcfg-rh-migrated.txt
# Bugfixes that are only relevant until next rebase of the package.
# Patch1001: 1001-some.patch
Patch1001: 1001-core-fail-early-if-we-cannot-get-current-FEC-value-86838.patch
Patch1002: 1002-oci-update-disconnected-vnics-83198.patch
Patch1003: 1003-dns-Fix-invalid-memory-access-on-Dnsconfd-DBUS-error-83175.patch
Patch1004: 1004-ovs-allow-reapplying-ovs-bridge-and-ovs-port-properties-87597.patch
Patch1005: 1005-core-ovs-fix-NULL-pointer-dereference-in-ovsdb-read-timeout-callback-87348.patch
Patch1006: 1006-fix-crash-in-dns-options-rhel-97261.patch
Patch1007: 1007-ovs-only-keep-bridges-and-ports-with-NM-interfaces-attached-87169.patch
Patch1008: 1008-device-update-the-external-down-unmanaged-flag-on-port-attach-release-97258.patch
Patch1009: 1009-ovs-set-the-tun-interface-up-before-stage3-98552.patch
Patch1010: 1010-bridge-fix-reapplying-port-VLANs-102744.patch
Patch1011: 1011-device-dont-disable-IPv6-in-stage3-on-reapply-102773.patch
Patch1012: 1012-ovs-don-t-remove-unrelated-external-ports-rhel-121105.patch
Patch1013: 1013-support-reapplying-sriov-vfs-rhel-113955.patch
Requires(post): systemd
Requires(post): systemd-udev
@ -317,6 +304,7 @@ BuildRequires: libubsan
BuildRequires: firewalld-filesystem
BuildRequires: iproute
BuildRequires: iproute-tc
BuildRequires: libnvme-devel >= 1.5
Provides: %{name}-dispatcher%{?_isa} = %{epoch}:%{version}-%{release}
@ -777,6 +765,11 @@ rm -f %{buildroot}%{_libdir}/*.la
rm -f %{buildroot}%{_libdir}/pppd/%{ppp_version}/*.la
rm -f %{buildroot}%{nmplugindir}/*.la
# Don't use the *-initrd.service files yet, wait dracut to support them
rm -f %{buildroot}%{_unitdir}/NetworkManager-config-initrd.service
rm -f %{buildroot}%{_unitdir}/NetworkManager-initrd.service
rm -f %{buildroot}%{_unitdir}/NetworkManager-wait-online-initrd.service
# Ensure the documentation timestamps are constant to avoid multilib conflicts
find %{buildroot}%{_datadir}/gtk-doc -exec touch --reference meson.build '{}' \+
@ -1093,33 +1086,53 @@ fi
%changelog
* Wed Oct 15 2025 Íñigo Huguet <ihuguet@redhat.com> - 1:1.52.0-8
- Support reapplying sriov.vfs (RHEL-113955)
- Fix removing unrelated OVS ports (RHEL-121105)
* Mon Aug 04 2025 Filip Pokryvka <fpokryvk@redhat.com> - 1:1.54.0-1
- Update to 1.54.0
- Fix reaply on bridge port VLAN (RHEL-102318)
- Accept hostnames longer than 64 characters from DNS lookup (RHEL-104357)
* Wed Aug 13 2025 Vladimír Beneš <vbenes@redhat.com> - 1:1.52.0-7
- ovs: only keep bridges and ports with NM interfaces attached #2 (RHEL-87167)
* Fri Jul 11 2025 Filip Pokryvka <fpokryvk@redhat.com> - 1:1.53.92-1
- Update to 1.54.0 (rc3)
- Fix ipv6 static route deleted with dualstack (RHEL-102774)
- Allow setting IP method to disabled in port connections (RHEL-90756)
* Tue Aug 12 2025 Vladimír Beneš <vbenes@redhat.com> - 1:1.52.0-6
- ovs: only keep bridges and ports with NM interfaces attached (RHEL-87169)
- device: update the external-down unmanaged flag on port attach/release (RHEL-97258)
- ovs: set the tun interface up before stage3 (RHEL-98552)
- bridge: fix reapplying port VLANs (RHEL-102744)
- device: don't disable IPv6 in stage3 on reapply (RHEL-102773)
* Fri Jun 20 2025 Filip Pokryvka <fpokryvk@redhat.com> - 1:1.53.91-1
- Update to 1.54.0 (rc2)
- Support deactivating a connection without resetting SRIOV sriov_numvfs (RHEL-69125)
- Fix a race condition in ovs tun interface (RHEL-17358)
* Fri Jul 18 2025 Íñigo Huguet <ihuguet@redhat.com> - 1:1.52.0-5
- Fix crash in DNS options evaluation (RHEL-97261)
* Fri May 30 2025 Vladimír Beneš <vbenes@redhat.com> - 1:1.53.90-1
- Update to 1.54.0 (rc1)
- Devices not becoming managed sometimes (RHEL-89914)
- Crash on _l3cfg_notify_cb (RHEL-92020)
- Fix autoconnect-ports for unrealized VLANs and other virtual devices (NMT-1610)
* Thu May 15 2025 Wen Liang <wenliang@redhat.com> - 1:1.52.0-4
- ovs: allow reapplying ovs-bridge and ovs-port properties (RHEL-87597)
- core: ovs: fix NULL pointer dereference in ovsdb read timeout callback (RHEL-87348)
* Mon May 5 2025 Vladimír Beneš <vbenes@redhat.com> - 1:1.53.4-1
- Update to 1.53.4 (dev)
- initrd: add new NBFT parser (RHEL-83058)
- Add support for configuring per-device IPv4 sysctl forwarding option in NetworkManager (RHEL-89582)
- Support reapply on OVS settings (RHEL-86877)
- Add support for configuring the loopback interface in nmtui (RHEL-70484)
- Replace ioctl wth netlink for ethtool in NetworkManager (RHEL-1794)
- NetworkManager does not add the `lock` attribute when `rto_min` is used (RHEL-83752)
- Can not change `bridge.options.mcast-snooping-enable` on partial managemd OVS bridge (RHEL-86767)
* Sat Apr 12 2025 Vladimír Beneš <vbenes@redhat.com> - 1:1.52.0-3
- Invalid memory access on Dnsconfd DBUS error (RHEL-84691)
- Support IP configuration for secondary interfaces on Oracle VM from metadata (RHEL-85644)
* Mon Apr 14 2025 Filip Pokrývka <fpokryvk@redhat.com> - 1:1.53.3-1
- Update to 1.53.3 (dev)
- Add more IPv6 prefix delegation options (RHEL-81948)
- Fix order of parsing port/controller properies in nmcli (RHEL-80273)
- Improve interface activation logic (RHEL-80157)
- Fix WireGuard IPv6 firewall rules (RHEL-79975)
- Support OVS-DPDK dpdk-lsc-interrupt and mtu_request configurations (RHEL-78769)
* Wed Apr 09 2025 Wen Liang <wenliang@redhat.com> - 1:1.52.0-2
- core: fail early if we cannot get current FEC value (RHEL-86838)
* Mon Mar 24 2025 Vladimír Beneš <vbenes@redhat.com> - 1:1.53.2-1
- Update to 1.53.2 (dev)
- Fix invalid memory access on Dnsconfd DBUS error (RHEL-83175)
- Avoid getting transient hostname when "localhost" set in /etc/hostname (RHEL-55730)
* Mon Mar 03 2025 Íñigo Huguet <ihuguet@redhat.com> - 1:1.53.1-1
- Update to 1.53.1 (dev)
- Update MPTCP endpoints creation order (RHEL-80487)
* Mon Mar 03 2025 Íñigo Huguet <ihuguet@redhat.com> - 1:1.52.0-1
- Update to 1.52.0

View File

@ -1 +1 @@
SHA512 (NetworkManager-1.52.0.tar.xz) = 5a9e4273ef8b3a3bc9b9e15b7876e140c4accefd7d6143dfc6732b5ea62e6333838156338adcb8808b626586e0fe546bec2215a7e8e629560ce01c2e690bbffb
SHA512 (NetworkManager-1.54.0.tar.xz) = 78bb405f28918556fa921cf290e16a85a10c8b633d98fa764d1723f8e6af66ae9952b7a1a8576522081eead14b1171e55e766ba4b501e9c42665b179757a7626