diff options
author | Andrew Zaborowski <andrew.zaborowski@intel.com> | 2018-01-22 15:55:08 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-02-09 21:30:46 +0100 |
commit | 755d4e55c2253dc342a232aff725843fcfa727df (patch) | |
tree | 7e85c9927b6cb1775158c10b2ed825c0b3e77b48 | |
parent | 5f1c2e16c9cac48de7fa490df08de06080bd7a0c (diff) | |
download | NetworkManager-755d4e55c2253dc342a232aff725843fcfa727df.tar.gz |
iwd: simple periodic scanning
Add very simple periodic scanning because IWD itself only does periodic
scanning when it is in charge of autoconnecting (by policy). Since we
keep IWD out of the autoconnect state in order to use NM's autoconnect
logic, we need to request the scanning. The policy in this patch is to
use a simple 10s period between the end of one scan the requesting of
another while not connected, and 20s when connected. This is so that
users can expect similar results from both wifi backends but without
duplicating the more elaborate code in the wpa_supplicant backend which
can potentially be moved to a common superclass.
-rw-r--r-- | src/devices/wifi/nm-device-iwd.c | 98 |
1 files changed, 93 insertions, 5 deletions
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c index eaf504cc44..6c54120391 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/devices/wifi/nm-device-iwd.c @@ -75,10 +75,12 @@ typedef struct { GCancellable * cancellable; NMDeviceWifiCapabilities capabilities; NMActRequestGetSecretsCallId *wifi_secrets_id; + guint periodic_scan_id; bool enabled:1; bool can_scan:1; bool can_connect:1; bool scanning:1; + bool scan_requested:1; } NMDeviceIwdPrivate; struct _NMDeviceIwd { @@ -101,6 +103,9 @@ G_DEFINE_TYPE (NMDeviceIwd, nm_device_iwd, NM_TYPE_DEVICE) /*****************************************************************************/ +static void schedule_periodic_scan (NMDeviceIwd *self, + NMDeviceState current_state); + static void _ap_dump (NMDeviceIwd *self, NMLogLevel log_level, @@ -864,6 +869,33 @@ check_scanning_prohibited (NMDeviceIwd *self, gboolean periodic) } static void +scan_cb (GObject *source, GAsyncResult *res, gpointer user_data) +{ + NMDeviceIwd *self = user_data; + NMDeviceIwdPrivate *priv; + gs_free_error GError *error = NULL; + + if ( !_nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, + G_VARIANT_TYPE ("()"), &error) + && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + priv = NM_DEVICE_IWD_GET_PRIVATE (self); + priv->scan_requested = FALSE; + + /* On success, priv->scanning becomes true right before or right + * after this callback, so the next automatic scan will be + * scheduled when priv->scanning goes back to false. On error, + * schedule a retry now. + */ + if (error && !priv->scanning) { + NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); + + schedule_periodic_scan (self, state); + } +} + +static void dbus_request_scan_cb (NMDevice *device, GDBusMethodInvocation *context, NMAuthSubject *subject, @@ -912,8 +944,14 @@ dbus_request_scan_cb (NMDevice *device, } } - g_dbus_proxy_call (priv->dbus_proxy, "Scan", g_variant_new ("()"), - G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + if (!priv->scanning && !priv->scan_requested) { + g_dbus_proxy_call (priv->dbus_proxy, "Scan", + g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, -1, + priv->cancellable, scan_cb, self); + priv->scan_requested = TRUE; + } + g_dbus_method_invocation_return_value (context, NULL); } @@ -1461,6 +1499,45 @@ get_configured_mtu (NMDevice *device, gboolean *out_is_user_config) return mtu; } +static gboolean +periodic_scan_timeout_cb (gpointer user_data) +{ + NMDeviceIwd *self = user_data; + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); + + priv->periodic_scan_id = 0; + + if (priv->scanning || priv->scan_requested) + return FALSE; + + g_dbus_proxy_call (priv->dbus_proxy, "Scan", g_variant_new ("()"), + G_DBUS_CALL_FLAGS_NONE, -1, + priv->cancellable, scan_cb, self); + priv->scan_requested = TRUE; + + return FALSE; +} + +static void +schedule_periodic_scan (NMDeviceIwd *self, NMDeviceState current_state) +{ + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); + guint interval; + + if (current_state <= NM_DEVICE_STATE_UNAVAILABLE) + return; + + if (current_state == NM_DEVICE_STATE_DISCONNECTED) + interval = 10; + else + interval = 20; + + nm_clear_g_source (&priv->periodic_scan_id); + priv->periodic_scan_id = g_timeout_add_seconds (interval, + periodic_scan_timeout_cb, + self); +} + static void device_state_changed (NMDevice *device, NMDeviceState new_state, @@ -1470,10 +1547,13 @@ device_state_changed (NMDevice *device, NMDeviceIwd *self = NM_DEVICE_IWD (device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); - if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) + if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) { remove_all_aps (self); - else if (old_state <= NM_DEVICE_STATE_UNAVAILABLE) + nm_clear_g_source (&priv->periodic_scan_id); + } else if (old_state <= NM_DEVICE_STATE_UNAVAILABLE) { update_aps (self); + schedule_periodic_scan (self, new_state); + } switch (new_state) { case NM_DEVICE_STATE_UNMANAGED: @@ -1710,6 +1790,7 @@ static void scanning_changed (NMDeviceIwd *self, gboolean new_scanning) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self); + NMDeviceState state = nm_device_get_state (NM_DEVICE (self)); if (new_scanning == priv->scanning) return; @@ -1718,8 +1799,12 @@ scanning_changed (NMDeviceIwd *self, gboolean new_scanning) _notify (self, PROP_SCANNING); - if (!priv->scanning) + if (!priv->scanning) { update_aps (self); + + if (!priv->scan_requested) + schedule_periodic_scan (self, state); + } } static void @@ -1779,6 +1864,7 @@ nm_device_iwd_set_dbus_object (NMDeviceIwd *self, GDBusObject *object) value = g_dbus_proxy_get_cached_property (priv->dbus_proxy, "Scanning"); priv->scanning = g_variant_get_boolean (value); + priv->scan_requested = FALSE; g_signal_connect (priv->dbus_proxy, "g-properties-changed", G_CALLBACK (properties_changed), self); @@ -1861,6 +1947,8 @@ dispose (GObject *object) nm_clear_g_cancellable (&priv->cancellable); + nm_clear_g_source (&priv->periodic_scan_id); + wifi_secrets_cancel (self); cleanup_association_attempt (self, TRUE); |