[PATCH 4/4] ACS: handle ACS scan start request failure with error code -EBUSY

Aditya Kumar Singh quic_adisi at quicinc.com
Mon Apr 22 04:19:06 PDT 2024


From: Harshitha Prem <quic_hprem at quicinc.com>

Currently, if ACS scan request fails, states are cleared and returned.
However, in case of multi link opertion, there is a possibilty of getting
return value of -EBUSY. In this case, ACS can retry the scan request
after some time same like HT-40 scan.

Hence, add changes to retry the scan after 5 seconds if -EBUSY is
returned. Max 15 re-attempts would be made post which no further attempts
would be made.

Signed-off-by: Harshitha Prem <quic_hprem at quicinc.com>
Co-developed-by: Aditya Kumar Singh <quic_adisi at quicinc.com>
Signed-off-by: Aditya Kumar Singh <quic_adisi at quicinc.com>
---
 src/ap/acs.c     | 62 +++++++++++++++++++++++++++++++++++++++---------
 src/ap/acs.h     |  3 +++
 src/ap/hostapd.h |  1 +
 3 files changed, 55 insertions(+), 11 deletions(-)

diff --git a/src/ap/acs.c b/src/ap/acs.c
index 28b0ba71cc7b..24804e8ec8b2 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -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;
 		}
@@ -1378,11 +1383,10 @@ static int * acs_request_scan_add_freqs(struct hostapd_iface *iface,
 	return freq;
 }
 
-
 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 +1419,60 @@ static int acs_request_scan(struct hostapd_iface *iface)
 		return -1;
 	}
 
-	iface->scan_cb = acs_scan_complete;
-
-	wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
-		   iface->acs_num_completed_scans + 1,
-		   iface->conf->acs_num_scans);
+	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);
+
+	ret = hostapd_driver_scan(iface->bss[0], &params);
+	os_free(params.freqs);
 
-	if (hostapd_driver_scan(iface->bss[0], &params) < 0) {
+	if (ret == -EBUSY) {
+		iface->acs_num_retries++;
+		wpa_printf(MSG_ERROR, "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;
+	} else 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;
+	int ret;
+
+	if (iface->acs_num_retries >= ACS_SCAN_RETRY_MAX_COUNT) {
+		wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan (all re-attempts failed)");
+		goto acs_fail;
+	}
+
+	ret = acs_request_scan(iface);
+	if (!ret)
+		return;
+
+	wpa_printf(MSG_ERROR, "ACS: Failed to request re-try of initial scan");
+
+acs_fail:
+	acs_fail(iface);
+}
+
+
 enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
 {
 	int err;
diff --git a/src/ap/acs.h b/src/ap/acs.h
index ec84f0ee97f3..8be3de5b5f78 100644
--- a/src/ap/acs.h
+++ b/src/ap/acs.h
@@ -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)
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 1d1943ac52ec..7454cdab179d 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -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);
-- 
2.34.1




More information about the Hostap mailing list