Add support for multi-SSID scan requests
If the driver reports support for more than one SSID per scan request, optimize scan_ssid=1 operations in ap_scan=1 mode. This speeds up scanning whenever scan_ssid=1 is used since the broadcast SSID can be included in every scan request and if driver supports more than two SSIDs in the scan request, the benefits are even larger when multiple networks have been configured with ap_scan=1. This is also cleaning up wpa_supplicant_scan() function by moving code around so that the SSID list is not processed unnecessarily if the operation mode does not need this.
This commit is contained in:
parent
f55b218a5c
commit
e76baaac0c
1 changed files with 121 additions and 74 deletions
|
@ -65,77 +65,29 @@ static int wpas_wps_in_use(struct wpa_config *conf,
|
|||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
||||
|
||||
static int wpa_supplicant_enabled_networks(struct wpa_config *conf)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||
struct wpa_ssid *ssid;
|
||||
int enabled, scan_req = 0, ret;
|
||||
struct wpabuf *wps_ie = NULL;
|
||||
const u8 *extra_ie = NULL;
|
||||
size_t extra_ie_len = 0;
|
||||
int wps = 0;
|
||||
#ifdef CONFIG_WPS
|
||||
enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (wpa_s->disconnected && !wpa_s->scan_req)
|
||||
return;
|
||||
|
||||
enabled = 0;
|
||||
ssid = wpa_s->conf->ssid;
|
||||
struct wpa_ssid *ssid = conf->ssid;
|
||||
while (ssid) {
|
||||
if (!ssid->disabled) {
|
||||
enabled++;
|
||||
break;
|
||||
}
|
||||
if (!ssid->disabled)
|
||||
return 1;
|
||||
ssid = ssid->next;
|
||||
}
|
||||
if (!enabled && !wpa_s->scan_req) {
|
||||
wpa_printf(MSG_DEBUG, "No enabled networks - do not scan");
|
||||
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
|
||||
return;
|
||||
}
|
||||
scan_req = wpa_s->scan_req;
|
||||
wpa_s->scan_req = 0;
|
||||
|
||||
if (wpa_s->conf->ap_scan != 0 &&
|
||||
wpa_s->driver && IS_WIRED(wpa_s->driver)) {
|
||||
wpa_printf(MSG_DEBUG, "Using wired authentication - "
|
||||
"overriding ap_scan configuration");
|
||||
wpa_s->conf->ap_scan = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wpa_s->conf->ap_scan == 0) {
|
||||
wpa_supplicant_gen_assoc_event(wpa_s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wpa_s->wpa_state == WPA_DISCONNECTED ||
|
||||
wpa_s->wpa_state == WPA_INACTIVE)
|
||||
wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
|
||||
|
||||
ssid = wpa_s->conf->ssid;
|
||||
if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) {
|
||||
static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
while (ssid) {
|
||||
if (ssid == wpa_s->prev_scan_ssid) {
|
||||
ssid = ssid->next;
|
||||
break;
|
||||
}
|
||||
ssid = ssid->next;
|
||||
}
|
||||
}
|
||||
while (ssid) {
|
||||
if (!ssid->disabled &&
|
||||
(ssid->scan_ssid || wpa_s->conf->ap_scan == 2))
|
||||
if (!ssid->disabled)
|
||||
break;
|
||||
ssid = ssid->next;
|
||||
}
|
||||
|
||||
if (scan_req != 2 && wpa_s->conf->ap_scan == 2) {
|
||||
/*
|
||||
* ap_scan=2 mode - try to associate with each SSID instead of
|
||||
* scanning for each scan_ssid=1 network.
|
||||
*/
|
||||
/* ap_scan=2 mode - try to associate with each SSID. */
|
||||
if (ssid == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached "
|
||||
"end of scan list - go back to beginning");
|
||||
|
@ -151,17 +103,51 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
|
||||
}
|
||||
wpa_supplicant_associate(wpa_s, NULL, ssid);
|
||||
}
|
||||
|
||||
|
||||
static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
||||
{
|
||||
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||
struct wpa_ssid *ssid;
|
||||
int scan_req = 0, ret;
|
||||
struct wpabuf *wps_ie = NULL;
|
||||
int wps = 0;
|
||||
#ifdef CONFIG_WPS
|
||||
enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
|
||||
#endif /* CONFIG_WPS */
|
||||
struct wpa_driver_scan_params params;
|
||||
size_t max_ssids;
|
||||
|
||||
if (wpa_s->disconnected && !wpa_s->scan_req)
|
||||
return;
|
||||
|
||||
if (!wpa_supplicant_enabled_networks(wpa_s->conf) &&
|
||||
!wpa_s->scan_req) {
|
||||
wpa_printf(MSG_DEBUG, "No enabled networks - do not scan");
|
||||
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
|
||||
return;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)",
|
||||
ssid ? "specific": "broadcast");
|
||||
if (ssid) {
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
|
||||
ssid->ssid, ssid->ssid_len);
|
||||
wpa_s->prev_scan_ssid = ssid;
|
||||
} else
|
||||
wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
|
||||
if (wpa_s->conf->ap_scan != 0 &&
|
||||
wpa_s->driver && IS_WIRED(wpa_s->driver)) {
|
||||
wpa_printf(MSG_DEBUG, "Using wired authentication - "
|
||||
"overriding ap_scan configuration");
|
||||
wpa_s->conf->ap_scan = 0;
|
||||
}
|
||||
|
||||
if (wpa_s->conf->ap_scan == 0) {
|
||||
wpa_supplicant_gen_assoc_event(wpa_s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (wpa_s->use_client_mlme || wpa_s->conf->ap_scan == 2)
|
||||
max_ssids = 1;
|
||||
else {
|
||||
max_ssids = wpa_s->max_scan_ssids;
|
||||
if (max_ssids > WPAS_MAX_SCAN_SSIDS)
|
||||
max_ssids = WPAS_MAX_SCAN_SSIDS;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
wps = wpas_wps_in_use(wpa_s->conf, &req_type);
|
||||
|
@ -170,7 +156,6 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 &&
|
||||
!wpa_s->use_client_mlme && wps != 2) {
|
||||
wpa_s->scan_res_tried++;
|
||||
wpa_s->scan_req = scan_req;
|
||||
wpa_printf(MSG_DEBUG, "Trying to get current scan results "
|
||||
"first without requesting a new scan to speed up "
|
||||
"initial association");
|
||||
|
@ -178,32 +163,94 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
|||
return;
|
||||
}
|
||||
|
||||
scan_req = wpa_s->scan_req;
|
||||
wpa_s->scan_req = 0;
|
||||
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
|
||||
if (wpa_s->wpa_state == WPA_DISCONNECTED ||
|
||||
wpa_s->wpa_state == WPA_INACTIVE)
|
||||
wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
|
||||
|
||||
/* Find the starting point from which to continue scanning */
|
||||
ssid = wpa_s->conf->ssid;
|
||||
if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) {
|
||||
while (ssid) {
|
||||
if (ssid == wpa_s->prev_scan_ssid) {
|
||||
ssid = ssid->next;
|
||||
break;
|
||||
}
|
||||
ssid = ssid->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (scan_req != 2 && wpa_s->conf->ap_scan == 2) {
|
||||
wpa_supplicant_assoc_try(wpa_s, ssid);
|
||||
return;
|
||||
} else if (wpa_s->conf->ap_scan == 2) {
|
||||
/*
|
||||
* User-initiated scan request in ap_scan == 2; use broadcast
|
||||
* scan.
|
||||
*/
|
||||
ssid = NULL;
|
||||
} else {
|
||||
struct wpa_ssid *start = ssid;
|
||||
if (ssid == NULL && max_ssids > 1)
|
||||
ssid = wpa_s->conf->ssid;
|
||||
while (ssid) {
|
||||
if (!ssid->disabled && ssid->scan_ssid) {
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
|
||||
ssid->ssid, ssid->ssid_len);
|
||||
params.ssids[params.num_ssids].ssid =
|
||||
ssid->ssid;
|
||||
params.ssids[params.num_ssids].ssid_len =
|
||||
ssid->ssid_len;
|
||||
params.num_ssids++;
|
||||
if (params.num_ssids + 1 >= max_ssids)
|
||||
break;
|
||||
}
|
||||
ssid = ssid->next;
|
||||
if (ssid == start)
|
||||
break;
|
||||
if (ssid == NULL && max_ssids > 1 &&
|
||||
start != wpa_s->conf->ssid)
|
||||
ssid = wpa_s->conf->ssid;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssid) {
|
||||
wpa_s->prev_scan_ssid = ssid;
|
||||
if (max_ssids > 1) {
|
||||
wpa_printf(MSG_DEBUG, "Include broadcast SSID in the "
|
||||
"scan request");
|
||||
params.num_ssids++; /* Broadcast scan */
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "Starting AP scan for specific SSID(s)");
|
||||
} else {
|
||||
wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
|
||||
params.num_ssids++;
|
||||
wpa_printf(MSG_DEBUG, "Starting AP scan for broadcast SSID");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
if (wps) {
|
||||
wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev,
|
||||
wpa_s->wps->uuid, req_type);
|
||||
if (wps_ie) {
|
||||
extra_ie = wpabuf_head(wps_ie);
|
||||
extra_ie_len = wpabuf_len(wps_ie);
|
||||
params.extra_ies = wpabuf_head(wps_ie);
|
||||
params.extra_ies_len = wpabuf_len(wps_ie);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
if (wpa_s->use_client_mlme) {
|
||||
ieee80211_sta_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len);
|
||||
ret = ieee80211_sta_req_scan(wpa_s, ssid ? ssid->ssid : NULL,
|
||||
ssid ? ssid->ssid_len : 0);
|
||||
ieee80211_sta_set_probe_req_ie(wpa_s, params.extra_ies,
|
||||
params.extra_ies_len);
|
||||
ret = ieee80211_sta_req_scan(wpa_s, params.ssids[0].ssid,
|
||||
params.ssids[0].ssid_len);
|
||||
} else {
|
||||
struct wpa_driver_scan_params params;
|
||||
os_memset(¶ms, 0, sizeof(params));
|
||||
wpa_drv_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len);
|
||||
if (ssid) {
|
||||
params.ssids[0].ssid = ssid->ssid;
|
||||
params.ssids[0].ssid_len = ssid->ssid_len;
|
||||
}
|
||||
params.num_ssids = 1;
|
||||
params.extra_ies = extra_ie;
|
||||
params.extra_ies_len = extra_ie_len;
|
||||
wpa_drv_set_probe_req_ie(wpa_s, params.extra_ies,
|
||||
params.extra_ies_len);
|
||||
ret = wpa_drv_scan(wpa_s, ¶ms);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue