[PATCH] don't re-scan on SELECT_NETWORK with recent scan results
Dan Williams
dcbw
Sun Nov 29 15:37:32 PST 2009
It's pretty pointless to trigger a new scan when a control interface
calls SELECT_NETWORK if the scan results are less than 10 seconds old.
This speeds up associations when the connection manager has already
requested a scan to determine what BSS to connect to, and then tells the
supplicant to select that BSS, which previously would trigger yet
another scan a few seconds after the first one.
Signed-off-by: Dan Williams <dcbw at redhat.com>
---
Jouni: if this approach is acceptable, I'll send along the patch for 0.6.x too
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 5f55180..e9378b8 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -681,15 +681,16 @@ static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s,
}
-static void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
- struct wpa_scan_res *selected,
- struct wpa_ssid *ssid)
+static int wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
+ struct wpa_scan_res *selected,
+ struct wpa_ssid *ssid,
+ int *out_timeout)
{
if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) {
wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP
"PBC session overlap");
- wpa_supplicant_req_new_scan(wpa_s, 10);
- return;
+ *out_timeout = 10;
+ return -1;
}
/*
@@ -703,15 +704,16 @@ static void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) !=
0))) {
if (wpa_supplicant_scard_init(wpa_s, ssid)) {
- wpa_supplicant_req_new_scan(wpa_s, 10);
- return;
+ *out_timeout = 10;
+ return -1;
}
wpa_supplicant_associate(wpa_s, selected, ssid);
} else {
wpa_printf(MSG_DEBUG, "Already associated with the selected "
"AP");
}
- rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res);
+
+ return 0;
}
@@ -734,11 +736,34 @@ wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s)
return NULL;
}
-
-static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
+int wpa_supplicant_pick_and_connect(struct wpa_supplicant *wpa_s,
+ int *out_timeout)
{
struct wpa_scan_res *selected;
struct wpa_ssid *ssid = NULL;
+ int ret = 0;
+
+ selected = wpa_supplicant_pick_network(wpa_s, &ssid);
+ if (selected) {
+ ret = wpa_supplicant_connect(wpa_s, selected, ssid, out_timeout);
+ } else {
+ wpa_printf(MSG_DEBUG, "No suitable network found");
+ ssid = wpa_supplicant_pick_new_network(wpa_s);
+ if (ssid) {
+ wpa_printf(MSG_DEBUG, "Setup a new network");
+ wpa_supplicant_associate(wpa_s, NULL, ssid);
+ } else {
+ *out_timeout = 5;
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
+{
+ int timeout = 0;
wpa_supplicant_notify_scanning(wpa_s, 0);
@@ -767,6 +792,10 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
wpas_notify_scan_done(wpa_s, 1);
+ /* Update scan timestamp if there are any scan results */
+ if (wpa_s->scan_res->num > 0)
+ os_get_time(&(wpa_s->last_scan));
+
if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)))
return;
@@ -778,18 +807,10 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s)
if (bgscan_notify_scan(wpa_s) == 1)
return;
- selected = wpa_supplicant_pick_network(wpa_s, &ssid);
- if (selected) {
- wpa_supplicant_connect(wpa_s, selected, ssid);
- } else {
- wpa_printf(MSG_DEBUG, "No suitable network found");
- ssid = wpa_supplicant_pick_new_network(wpa_s);
- if (ssid) {
- wpa_printf(MSG_DEBUG, "Setup a new network");
- wpa_supplicant_associate(wpa_s, NULL, ssid);
- } else
- wpa_supplicant_req_new_scan(wpa_s, 5);
- }
+ if (wpa_supplicant_pick_and_connect(wpa_s, &timeout))
+ wpa_supplicant_req_new_scan(wpa_s, timeout);
+ else
+ rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res);
}
#endif /* CONFIG_NO_SCAN_PROCESSING */
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 5ea06f4..ed675a7 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1450,6 +1450,8 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
{
struct wpa_ssid *other_ssid;
+ struct os_time now;
+ int do_scan = 1, timeout;
if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid)
wpa_supplicant_disassociate(
@@ -1472,7 +1474,22 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
}
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
+
+ /* Just associate and don't request a scan if the latest
+ * scan results are less than 10 seconds old.
+ */
+ if (os_get_time(&now) == 0) {
+ now.sec -= 10;
+ if (os_time_before(&now, &(wpa_s->last_scan))) {
+ if (wpa_supplicant_pick_and_connect (wpa_s,
+ &timeout) >= 0) {
+ do_scan = 0;
+ }
+ }
+ }
+
+ if (do_scan)
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
if (ssid)
wpas_notify_network_selected(wpa_s, ssid);
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 5578802..29c7f27 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -376,6 +376,7 @@ struct wpa_supplicant {
* to speed up the first association if the driver
* has already available scan results. */
int scan_runs; /* number of scan runs since WPS was started */
+ struct os_time last_scan; /* timestamp of last scan results */
struct wpa_client_mlme mlme;
unsigned int drv_flags;
@@ -491,5 +492,7 @@ int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
/* events.c */
void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s);
+int wpa_supplicant_pick_and_connect(struct wpa_supplicant *wpa_s,
+ int *out_timeout);
#endif /* WPA_SUPPLICANT_I_H */
More information about the Hostap
mailing list