]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
ACS: Handle scan start request failure with error code -EBUSY
authorHarshitha Prem <quic_hprem@quicinc.com>
Mon, 22 Apr 2024 11:19:06 +0000 (16:49 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 11 Jun 2024 21:25:17 +0000 (00:25 +0300)
Currently, if ACS scan request fails, states are cleared and returned.
However, in case of MLO, there is a possibilty of getting return value
of -EBUSY. In this case, ACS can retry the scan request after some time
similary to the HT40 scan.

Hence, retry the scan after 5 seconds if -EBUSY is returned. Maximum of
15 re-attempts are made before giving up.

Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
Co-developed-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
src/ap/acs.c
src/ap/acs.h
src/ap/hostapd.h

index 28b0ba71cc7b50360d218c7e6a06db2861c8daa0..6003f0e3878471f3c34fea04283c3f5f12260d41 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "utils/common.h"
 #include "utils/list.h"
+#include "utils/eloop.h"
 #include "common/ieee802_11_defs.h"
 #include "common/hw_features_common.h"
 #include "common/wpa_ctrl.h"
@@ -307,6 +308,7 @@ static const struct bw_item *bw_desc[] = {
 
 static int acs_request_scan(struct hostapd_iface *iface);
 static int acs_survey_is_sufficient(struct freq_survey *survey);
+static void acs_scan_retry(void *eloop_data, void *user_data);
 
 
 static void acs_clean_chan_surveys(struct hostapd_channel_data *chan)
@@ -352,6 +354,8 @@ void acs_cleanup(struct hostapd_iface *iface)
 
        iface->chans_surveyed = 0;
        iface->acs_num_completed_scans = 0;
+       iface->acs_num_retries = 0;
+       eloop_cancel_timeout(acs_scan_retry, iface, NULL);
 }
 
 
@@ -1317,6 +1321,7 @@ static void acs_scan_complete(struct hostapd_iface *iface)
        int err;
 
        iface->scan_cb = NULL;
+       iface->acs_num_retries = 0;
 
        wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)",
                   iface->conf->acs_num_scans);
@@ -1329,7 +1334,7 @@ static void acs_scan_complete(struct hostapd_iface *iface)
 
        if (++iface->acs_num_completed_scans < iface->conf->acs_num_scans) {
                err = acs_request_scan(iface);
-               if (err) {
+               if (err && err != -EBUSY) {
                        wpa_printf(MSG_ERROR, "ACS: Failed to request scan");
                        goto fail;
                }
@@ -1382,7 +1387,7 @@ static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
 static int acs_request_scan(struct hostapd_iface *iface)
 {
        struct wpa_driver_scan_params params;
-       int i, *freq;
+       int i, *freq, ret;
        int num_channels;
        struct hostapd_hw_modes *mode;
 
@@ -1415,24 +1420,62 @@ static int acs_request_scan(struct hostapd_iface *iface)
                return -1;
        }
 
-       iface->scan_cb = acs_scan_complete;
+       if (!iface->acs_num_retries)
+               wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
+                          iface->acs_num_completed_scans + 1,
+                          iface->conf->acs_num_scans);
+       else
+               wpa_printf(MSG_DEBUG,
+                          "ACS: Re-try scanning attempt %d (%d / %d)",
+                          iface->acs_num_retries,
+                          iface->acs_num_completed_scans + 1,
+                          iface->conf->acs_num_scans);
 
-       wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
-                  iface->acs_num_completed_scans + 1,
-                  iface->conf->acs_num_scans);
+       ret = hostapd_driver_scan(iface->bss[0], &params);
+       os_free(params.freqs);
+
+       if (ret == -EBUSY) {
+               iface->acs_num_retries++;
+               if (iface->acs_num_retries >= ACS_SCAN_RETRY_MAX_COUNT) {
+                       wpa_printf(MSG_ERROR,
+                                  "ACS: Failed to request initial scan (all re-attempts failed)");
+                       acs_fail(iface);
+                       return -1;
+               }
+
+               wpa_printf(MSG_INFO,
+                          "Failed to request acs scan ret=%d (%s) - try to scan after %d seconds",
+                          ret, strerror(-ret), ACS_SCAN_RETRY_INTERVAL);
+               eloop_cancel_timeout(acs_scan_retry, iface, NULL);
+               eloop_register_timeout(ACS_SCAN_RETRY_INTERVAL, 0,
+                                      acs_scan_retry, iface, NULL);
+               return 0;
+       }
 
-       if (hostapd_driver_scan(iface->bss[0], &params) < 0) {
+       if (ret < 0) {
                wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan");
                acs_cleanup(iface);
-               os_free(params.freqs);
                return -1;
        }
 
-       os_free(params.freqs);
+       iface->scan_cb = acs_scan_complete;
+
        return 0;
 }
 
 
+static void acs_scan_retry(void *eloop_data, void *user_data)
+{
+       struct hostapd_iface *iface = eloop_data;
+
+       if (acs_request_scan(iface)) {
+               wpa_printf(MSG_ERROR,
+                          "ACS: Failed to request re-try of initial scan");
+               acs_fail(iface);
+       }
+}
+
+
 enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
 {
        int err;
index ec84f0ee97f34d501069f171e3494833be6af884..8be3de5b5f7862f877f7c39adb9641738c9dcbf9 100644 (file)
@@ -15,6 +15,9 @@
 enum hostapd_chan_status acs_init(struct hostapd_iface *iface);
 void acs_cleanup(struct hostapd_iface *iface);
 
+#define ACS_SCAN_RETRY_MAX_COUNT       15
+#define ACS_SCAN_RETRY_INTERVAL                5
+
 #else /* CONFIG_ACS */
 
 static inline enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
index 1d1943ac52ecbc82f40b9e60cf66b79f43318ddb..7454cdab179d01d349045a966a72ae42dee7106b 100644 (file)
@@ -682,6 +682,7 @@ struct hostapd_iface {
 
 #ifdef CONFIG_ACS
        unsigned int acs_num_completed_scans;
+       unsigned int acs_num_retries;
 #endif /* CONFIG_ACS */
 
        void (*scan_cb)(struct hostapd_iface *iface);