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 <fge@redhat.com>
This commit is contained in:
Gris Ge 2024-03-15 15:46:02 +08:00
parent b40e2eb721
commit 7096f52a59
3 changed files with 21 additions and 5 deletions

View File

@ -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

View File

@ -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);

View File

@ -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,