summary refs log tree commit diff
path: root/src/core/nm-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/nm-manager.c')
-rw-r--r--src/core/nm-manager.c164
1 files changed, 82 insertions, 82 deletions
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index c9bcbd12..a861b2fe 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -2594,7 +2594,7 @@ nm_manager_remove_device(NMManager *self, const char *ifname, NMDeviceType devic
  * Returns: A #NMDevice that was just realized; %NULL if none
  */
 static NMDevice *
-system_create_virtual_device(NMManager *self, NMConnection *connection)
+system_create_virtual_device(NMManager *self, NMConnection *connection, GError **error)
 {
     NMManagerPrivate            *priv = NM_MANAGER_GET_PRIVATE(self);
     NMDeviceFactory             *factory;
@@ -2605,20 +2605,20 @@ system_create_virtual_device(NMManager *self, NMConnection *connection)
     NMDevice                    *device = NULL;
     NMDevice                    *parent = NULL;
     NMDevice                    *dev_candidate;
-    gs_free_error GError        *error = NULL;
-    NMLogLevel                   log_level;
 
     g_return_val_if_fail(NM_IS_MANAGER(self), NULL);
     g_return_val_if_fail(NM_IS_CONNECTION(connection), NULL);
 
-    iface = nm_manager_get_connection_iface(self, connection, &parent, &parent_spec, &error);
-    if (!iface) {
-        _LOG3D(LOGD_DEVICE, connection, "can't get a name of a virtual device: %s", error->message);
+    iface = nm_manager_get_connection_iface(self, connection, &parent, &parent_spec, error);
+    if (!iface)
         return NULL;
-    }
 
     if (parent_spec && !parent) {
-        /* parent is not ready, wait */
+        g_set_error(error,
+                    NM_MANAGER_ERROR,
+                    NM_MANAGER_ERROR_DEPENDENCY_FAILED,
+                    "Parent device for '%s' not available",
+                    iface);
         return NULL;
     }
 
@@ -2626,7 +2626,11 @@ system_create_virtual_device(NMManager *self, NMConnection *connection)
     c_list_for_each_entry (dev_candidate, &priv->devices_lst_head, devices_lst) {
         if (nm_device_check_connection_compatible(dev_candidate, connection, FALSE, NULL)) {
             if (nm_device_is_real(dev_candidate)) {
-                _LOG3D(LOGD_DEVICE, connection, "already created virtual interface name %s", iface);
+                g_set_error(error,
+                            NM_MANAGER_ERROR,
+                            NM_MANAGER_ERROR_UNKNOWN_DEVICE,
+                            "Device named '%s' already exists",
+                            iface);
                 return NULL;
             }
 
@@ -2640,27 +2644,22 @@ system_create_virtual_device(NMManager *self, NMConnection *connection)
 
         factory = nm_device_factory_manager_find_factory_for_connection(connection);
         if (!factory) {
-            _LOG3E(LOGD_DEVICE,
-                   connection,
-                   "(%s) NetworkManager plugin for '%s' unavailable",
-                   iface,
-                   nm_connection_get_connection_type(connection));
+            g_set_error(error,
+                        NM_MANAGER_ERROR,
+                        NM_MANAGER_ERROR_UNKNOWN_DEVICE,
+                        "'%s' plugin for '%s' unavailable",
+                        nm_connection_get_connection_type(connection),
+                        iface);
             return NULL;
         }
 
-        device = nm_device_factory_create_device(factory, iface, NULL, connection, NULL, &error);
-        if (!device) {
-            _LOG3W(LOGD_DEVICE, connection, "factory can't create the device: %s", error->message);
+        device = nm_device_factory_create_device(factory, iface, NULL, connection, NULL, error);
+        if (!device)
             return NULL;
-        }
 
         _LOG3D(LOGD_DEVICE, connection, "create virtual device %s", nm_device_get_iface(device));
 
-        if (!add_device(self, device, &error)) {
-            _LOG3W(LOGD_DEVICE,
-                   connection,
-                   "can't register the device with manager: %s",
-                   error->message);
+        if (!add_device(self, device, error)) {
             g_object_unref(device);
             return NULL;
         }
@@ -2679,10 +2678,8 @@ system_create_virtual_device(NMManager *self, NMConnection *connection)
         return device;
     }
 
-    if (!find_controller(self, connection, device, NULL, NULL, NULL, &error)) {
-        _LOG3D(LOGD_DEVICE, connection, "skip activation: %s", error->message);
+    if (!find_controller(self, connection, device, NULL, NULL, NULL, error))
         return device;
-    }
 
     /* Create backing resources if the device has any autoconnect connections */
     connections = nm_settings_get_connections_sorted_by_autoconnect_priority(priv->settings, NULL);
@@ -2699,18 +2696,8 @@ system_create_virtual_device(NMManager *self, NMConnection *connection)
             continue;
 
         /* Create any backing resources the device needs */
-        if (!nm_device_create_and_realize(device, connection, parent, &error)) {
-            log_level =
-                g_error_matches(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_MISSING_DEPENDENCIES)
-                    ? LOGL_DEBUG
-                    : LOGL_ERR;
-            _NMLOG3(log_level,
-                    LOGD_DEVICE,
-                    connection,
-                    "couldn't create the device: %s",
-                    error->message);
+        if (!nm_device_create_and_realize(device, connection, parent, error))
             return NULL;
-        }
 
         retry_connections_for_parent_device(self, device);
         break;
@@ -2751,8 +2738,9 @@ retry_connections_for_parent_device(NMManager *self, NMDevice *device)
 static void
 connection_changed(NMManager *self, NMSettingsConnection *sett_conn)
 {
-    NMConnection *connection;
-    NMDevice     *device;
+    NMConnection         *connection;
+    NMDevice             *device;
+    gs_free_error GError *error = NULL;
 
     if (NM_FLAGS_ANY(nm_settings_connection_get_flags(sett_conn),
                      NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE
@@ -2764,9 +2752,11 @@ connection_changed(NMManager *self, NMSettingsConnection *sett_conn)
     if (!nm_connection_is_virtual(connection))
         return;
 
-    device = system_create_virtual_device(self, connection);
-    if (!device)
+    device = system_create_virtual_device(self, connection, &error);
+    if (!device) {
+        _LOG3D(LOGD_DEVICE, connection, "Can't create a virtual device: %s", error->message);
         return;
+    }
 
     /* Maybe the device that was created was needed by some other
      * connection's device (parent of a VLAN). Let the connections
@@ -4699,10 +4689,16 @@ found_better:
         if (nm_g_hash_table_contains(exclude_devices, device))
             continue;
 
-        if (!nm_device_is_available(device,
-                                    for_user_request
-                                        ? NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST
-                                        : NM_DEVICE_CHECK_DEV_AVAILABLE_NONE))
+        /* During startup, NM performs a cleanup of the ovsdb to remove previous entries.
+         * Before the device is suitable for the connection, it must have ovsdb->ready set
+         * to TRUE. Performing this check in all kind of interfaces is too agressive and leads
+         * to race conditions, e.g when a non-virtual bond port gets a carrier, preventing the
+         * device to be a good candidate for the connection. */
+        if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_OVS_INTERFACE
+            && !nm_device_is_available(device,
+                                       for_user_request
+                                           ? NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST
+                                           : NM_DEVICE_CHECK_DEV_AVAILABLE_NONE))
             continue;
 
         /* determine the priority of this device. Currently, this priority is independent
@@ -6542,18 +6538,9 @@ find_device_for_activation(NMManager            *self,
                 return FALSE;
 
             device = find_device_by_iface(self, iface, connection, NULL, NULL);
-            if (!device) {
-                g_set_error_literal(error,
-                                    NM_MANAGER_ERROR,
-                                    NM_MANAGER_ERROR_UNKNOWN_DEVICE,
-                                    "Failed to find a compatible device for this connection");
-                return FALSE;
-            }
         }
     }
 
-    nm_assert(is_vpn || NM_IS_DEVICE(device));
-
     *out_device = device;
     *out_is_vpn = is_vpn;
 
@@ -6678,7 +6665,14 @@ impl_manager_activate_connection(NMDBusObject                      *obj,
     if (!subject)
         goto error;
 
-    if (!find_device_for_activation(self, sett_conn, NULL, device_path, &device, &is_vpn, &error)) {
+    if (!find_device_for_activation(self, sett_conn, NULL, device_path, &device, &is_vpn, &error))
+        goto error;
+
+    if (!device && !is_vpn) {
+        g_set_error_literal(&error,
+                            NM_MANAGER_ERROR,
+                            NM_MANAGER_ERROR_UNKNOWN_DEVICE,
+                            "Failed to find a compatible device for this connection");
         goto error;
     }
 
@@ -6801,6 +6795,7 @@ _add_and_activate_auth_done(NMManager                      *self,
                             const char                     *error_desc)
 {
     NMManagerPrivate *priv;
+    NMDevice         *device;
     GError           *error = NULL;
 
     if (!success) {
@@ -6813,6 +6808,14 @@ _add_and_activate_auth_done(NMManager                      *self,
                                    nm_active_connection_get_subject(active),
                                    error->message);
         g_dbus_method_invocation_take_error(invocation, error);
+
+        device = nm_active_connection_get_device(active);
+        if (device && nm_device_is_software(device)
+            && !nm_device_managed_type_is_external_or_assume(device)
+            && _check_remove_dev_on_link_deleted(self, device)) {
+            remove_device(self, device, FALSE);
+        }
+
         return;
     }
 
@@ -6968,32 +6971,11 @@ impl_manager_add_and_activate_connection(NMDBusObject                      *obj,
         goto error;
     }
 
-    if (is_vpn) {
-        /* Try to fill the VPN's connection setting and name at least */
-        if (!nm_connection_get_setting_vpn(incompl_conn)) {
-            error = g_error_new_literal(NM_CONNECTION_ERROR,
-                                        NM_CONNECTION_ERROR_MISSING_SETTING,
-                                        "VPN connections require a 'vpn' setting");
-            g_prefix_error(&error, "%s: ", NM_SETTING_VPN_SETTING_NAME);
-            goto error;
-        }
-
-        conns = nm_settings_connections_array_to_connections(
-            nm_settings_get_connections(priv->settings, NULL),
-            -1);
+    conns = nm_settings_connections_array_to_connections(
+        nm_settings_get_connections(priv->settings, NULL),
+        -1);
 
-        nm_utils_complete_generic(priv->platform,
-                                  incompl_conn,
-                                  NM_SETTING_VPN_SETTING_NAME,
-                                  conns,
-                                  NULL,
-                                  _("VPN connection"),
-                                  NULL,
-                                  NULL);
-    } else {
-        conns = nm_settings_connections_array_to_connections(
-            nm_settings_get_connections(priv->settings, NULL),
-            -1);
+    if (device) {
         /* Let each device subclass complete the connection */
         if (!nm_device_complete_connection(device,
                                            incompl_conn,
@@ -7001,9 +6983,27 @@ impl_manager_add_and_activate_connection(NMDBusObject                      *obj,
                                            conns,
                                            &error))
             goto error;
-    }
+    } else {
+        nm_utils_complete_generic(priv->platform,
+                                  incompl_conn,
+                                  nm_connection_get_connection_type(incompl_conn),
+                                  conns,
+                                  is_vpn ? _("VPN connection") : NULL,
+                                  nm_connection_get_connection_type(incompl_conn),
+                                  NULL,
+                                  NULL);
+
+        if (!nm_connection_verify(incompl_conn, &error))
+            goto error;
+
+        if (!is_vpn && !device) {
+            nm_assert(nm_connection_is_virtual(incompl_conn));
 
-    nm_assert(_nm_connection_verify(incompl_conn, NULL) == NM_SETTING_VERIFY_SUCCESS);
+            device = system_create_virtual_device(self, incompl_conn, &error);
+            if (!device)
+                goto error;
+        }
+    }
 
     active = _new_active_connection(self,
                                     is_vpn,