diff options
author | Thomas Haller <thaller@redhat.com> | 2023-04-05 11:55:28 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2023-04-27 08:40:12 +0200 |
commit | a22e5080a0a67a76fd9fa17f69491267fbe89f72 (patch) | |
tree | 424f1b4fad3037c6dac26fce351a86e0830ea06e | |
parent | 520fcc8667e9939275f51da355fceb964815c42b (diff) | |
download | NetworkManager-a22e5080a0a67a76fd9fa17f69491267fbe89f72.tar.gz |
core: rework tracking of auto-activating devices in NMPolicy
Hook the information for tracking the activation of a device, to the
NMDevice itself. Sure, that slightly couples the NMPolicy closer to
NMDevice, but the result is still simpler code because we don't need a
separate ActivateData.
It also means we can immediately tell whether the auto activation check
for NMDevice is already scheduled and don't need to search through the
list.
-rw-r--r-- | src/core/devices/nm-device.c | 3 | ||||
-rw-r--r-- | src/core/devices/nm-device.h | 3 | ||||
-rw-r--r-- | src/core/nm-policy.c | 94 |
3 files changed, 44 insertions, 56 deletions
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 4547b6a3a5..a33a01efde 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -17945,6 +17945,7 @@ nm_device_init(NMDevice *self) c_list_init(&priv->concheck_lst_head); c_list_init(&self->devices_lst); c_list_init(&self->devcon_dev_lst_head); + c_list_init(&self->policy_auto_activate_lst); c_list_init(&priv->slaves); priv->ipdhcp_data_6.v6.mode = NM_NDISC_DHCP_LEVEL_NONE; @@ -18066,6 +18067,8 @@ dispose(GObject *object) nm_assert(c_list_is_empty(&self->devices_lst)); nm_assert(c_list_is_empty(&self->devcon_dev_lst_head)); + nm_assert(c_list_is_empty(&self->policy_auto_activate_lst)); + nm_assert(!self->policy_auto_activate_idle_source); while ((con_handle = c_list_first_entry(&priv->concheck_lst_head, NMDeviceConnectivityHandle, diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h index f14e4638e2..d32b77dc83 100644 --- a/src/core/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -144,6 +144,9 @@ struct _NMDevice { struct _NMDevicePrivate *_priv; CList devices_lst; CList devcon_dev_lst_head; + + CList policy_auto_activate_lst; + GSource *policy_auto_activate_idle_source; }; /* The flags have an relaxing meaning, that means, specifying more flags, can make diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index c5864967cc..26556c347e 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -51,7 +51,7 @@ typedef struct { NMManager *manager; NMNetns *netns; NMFirewalldManager *firewalld_manager; - CList pending_activation_checks; + CList policy_auto_activate_lst_head; NMAgentManager *agent_mgr; @@ -1282,23 +1282,6 @@ check_activating_active_connections(NMPolicy *self) g_object_thaw_notify(G_OBJECT(self)); } -typedef struct { - CList pending_lst; - NMPolicy *policy; - NMDevice *device; - guint autoactivate_id; -} ActivateData; - -static void -activate_data_free(ActivateData *data) -{ - nm_device_remove_pending_action(data->device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE); - c_list_unlink_stale(&data->pending_lst); - nm_clear_g_source(&data->autoactivate_id); - g_object_unref(data->device); - g_slice_free(ActivateData, data); -} - static void pending_ac_gone(gpointer data, GObject *where_the_object_was) { @@ -1348,7 +1331,7 @@ pending_ac_state_changed(NMActiveConnection *ac, guint state, guint reason, NMPo } static void -auto_activate_device(NMPolicy *self, NMDevice *device) +_auto_activate_device(NMPolicy *self, NMDevice *device) { NMPolicyPrivate *priv; NMSettingsConnection *best_connection; @@ -1461,32 +1444,34 @@ auto_activate_device(NMPolicy *self, NMDevice *device) } } -static gboolean -auto_activate_device_cb(gpointer user_data) +static void +_auto_activate_device_clear(NMPolicy *self, NMDevice *device, gboolean do_activate) { - ActivateData *data = user_data; + nm_assert(NM_IS_DEVICE(device)); + nm_assert(NM_IS_POLICY(self)); + nm_assert(c_list_is_linked(&device->policy_auto_activate_lst)); + nm_assert(c_list_contains(&NM_POLICY_GET_PRIVATE(self)->policy_auto_activate_lst_head, + &device->policy_auto_activate_lst)); + + c_list_unlink(&device->policy_auto_activate_lst); + nm_clear_g_source_inst(&device->policy_auto_activate_idle_source); - g_assert(data); - g_assert(NM_IS_POLICY(data->policy)); - g_assert(NM_IS_DEVICE(data->device)); + if (do_activate) + _auto_activate_device(self, device); - data->autoactivate_id = 0; - auto_activate_device(data->policy, data->device); - activate_data_free(data); - return G_SOURCE_REMOVE; + nm_device_remove_pending_action(device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE); + g_object_unref(device); } -static ActivateData * -find_pending_activation(NMPolicy *self, NMDevice *device) +static gboolean +_auto_activate_idle_cb(gpointer user_data) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); - ActivateData *data; + NMDevice *device = user_data; - c_list_for_each_entry (data, &priv->pending_activation_checks, pending_lst) { - if (data->device == device) - return data; - } - return NULL; + nm_assert(NM_IS_DEVICE(device)); + + _auto_activate_device_clear(nm_manager_get_policy(nm_device_get_manager(device)), device, TRUE); + return G_SOURCE_CONTINUE; } /*****************************************************************************/ @@ -1673,13 +1658,17 @@ void nm_policy_device_recheck_auto_activate_schedule(NMPolicy *self, NMDevice *device) { NMPolicyPrivate *priv; - ActivateData *data; NMActiveConnection *ac; const CList *tmp_list; g_return_if_fail(NM_IS_POLICY(self)); g_return_if_fail(NM_IS_DEVICE(device)); + if (!c_list_is_empty(&device->policy_auto_activate_lst)) { + /* already queued. Return. */ + return; + } + priv = NM_POLICY_GET_PRIVATE(self); if (nm_manager_get_state(priv->manager) == NM_STATE_ASLEEP) @@ -1688,9 +1677,6 @@ nm_policy_device_recheck_auto_activate_schedule(NMPolicy *self, NMDevice *device if (!nm_device_autoconnect_allowed(device)) return; - if (find_pending_activation(self, device)) - return; - nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) { if (nm_active_connection_get_device(ac) == device) { if (nm_device_sys_iface_state_is_external(device) @@ -1703,11 +1689,9 @@ nm_policy_device_recheck_auto_activate_schedule(NMPolicy *self, NMDevice *device nm_device_add_pending_action(device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE); - data = g_slice_new0(ActivateData); - data->policy = self; - data->device = g_object_ref(device); - data->autoactivate_id = g_idle_add(auto_activate_device_cb, data); - c_list_link_tail(&priv->pending_activation_checks, &data->pending_lst); + c_list_link_tail(&priv->policy_auto_activate_lst_head, &device->policy_auto_activate_lst); + device->policy_auto_activate_idle_source = nm_g_idle_add_source(_auto_activate_idle_cb, device); + g_object_ref(device); } static gboolean @@ -2326,16 +2310,13 @@ device_removed(NMManager *manager, NMDevice *device, gpointer user_data) { NMPolicyPrivate *priv = user_data; NMPolicy *self = _PRIV_TO_SELF(priv); - ActivateData *data; /* TODO: is this needed? The delegations are cleaned up * on transition to deactivated too. */ ip6_remove_device_prefix_delegations(self, device); - /* Clear any idle callbacks for this device */ - data = find_pending_activation(self, device); - if (data && data->autoactivate_id) - activate_data_free(data); + if (c_list_is_linked(&device->policy_auto_activate_lst)) + _auto_activate_device_clear(self, device, FALSE); if (g_hash_table_remove(priv->devices, device)) devices_list_unregister(self, device); @@ -2747,7 +2728,7 @@ nm_policy_init(NMPolicy *self) NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); gs_free char *hostname_mode = NULL; - c_list_init(&priv->pending_activation_checks); + c_list_init(&priv->policy_auto_activate_lst_head); priv->netns = g_object_ref(nm_netns_get()); @@ -2885,7 +2866,6 @@ dispose(GObject *object) NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); GHashTableIter h_iter; NMDevice *device; - ActivateData *data, *data_safe; nm_clear_g_object(&priv->default_ac4); nm_clear_g_object(&priv->default_ac6); @@ -2893,8 +2873,10 @@ dispose(GObject *object) nm_clear_g_object(&priv->activating_ac6); nm_clear_pointer(&priv->pending_active_connections, g_hash_table_unref); - c_list_for_each_entry_safe (data, data_safe, &priv->pending_activation_checks, pending_lst) - activate_data_free(data); + while ((device = c_list_first_entry(&priv->policy_auto_activate_lst_head, + NMDevice, + policy_auto_activate_lst))) + _auto_activate_device_clear(self, device, FALSE); g_slist_free_full(priv->pending_secondaries, (GDestroyNotify) pending_secondary_data_free); priv->pending_secondaries = NULL; |