device: ensure that sw devices are unrealized after connection deletion

When a software device becomes deactivated, we check whether it can
be unrealized (= deleted in kernel), by calling function
delete_on_deactivate_check_and_schedule().

The function returns without doing anything if there is a new
activation enqueued on the device (priv->queued_act_request), because
in that case the device will be reused for the next activation.

This commit fixes a problem seen in NMCI test
@ovs_delete_connecting_interface: sometimes the device is not
unrealized after deleting the connection. That happens because if the
queued activation fails, we never try again to unrealize the device.

Fix that by calling delete_on_deactivate_check_and_schedule() when
there is a failure starting the queued activation.

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/2258
This commit is contained in:
Beniamino Galvani 2025-08-21 15:43:35 +02:00
parent 8b26cb35ee
commit 0b03614b68

View file

@ -14751,13 +14751,15 @@ impl_device_delete(NMDBusObject *obj,
NULL);
}
static void
static gboolean
_device_activate(NMDevice *self, NMActRequest *req)
{
NMConnection *connection;
g_return_if_fail(NM_IS_DEVICE(self));
g_return_if_fail(NM_IS_ACT_REQUEST(req));
/* Returns TRUE on success, FALSE if the activation request could not be started */
g_return_val_if_fail(NM_IS_DEVICE(self), FALSE);
g_return_val_if_fail(NM_IS_ACT_REQUEST(req), FALSE);
nm_assert(nm_device_is_real(self));
/* Ensure the activation request is still valid; the controller may have
@ -14765,7 +14767,7 @@ _device_activate(NMDevice *self, NMActRequest *req)
*/
if (nm_active_connection_get_state(NM_ACTIVE_CONNECTION(req))
>= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)
return;
return FALSE;
if (!nm_device_get_managed(self, FALSE)) {
/* It's unclear why the device would be unmanaged at this point.
@ -14776,7 +14778,7 @@ _device_activate(NMDevice *self, NMActRequest *req)
nm_active_connection_set_state_fail((NMActiveConnection *) req,
NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN,
NULL);
return;
return FALSE;
}
connection = nm_act_request_get_applied_connection(req);
@ -14792,6 +14794,8 @@ _device_activate(NMDevice *self, NMActRequest *req)
act_request_set(self, req);
nm_device_activate_schedule_stage1_device_prepare(self, FALSE);
return TRUE;
}
static void
@ -14811,7 +14815,9 @@ _carrier_wait_check_queued_act_request(NMDevice *self)
_LOGD(LOGD_DEVICE, "Activate queued activation request as we now have carrier");
queued_req = g_steal_pointer(&priv->queued_act_request);
_device_activate(self, queued_req);
if (!_device_activate(self, queued_req)) {
delete_on_deactivate_check_and_schedule(self);
}
}
}
@ -17599,7 +17605,8 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
gs_unref_object NMActRequest *queued_req = NULL;
queued_req = g_steal_pointer(&priv->queued_act_request);
_device_activate(self, queued_req);
if (!_device_activate(self, queued_req))
delete_on_deactivate_check_and_schedule(self);
}
break;
case NM_DEVICE_STATE_ACTIVATED: