[PATCH] Improve performance of reconnect operation

Peter Qiu zqiu
Thu Mar 6 10:06:04 PST 2014


Added "reattach" command to perform single-channel single-ssid
scan instead of full scan when trying to reconnect to the currently
"connected" network. This allows the scan result to come
back in much faster time. In ath9k, the scan took around 12 seconds
with full background scan, and only 0.1 second with the single-channel
single-ssid scan. Thus, take much less time for the client to re-establish
connection with the currently "connected" network.

Signed-hostap: Peter Qiu <zqiu at chromium.org>
---
 wpa_supplicant/ctrl_iface.c             | 10 ++++++++++
 wpa_supplicant/dbus/dbus_new.c          |  6 ++++++
 wpa_supplicant/dbus/dbus_new_handlers.c | 27 +++++++++++++++++++++++++++
 wpa_supplicant/dbus/dbus_new_handlers.h |  3 +++
 wpa_supplicant/scan.c                   | 30 ++++++++++++++++++++++++++++++
 wpa_supplicant/wpa_cli.c                | 10 ++++++++++
 wpa_supplicant/wpa_supplicant_i.h       |  1 +
 7 files changed, 87 insertions(+)

diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 2935ce7..8c1aa3c 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5961,6 +5961,16 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 			reply_len = -1;
 		else
 			wpas_request_connection(wpa_s);
+	} else if (os_strcmp(buf, "REATTACH") == 0) {
+		wpa_s->normal_scans = 0;
+		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
+			reply_len = -1;
+		else {
+			wpa_s->disconnected = 0;
+			wpa_s->reassociate = 1;
+			wpa_s->reattach = 1;
+			wpa_supplicant_req_scan(wpa_s, 0, 0);
+		}
 	} else if (os_strcmp(buf, "RECONNECT") == 0) {
 		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
 			reply_len = -1;
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index f40d421..5e02956 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -2462,6 +2462,12 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
 		  END_ARGS
 	  }
 	},
+	{ "Reattach", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_reattach,
+	  {
+		  END_ARGS
+	  }
+	},
 	{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
 	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
 	  {
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index bfb33d5..d058b9f 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -1487,6 +1487,33 @@ DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
 
 
 /**
+ * wpas_dbus_handler_reattach - Reattach to current AP
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NotConnected DBus error message if not connected
+ * or NULL otherwise.
+ *
+ * Handler function for "Reattach" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->current_ssid != NULL) {
+		wpa_s->normal_scans = 0;
+		wpa_s->disconnected = 0;
+		wpa_s->reassociate = 1;
+		wpa_s->reattach = 1;
+		wpa_supplicant_req_scan(wpa_s, 0, 0);
+
+		return NULL;
+	}
+
+	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
+				      "This interface is not connected");
+}
+
+
+/**
  * wpas_dbus_handler_remove_network - Remove a configured network
  * @message: Pointer to incoming dbus message
  * @wpa_s: wpa_supplicant structure for a network interface
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index c066944..461970d 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -101,6 +101,9 @@ DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
 DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
 					    struct wpa_supplicant *wpa_s);
 
+DBusMessage * wpas_dbus_handler_reattach(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s);
+
 DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
 					       struct wpa_supplicant *wpa_s);
 
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index f7eb537..093ea9a 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -665,6 +665,36 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 		 * wildcard SSID.
 		 */
 		ssid = NULL;
+	} else if (wpa_s->reattach && wpa_s->current_ssid != NULL) {
+		/*
+		 * Perform single-channel single-SSID scan for reassociate
+		 * operation.
+		 */
+		/* Setup SSID */
+		ssid = wpa_s->current_ssid;
+		wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
+				  ssid->ssid, ssid->ssid_len);
+		params.ssids[0].ssid = ssid->ssid;
+		params.ssids[0].ssid_len = ssid->ssid_len;
+		params.num_ssids = 1;
+
+		/*
+		 * Allocate memory for frequency array, allocate one extra
+		 * slot for the zero-terminator.
+		 */
+		params.freqs = (int *)os_malloc(sizeof(int)*2);
+		if (params.freqs == NULL) {
+			wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed");
+			return;
+		}
+		params.freqs[0] = wpa_s->assoc_freq;
+		params.freqs[1] = 0;
+
+		/*
+		 * Reset the reattach flag so that it can fall back to
+		 * full scan if this scan failed.
+		 */
+		wpa_s->reattach = 0;
 	} else {
 		struct wpa_ssid *start = ssid, *tssid;
 		int freqs_set = 0;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 63ea1df..6ffd400 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -676,6 +676,13 @@ static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
 }
 
 
+static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc,
+				char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "REATTACH");
+}
+
+
 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
 				       char *argv[])
 {
@@ -2510,6 +2517,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
 	{ "reassociate", wpa_cli_cmd_reassociate, NULL,
 	  cli_cmd_flag_none,
 	  "= force reassociation" },
+	{ "reattach", wpa_cli_cmd_reattach,
+	  cli_cmd_flag_none,
+	  "= force reattach" },
 	{ "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
 	  cli_cmd_flag_none,
 	  "<BSSID> = force preauthentication" },
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 376a250..53b65cc 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -415,6 +415,7 @@ struct wpa_supplicant {
 	struct wpa_bss *current_bss;
 	int ap_ies_from_associnfo;
 	unsigned int assoc_freq;
+	int reattach;			/* reattach requested */
 
 	/* Selected configuration (based on Beacon/ProbeResp WPA IE) */
 	int pairwise_cipher;
-- 
1.9.0.279.gdc9e3eb




More information about the Hostap mailing list