From cf4f45af5cb23978123a991c191bf409bc237a9b Mon Sep 17 00:00:00 2001 From: Wen Liang Date: Mon, 29 Jul 2024 14:42:05 -0400 Subject: [PATCH 1/1] policy: unblock the autoconnect for children when parent is available When parent is available and in the process of activation, we should unblock the autoconnect and schedule an auto activate for the children. Notice that when the parent is the ovs-interface, the kernel link is only created in stage3, if we only unblock the children in the stage1, then the children device and connection will be blocked again due to the fact the kernel link for the parent ovs-interface is not existed yet, thus, we have to separately unblock the children when the parent ovs-interface is in the activated state. https://issues.redhat.com/browse/RHEL-46904 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2003 https://gitlab.freedesktop.org/NetworkManager/NetworkManager-ci/-/merge_requests/1735 (cherry picked from commit 5f64f292e6a518098f874ba9ff876e413e38a3ca) (cherry picked from commit 8243425c6d031c685518a74018cd39cd6c10a36b) (cherry picked from commit 02db74ed0bc5ac8b3c942c2c4bc61a56258cc063) --- src/core/nm-policy.c | 136 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 111 insertions(+), 25 deletions(-) diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index feea97b114..9777cf326f 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -17,6 +17,7 @@ #include "NetworkManagerUtils.h" #include "devices/nm-device.h" +#include "devices/nm-device-factory.h" #include "dns/nm-dns-manager.h" #include "nm-act-request.h" #include "nm-auth-utils.h" @@ -1773,6 +1774,74 @@ _connection_autoconnect_retries_set(NMPolicy *self, } } +static void +unblock_autoconnect_for_children(NMPolicy *self, + const char *parent_device, + const char *parent_uuid_settings, + const char *parent_uuid_applied, + const char *parent_mac_addr, + gboolean reset_devcon_autoconnect) +{ + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); + NMSettingsConnection *const *connections; + gboolean changed; + guint i; + + _LOGT(LOGD_CORE, + "block-autoconnect: unblocking child profiles for parent ifname=%s%s%s, uuid=%s%s%s" + "%s%s%s", + NM_PRINT_FMT_QUOTE_STRING(parent_device), + NM_PRINT_FMT_QUOTE_STRING(parent_uuid_settings), + NM_PRINT_FMT_QUOTED(parent_uuid_applied, + ", applied-uuid=\"", + parent_uuid_applied, + "\"", + "")); + + changed = FALSE; + connections = nm_settings_get_connections(priv->settings, NULL); + for (i = 0; connections[i]; i++) { + NMSettingsConnection *sett_conn = connections[i]; + NMConnection *connection; + NMDeviceFactory *factory; + const char *parent_name = NULL; + + connection = nm_settings_connection_get_connection(sett_conn); + factory = nm_device_factory_manager_find_factory_for_connection(connection); + if (factory) + parent_name = nm_device_factory_get_connection_parent(factory, connection); + + if (!parent_name) + continue; + + if (!NM_IN_STRSET(parent_name, + parent_device, + parent_uuid_applied, + parent_uuid_settings, + parent_mac_addr)) + continue; + + if (reset_devcon_autoconnect) { + if (nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn)) + changed = TRUE; + } + + /* unblock the devices associated with that connection */ + if (nm_manager_devcon_autoconnect_blocked_reason_set( + priv->manager, + NULL, + sett_conn, + NM_SETTINGS_AUTOCONNECT_BLOCKED_REASON_FAILED, + FALSE)) { + if (!nm_settings_connection_autoconnect_is_blocked(sett_conn)) + changed = TRUE; + } + } + + if (changed) + nm_policy_device_recheck_auto_activate_all_schedule(self); +} + static void unblock_autoconnect_for_ports(NMPolicy *self, const char *master_device, @@ -1854,16 +1923,21 @@ unblock_autoconnect_for_ports_for_sett_conn(NMPolicy *self, NMSettingsConnection } static void -activate_slave_connections(NMPolicy *self, NMDevice *device) -{ - const char *master_device; - const char *master_uuid_settings = NULL; - const char *master_uuid_applied = NULL; +activate_port_or_children_connections(NMPolicy *self, + NMDevice *device, + gboolean activate_children_connections_only) +{ + const char *controller_device; + const char *controller_uuid_settings = NULL; + const char *controller_uuid_applied = NULL; + const char *parent_mac_addr = NULL; NMActRequest *req; gboolean internal_activation = FALSE; - master_device = nm_device_get_iface(device); - nm_assert(master_device); + controller_device = nm_device_get_iface(device); + nm_assert(controller_device); + + parent_mac_addr = nm_device_get_permanent_hw_address(device); req = nm_device_get_act_request(device); if (req) { @@ -1873,25 +1947,33 @@ activate_slave_connections(NMPolicy *self, NMDevice *device) sett_conn = nm_active_connection_get_settings_connection(NM_ACTIVE_CONNECTION(req)); if (sett_conn) - master_uuid_settings = nm_settings_connection_get_uuid(sett_conn); + controller_uuid_settings = nm_settings_connection_get_uuid(sett_conn); connection = nm_active_connection_get_applied_connection(NM_ACTIVE_CONNECTION(req)); if (connection) - master_uuid_applied = nm_connection_get_uuid(connection); + controller_uuid_applied = nm_connection_get_uuid(connection); - if (nm_streq0(master_uuid_settings, master_uuid_applied)) - master_uuid_applied = NULL; + if (nm_streq0(controller_uuid_settings, controller_uuid_applied)) + controller_uuid_applied = NULL; subject = nm_active_connection_get_subject(NM_ACTIVE_CONNECTION(req)); internal_activation = subject && (nm_auth_subject_get_subject_type(subject) == NM_AUTH_SUBJECT_TYPE_INTERNAL); } - unblock_autoconnect_for_ports(self, - master_device, - master_uuid_settings, - master_uuid_applied, - !internal_activation); + if (!activate_children_connections_only) { + unblock_autoconnect_for_ports(self, + controller_device, + controller_uuid_settings, + controller_uuid_applied, + !internal_activation); + } + unblock_autoconnect_for_children(self, + controller_device, + controller_uuid_settings, + controller_uuid_applied, + parent_mac_addr, + !internal_activation); } static gboolean @@ -2059,13 +2141,12 @@ device_state_changed(NMDevice *device, } break; case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED: - /* A connection that fails due to dependency-failed is not - * able to reconnect until the master connection activates - * again; when this happens, the master clears the blocked - * reason for all its slaves in activate_slave_connections() - * and tries to reconnect them. For this to work, the slave - * should be marked as blocked when it fails with - * dependency-failed. + /* A connection that fails due to dependency-failed is not able to + * reconnect until the connection it depends on activates again; + * when this happens, the controller or parent clears the blocked + * reason for all its dependent devices in activate_port_or_children_connections() + * and tries to reconnect them. For this to work, the port should + * be marked as blocked when it fails with dependency-failed. */ _LOGD(LOGD_DEVICE, "block-autoconnect: connection[%p] (%s) now blocked from autoconnect due to " @@ -2109,6 +2190,11 @@ device_state_changed(NMDevice *device, } break; case NM_DEVICE_STATE_ACTIVATED: + if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_OVS_INTERFACE) { + /* When parent is ovs-interface, the kernel link is only created in stage3, we have to + * delay unblocking the children and schedule them for activation until parent is activated */ + activate_port_or_children_connections(self, device, TRUE); + } if (sett_conn) { /* Reset auto retries back to default since connection was successful */ nm_manager_devcon_autoconnect_retries_reset(priv->manager, device, sett_conn); @@ -2193,9 +2279,9 @@ device_state_changed(NMDevice *device, break; case NM_DEVICE_STATE_PREPARE: - /* Reset auto-connect retries of all slaves and schedule them for + /* Reset auto-connect retries of all ports or children and schedule them for * activation. */ - activate_slave_connections(self, device); + activate_port_or_children_connections(self, device, FALSE); /* Now that the device state is progressing, we don't care * anymore for the AC state. */ -- 2.45.0