ACS: Use weighted average for 2.4 GHz adjacent channel interference
The interference factors for adjacent 2.4 GHz channels were summed together without doing any kind of weighted average on them. This resulted in the channels at the band edges getting undue preference due to only including interference factors from three channels vs. five for the channels in the middle of the band. While it is somewhat unclear whether the design here was supposed to count overlapping channels together in this way or whether that is already covered in channel survey results, it is clear that this summing of three to five values together and then comparing the sum rather than average of some kind gives too much preference to the channels at the edges of the band by assuming that there is no interference whatsoever outside the band. Use weighted average of the interference factors rather than a sum from different number of values. For now, the adjacent 2.4 GHz channels get weight of 0.85 (1.0 for the main channel itself) and the neighboring channels to those adjacent ones get 0.55 weight. Band-edge channels are handled in a way that takes average over the channels that were actually considered instead of assuming zero interference from neighboring bands. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
1cb3ad7362
commit
6f41a25805
1 changed files with 36 additions and 12 deletions
48
src/ap/acs.c
48
src/ap/acs.c
|
@ -517,6 +517,14 @@ static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
|
|||
}
|
||||
|
||||
|
||||
#ifndef ACS_ADJ_WEIGHT
|
||||
#define ACS_ADJ_WEIGHT 0.85
|
||||
#endif /* ACS_ADJ_WEIGHT */
|
||||
|
||||
#ifndef ACS_NEXT_ADJ_WEIGHT
|
||||
#define ACS_NEXT_ADJ_WEIGHT 0.55
|
||||
#endif /* ACS_NEXT_ADJ_WEIGHT */
|
||||
|
||||
/*
|
||||
* At this point it's assumed chan->interface_factor has been computed.
|
||||
* This function should be reusable regardless of interference computation
|
||||
|
@ -557,6 +565,8 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
-1);
|
||||
|
||||
for (i = 0; i < iface->current_mode->num_channels; i++) {
|
||||
double total_weight;
|
||||
|
||||
chan = &iface->current_mode->channels[i];
|
||||
|
||||
if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
||||
|
@ -588,14 +598,17 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
factor = 0;
|
||||
if (acs_usable_chan(chan))
|
||||
factor = chan->interference_factor;
|
||||
total_weight = 1;
|
||||
|
||||
for (j = 1; j < n_chans; j++) {
|
||||
adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
|
||||
if (!adj_chan)
|
||||
break;
|
||||
|
||||
if (acs_usable_chan(adj_chan))
|
||||
if (acs_usable_chan(adj_chan)) {
|
||||
factor += adj_chan->interference_factor;
|
||||
total_weight += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (j != n_chans) {
|
||||
|
@ -609,31 +622,42 @@ acs_find_ideal_chan(struct hostapd_iface *iface)
|
|||
if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B ||
|
||||
iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) {
|
||||
for (j = 0; j < n_chans; j++) {
|
||||
/* TODO: perhaps a multiplier should be used
|
||||
* here? */
|
||||
|
||||
adj_chan = acs_find_chan(iface, chan->freq +
|
||||
(j * 20) - 5);
|
||||
if (adj_chan && acs_usable_chan(adj_chan))
|
||||
factor += adj_chan->interference_factor;
|
||||
if (adj_chan && acs_usable_chan(adj_chan)) {
|
||||
factor += ACS_ADJ_WEIGHT *
|
||||
adj_chan->interference_factor;
|
||||
total_weight += ACS_ADJ_WEIGHT;
|
||||
}
|
||||
|
||||
adj_chan = acs_find_chan(iface, chan->freq +
|
||||
(j * 20) - 10);
|
||||
if (adj_chan && acs_usable_chan(adj_chan))
|
||||
factor += adj_chan->interference_factor;
|
||||
if (adj_chan && acs_usable_chan(adj_chan)) {
|
||||
factor += ACS_NEXT_ADJ_WEIGHT *
|
||||
adj_chan->interference_factor;
|
||||
total_weight += ACS_NEXT_ADJ_WEIGHT;
|
||||
}
|
||||
|
||||
adj_chan = acs_find_chan(iface, chan->freq +
|
||||
(j * 20) + 5);
|
||||
if (adj_chan && acs_usable_chan(adj_chan))
|
||||
factor += adj_chan->interference_factor;
|
||||
if (adj_chan && acs_usable_chan(adj_chan)) {
|
||||
factor += ACS_ADJ_WEIGHT *
|
||||
adj_chan->interference_factor;
|
||||
total_weight += ACS_ADJ_WEIGHT;
|
||||
}
|
||||
|
||||
adj_chan = acs_find_chan(iface, chan->freq +
|
||||
(j * 20) + 10);
|
||||
if (adj_chan && acs_usable_chan(adj_chan))
|
||||
factor += adj_chan->interference_factor;
|
||||
if (adj_chan && acs_usable_chan(adj_chan)) {
|
||||
factor += ACS_NEXT_ADJ_WEIGHT *
|
||||
adj_chan->interference_factor;
|
||||
total_weight += ACS_NEXT_ADJ_WEIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
factor /= total_weight;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "ACS: * channel %d: total interference = %Lg",
|
||||
chan->chan, factor);
|
||||
|
||||
|
|
Loading…
Reference in a new issue