diff mbox

ACS seems not to select the best channel in 2.4GHz.

Message ID 20150205161827.GA10519@w1.fi
State Accepted
Headers show

Commit Message

Jouni Malinen Feb. 5, 2015, 4:18 p.m. UTC
On Fri, Jan 30, 2015 at 02:45:25PM -0800, Fumikazu Yobimoto wrote:
> I verified the ACS(Auto Channel Select) in 2.4GHz environment.
> Set 2 APs, one is ch.1 and one is ch.11, and then transmit a heavy traffic
> at each channel.
> I'm expecting ACS should choose ch.6 for ideal channel, but it always
> choose ch.1 or ch.11 in any case.

> However, acs.c tries to add adjacent channel's value. Thus eventually,
> those values go like as following.
> 1=1.928 (1+2+3)
> 2=2.658 (1+2+3+4)
> 3=3.024 (1+2+3+4+5)

I guess the logic here could have been to assume that "channels" 0 and
-1 would have zero interference. That would not really be the case and I
agree that this would give way too much preference to channels 1 and 11
(and too much for 2 and 10 as well).

> I think it's not necessary to add adjacent value. Because radio survey data
> of each channel would detect the adjacent interference actually 20MHz.
> In fact, the test result shows that ch.4 detect the interference of ch.1,
> similarly ch.8 detect the interference of ch.11.
> I attached a patch file for hostapd-v2.3 .

I'm not sure skipping the adjacent channels completely on 2.4 GHz would
be ideal solution here. It is clear that the channels at each end of the
band will require something more accurate. It may also be reasonable to
at least drop the importance of the impact from adjacent channels. I'm
consider the following patch as a way of addressing this. If you define
ACS_ADJ_WEIGHT 0, ACS_NEXT_ADJ_WEIGHT 0, and ACS_24GHZ_PREFER_1_6_11 1,
you'd get the behavior you should saw with the patch you sent. If
someone has good suggestions on what the best numbers to use here as the
default would be, I'm certainly open to changing these. As noted in the
commit message, I did not really do any real research on picking the
numbers.


[PATCH] ACS: Fix 2.4 GHz adjacent channel interference summing

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 cannot be correct.

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.5 (1.0 for the main channel itself) and the neighboring
channels to those adjacent ones get 0.25 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.

This change results in significantly less preference for the band-edge
channels. That is arguable good thing to do here, but it would also be
good to avoid picking some arbitrary 2.4 GHz channel and rather give
significant extra preference for the commonly used channels 1, 6, 11.
This is now done by picking those channels over the other ones unless
another channel has significantly better interference factor (0.8 or
smaller times the one on 1, 6, 11).

The initially used multiplier values used here are not based on any real
research, i.e., these are just a wild guess of somethign
semi-reasonable. The values can be optimized in the future and can also
be overridden in build parameters with C preprocessor macros
(ACS_ADJ_WEIGHT, ACS_NEXT_ADJ_WEIGHT, ACS_24GHZ_PREFER_1_6_11).

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
 src/ap/acs.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 104 insertions(+), 18 deletions(-)

Comments

Eduard GV Feb. 5, 2015, 6:03 p.m. UTC | #1
Hi,

>> I think it's not necessary to add adjacent value. Because radio survey data
>> of each channel would detect the adjacent interference actually 20MHz.
>> In fact, the test result shows that ch.4 detect the interference of ch.1,
>> similarly ch.8 detect the interference of ch.11.
>> I attached a patch file for hostapd-v2.3 .
>
> I'm not sure skipping the adjacent channels completely on 2.4 GHz would
> be ideal solution here. It is clear that the channels at each end of the
> band will require something more accurate. It may also be reasonable to
> at least drop the importance of the impact from adjacent channels.

Agreed. Our experience shows that the use of partially overlapping
channels (i.e., not only 1, 6 and 11) is beneficial in dense
environments [1][2], but adjacent channel interference must be taken
into account.

