Re: [RFC] Make scan mode configurable



On Tue, 2009-02-10 at 08:50 +0100, Daniel Wagner wrote:
> This adds support for continuously scanning. Also it alows to specify
> the scan inteval and the pruning time at runtime.

Ideally, nobody should have to touch internal scan details.  The reason
people keep wanting to is a combination of issues in drivers, the
supplicant, and NetworkManager itself.

* kernel drivers
    - Many drivers can't do specific-SSID scans (airo and out-of-tree
          drivers mainly)
    - Drivers don't always honor specific-SSID scans; with iwlwifi and
          hardware scanning, errors aren't returned to userspace so NM
          doesn't know when requested scans can't be performed.
    - Not all drivers report last beacon times

* WEXT
    - Cannot adequately report errors from most operations

* wpa_supplicant
    - D-Bus interface can't take specific SSIDs to scan

* NetworkManager
    - Doesn't have a good mechanism to report when users want better
          scan information
    - Scan backoff algorithm needs to be optimized
    - There could be bugs in the pruning algorithm

Obviously, the main problem is that not every AP is reported in each
scan, which is partially the fault of the drivers for not supporting
specific-SSID and active scans, and partly just wireless being
unreliable by definition.  This is what kills continuous scanning which
throws away the AP list each scan.  Sometimes your AP will be there,
sometimes it won't, depending on whether somebody turned on a microwave
during the scan.  You really do need some meta-tracking of scan results
across scans.

There's a few things we can do, patches for them gratefully accepted:

- Scan more often when not associated to anything, which helps your case

- If the scan list changes substantially (in a car, on the train, etc)
across a few scans, make the prune interval smaller.  ie, if AP turnover
is > 50% in two successive scans, be more aggressive about dropping
older APs.  This would work much better in combination with 

- 0.6 had a mechanism for the applet to notify NetworkManager that the
user was actively interested in the network status; each time the menu
was pulled down, the applet would tell NM, and NM would assume the user
was interested in the network topology, and decrease the scan interval,
or perform an immediate scan if one hadn't been done recently.  Ideally
this would take the form of a new signal of the
org.freedesktop.NetworkManagerSettings interface for "UserActivity" (or
some better name) that NM would listen for.

Any of these sound interesting to you?

Cheers,
Dan


