[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