ACS: Handle scan start request failure with error code -EBUSY
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>
This commit is contained in:
parent
3cf7bf68f4
commit
3e52a90d34
3 changed files with 56 additions and 9 deletions
59
src/ap/acs.c
59
src/ap/acs.c
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "utils/common.h"
|
#include "utils/common.h"
|
||||||
#include "utils/list.h"
|
#include "utils/list.h"
|
||||||
|
#include "utils/eloop.h"
|
||||||
#include "common/ieee802_11_defs.h"
|
#include "common/ieee802_11_defs.h"
|
||||||
#include "common/hw_features_common.h"
|
#include "common/hw_features_common.h"
|
||||||
#include "common/wpa_ctrl.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_request_scan(struct hostapd_iface *iface);
|
||||||
static int acs_survey_is_sufficient(struct freq_survey *survey);
|
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)
|
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->chans_surveyed = 0;
|
||||||
iface->acs_num_completed_scans = 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;
|
int err;
|
||||||
|
|
||||||
iface->scan_cb = NULL;
|
iface->scan_cb = NULL;
|
||||||
|
iface->acs_num_retries = 0;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)",
|
wpa_printf(MSG_DEBUG, "ACS: Using survey based algorithm (acs_num_scans=%d)",
|
||||||
iface->conf->acs_num_scans);
|
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) {
|
if (++iface->acs_num_completed_scans < iface->conf->acs_num_scans) {
|
||||||
err = acs_request_scan(iface);
|
err = acs_request_scan(iface);
|
||||||
if (err) {
|
if (err && err != -EBUSY) {
|
||||||
wpa_printf(MSG_ERROR, "ACS: Failed to request scan");
|
wpa_printf(MSG_ERROR, "ACS: Failed to request scan");
|
||||||
goto fail;
|
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)
|
static int acs_request_scan(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
struct wpa_driver_scan_params params;
|
struct wpa_driver_scan_params params;
|
||||||
int i, *freq;
|
int i, *freq, ret;
|
||||||
int num_channels;
|
int num_channels;
|
||||||
struct hostapd_hw_modes *mode;
|
struct hostapd_hw_modes *mode;
|
||||||
|
|
||||||
|
@ -1415,21 +1420,59 @@ static int acs_request_scan(struct hostapd_iface *iface)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
iface->scan_cb = acs_scan_complete;
|
if (!iface->acs_num_retries)
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
|
wpa_printf(MSG_DEBUG, "ACS: Scanning %d / %d",
|
||||||
iface->acs_num_completed_scans + 1,
|
iface->acs_num_completed_scans + 1,
|
||||||
iface->conf->acs_num_scans);
|
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);
|
||||||
|
|
||||||
if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) {
|
ret = hostapd_driver_scan(iface->bss[0], ¶ms);
|
||||||
wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan");
|
|
||||||
acs_cleanup(iface);
|
|
||||||
os_free(params.freqs);
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
os_free(params.freqs);
|
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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
wpa_printf(MSG_ERROR, "ACS: Failed to request initial scan");
|
||||||
|
acs_cleanup(iface);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
enum hostapd_chan_status acs_init(struct hostapd_iface *iface);
|
enum hostapd_chan_status acs_init(struct hostapd_iface *iface);
|
||||||
void acs_cleanup(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 */
|
#else /* CONFIG_ACS */
|
||||||
|
|
||||||
static inline enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
|
static inline enum hostapd_chan_status acs_init(struct hostapd_iface *iface)
|
||||||
|
|
|
@ -682,6 +682,7 @@ struct hostapd_iface {
|
||||||
|
|
||||||
#ifdef CONFIG_ACS
|
#ifdef CONFIG_ACS
|
||||||
unsigned int acs_num_completed_scans;
|
unsigned int acs_num_completed_scans;
|
||||||
|
unsigned int acs_num_retries;
|
||||||
#endif /* CONFIG_ACS */
|
#endif /* CONFIG_ACS */
|
||||||
|
|
||||||
void (*scan_cb)(struct hostapd_iface *iface);
|
void (*scan_cb)(struct hostapd_iface *iface);
|
||||||
|
|
Loading…
Reference in a new issue