]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
ACS: Fix not selecting the best channel in the segment
authorMichael-CY Lee <michael-cy.lee@mediatek.com>
Fri, 22 Dec 2023 04:59:09 +0000 (12:59 +0800)
committerJouni Malinen <j@w1.fi>
Sat, 23 Dec 2023 13:28:50 +0000 (15:28 +0200)
Fix the following bugs about selecting the best channels in the segment:
1. If the 'update_best' once became false, it never becomes true again.
   In other word, if one of the channels in the segment is not usable,
   the remaining channels in the segment were never able to be the best
   channel.
2. The primary channel in the segment might not be usable due to the
   insufficient survey data. Therefore, it cannot be the best channel and
   we cannot take its factor/weight into account.

Co-developed-by: Money Wang <money.wang@mediatek.com>
Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
src/ap/acs.c

index 8c6621f0edbc22fcc3197a1df8c43617705adcfa..2b7a43e1431fba7d438303e40468e6fd56ad9611 100644 (file)
@@ -793,11 +793,10 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
                secondary_channel = iface->conf->secondary_channel;
 
        for (i = 0; i < mode->num_channels; i++) {
-               double total_weight;
+               double total_weight = 0;
                struct acs_bias *bias, tmp_bias;
-               bool update_best = true;
 
-               best = chan = &mode->channels[i];
+               chan = &mode->channels[i];
 
                /* Since in the current ACS implementation the first channel is
                 * always a primary channel, skip channels not available as
@@ -883,9 +882,12 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
                }
 
                factor = 0;
-               if (acs_usable_chan(chan))
+               best = NULL;
+               if (acs_usable_chan(chan)) {
                        factor = chan->interference_factor;
-               total_weight = 1;
+                       total_weight = 1;
+                       best = chan;
+               }
 
                for (j = 1; j < n_chans; j++) {
                        adj_chan = acs_find_chan(iface, chan->freq +
@@ -900,16 +902,14 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
                                break;
                        }
 
-                       if (acs_usable_chan(adj_chan)) {
-                               factor += adj_chan->interference_factor;
-                               total_weight += 1;
-                       } else {
-                               update_best = false;
-                       }
+                       if (!acs_usable_chan(adj_chan))
+                               continue;
+
+                       factor += adj_chan->interference_factor;
+                       total_weight += 1;
 
                        /* find the best channel in this segment */
-                       if (update_best &&
-                           adj_chan->interference_factor <
+                       if (!best || adj_chan->interference_factor <
                            best->interference_factor)
                                best = adj_chan;
                }
@@ -972,6 +972,9 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
                        }
                }
 
+               if (total_weight == 0)
+                       continue;
+
                factor /= total_weight;
 
                bias = NULL;