summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2021-04-22 08:02:16 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2021-04-22 08:02:16 +0200
commit1186d5e5cd8ecb54600df72bcbf12670b48cd094 (patch)
treeee23bb2b32cd28ddf712a6680d4ca36559a9172b
parent9eac9c846c6bb7b0baa77b72638aaf79df4a5ca6 (diff)
parentd19773ecd4bee36f11749085a15d70a49168c0b7 (diff)
downloadNetworkManager-1186d5e5cd8ecb54600df72bcbf12670b48cd094.tar.gz
merge: branch 'bg/rh1945282' into main
https://bugzilla.redhat.com/show_bug.cgi?id=1945282 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/803
-rw-r--r--src/core/devices/nm-device.c44
-rw-r--r--src/core/nm-manager.c45
2 files changed, 58 insertions, 31 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 0207a048c0..2aacb63618 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -125,7 +125,6 @@ typedef struct {
typedef struct {
NMDevice *device;
guint idle_add_id;
- int ifindex;
} DeleteOnDeactivateData;
typedef struct {
@@ -12169,28 +12168,19 @@ nm_device_is_nm_owned(NMDevice *self)
static gboolean
delete_on_deactivate_link_delete(gpointer user_data)
{
- DeleteOnDeactivateData *data = user_data;
- NMDevice * self = data->device;
+ DeleteOnDeactivateData *data = user_data;
+ nm_auto_unref_object NMDevice *self = data->device;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ gs_free_error GError *error = NULL;
_LOGD(LOGD_DEVICE,
- "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)",
- data->ifindex,
+ "delete_on_deactivate: cleanup and delete virtual link (id=%u)",
data->idle_add_id);
- if (data->device) {
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(data->device);
- gs_free_error GError *error = NULL;
+ priv->delete_on_deactivate_data = NULL;
- g_object_remove_weak_pointer(G_OBJECT(data->device), (void **) &data->device);
- priv->delete_on_deactivate_data = NULL;
-
- if (!nm_device_unrealize(data->device, TRUE, &error))
- _LOGD(LOGD_DEVICE,
- "delete_on_deactivate: unrealizing %d failed (%s)",
- data->ifindex,
- error->message);
- } else if (data->ifindex > 0)
- nm_platform_link_delete(nm_device_get_platform(self), data->ifindex);
+ if (!nm_device_unrealize(self, TRUE, &error))
+ _LOGD(LOGD_DEVICE, "delete_on_deactivate: unrealizing failed (%s)", error->message);
nm_device_emit_recheck_auto_activate(self);
@@ -12209,17 +12199,16 @@ delete_on_deactivate_unschedule(NMDevice *self)
priv->delete_on_deactivate_data = NULL;
g_source_remove(data->idle_add_id);
- g_object_remove_weak_pointer(G_OBJECT(self), (void **) &data->device);
_LOGD(LOGD_DEVICE,
- "delete_on_deactivate: cancel cleanup and delete virtual link #%d (id=%u)",
- data->ifindex,
+ "delete_on_deactivate: cancel cleanup and delete virtual link (id=%u)",
data->idle_add_id);
+ g_object_unref(data->device);
g_free(data);
}
}
static void
-delete_on_deactivate_check_and_schedule(NMDevice *self, int ifindex)
+delete_on_deactivate_check_and_schedule(NMDevice *self)
{
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
DeleteOnDeactivateData *data;
@@ -12236,16 +12225,13 @@ delete_on_deactivate_check_and_schedule(NMDevice *self, int ifindex)
return;
delete_on_deactivate_unschedule(self); /* always cancel and reschedule */
- data = g_new(DeleteOnDeactivateData, 1);
- g_object_add_weak_pointer(G_OBJECT(self), (void **) &data->device);
- data->device = self;
- data->ifindex = ifindex;
+ data = g_new(DeleteOnDeactivateData, 1);
+ data->device = g_object_ref(self);
data->idle_add_id = g_idle_add(delete_on_deactivate_link_delete, data);
priv->delete_on_deactivate_data = data;
_LOGD(LOGD_DEVICE,
- "delete_on_deactivate: schedule cleanup and delete virtual link #%d (id=%u)",
- ifindex,
+ "delete_on_deactivate: schedule cleanup and delete virtual link (id=%u)",
data->idle_add_id);
}
@@ -15883,7 +15869,7 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type)
/* Check if the device was deactivated, and if so, delete_link.
* Don't call delete_link synchronously because we are currently
* handling a state change -- which is not reentrant. */
- delete_on_deactivate_check_and_schedule(self, nm_device_get_ip_ifindex(self));
+ delete_on_deactivate_check_and_schedule(self);
}
/* ip_iface should be cleared after flushing all routes and addresses, since
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index 90bfad73ee..216dc8d2dd 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -3511,6 +3511,45 @@ typedef struct {
} PlatformLinkCbData;
static gboolean
+_check_remove_dev_on_link_deleted(NMManager *self, NMDevice *device)
+{
+ NMManagerPrivate * priv = NM_MANAGER_GET_PRIVATE(self);
+ NMSettingsConnection *const *scons = NULL;
+ NMConnection * con;
+ guint i;
+
+ nm_assert(nm_device_is_software(device));
+
+ /* In general, software devices stick around as unrealized
+ * until their connection is removed. However, we don't want
+ * that a NM-generated connection keeps the device alive.
+ * If there are no other compatible connections, the device
+ * should be also removed.
+ */
+
+ scons = nm_settings_get_connections(priv->settings, NULL);
+
+ for (i = 0; scons[i]; i++) {
+ con = nm_settings_connection_get_connection(scons[i]);
+ if (!nm_connection_is_virtual(con))
+ continue;
+
+ if (NM_FLAGS_HAS(nm_settings_connection_get_flags(scons[i]),
+ NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED))
+ continue;
+
+ if (!nm_device_check_connection_compatible(device, con, NULL))
+ continue;
+
+ /* Found a virtual connection compatible, the device must
+ * stay around unrealized. */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
_platform_link_cb_idle(PlatformLinkCbData *data)
{
int ifindex = data->ifindex;
@@ -3535,13 +3574,15 @@ _platform_link_cb_idle(PlatformLinkCbData *data)
if (device) {
if (nm_device_is_software(device)) {
nm_device_sys_iface_state_set(device, NM_DEVICE_SYS_IFACE_STATE_REMOVED);
- /* Our software devices stick around until their connection is removed */
if (!nm_device_unrealize(device, FALSE, &error)) {
_LOG2W(LOGD_DEVICE, device, "failed to unrealize: %s", error->message);
g_clear_error(&error);
remove_device(self, device, FALSE);
} else {
- nm_device_update_from_platform_link(device, NULL);
+ if (_check_remove_dev_on_link_deleted(self, device))
+ remove_device(self, device, FALSE);
+ else
+ nm_device_update_from_platform_link(device, NULL);
}
} else {
/* Hardware and external devices always get removed when their kernel link is gone */