From 6f41a258057294c6006fab477754da80c93c890e Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 5 Feb 2015 17:57:06 +0200 Subject: [PATCH] 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 --- src/ap/acs.c | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/ap/acs.c b/src/ap/acs.c index e4c834ce0..78fd949af 100644 --- a/src/ap/acs.c +++ b/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);