Maintain BSS entries for 5 seconds after interface is disabled

This is targeting the case of MAC address change for an association
which may require the interface to be set down for a short moment.
Previously, this ended up flushing the BSS table that wpa_supplicant
maintained and that resulted in having to scan again if the MAC address
was changed between the previous scan and the connection attempt. This
is unnecessary extra latency, so maintain the BSS entries for 5 seconds
(i.e., the same time that the old scan results are consider valid for a
new connection attempt) after an interface goes down.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2020-01-02 11:51:04 +02:00
parent 988f14448a
commit ad2f096609
3 changed files with 35 additions and 2 deletions

View file

@ -2253,7 +2253,8 @@ int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s)
return -1; return -1;
os_get_reltime(&now); os_get_reltime(&now);
if (os_reltime_expired(&now, &wpa_s->last_scan, 5)) { if (os_reltime_expired(&now, &wpa_s->last_scan,
SCAN_RES_VALID_FOR_CONNECT)) {
wpa_printf(MSG_DEBUG, "Fast associate: Old scan results"); wpa_printf(MSG_DEBUG, "Fast associate: Old scan results");
return -1; return -1;
} }
@ -4321,6 +4322,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
{ {
struct wpa_supplicant *wpa_s = ctx; struct wpa_supplicant *wpa_s = ctx;
int resched; int resched;
struct os_reltime age, clear_at;
#ifndef CONFIG_NO_STDOUT_DEBUG #ifndef CONFIG_NO_STDOUT_DEBUG
int level = MSG_DEBUG; int level = MSG_DEBUG;
#endif /* CONFIG_NO_STDOUT_DEBUG */ #endif /* CONFIG_NO_STDOUT_DEBUG */
@ -4859,6 +4861,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
case EVENT_INTERFACE_ENABLED: case EVENT_INTERFACE_ENABLED:
wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled"); wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
eloop_cancel_timeout(wpas_clear_disabled_interface,
wpa_s, NULL);
wpa_supplicant_update_mac_addr(wpa_s); wpa_supplicant_update_mac_addr(wpa_s);
wpa_supplicant_set_default_scan_ies(wpa_s); wpa_supplicant_set_default_scan_ies(wpa_s);
if (wpa_s->p2p_mgmt) { if (wpa_s->p2p_mgmt) {
@ -4927,7 +4931,20 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_s, WLAN_REASON_DEAUTH_LEAVING, 1); wpa_s, WLAN_REASON_DEAUTH_LEAVING, 1);
} }
wpa_supplicant_mark_disassoc(wpa_s); wpa_supplicant_mark_disassoc(wpa_s);
wpa_bss_flush(wpa_s); os_reltime_age(&wpa_s->last_scan, &age);
if (age.sec >= SCAN_RES_VALID_FOR_CONNECT) {
clear_at.sec = SCAN_RES_VALID_FOR_CONNECT;
clear_at.usec = 0;
} else {
struct os_reltime tmp;
tmp.sec = SCAN_RES_VALID_FOR_CONNECT;
tmp.usec = 0;
os_reltime_sub(&tmp, &age, &clear_at);
}
eloop_register_timeout(clear_at.sec, clear_at.usec,
wpas_clear_disabled_interface,
wpa_s, NULL);
radio_remove_works(wpa_s, NULL, 0); radio_remove_works(wpa_s, NULL, 0);
wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);

View file

@ -476,6 +476,17 @@ void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
} }
void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_supplicant *wpa_s = eloop_ctx;
if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
return;
wpa_dbg(wpa_s, MSG_DEBUG, "Clear cached state on disabled interface");
wpa_bss_flush(wpa_s);
}
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
{ {
int i; int i;
@ -551,6 +562,7 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */ #endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL);
wpas_wps_deinit(wpa_s); wpas_wps_deinit(wpa_s);

View file

@ -47,6 +47,9 @@ struct ctrl_iface_global_priv;
struct wpas_dbus_priv; struct wpas_dbus_priv;
struct wpas_binder_priv; struct wpas_binder_priv;
/* How many seconds to consider old scan results valid for association. */
#define SCAN_RES_VALID_FOR_CONNECT 5
/** /**
* struct wpa_interface - Parameters for wpa_supplicant_add_iface() * struct wpa_interface - Parameters for wpa_supplicant_add_iface()
*/ */
@ -1399,6 +1402,7 @@ int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
struct scan_info *info); struct scan_info *info);
void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s); void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s);
void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s); void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s);
void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx);
/* MBO functions */ /* MBO functions */