From 1494774bd129ae00f6bdf3a88881952fdf8a10a7 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 10 May 2023 16:22:08 +0200 Subject: [PATCH 1/2] device: add functions to get and set sys-iface-state before sleep --- src/core/devices/nm-device.c | 24 +++++++++++++++++++++++- src/core/devices/nm-device.h | 4 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 6639492ee5..516fc657a0 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -570,6 +570,8 @@ typedef struct _NMDevicePrivate { NMDeviceSysIfaceState sys_iface_state_; }; + NMDeviceSysIfaceState sys_iface_state_before_sleep; + bool carrier : 1; bool ignore_carrier : 1; @@ -3052,6 +3054,22 @@ nm_device_sys_iface_state_set(NMDevice *self, NMDeviceSysIfaceState sys_iface_st nm_assert(priv->sys_iface_state == sys_iface_state); } +void +nm_device_notify_sleeping(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + priv->sys_iface_state_before_sleep = priv->sys_iface_state; +} + +NMDeviceSysIfaceState +nm_device_get_sys_iface_state_before_sleep(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + return priv->sys_iface_state_before_sleep; +} + static void _active_connection_set_state_flags_full(NMDevice *self, NMActivationStateFlags flags, @@ -17961,7 +17979,11 @@ nm_device_init(NMDevice *self) priv->unmanaged_mask = priv->unmanaged_flags; priv->available_connections = g_hash_table_new_full(nm_direct_hash, NULL, g_object_unref, NULL); priv->ip6_saved_properties = g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, g_free); - priv->sys_iface_state_ = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL; + + priv->sys_iface_state_ = NM_DEVICE_SYS_IFACE_STATE_EXTERNAL; + /* If networking is already disabled at boot, we want to manage all devices + * after re-enabling networking; hence, the initial state is MANAGED. */ + priv->sys_iface_state_before_sleep = NM_DEVICE_SYS_IFACE_STATE_MANAGED; priv->promisc_reset = NM_OPTION_BOOL_DEFAULT; } diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index d32b77dc83..8d8249d1a2 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -728,6 +728,10 @@ gboolean nm_device_sys_iface_state_is_external_or_assume(NMDevice *self); void nm_device_sys_iface_state_set(NMDevice *device, NMDeviceSysIfaceState sys_iface_state); +void nm_device_notify_sleeping(NMDevice *self); + +NMDeviceSysIfaceState nm_device_get_sys_iface_state_before_sleep(NMDevice *self); + void nm_device_state_changed(NMDevice *device, NMDeviceState state, NMDeviceStateReason reason); void nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason); From 5e3bef6ae9f8441a95767191b829d0d57673506c Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 10 May 2023 16:28:08 +0200 Subject: [PATCH 2/2] manager: use the right reason for managing devices after wake/reenable When managing the interface after wake/reenable, the reason determines whether the device will be sys-iface-state=managed or external. Commit 5a9a7623c5a4 ('core: set STATE_REASON_CONNECTION_ASSUMED when waking up') changed the reason from 'now-managed' to 'connection-assumed'; the effect was that devices that were fully managed before sleeping become external after a wake up. For example: $ nmcli connection add type ethernet ifname enp1s0 Connection 'ethernet-enp1s0' (47fcd81e-bf00-4c02-b25b-354894f5657e) successfully added. $ nmcli device | grep enp1s0 enp1s0 ethernet connected ethernet-enp1s0 $ nmcli networking off $ nmcli device | grep enp1s0 enp1s0 ethernet unmanaged -- $ nmcli networking on $ nmcli device | grep enp1s0 enp1s0 ethernet unavailable -- Set the correct reason during wake up so that the previous state is restored. Fixes: 5a9a7623c5a4 ('core: set STATE_REASON_CONNECTION_ASSUMED when waking up') https://bugzilla.redhat.com/show_bug.cgi?id=2193422 --- src/core/nm-manager.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index c6cf2cb943..fc63fbcf04 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -7089,6 +7089,8 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) continue; } + nm_device_notify_sleeping(device); + if (nm_device_is_activating(device) || nm_device_get_state(device) == NM_DEVICE_STATE_ACTIVATED) { _LOGD(LOGD_SUSPEND, @@ -7145,7 +7147,8 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) /* Re-manage managed devices */ c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) { - guint i; + NMDeviceStateReason reason; + guint i; if (nm_device_is_software(device) && !nm_device_get_unmanaged_flags(device, NM_UNMANAGED_SLEEPING)) { @@ -7176,10 +7179,17 @@ do_sleep_wake(NMManager *self, gboolean sleeping_changed) nm_device_set_enabled(device, enabled); } + /* The reason determines whether the device will be sys-iface-state=managed + * or sys-iface-state=external. Pass the correct reason to restore the state + * that was set before sleeping. */ + reason = nm_device_get_sys_iface_state_before_sleep(device) + == NM_DEVICE_SYS_IFACE_STATE_EXTERNAL + ? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED + : NM_DEVICE_STATE_REASON_NOW_MANAGED; nm_device_set_unmanaged_by_flags(device, NM_UNMANAGED_SLEEPING, NM_UNMAN_FLAG_OP_SET_MANAGED, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + reason); } /* Give the connections a chance to recreate the virtual devices.