From 7096f52a5967ef053a4cf8e5ca8a71c1495578f9 Mon Sep 17 00:00:00 2001 From: Gris Ge Date: Fri, 15 Mar 2024 15:46:02 +0800 Subject: [PATCH] ovs: Do not allow OVS bridge and port to be parent When creating VLAN over OVS internal interface which holding the same name as its controller OVS bridge, NetworkManager will fail with error: Error: Connection activation failed: br0.101 failed to create resources: cannot retrieve ifindex of interface br0 (Open vSwitch Bridge) Expanded the `find_device_by_iface()` with additional argument `child: NmConnection *` which will validate whether candidate is suitable to be parent device. In `nm_device_check_parent_connection_compatible()`, we only not allow OVS bridge and OVS port being parent. Resolves: https://issues.redhat.com/browse/RHEL-26753 Signed-off-by: Gris Ge --- src/core/devices/nm-device.c | 11 +++++++++++ src/core/devices/nm-device.h | 1 + src/core/nm-manager.c | 14 +++++++++----- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 2557e7a982..84bb172aa1 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -9512,6 +9512,17 @@ nm_device_check_slave_connection_compatible(NMDevice *self, NMConnection *slave) return nm_streq(connection_type, slave_type); } +gboolean +nm_device_can_be_parent(NMDevice *self) +{ + NMDeviceType device_type = nm_device_get_device_type(self); + + if ((device_type == NM_DEVICE_TYPE_OVS_BRIDGE) || (device_type == NM_DEVICE_TYPE_OVS_PORT)) + return FALSE; + else + return TRUE; +} + /** * nm_device_can_assume_connections: * @self: #NMDevice instance diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index 2c92122d29..ffe6b1af99 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -550,6 +550,7 @@ gboolean nm_device_check_connection_compatible(NMDevice *device, GError **error); gboolean nm_device_check_slave_connection_compatible(NMDevice *device, NMConnection *connection); +gboolean nm_device_can_be_parent(NMDevice *device); gboolean nm_device_can_assume_connections(NMDevice *self); gboolean nm_device_unmanage_on_quit(NMDevice *self); diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index a8176546fc..f607569d88 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -1914,7 +1914,8 @@ find_device_by_ip_iface(NMManager *self, const char *iface) * is given, this function will only return master devices and will ensure * @slave, when activated, can be a slave of the returned master device. If * @connection is given, this function will only consider devices that are - * compatible with @connection. + * compatible with @connection. If @child is given, this function will only + * return parent device. * * Returns: the matching #NMDevice */ @@ -1922,7 +1923,8 @@ static NMDevice * find_device_by_iface(NMManager *self, const char *iface, NMConnection *connection, - NMConnection *slave) + NMConnection *slave, + NMConnection *child) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); NMDevice *fallback = NULL; @@ -1941,6 +1943,8 @@ find_device_by_iface(NMManager *self, if (!nm_device_check_slave_connection_compatible(candidate, slave)) continue; } + if (child && !nm_device_can_be_parent(candidate)) + continue; if (nm_device_is_real(candidate)) return candidate; @@ -2405,7 +2409,7 @@ find_parent_device_for_connection(NMManager *self, NM_SET_OUT(out_parent_spec, parent_name); /* Try as an interface name of a parent device */ - parent = find_device_by_iface(self, parent_name, NULL, NULL); + parent = find_device_by_iface(self, parent_name, NULL, NULL, connection); if (parent) return parent; @@ -5003,7 +5007,7 @@ find_master(NMManager *self, } if (!master_connection) { - master_device = find_device_by_iface(self, master, NULL, connection); + master_device = find_device_by_iface(self, master, NULL, connection, NULL); if (!master_device) { g_set_error(error, NM_MANAGER_ERROR, @@ -6445,7 +6449,7 @@ validate_activation_request(NMManager *self, if (!iface) return NULL; - device = find_device_by_iface(self, iface, connection, NULL); + device = find_device_by_iface(self, iface, connection, NULL, NULL); if (!device) { g_set_error_literal(error, NM_MANAGER_ERROR,