Delay AP selection if all networks are temporarily disabled

If all networks are temporarily disabled, delay AP selection until at
least one network is enabled. Running AP selection when all networks are
disabled is useless as wpa_supplicant will not try to connect. In
addition, it will result in needless scan iterations that may delay the
connection when it is needed.

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
This commit is contained in:
Avraham Stern 2015-03-16 01:20:02 -04:00 committed by Jouni Malinen
parent 701f3961e3
commit 9bd566a33a
4 changed files with 72 additions and 0 deletions

View file

@ -6702,6 +6702,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->bssid),
MAC2STR(wpa_s->pending_bssid)); MAC2STR(wpa_s->pending_bssid));
} }
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
} }
@ -8262,6 +8264,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
wpa_supplicant_cancel_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s);
wpa_supplicant_deauthenticate(wpa_s, wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING); WLAN_REASON_DEAUTH_LEAVING);
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
} else if (os_strcmp(buf, "SCAN") == 0) { } else if (os_strcmp(buf, "SCAN") == 0) {
wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len); wpas_ctrl_scan(wpa_s, NULL, reply, reply_size, &reply_len);
} else if (os_strncmp(buf, "SCAN ", 5) == 0) { } else if (os_strncmp(buf, "SCAN ", 5) == 0) {

View file

@ -71,6 +71,59 @@ static int wpas_temp_disabled(struct wpa_supplicant *wpa_s,
} }
/**
* wpas_reenabled_network_time - Time until first network is re-enabled
* @wpa_s: Pointer to wpa_supplicant data
* Returns: If all enabled networks are temporarily disabled, returns the time
* (in sec) until the first network is re-enabled. Otherwise returns 0.
*
* This function is used in case all enabled networks are temporarily disabled,
* in which case it returns the time (in sec) that the first network will be
* re-enabled. The function assumes that at least one network is enabled.
*/
static int wpas_reenabled_network_time(struct wpa_supplicant *wpa_s)
{
struct wpa_ssid *ssid;
int disabled_for, res = 0;
#ifdef CONFIG_INTERWORKING
if (wpa_s->conf->auto_interworking && wpa_s->conf->interworking &&
wpa_s->conf->cred)
return 0;
#endif /* CONFIG_INTERWORKING */
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
if (ssid->disabled)
continue;
disabled_for = wpas_temp_disabled(wpa_s, ssid);
if (!disabled_for)
return 0;
if (!res || disabled_for < res)
res = disabled_for;
}
return res;
}
void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
if (wpa_s->disconnected || wpa_s->wpa_state != WPA_SCANNING)
return;
wpa_dbg(wpa_s, MSG_DEBUG,
"Try to associate due to network getting re-enabled");
if (wpa_supplicant_fast_associate(wpa_s) != 1) {
wpa_supplicant_cancel_sched_scan(wpa_s);
wpa_supplicant_req_scan(wpa_s, 0, 0);
}
}
static struct wpa_bss * wpa_supplicant_get_new_bss( static struct wpa_bss * wpa_supplicant_get_new_bss(
struct wpa_supplicant *wpa_s, const u8 *bssid) struct wpa_supplicant *wpa_s, const u8 *bssid)
{ {
@ -1421,6 +1474,17 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
{ {
struct wpa_bss *selected; struct wpa_bss *selected;
struct wpa_ssid *ssid = NULL; struct wpa_ssid *ssid = NULL;
int time_to_reenable = wpas_reenabled_network_time(wpa_s);
if (time_to_reenable > 0) {
wpa_dbg(wpa_s, MSG_DEBUG,
"Postpone network selection by %d seconds since all networks are disabled",
time_to_reenable);
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
eloop_register_timeout(time_to_reenable, 0,
wpas_network_reenabled, wpa_s, NULL);
return 0;
}
if (wpa_s->p2p_mgmt) if (wpa_s->p2p_mgmt)
return 0; /* no normal connection on p2p_mgmt interface */ return 0; /* no normal connection on p2p_mgmt interface */
@ -1946,6 +2010,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
} }
#endif /* CONFIG_AP */ #endif /* CONFIG_AP */
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
ft_completed = wpa_ft_is_completed(wpa_s->wpa); ft_completed = wpa_ft_is_completed(wpa_s->wpa);
if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0) if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0)
return; return;

View file

@ -456,6 +456,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
wpa_s, NULL); wpa_s, NULL);
#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */ #endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
wpas_wps_deinit(wpa_s); wpas_wps_deinit(wpa_s);
wpabuf_free(wpa_s->pending_eapol_rx); wpabuf_free(wpa_s->pending_eapol_rx);

View file

@ -1140,4 +1140,5 @@ int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
int get_shared_radio_freqs(struct wpa_supplicant *wpa_s, int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
int *freq_array, unsigned int len); int *freq_array, unsigned int len);
void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx);
#endif /* WPA_SUPPLICANT_I_H */ #endif /* WPA_SUPPLICANT_I_H */