import UBI NetworkManager-1.52.0-7.el9_6

This commit is contained in:
eabdullin 2025-09-16 08:20:34 +00:00
parent 2d77189a81
commit bfc589ffb6
6 changed files with 657 additions and 2 deletions

View File

@ -0,0 +1,223 @@
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

@ -0,0 +1,64 @@
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

@ -0,0 +1,217 @@
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

@ -0,0 +1,82 @@
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

@ -0,0 +1,54 @@
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

@ -7,7 +7,7 @@
%global real_version 1.52.0
%global git_tag_version_suffix %{nil}
%global rpm_version %{real_version}
%global release_version 5
%global release_version 7
%global snapshot %{nil}
%global git_sha %{nil}
%global bcond_default_debug 0
@ -196,6 +196,11 @@ Patch1003: 1003-dns-Fix-invalid-memory-access-on-Dnsconfd-DBUS-error-84692.patch
Patch1004: 1004-ovs-allow-reapplying-ovs-bridge-and-ovs-port-properties-87595.patch
Patch1005: 1005-core-ovs-fix-NULL-pointer-dereference-in-ovsdb-read-timeout-callback-87347.patch
Patch1006: 1006-fix-crash-in-dns-options-rhel-92313.patch
Patch1007: 1007-ovs-only-keep-bridges-and-ports-with-NM-interfaces-attached-87167.patch
Patch1008: 1008-device-update-the-external-down-unmanaged-flag-on-port-attach-release-93183.patch
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
Requires(post): systemd
Requires(post): systemd-udev
@ -1087,6 +1092,16 @@ fi
%changelog
* 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)
* 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-87167)
- device: update the external-down unmanaged flag on port attach/release (RHEL-93183)
- ovs: set the tun interface up before stage3 (RHEL-98550)
- bridge: fix reapplying port VLANs (RHEL-102742)
- device: don't disable IPv6 in stage3 on reapply (RHEL-102771)
* Fri Jul 18 2025 Íñigo Huguet <ihuguet@redhat.com> - 1:1.52.0-5
- Fix crash in DNS options evaluation (RHEL-92313)
@ -1107,7 +1122,7 @@ fi
- Always reset retries when unblocking children or ports (RHEL-78122)
- Prevent the activation of unavailable OVS interfaces (RHEL-79997)
* Mon Fed 17 2025 Beniamino Galvani <bgalvani@redhat.com> - 1:1.51.90-2
* Mon Feb 17 2025 Beniamino Galvani <bgalvani@redhat.com> - 1:1.51.90-2
- Fix state handling in the dnsconfd DNS plugin (RHEL-79693)
* Wed Feb 12 2025 Filip Pokryvka <fpokryvk@redhat.com> - 1:1.51.90-1