]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Try the next AP from scan results if connection attempt fails
authorAvraham Stern <avraham.stern@intel.com>
Tue, 5 Aug 2025 15:13:15 +0000 (17:13 +0200)
committerJouni Malinen <j@w1.fi>
Mon, 6 Oct 2025 17:38:38 +0000 (20:38 +0300)
If connection to a selected AP fails and there are other candidates in
the BSS table and scan results are not too old, try to fast associate to
the next available candidate without triggering another full scan.

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Reviewed-by: Peer, Ilan <ilan.peer@intel.com>
Reviewed-by: Otcheretianski, Andrei <andrei.otcheretianski@intel.com>
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
wpa_supplicant/events.c
wpa_supplicant/interworking.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h
wpa_supplicant/wps_supplicant.c

index 42a52899d881b32301818512ce679c75f624d74e..9d5024c43e5dc3e30e120e0a0566713005c93a32 100644 (file)
@@ -1770,7 +1770,8 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
 
 
 struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
-                                            struct wpa_ssid **selected_ssid)
+                                            struct wpa_ssid **selected_ssid,
+                                            bool clear_ignorelist)
 {
        struct wpa_bss *selected = NULL;
        size_t prio;
@@ -1809,7 +1810,7 @@ struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
 
                if (!selected &&
                    (wpa_s->bssid_ignore || wnm_active_bss_trans_mgmt(wpa_s)) &&
-                   !wpa_s->countermeasures) {
+                   !wpa_s->countermeasures && clear_ignorelist) {
                        wpa_dbg(wpa_s, MSG_DEBUG,
                                "No APs found - clear BSSID ignore list and try again");
                        wnm_btm_reset(wpa_s);
@@ -2725,7 +2726,7 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
        os_free(wpa_s->owe_trans_scan_freq);
        wpa_s->owe_trans_scan_freq = NULL;
 #endif /* CONFIG_OWE */
-       selected = wpa_supplicant_pick_network(wpa_s, &ssid);
+       selected = wpa_supplicant_pick_network(wpa_s, &ssid, new_scan);
 
 #ifdef CONFIG_MESH
        if (wpa_s->ifmsh) {
index faefb6699592cf1e6a081745f427d11a045eccde..f77880409ad79858e7b0c1de6df3368d4945be5c 100644 (file)
@@ -899,7 +899,7 @@ static int already_connected(struct wpa_supplicant *wpa_s,
                return 0;
 
        sel_ssid = NULL;
-       selected = wpa_supplicant_pick_network(wpa_s, &sel_ssid);
+       selected = wpa_supplicant_pick_network(wpa_s, &sel_ssid, true);
        if (selected && sel_ssid && sel_ssid->priority > ssid->priority)
                return 0; /* higher priority network in scan results */
 
index d45002fd912f1214eb3cb89143ff3eeed93ec98c..bbd3e1a053cc26c462b9235d77262c2bbd2966ac 100644 (file)
@@ -8783,46 +8783,11 @@ void add_freq(int *freqs, int *num_freqs, int freq)
 }
 
 
-static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
-{
-       struct wpa_bss *bss, *cbss;
-       const int max_freqs = 10;
-       int *freqs;
-       int num_freqs = 0;
-
-       freqs = os_calloc(max_freqs + 1, sizeof(int));
-       if (freqs == NULL)
-               return NULL;
-
-       cbss = wpa_s->current_bss;
-
-       dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
-               if (bss == cbss)
-                       continue;
-               if (bss->ssid_len == cbss->ssid_len &&
-                   os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
-                   !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
-                       add_freq(freqs, &num_freqs, bss->freq);
-                       if (num_freqs == max_freqs)
-                               break;
-               }
-       }
-
-       if (num_freqs == 0) {
-               os_free(freqs);
-               freqs = NULL;
-       }
-
-       return freqs;
-}
-
-
 void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
                            const u8 **link_bssids)
 {
        int timeout;
        int count;
-       int *freqs = NULL;
 
        wpas_connect_work_done(wpa_s);
 
@@ -8859,27 +8824,15 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
         * attempt if there could be other APs that could accept association.
         */
        count = wpa_bssid_ignore_add(wpa_s, bssid);
-       if (count == 1 && wpa_s->current_bss) {
-               /*
-                * This BSS was not in the ignore list before. If there is
-                * another BSS available for the same ESS, we should try that
-                * next. Otherwise, we may as well try this one once more
-                * before allowing other, likely worse, ESSes to be considered.
-                */
-               freqs = get_bss_freqs_in_ess(wpa_s);
-               if (freqs) {
-                       wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
-                               "has been seen; try it next");
-                       wpa_bssid_ignore_add(wpa_s, bssid);
-                       /*
-                        * On the next scan, go through only the known channels
-                        * used in this ESS based on previous scans to speed up
-                        * common load balancing use case.
-                        */
-                       os_free(wpa_s->next_scan_freqs);
-                       wpa_s->next_scan_freqs = freqs;
-               }
-       }
+
+       /*
+        * This BSS was not in the ignore list before. If there is
+        * another BSS available for the same ESS, we should try that
+        * next. Otherwise, we may as well try this one once more
+        * before allowing other, likely worse, ESSes to be considered.
+        */
+       if (count == 1 && wpa_supplicant_fast_associate(wpa_s) == 1)
+               return;
 
        wpa_s->consecutive_conn_failures++;
 
@@ -8915,11 +8868,6 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid,
                "Consecutive connection failures: %d --> request scan in %d ms",
                wpa_s->consecutive_conn_failures, timeout);
 
-       /*
-        * TODO: if more than one possible AP is available in scan results,
-        * could try the other ones before requesting a new scan.
-        */
-
        /* speed up the connection attempt with normal scan */
        wpa_s->normal_scans = 0;
        wpa_supplicant_req_scan(wpa_s, timeout / 1000,
index e7675a4abe0a354789e1a8902b33aa570f347b6c..cf27add7245bac20cf576f6066db342ffe2870c0 100644 (file)
@@ -1875,7 +1875,8 @@ void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s);
 int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s);
 int wpa_wps_supplicant_fast_associate(struct wpa_supplicant *wpa_s);
 struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
-                                            struct wpa_ssid **selected_ssid);
+                                            struct wpa_ssid **selected_ssid,
+                                            bool clear_ignorelist);
 int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
 void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s,
                                        struct channel_list_changed *info);
index 405c5d6051ab9cad7b50b15cd6f06c4e924cb18e..25a5598ce77749db7f2f7b3ee474f33daa3a7ae7 100644 (file)
@@ -148,7 +148,7 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
 
                wpa_printf(MSG_DEBUG, "WPS: Checking whether fast association "
                           "without a new scan can be used");
-               bss = wpa_supplicant_pick_network(wpa_s, &ssid);
+               bss = wpa_supplicant_pick_network(wpa_s, &ssid, true);
                if (bss) {
                        struct wpabuf *wps;
                        struct wps_parse_attr attr;