]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
ACS: BSS-based interference computation
authorMatej Vrba <Matej.Vrba@advantech.cz>
Tue, 4 Mar 2025 14:12:06 +0000 (14:12 +0000)
committerJouni Malinen <j@w1.fi>
Tue, 18 Mar 2025 20:51:28 +0000 (22:51 +0200)
Add a fallback BSS-based channel selection if survey-based selection
fails. Interference factor is simply the number of BSSs on the channel.

Signed-off-by: Matěj Vrba <matej.vrba@advantech.cz>
src/ap/acs.c
src/drivers/driver.h

index f5b36d327a74f39fe3c7bcd7571661214fa572e8..44d083684471c525c68de2c91a22ca03cb93b226 100644 (file)
@@ -54,7 +54,7 @@
  * Todo / Ideas
  * ------------
  * - implement other interference computation methods
- *   - BSS/RSSI based
+ *   - RSSI based
  *   - spectral scan based
  *   (should be possibly to hook this up with current ACS scans)
  * - add wpa_supplicant support (for P2P)
@@ -557,6 +557,9 @@ static int acs_surveys_are_sufficient(struct hostapd_iface *iface)
 
 static int acs_usable_chan(struct hostapd_channel_data *chan)
 {
+       if (chan->interference_bss_based)
+               return 1;
+
        return !dl_list_empty(&chan->survey_list) &&
                !(chan->flag & HOSTAPD_CHAN_DISABLED) &&
                acs_survey_list_is_sufficient(chan);
@@ -1254,13 +1257,53 @@ static int acs_study_survey_based(struct hostapd_iface *iface)
 }
 
 
+static int acs_study_bss_based(struct hostapd_iface *iface)
+{
+       struct wpa_scan_results *scan_res;
+       int j;
+
+       wpa_printf(MSG_DEBUG, "ACS: Trying BSS-based ACS");
+
+       scan_res = hostapd_driver_get_scan_results(iface->bss[0]);
+       if (!scan_res) {
+               wpa_printf(MSG_INFO, "ACS: Scan request failed");
+               hostapd_setup_interface_complete(iface, 1);
+               return -1;
+       }
+
+       for (j = 0; j < iface->current_mode->num_channels; j++) {
+               struct hostapd_channel_data *chan;
+               unsigned int bss_on_ch = 0;
+               size_t i;
+
+               chan = &iface->current_mode->channels[j];
+               for (i = 0; i < scan_res->num; i++) {
+                       struct wpa_scan_res *bss = scan_res->res[i];
+
+                       if (bss->freq == chan->freq)
+                               bss_on_ch++;
+               }
+
+               wpa_printf(MSG_MSGDUMP,
+                          "ACS: Interference on ch %d (%d MHz): %d",
+                          chan->chan, chan->freq, bss_on_ch);
+               chan->interference_factor = bss_on_ch;
+               chan->interference_bss_based = true;
+       }
+
+       wpa_scan_results_free(scan_res);
+       return 0;
+}
+
+
 static int acs_study_options(struct hostapd_iface *iface)
 {
        if (acs_study_survey_based(iface) == 0)
                return 0;
 
-       /* TODO: If no surveys are available/sufficient this is a good
-        * place to fallback to BSS-based ACS */
+       wpa_printf(MSG_INFO, "ACS: Survey based ACS failed");
+       if (acs_study_bss_based(iface) == 0)
+               return 0;
 
        return -1;
 }
index 1830019eed7e84ced19ee3fc6e3cd4fa4582a9cc..b356371b590cc9678eb135028d27ebd89d325b2c 100644 (file)
@@ -159,6 +159,12 @@ struct hostapd_channel_data {
         * need to set this)
         */
        long double interference_factor;
+
+       /**
+        * interference_bss_based - Indicates whether the interference was
+        * calculated from number of BSSs
+        */
+       bool interference_bss_based;
 #endif /* CONFIG_ACS */
 
        /**