From 8326cc32d64441dd993b5b1e73ded21d548efa6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Thu, 9 Oct 2025 12:24:11 +0200 Subject: [PATCH 1/2] 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) --- src/core/devices/ovs/nm-ovsdb.c | 34 +++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/core/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index 164bfd3565..1c9484c486 100644 --- a/src/core/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -1460,40 +1460,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 { - 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 */ + /* 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) { + /* 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); + } } } - 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); } From 6f9ba5fcc595642aa79cd6ee2733e507a75e3229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8D=C3=B1igo=20Huguet?= Date: Thu, 9 Oct 2025 12:46:42 +0200 Subject: [PATCH 2/2] man: ovs: document known limitation when removing ifaces and ports Document a known limitation that we delete bridges and ports from ovsdb when we remove their last NM-owned attached port or interface, even if other externally added ports or interfaces exist. (cherry picked from commit 86ea2c59635ec58522d9926c2c1299ae986c7bad) --- man/nm-openvswitch.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/man/nm-openvswitch.xml b/man/nm-openvswitch.xml index ff85212908..82bcba50e9 100644 --- a/man/nm-openvswitch.xml +++ b/man/nm-openvswitch.xml @@ -91,6 +91,10 @@ NetworkManager inserts the records for Bridges into OVSDB when a Port is attached. + + Known limitation: when the last NetworkManager's owned port is removed, + the bridge is removed too, even if there are other externally attached ports. + @@ -102,6 +106,10 @@ exist. Ports can also be configured to do VLAN tagging or Bonding. NetworkManager inserts the records for Ports into OVSDB when an Interface is attached. Ports must be attached to a Bridge. + + Known limitation: when the last NetworkManager's owned interface is removed, + the port is removed too, even if there are other externally attached interfaces. +