> Signed-off-by: Daniel Wagner <wagi monom org>
> ---
> The idea behind this patch is to be able to recognize AP a bit faster then
> the standard algorithm in NM. I'm not completely sure where this continuously
> scaning code should go. Propably all that should be handled by wpa_supplicant?
> 
> If you don't like this patch, no problem with me. In case you like it I guess
> some more work is needed. For example I really don't know how you get those
> interesting tab-space indentions. :) 
> 
>  include/NetworkManager.h         |    8 ++
>  introspection/nm-device-wifi.xml |   16 +++
>  libnm-glib/nm-device-wifi.c      |  203 ++++++++++++++++++++++++++++++++++++++
>  libnm-glib/nm-device-wifi.h      |   12 +++
>  src/nm-device-wifi.c             |  164 ++++++++++++++++++++++++++-----
>  src/nm-device-wifi.h             |    3 +
>  6 files changed, 380 insertions(+), 26 deletions(-)
> 
> diff --git a/include/NetworkManager.h b/include/NetworkManager.h
> index d61a89c..380d896 100644
> --- a/include/NetworkManager.h
> +++ b/include/NetworkManager.h
> @@ -141,6 +141,14 @@ typedef enum {
>  	NM_802_11_MODE_INFRA
>  } NM80211Mode;
>  
> +/*
> + * 802.11 Scan mode behaviour
> + *
> + */
> +typedef enum {
> +	NM_802_11_SCAN_MODE_DEFAULT = 0,
> +	NM_802_11_SCAN_MODE_CONTINUOUSLY, 
> +} NM80211ScanMode;
>  
>  /*
>   * Device states
> diff --git a/introspection/nm-device-wifi.xml b/introspection/nm-device-wifi.xml
> index 21ace0a..55d4135 100644
> --- a/introspection/nm-device-wifi.xml
> +++ b/introspection/nm-device-wifi.xml
> @@ -41,6 +41,22 @@
>        </tp:docstring>
>      </property>
>  
> +    <property name="WirelessScanMode" type="u" access="readwrite">
> +      <tp:docstring>
> +	Scan mode.
> +      </tp:docstring>
> +    </property>
> +    <property name="WirelessScanInterval" type="u" access="readwrite">
> +      <tp:docstring>
> +	Scan interval value in seconds.
> +      </tp:docstring>
> +    </property>
> +    <property name="WirelessScanPrune" type="u" access="readwrite">
> +      <tp:docstring>
> +	Scan prune value in seconds.
> +      </tp:docstring>
> +    </property>
> +
>      <signal name="PropertiesChanged">
>          <arg name="properties" type="a{sv}" tp:type="String_Variant_Map">
>              <tp:docstring>
> diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c
> index 1729c8a..dde76d1 100644
> --- a/libnm-glib/nm-device-wifi.c
> +++ b/libnm-glib/nm-device-wifi.c
> @@ -51,6 +51,9 @@ typedef struct {
>  	gboolean null_active_ap;
>  	guint32 wireless_caps;
>  	GPtrArray *aps;
> +	guint scan_mode;
> +	guint scan_interval;      /* seconds */
> +	guint scan_prune;         /* seconds */
>  
>  	gboolean wireless_enabled;
>  } NMDeviceWifiPrivate;
> @@ -62,6 +65,9 @@ enum {
>  	PROP_BITRATE,
>  	PROP_ACTIVE_ACCESS_POINT,
>  	PROP_WIRELESS_CAPABILITIES,
> +	PROP_WIRELESS_SCAN_MODE,
> +	PROP_WIRELESS_SCAN_INTERVAL,
> +	PROP_WIRELESS_SCAN_PRUNE,
>  
>  	LAST_PROP
>  };
> @@ -71,6 +77,9 @@ enum {
>  #define DBUS_PROP_BITRATE "Bitrate"
>  #define DBUS_PROP_ACTIVE_ACCESS_POINT "ActiveAccessPoint"
>  #define DBUS_PROP_WIRELESS_CAPABILITIES "WirelessCapabilities"
> +#define DBUS_PROP_WIRELESS_SCAN_MODE "WirelessScanMode"
> +#define DBUS_PROP_WIRELESS_SCAN_INTERVAL "WirelessScanInterval"
> +#define DBUS_PROP_WIRELESS_SCAN_PRUNE "WirelessScanPrune"
>  
>  enum {
>  	ACCESS_POINT_ADDED,
> @@ -218,6 +227,138 @@ nm_device_wifi_get_capabilities (NMDeviceWifi *device)
>  }
>  
>  /**
> + * nm_device_wifi_get_scan_mode:
> + * @device: a #NMDeviceWifi
> + *
> + * Gets the wireless scan mode of the #NMDeviceWifi.
> + *
> + * Returns: the wireless scan mode
> + **/
> +guint32
> +nm_device_wifi_get_scan_mode (NMDeviceWifi *device)
> +{
> +	NMDeviceWifiPrivate *priv;
> +
> +	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0);
> +
> +	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
> +	priv->scan_mode = _nm_object_get_uint_property (NM_OBJECT (device),
> +													NM_DBUS_INTERFACE_DEVICE_WIRELESS,
> +													DBUS_PROP_WIRELESS_SCAN_MODE);
> +	return priv->scan_mode;
> +}
> +
> +/**
> + * nm_device_wifi_get_scan_interval:
> + * @device: a #NMDeviceWifi
> + *
> + * Gets the wireless scan interval of the #NMDeviceWifi.
> + *
> + * Returns: the wireless scan interval
> + **/
> +guint32
> +nm_device_wifi_get_scan_interval (NMDeviceWifi *device)
> +{
> +	NMDeviceWifiPrivate *priv;
> +
> +	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0);
> +
> +	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
> +	priv->scan_interval = _nm_object_get_uint_property (NM_OBJECT (device),
> +														NM_DBUS_INTERFACE_DEVICE_WIRELESS,
> +														DBUS_PROP_WIRELESS_SCAN_INTERVAL);
> +	return priv->scan_interval;
> +}
> +
> +/**
> + * nm_device_wifi_get_scan_prune:
> + * @device: a #NMDeviceWifi
> + *
> + * Gets the wireless scan prune of the #NMDeviceWifi.
> + *
> + * Returns: the wireless scan prune
> + **/
> +guint32
> +nm_device_wifi_get_scan_prune (NMDeviceWifi *device)
> +{
> +	NMDeviceWifiPrivate *priv;
> +
> +	g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0);
> +
> +	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
> +	priv->scan_prune = _nm_object_get_uint_property (NM_OBJECT (device),
> +													 NM_DBUS_INTERFACE_DEVICE_WIRELESS,
> +													 DBUS_PROP_WIRELESS_SCAN_PRUNE);
> +	return priv->scan_prune;
> +}
> +
> +/**
> + * nm_device_wifi_set_scan_interval:
> + * @device: a #NMDeviceWifi
> + *
> + * Sets the wireless scan interval of the #NMDeviceWifi.
> + **/
> +void nm_device_wifi_set_scan_interval (NMDeviceWifi *device, const GValue *value)
> +{
> +	NMDeviceWifiPrivate *priv;
> +	GValue val = {0,};
> +	g_return_if_fail (NM_IS_DEVICE_WIFI (device));
> +	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
> +
> +	priv->scan_interval = g_value_get_uint(value);
> +
> +	g_value_copy (value, &val);
> +	_nm_object_set_property (NM_OBJECT(device),
> +							 NM_DBUS_INTERFACE_DEVICE_WIRELESS,
> +							 DBUS_PROP_WIRELESS_SCAN_INTERVAL,
> +							 &val);
> +}
> +
> +/**
> + * nm_device_wifi_set_scan_mode:
> + * @device: a #NMDeviceWifi
> + *
> + * Sets the wireless scan mode of the #NMDeviceWifi.
> + **/
> +void nm_device_wifi_set_scan_mode (NMDeviceWifi *device, const GValue *value)
> +{
> +	NMDeviceWifiPrivate *priv;
> +	GValue val = {0,};
> +	g_return_if_fail (NM_IS_DEVICE_WIFI (device));
> +	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
> +
> +	priv->scan_interval = g_value_get_uint(value);
> +
> +	g_value_copy (value, &val);
> +	_nm_object_set_property (NM_OBJECT(device),
> +							 NM_DBUS_INTERFACE_DEVICE_WIRELESS,
> +							 DBUS_PROP_WIRELESS_SCAN_MODE,
> +							 &val);
> +}
> +
> +/**
> + * nm_device_wifi_set_scan_prune:
> + * @device: a #NMDeviceWifi
> + *
> + * Sets the wireless scan prune of the #NMDeviceWifi.
> + **/
> +void nm_device_wifi_set_scan_prune (NMDeviceWifi *device, const GValue *value)
> +{
> +	NMDeviceWifiPrivate *priv;
> +	GValue val = {0,};
> +	g_return_if_fail (NM_IS_DEVICE_WIFI (device));
> +	priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
> +
> +	priv->scan_prune = g_value_get_uint(value);
> +
> +	g_value_copy (value, &val);
> +	_nm_object_set_property (NM_OBJECT(device),
> +							 NM_DBUS_INTERFACE_DEVICE_WIRELESS,
> +							 DBUS_PROP_WIRELESS_SCAN_PRUNE,
> +							 &val);
> +}
> +
> +/**
>   * nm_device_wifi_get_active_access_point:
>   * @device: a #NMDeviceWifi
>   *
> @@ -476,6 +617,25 @@ get_property (GObject *object,
>  	case PROP_WIRELESS_CAPABILITIES:
>  		g_value_set_uint (value, nm_device_wifi_get_capabilities (self));
>  		break;
> +	case PROP_WIRELESS_SCAN_INTERVAL:
> +		g_value_set_uint (value, nm_device_wifi_get_scan_interval (self));
> +		break;
> +	default:
> +		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
> +		break;
> +	}
> +}
> +
> +static void
> +set_property (GObject *object, guint prop_id,
> +			  const GValue *value, GParamSpec *pspec)
> +{
> +	NMDeviceWifi *self = NM_DEVICE_WIFI (object);
> +
> +	switch (prop_id) {
> +	case PROP_WIRELESS_SCAN_INTERVAL:
> +		nm_device_wifi_set_scan_interval (self, value);
> +		break;
>  	default:
>  		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
>  		break;
> @@ -559,6 +719,9 @@ register_for_property_changed (NMDeviceWifi *device)
>  		{ NM_DEVICE_WIFI_BITRATE,             _nm_object_demarshal_generic, &priv->rate },
>  		{ NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, demarshal_active_ap,         &priv->active_ap },
>  		{ NM_DEVICE_WIFI_CAPABILITIES,        _nm_object_demarshal_generic, &priv->wireless_caps },
> +		{ NM_DEVICE_WIFI_SCAN_MODE,           _nm_object_demarshal_generic, &priv->scan_mode },
> +		{ NM_DEVICE_WIFI_SCAN_INTERVAL,       _nm_object_demarshal_generic, &priv->scan_interval },
> +		{ NM_DEVICE_WIFI_SCAN_PRUNE,          _nm_object_demarshal_generic, &priv->scan_prune },
>  		{ NULL },
>  	};
>  
> @@ -651,6 +814,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *device_class)
>  	/* virtual methods */
>  	object_class->constructor = constructor;
>  	object_class->get_property = get_property;
> +	object_class->set_property = set_property;
>  	object_class->dispose = dispose;
>  	object_class->finalize = finalize;
>  
> @@ -721,6 +885,45 @@ nm_device_wifi_class_init (NMDeviceWifiClass *device_class)
>  		                    0, G_MAXUINT32, 0,
>  		                    G_PARAM_READABLE));
>  
> +	/**
> +	 * NMDeviceWifi:wireless-scan-mode:
> +	 *
> +	 * The wireless scan mode
> +	 **/
> +	g_object_class_install_property
> +		(object_class, PROP_WIRELESS_SCAN_MODE,
> +		 g_param_spec_uint (NM_DEVICE_WIFI_SCAN_MODE,
> +							"Wireless Scan Mode",
> +							"Wireless Scan Mode",
> +							0, G_MAXUINT32, 0,
> +							G_PARAM_READWRITE));
> +
> +	/**
> +	 * NMDeviceWifi:wireless-scan-interval:
> +	 *
> +	 * The wireless scan interval
> +	 **/
> +	g_object_class_install_property
> +		(object_class, PROP_WIRELESS_SCAN_INTERVAL,
> +		 g_param_spec_uint (NM_DEVICE_WIFI_SCAN_INTERVAL,
> +					    "Wireless Scan Interval",
> +					    "Wireless Scan Interval",
> +					    0, G_MAXUINT32, 0,
> +					    G_PARAM_READWRITE));
> +
> +	/**
> +	 * NMDeviceWifi:wireless-scan-prune:
> +	 *
> +	 * The wireless scan prune
> +	 **/
> +	g_object_class_install_property
> +		(object_class, PROP_WIRELESS_SCAN_PRUNE,
> +		 g_param_spec_uint (NM_DEVICE_WIFI_SCAN_PRUNE,
> +					    "Wireless Scan Prune",
> +					    "Wireless Scan Prunde",
> +					    0, G_MAXUINT32, 0,
> +					    G_PARAM_READWRITE));
> +
>  	/* signals */
>  
>  	/**
> diff --git a/libnm-glib/nm-device-wifi.h b/libnm-glib/nm-device-wifi.h
> index 69e6dd7..0b23a43 100644
> --- a/libnm-glib/nm-device-wifi.h
> +++ b/libnm-glib/nm-device-wifi.h
> @@ -41,6 +41,9 @@ G_BEGIN_DECLS
>  #define NM_DEVICE_WIFI_BITRATE             "bitrate"
>  #define NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT "active-access-point"
>  #define NM_DEVICE_WIFI_CAPABILITIES        "wireless-capabilities"
> +#define NM_DEVICE_WIFI_SCAN_MODE           "wireless-scan-mode"
> +#define NM_DEVICE_WIFI_SCAN_INTERVAL       "wireless-scan-interval"
> +#define NM_DEVICE_WIFI_SCAN_PRUNE          "wireless-scan-prune"
>  
>  typedef struct {
>  	NMDevice parent;
> @@ -62,6 +65,15 @@ const char *    nm_device_wifi_get_hw_address           (NMDeviceWifi *device);
>  NM80211Mode     nm_device_wifi_get_mode                 (NMDeviceWifi *device);
>  guint32         nm_device_wifi_get_bitrate              (NMDeviceWifi *device);
>  guint32         nm_device_wifi_get_capabilities         (NMDeviceWifi *device);
> +guint32         nm_device_wifi_get_scan_mode            (NMDeviceWifi *device);
> +guint32         nm_device_wifi_get_scan_interval        (NMDeviceWifi *device);
> +guint32         nm_device_wifi_get_scan_prune           (NMDeviceWifi *device);
> +void            nm_device_wifi_set_scan_mode            (NMDeviceWifi *device, 
> +														 const GValue *value);
> +void            nm_device_wifi_set_scan_interval        (NMDeviceWifi *device, 
> +														 const GValue *value);
> +void            nm_device_wifi_set_scan_prune           (NMDeviceWifi *device, 
> +														 const GValue *value);
>  NMAccessPoint * nm_device_wifi_get_active_access_point  (NMDeviceWifi *device);
>  
>  NMAccessPoint * nm_device_wifi_get_access_point_by_path (NMDeviceWifi *device,
> diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c
> index d7cc2f3..f1ff9b8 100644
> --- a/src/nm-device-wifi.c
> +++ b/src/nm-device-wifi.c
> @@ -64,6 +64,8 @@ static gboolean impl_device_get_access_points (NMDeviceWifi *device,
>  #define SCAN_INTERVAL_MIN 0
>  #define SCAN_INTERVAL_STEP 20
>  #define SCAN_INTERVAL_MAX 120
> +#define SCAN_PRUNE (SCAN_INTERVAL_MAX * 3)
> +#define SCAN_MODE NM_802_11_SCAN_MODE_DEFAULT
>  
>  #define WIRELESS_SECRETS_TRIES "wireless-secrets-tries"
>  
> @@ -80,6 +82,9 @@ enum {
>  	PROP_BITRATE,
>  	PROP_ACTIVE_ACCESS_POINT,
>  	PROP_CAPABILITIES,
> +	PROP_WIRELESS_SCAN_MODE,
> +	PROP_WIRELESS_SCAN_INTERVAL,
> +	PROP_WIRELESS_SCAN_PRUNE,
>  
>  	LAST_PROP
>  };
> @@ -155,8 +160,10 @@ struct _NMDeviceWifiPrivate
>  	
>  	gboolean			scanning;
>  	glong			scheduled_scan_time;
> -	guint8			scan_interval; /* seconds */
>  	guint               pending_scan_id;
> +	NM80211ScanMode scan_mode;
> +	guint			scan_interval;      /* seconds */
> +	guint           scan_prune;         /* seconds */
>  
>  	Supplicant      supplicant;
>  
> @@ -221,6 +228,10 @@ static void supplicant_mgr_state_cb (NMSupplicantInterface * iface,
>  static guint32 nm_device_wifi_get_bitrate (NMDeviceWifi *self);
>  
> 
> +static gboolean nm_device_wifi_set_scan_mode(NMDeviceWifi *self, NM80211ScanMode mode);
> +static gboolean nm_device_wifi_set_scan_interval(NMDeviceWifi *self, guint ival);
> +static gboolean nm_device_wifi_set_scan_prune(NMDeviceWifi *self, guint prune);
> +
>  static GQuark
>  nm_wifi_error_quark (void)
>  {
> @@ -686,8 +697,11 @@ supplicant_interface_release (NMDeviceWifi *self)
>  
>  	cancel_pending_scan (self);
>  
> -	/* Reset the scan interval to be pretty frequent when disconnected */
> -	priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP;
> +	if (priv->scan_mode == NM_802_11_SCAN_MODE_DEFAULT) {
> +		/* Reset the scan interval to be pretty frequent when disconnected */
> +		priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP;
> +		priv->scan_prune = SCAN_PRUNE;
> +	}
>  
>  	remove_supplicant_interface_error_handler (self);
>  
> @@ -1711,33 +1725,38 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff)
>  	}
>  
>  	if (!priv->pending_scan_id) {
> -		guint factor = 2;
> +		if (priv->scan_mode == NM_802_11_SCAN_MODE_DEFAULT) {
> +			guint factor = 2;
>  
> -		if (    nm_device_is_activating (NM_DEVICE (self))
> -		    || (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED))
> -			factor = 1;
> +			if (    nm_device_is_activating (NM_DEVICE (self))
> +					|| (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED))
> +				factor = 1;
>  
> -		priv->pending_scan_id = g_timeout_add (priv->scan_interval * 1000,
> -											   request_wireless_scan,
> -											   self);
> +			priv->pending_scan_id = g_timeout_add (priv->scan_interval * 1000,
> +												   request_wireless_scan,
> +												   self);
>  
> -		priv->scheduled_scan_time = now.tv_sec + priv->scan_interval;
> -		if (backoff && (priv->scan_interval < (SCAN_INTERVAL_MAX / factor))) {
> +			priv->scheduled_scan_time = now.tv_sec + priv->scan_interval;
> +			if (backoff && (priv->scan_interval < (SCAN_INTERVAL_MAX / factor))) {
>  				priv->scan_interval += (SCAN_INTERVAL_STEP / factor);
>  				/* Ensure the scan interval will never be less than 20s... */
>  				priv->scan_interval = MAX(priv->scan_interval, SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP);
>  				/* ... or more than 120s */
>  				priv->scan_interval = MIN(priv->scan_interval, SCAN_INTERVAL_MAX);
> -		} else if (!backoff && (priv->scan_interval == 0)) {
> -			/* Invalid combination; would cause continual rescheduling of
> -			 * the scan and hog CPU.  Reset to something minimally sane.
> -			 */
> -			priv->scan_interval = 5;
> +			} else if (!backoff && (priv->scan_interval == 0)) {
> +				/* Invalid combination; would cause continual rescheduling of
> +				 * the scan and hog CPU.  Reset to something minimally sane.
> +				 */
> +				priv->scan_interval = 5;
> +			}
> +		} else if (priv->scan_mode == NM_802_11_SCAN_MODE_CONTINUOUSLY) {
> +			priv->pending_scan_id = g_timeout_add (priv->scan_interval * 1000,
> +												   request_wireless_scan,
> +												   self);
>  		}
>  	}
>  }
>  
> -
>  static void
>  cancel_pending_scan (NMDeviceWifi *self)
>  {
> @@ -1931,7 +1950,6 @@ cull_scan_list (NMDeviceWifi *self)
>  		NMAccessPoint * ap = NM_AP (elt->data);
>  		const glong     ap_time = nm_ap_get_last_seen (ap);
>  		gboolean        keep = FALSE;
> -		const guint     prune_interval_s = SCAN_INTERVAL_MAX * 3;
>  
>  		/* Don't ever prune the AP we're currently associated with */
>  		if (cur_ap_path && !strcmp (cur_ap_path, nm_ap_get_dbus_path (ap)))
> @@ -1939,7 +1957,7 @@ cull_scan_list (NMDeviceWifi *self)
>  		if (nm_ap_get_fake (ap))
>  			keep = TRUE;
>  
> -		if (!keep && (ap_time + prune_interval_s < cur_time.tv_sec))
> +		if (!keep && (ap_time + priv->scan_prune < cur_time.tv_sec))
>  			outdated_list = g_slist_append (outdated_list, ap);
>  	}
>  
> @@ -2197,11 +2215,17 @@ supplicant_iface_state_cb_handler (gpointer user_data)
>  	         nm_supplicant_interface_state_to_string (task->new_state));
>  
>  	if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
> -		priv->scan_interval = SCAN_INTERVAL_MIN;
> +		if (priv->scan_mode == NM_802_11_SCAN_MODE_DEFAULT) {
> +			priv->scan_interval = SCAN_INTERVAL_MIN;
> +			priv->scan_prune = SCAN_PRUNE;
>  
> -		/* Request a scan to get latest results */
> -		cancel_pending_scan (self);
> -		request_wireless_scan (self);
> +			/* Request a scan to get latest results */
> +			cancel_pending_scan (self);
> +			request_wireless_scan (self);
> +		} else if (priv->scan_mode == NM_802_11_SCAN_MODE_CONTINUOUSLY) {
> +			priv->scan_interval = SCAN_INTERVAL_MIN;
> +			priv->scan_prune = priv->scan_interval * 3;
> +		}
>  	} else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
>  		cleanup_association_attempt (self, FALSE);
>  		supplicant_interface_release (self);
> @@ -3089,8 +3113,11 @@ activation_success_handler (NMDevice *dev)
>  done:
>  	periodic_update (self);
>  
> -	/* Reset scan interval to something reasonable */
> -	priv->scan_interval = SCAN_INTERVAL_MIN + (SCAN_INTERVAL_STEP * 2);
> +	if (priv->scan_mode == NM_802_11_SCAN_MODE_DEFAULT) {
> +		/* Reset scan interval to something reasonable */
> +		priv->scan_interval = SCAN_INTERVAL_MIN + (SCAN_INTERVAL_STEP * 2);
> +		priv->scan_prune = SCAN_PRUNE;
> +	}
>  }
>  
> 
> @@ -3228,6 +3255,15 @@ get_property (GObject *object, guint prop_id,
>  	case PROP_CAPABILITIES:
>  		g_value_set_uint (value, priv->capabilities);
>  		break;
> +	case PROP_WIRELESS_SCAN_MODE:
> +		g_value_set_uint(value, priv->scan_mode);
> +		break;
> +	case PROP_WIRELESS_SCAN_INTERVAL:
> +		g_value_set_uint(value, priv->scan_interval);
> +		break;
> +	case PROP_WIRELESS_SCAN_PRUNE:
> +		g_value_set_uint(value, priv->scan_prune);
> +		break;
>  	case PROP_ACTIVE_ACCESS_POINT:
>  		if (priv->current_ap)
>  			g_value_set_boxed (value, nm_ap_get_dbus_path (priv->current_ap));
> @@ -3241,6 +3277,28 @@ get_property (GObject *object, guint prop_id,
>  }
>  
>  static void
> +set_property (GObject *object, guint prop_id,
> +			  const GValue *value, GParamSpec *pspec)
> +{
> +	NMDeviceWifi *device = NM_DEVICE_WIFI (object);
> +
> +	switch (prop_id) {
> +	case PROP_WIRELESS_SCAN_MODE:
> +		nm_device_wifi_set_scan_mode(device, g_value_get_uint(value));
> +		break;
> +	case PROP_WIRELESS_SCAN_INTERVAL:
> +		nm_device_wifi_set_scan_interval(device, g_value_get_uint(value));
> +		break;
> +	case PROP_WIRELESS_SCAN_PRUNE:
> +		nm_device_wifi_set_scan_prune(device, g_value_get_uint(value));
> +		break;
> +	default:
> +		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
> +		break;
> +	}
> +}
> +
> +static void
>  nm_device_wifi_class_init (NMDeviceWifiClass *klass)
>  {
>  	GObjectClass *object_class = G_OBJECT_CLASS (klass);
> @@ -3250,6 +3308,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
>  
>  	object_class->constructor = constructor;
>  	object_class->get_property = get_property;
> +	object_class->set_property = set_property;
>  	object_class->dispose = nm_device_wifi_dispose;
>  
>  	parent_class->get_type_capabilities = real_get_type_capabilities;
> @@ -3310,6 +3369,27 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
>  							"Wireless Capabilities",
>  							0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE,
>  							G_PARAM_READABLE));
> +	g_object_class_install_property
> +		(object_class, PROP_WIRELESS_SCAN_MODE,
> +		 g_param_spec_uint (NM_DEVICE_WIFI_SCAN_MODE,
> +						   "WirelessScanMode",
> +						   "Scan mode",
> +						   0, G_MAXUINT32, SCAN_MODE,
> +						   G_PARAM_READABLE | G_PARAM_WRITABLE));
> +	g_object_class_install_property
> +		(object_class, PROP_WIRELESS_SCAN_INTERVAL,
> +		 g_param_spec_uint (NM_DEVICE_WIFI_SCAN_INTERVAL,
> +						   "WirelessScanInterval",
> +						   "Scan interval",
> +						   0, G_MAXUINT32, 0,
> +						   G_PARAM_READABLE | G_PARAM_WRITABLE));
> +	g_object_class_install_property
> +		(object_class, PROP_WIRELESS_SCAN_PRUNE,
> +		 g_param_spec_uint (NM_DEVICE_WIFI_SCAN_PRUNE,
> +						   "WirelessScanPrune",
> +						   "Scan prune",
> +						   0, G_MAXUINT32, 0,
> +						   G_PARAM_READABLE | G_PARAM_WRITABLE));
>  
>  	/* Signals */
>  	signals[ACCESS_POINT_ADDED] =
> @@ -3535,3 +3615,35 @@ nm_device_wifi_set_enabled (NMDeviceWifi *self, gboolean enabled)
>  	}
>  }
>  
> +gboolean 
> +nm_device_wifi_set_scan_mode(NMDeviceWifi *self, NM80211ScanMode mode)
> +{
> +	NMDeviceWifiPrivate *priv;
> +
> +	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
> +	priv->scan_mode = mode;
> +	schedule_scan(self, TRUE);
> +	return TRUE;
> +}
> +
> +gboolean 
> +nm_device_wifi_set_scan_interval(NMDeviceWifi *self, guint ival)
> +{
> +	NMDeviceWifiPrivate *priv;
> +
> +	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
> +	priv->scan_interval = ival;
> +	schedule_scan(self, TRUE);
> +	return TRUE;
> +}
> +
> +gboolean 
> +nm_device_wifi_set_scan_prune(NMDeviceWifi *self, guint prune)
> +{
> +	NMDeviceWifiPrivate *priv;
> +
> +	priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
> +	priv->scan_prune = prune;
> +	return TRUE;
> +}
> +
> diff --git a/src/nm-device-wifi.h b/src/nm-device-wifi.h
> index 1e885cb..0d240f9 100644
> --- a/src/nm-device-wifi.h
> +++ b/src/nm-device-wifi.h
> @@ -47,6 +47,9 @@ G_BEGIN_DECLS
>  #define NM_DEVICE_WIFI_BITRATE "bitrate"
>  #define NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT "active-access-point"
>  #define NM_DEVICE_WIFI_CAPABILITIES "wireless-capabilities"
> +#define NM_DEVICE_WIFI_SCAN_MODE "wireless-scan-mode"
> +#define NM_DEVICE_WIFI_SCAN_INTERVAL "wireless-scan-interval"
> +#define NM_DEVICE_WIFI_SCAN_PRUNE "wireless-scan-prune"
>  
>  #ifndef NM_DEVICE_WIFI_DEFINED
>  #define NM_DEVICE_WIFI_DEFINED



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]