> I'm
> consider the following patch as a way of addressing this. If you define
> ACS_ADJ_WEIGHT 0, ACS_NEXT_ADJ_WEIGHT 0, and ACS_24GHZ_PREFER_1_6_11 1,
> you'd get the behavior you should saw with the patch you sent. If
> someone has good suggestions on what the best numbers to use here as the
> default would be, I'm certainly open to changing these. As noted in the
> commit message, I did not really do any real research on picking the
> numbers.
>

After some experiments and some math[3], we concluded that the
adjacent channel (i.e. my center frequency +- 5MHz) is barely filtered
(~0.5dB), so I'd suggest
#define ACS_ADJ_WEIGHT 0.85

For the case of 2-channel separation (i.e. my center frequency +
10MHz) , the attenuation was ~2.5dB, so I'd suggest
#define ACS_NEXT_ADJ_WEIGHT 0.55

In fact, I'd also suggest that the "next to the next" adjacent channel
(i.e. my center frequency +- 15MHz) should also be taken into account
with a weight of 0.22 since transmissions three channels away do have
an impact on my current channel.

> it is clear that this summing
> of three to five values together and then comparing the sum rather than
> average of some kind cannot be correct.
>(...)
>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.
>

On the one hand, I agree that summing of interference_factors doesn't
make much sense (you are summing channel utilization ratios, which
could produce values > 100% of channel utilization?!?). On the other
hand, band-edge channels are actually less interfered since they have
less adjacent channels and, hence, it makes sense they are preferred
(i.e., averaging those interference_factors is not my favorite option
either).
What I'd like to try (at some point, when I have time and resources)
is a different formula for the interference_factor. Something like the
linear sum of the average signal level measured in all channels
(applying attenuation factors) and weighted by their utilization.

> This change results in significantly less preference for the band-edge
> channels. That is arguable good thing to do here, but it would also be
> good to avoid picking some arbitrary 2.4 GHz channel and rather give
> significant extra preference for the commonly used channels 1, 6, 11.
> This is now done by picking those channels over the other ones unless
> another channel has significantly better interference factor (0.8 or
> smaller times the one on 1, 6, 11).
>

Why not 1, 5, 9, 13 (where available)?


[1] http://dx.doi.org/10.1109/PIMRC.2013.6666557
[2] http://dx.doi.org/10.1002/wcm.670
[3] http://hdl.handle.net/2117/1234
Jouni Malinen Feb. 5, 2015, 8:52 p.m. UTC | #2
On Thu, Feb 05, 2015 at 07:03:16PM +0100, Eduard GV wrote:
> After some experiments and some math[3], we concluded that the
> adjacent channel (i.e. my center frequency +- 5MHz) is barely filtered
> (~0.5dB), so I'd suggest
> #define ACS_ADJ_WEIGHT 0.85
> 
> For the case of 2-channel separation (i.e. my center frequency +
> 10MHz) , the attenuation was ~2.5dB, so I'd suggest
> #define ACS_NEXT_ADJ_WEIGHT 0.55

Thanks, I'll update to those values.

> In fact, I'd also suggest that the "next to the next" adjacent channel
> (i.e. my center frequency +- 15MHz) should also be taken into account
> with a weight of 0.22 since transmissions three channels away do have
> an impact on my current channel.

I'm open to considering this extension, but for the initial step, I'd
likely to keep changes rather minimal.

> On the one hand, I agree that summing of interference_factors doesn't
> make much sense (you are summing channel utilization ratios, which
> could produce values > 100% of channel utilization?!?). On the other
> hand, band-edge channels are actually less interfered since they have
> less adjacent channels and, hence, it makes sense they are preferred
> (i.e., averaging those interference_factors is not my favorite option
> either).
> What I'd like to try (at some point, when I have time and resources)
> is a different formula for the interference_factor. Something like the
> linear sum of the average signal level measured in all channels
> (applying attenuation factors) and weighted by their utilization.

I'd certainly welcome experimentation in this area. I agree that there
may indeed be many cases where the band-edge channels are the best
candidates, but there are also reasons for not using these in some
cases. I don't think the current changes give too much of a preference
to channel 6, but if that turns out to be the case, this can obviously
be fine-tuned.

> Why not 1, 5, 9, 13 (where available)?

