From ad2f0966098a8c01ad08959606111a0360fb998d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 2 Jan 2020 11:51:04 +0200 Subject: [PATCH] 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 --- wpa_supplicant/events.c | 21 +++++++++++++++++++-- wpa_supplicant/wpa_supplicant.c | 12 ++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 4 ++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 603d4dabb..9b3755113 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2253,7 +2253,8 @@ int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s) return -1; 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"); return -1; } @@ -4321,6 +4322,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, { struct wpa_supplicant *wpa_s = ctx; int resched; + struct os_reltime age, clear_at; #ifndef CONFIG_NO_STDOUT_DEBUG int level = MSG_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: wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled"); 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_set_default_scan_ies(wpa_s); 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_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); wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index ce4ce0bfb..08e70e57a 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -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) { int i; @@ -551,6 +562,7 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) #endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */ eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); + eloop_cancel_timeout(wpas_clear_disabled_interface, wpa_s, NULL); wpas_wps_deinit(wpa_s); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 56df23732..422f2cb24 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -47,6 +47,9 @@ struct ctrl_iface_global_priv; struct wpas_dbus_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() */ @@ -1399,6 +1402,7 @@ int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s, struct scan_info *info); void wpas_clear_beacon_rep_data(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 */