]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Maintain BSS entries for 5 seconds after interface is disabled
authorJouni Malinen <j@w1.fi>
Thu, 2 Jan 2020 09:51:04 +0000 (11:51 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 2 Jan 2020 10:58:58 +0000 (12:58 +0200)
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>
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 603d4dabbd655911d08208d06ae1cf723b31448c..9b3755113de44468fdc761ca2af5cf4b42b7a305 100644 (file)
@@ -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);
index ce4ce0bfb22f61444e51ba6ee92774e7e64213b5..08e70e57ac5c658567273100819e177a5b615dc5 100644 (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)
 {
        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);
 
index 56df23732ed2d651cb03317cec56ac54dcf8e972..422f2cb2470f796e543daf3400430f68b46e1529 100644 (file)
@@ -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 */