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:
Jouni Malinen 2009-02-14 20:59:26 +02:00
parent f55b218a5c
commit e76baaac0c

View file

@ -65,77 +65,29 @@ static int wpas_wps_in_use(struct wpa_config *conf,
} }
#endif /* CONFIG_WPS */ #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 = conf->ssid;
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;
while (ssid) { while (ssid) {
if (!ssid->disabled) { if (!ssid->disabled)
enabled++; return 1;
break;
}
ssid = ssid->next; ssid = ssid->next;
} }
if (!enabled && !wpa_s->scan_req) { return 0;
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;
}
if (wpa_s->conf->ap_scan == 0) { static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
wpa_supplicant_gen_assoc_event(wpa_s); struct wpa_ssid *ssid)
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) {
while (ssid) { while (ssid) {
if (ssid == wpa_s->prev_scan_ssid) { if (!ssid->disabled)
ssid = ssid->next;
break;
}
ssid = ssid->next;
}
}
while (ssid) {
if (!ssid->disabled &&
(ssid->scan_ssid || wpa_s->conf->ap_scan == 2))
break; break;
ssid = ssid->next; ssid = ssid->next;
} }
if (scan_req != 2 && wpa_s->conf->ap_scan == 2) { /* ap_scan=2 mode - try to associate with each SSID. */
/*
* ap_scan=2 mode - try to associate with each SSID instead of
* scanning for each scan_ssid=1 network.
*/
if (ssid == NULL) { if (ssid == NULL) {
wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached " wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached "
"end of scan list - go back to beginning"); "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_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
} }
wpa_supplicant_associate(wpa_s, NULL, ssid); 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; return;
} }
wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)", if (wpa_s->conf->ap_scan != 0 &&
ssid ? "specific": "broadcast"); wpa_s->driver && IS_WIRED(wpa_s->driver)) {
if (ssid) { wpa_printf(MSG_DEBUG, "Using wired authentication - "
wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", "overriding ap_scan configuration");
ssid->ssid, ssid->ssid_len); wpa_s->conf->ap_scan = 0;
wpa_s->prev_scan_ssid = ssid; }
} else
wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; 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 #ifdef CONFIG_WPS
wps = wpas_wps_in_use(wpa_s->conf, &req_type); 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 && if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 &&
!wpa_s->use_client_mlme && wps != 2) { !wpa_s->use_client_mlme && wps != 2) {
wpa_s->scan_res_tried++; wpa_s->scan_res_tried++;
wpa_s->scan_req = scan_req;
wpa_printf(MSG_DEBUG, "Trying to get current scan results " wpa_printf(MSG_DEBUG, "Trying to get current scan results "
"first without requesting a new scan to speed up " "first without requesting a new scan to speed up "
"initial association"); "initial association");
@ -178,32 +163,94 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
return; return;
} }
scan_req = wpa_s->scan_req;
wpa_s->scan_req = 0;
os_memset(&params, 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 #ifdef CONFIG_WPS
if (wps) { if (wps) {
wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev, wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev,
wpa_s->wps->uuid, req_type); wpa_s->wps->uuid, req_type);
if (wps_ie) { if (wps_ie) {
extra_ie = wpabuf_head(wps_ie); params.extra_ies = wpabuf_head(wps_ie);
extra_ie_len = wpabuf_len(wps_ie); params.extra_ies_len = wpabuf_len(wps_ie);
} }
} }
#endif /* CONFIG_WPS */ #endif /* CONFIG_WPS */
if (wpa_s->use_client_mlme) { if (wpa_s->use_client_mlme) {
ieee80211_sta_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len); ieee80211_sta_set_probe_req_ie(wpa_s, params.extra_ies,
ret = ieee80211_sta_req_scan(wpa_s, ssid ? ssid->ssid : NULL, params.extra_ies_len);
ssid ? ssid->ssid_len : 0); ret = ieee80211_sta_req_scan(wpa_s, params.ssids[0].ssid,
params.ssids[0].ssid_len);
} else { } else {
struct wpa_driver_scan_params params; wpa_drv_set_probe_req_ie(wpa_s, params.extra_ies,
os_memset(&params, 0, sizeof(params)); params.extra_ies_len);
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;
ret = wpa_drv_scan(wpa_s, &params); ret = wpa_drv_scan(wpa_s, &params);
} }