That is somewhat of a complex area.. In theory, if most devices around
you were to be using those channels efficiently, I'd agree with that
being a good default policy. However, that does not seem to be the case.
At least most of the APs that I've used in Europe end up defaulting to
channel 1, 6, or 11 and might not even always provide the option of
using 12-13. As such, I'd assume there is a significant existing
deployment of APs on channels 1, 6, and 11 and it may be better to use
those channels by default rather than try to bring in a different mix as
another "standard".

It would actually be interesting to see some statistics on operating
channel use in European deployments. Some quick searches through public
reports on this seemed to point towards channels 1, 6, 11 being used in
around 75% cases and 5, 9, 13 having a minimal (< 10 % in total) use.

In addition to the actual deployments, there are station implementation
reasons for 1, 6, 11 being a convenient set. Number of scan
optimizations make it more likely for APs to be found on those channels,
e.g., due to them being searched first or more frequently and channel 13
being scanned only with passive scanning. In addition, some P2P use
cases are quite a bit more efficient if the AP connection is on one of
the social channels (which, surprise surprise, are those 1, 6, 11).

All that said, it may make sense to provide an option for configuring
different bias for which channels to prefer. There may be reasons that
give different preferences even between whatever the set of selected
common channels are, so making this a bit more flexible could be useful.
Eduard GV Feb. 6, 2015, 10:14 a.m. UTC | #3
>> What I'd like to try (at some point, when I have time and resources)
>> is a different formula for the interference_factor. Something like the
>> linear sum of the average signal level measured in all channels
>> (applying attenuation factors) and weighted by their utilization.
>
> I'd certainly welcome experimentation in this area.

Does anyone have half a dozen or so compatible devices to spare :D ?


>> Why not 1, 5, 9, 13 (where available)?
>
> That is somewhat of a complex area..

Indeed

>
> It would actually be interesting to see some statistics on operating
> channel use in European deployments. Some quick searches through public
> reports on this seemed to point towards channels 1, 6, 11 being used in
> around 75% cases and 5, 9, 13 having a minimal (< 10 % in total) use.
>

We conducted a survey in Barcelona and found it was ~60% for the
triumvirate (i.e. 1, 6, 11), and ~40% for the rest of the 2.4GHz
channels (~15% of the total in the set 5, 9, 13). We gathered more
interesting data which we will hopefully publish soon.

> In addition to the actual deployments, there are station implementation
> reasons for 1, 6, 11 being a convenient set. Number of scan
> optimizations make it more likely for APs to be found on those channels,
> e.g., due to them being searched first or more frequently and channel 13
> being scanned only with passive scanning. In addition, some P2P use
> cases are quite a bit more efficient if the AP connection is on one of
> the social channels (which, surprise surprise, are those 1, 6, 11).

One final insight in this regard... we were allowed to "play" with the
Wi-Fi infrastructure of a small campus to test our centralized channel
management algorithm with their ~100 APs. Those APs coexisted with
other ~100 "rogue" APs. In the beginning, most of the ~200 APs were on
either 1, 6 or 11. After two weeks managing our ~100 APs' channels
(using the whole available spectrum), the "rogue" APs (the channel
selection mechanism of which is unknown to us) reacted so that,
eventually, the channel distribution became fairer (> 50% of them in
the set 1, 5, 9, 13).

> All that said, it may make sense to provide an option for configuring
> different bias for which channels to prefer. There may be reasons that
> give different preferences even between whatever the set of selected
> common channels are, so making this a bit more flexible could be useful.
>

Amen.
diff mbox

Patch

diff --git a/src/ap/acs.c b/src/ap/acs.c
index e4c834c..616b810 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -517,6 +517,23 @@  static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface,
 }
 
 
+#ifndef ACS_ADJ_WEIGHT
+#define ACS_ADJ_WEIGHT 0.5
+#endif /* ACS_ADJ_WEIGHT */
+
+#ifndef ACS_NEXT_ADJ_WEIGHT
+#define ACS_NEXT_ADJ_WEIGHT 0.25
+#endif /* ACS_NEXT_ADJ_WEIGHT */
+
+#ifndef ACS_24GHZ_PREFER_1_6_11
+/*
+ * Select commonly used channels 1, 6, 11 even if a neighboring channel has
+ * a smaller interference factor as long as it is not better by more than this
+ * multiplier.
+ */
+#define ACS_24GHZ_PREFER_1_6_11 0.8
+#endif /* ACS_24GHZ_PREFER_1_6_11 */
+
 /*
  * At this point it's assumed chan->interface_factor has been computed.
  * This function should be reusable regardless of interference computation
@@ -529,7 +546,8 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 	struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL,
 		*rand_chan = NULL;
 	long double factor, ideal_factor = 0;
-	int i, j;
+	long double factor_chans[13];
+	int i, j, max_chans, ideal_idx = -1;
 	int n_chans = 1;
 
 	/* TODO: HT40- support */
@@ -556,7 +574,16 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 		   n_chans == 4 ? 80 :
 		   -1);
 
+	max_chans = iface->current_mode->num_channels;
+	if (max_chans > 13)
+		max_chans = 13;
+	for (i = 0; i < max_chans; i++)
+		factor_chans[i] = 0;
+
 	for (i = 0; i < iface->current_mode->num_channels; i++) {
+		double total_weight;
+		int usable;
+
 		chan = &iface->current_mode->channels[i];
 
 		if (chan->flag & HOSTAPD_CHAN_DISABLED)
@@ -586,16 +613,20 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 		}
 
 		factor = 0;
-		if (acs_usable_chan(chan))
+		usable = acs_usable_chan(chan);
+		if (usable)
 			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,38 +640,53 @@  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);
 
-		if (acs_usable_chan(chan) &&
-		    (!ideal_chan || factor < ideal_factor)) {
-			ideal_factor = factor;
-			ideal_chan = chan;
+		if (usable) {
+			if (i < max_chans)
+				factor_chans[i] = factor;
+			if (!ideal_chan || factor < ideal_factor) {
+				ideal_factor = factor;
+				ideal_chan = chan;
+				ideal_idx = i;
+			}
 		}
 
 		/* This channel would at least be usable */
@@ -648,6 +694,46 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 			rand_chan = chan;
 	}
 
+	/*
+	 * Try to prefer commonly used channels 1, 6, and 11 unless
+	 * there is a significantly better channel available.
+	 */
+	if ((iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B ||
+	     iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) &&
+	    ideal_idx >= 0 && ideal_chan) {
+		if ((ideal_idx == 1 || ideal_idx == 2) &&
+		    factor_chans[0] > 0 &&
+		    factor_chans[ideal_idx] >
+		    ACS_24GHZ_PREFER_1_6_11 * factor_chans[0]) {
+			wpa_printf(MSG_DEBUG,
+				   "ACS: Prefer common 2.4 GHz channel 1 over ideal channel %d",
+				   ideal_chan->chan);
+			ideal_chan = &iface->current_mode->channels[0];
+		}
+
+		if ((ideal_idx == 3 || ideal_idx == 4 ||
+		     ideal_idx == 6 || ideal_idx == 7) &&
+		    factor_chans[5] > 0 &&
+		    factor_chans[ideal_idx] >
+		    ACS_24GHZ_PREFER_1_6_11 * factor_chans[5]) {
+			wpa_printf(MSG_DEBUG,
+				   "ACS: Prefer common 2.4 GHz channel 6 over ideal channel %d",
+				   ideal_chan->chan);
+			ideal_chan = &iface->current_mode->channels[5];
+		}
+
+		if ((ideal_idx == 8 || ideal_idx == 9 ||
+		     ideal_idx == 11 || ideal_idx == 12) &&
+		    factor_chans[10] > 0 &&
+		    factor_chans[ideal_idx] >
+		    ACS_24GHZ_PREFER_1_6_11 * factor_chans[10]) {
+			wpa_printf(MSG_DEBUG,
+				   "ACS: Prefer common 2.4 GHz channel 11 over ideal channel %d",
+				   ideal_chan->chan);
+			ideal_chan = &iface->current_mode->channels[10];
+		}
+	}
+
 	if (ideal_chan) {
 		wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
 			   ideal_chan->chan, ideal_chan->freq, ideal_factor);