Patchwork [RFC] hostapd: ACS VHT get best control channel from segment

login
register
mail settings
Submitter Janusz.Dziedzic@tieto.com
Date March 11, 2014, 10:24 a.m.
Message ID <1394533469-16278-1-git-send-email-janusz.dziedzic@tieto.com>
Download mbox | patch
Permalink /patch/329024/
State RFC
Headers show

Comments

Janusz.Dziedzic@tieto.com - March 11, 2014, 10:24 a.m.
In case of VHT40/VHT80 get best control channel
from the segment instead of first one.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
---
 src/ap/acs.c |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 58 insertions(+), 9 deletions(-)
Jouni Malinen - March 7, 2015, 7:48 p.m.
On Tue, Mar 11, 2014 at 11:24:29AM +0100, Janusz Dziedzic wrote:
> In case of VHT40/VHT80 get best control channel
> from the segment instead of first one.

I don't think there was any comments or followup on this RFC. Was there
some continued development on this and is this still something that
should be applied? If so, could you please provide a rebased version?

Patch

diff --git a/src/ap/acs.c b/src/ap/acs.c
index 3e0155c..0c4a40c 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -508,8 +508,8 @@  static struct hostapd_channel_data *
 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;
+		*rand_chan = NULL, *control_chan = NULL;
+	long double factor, ideal_factor = 0, control_factor = 0;
 	int i, j;
 	int n_chans = 1;
 
@@ -550,7 +550,7 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 		    iface->conf->ieee80211n &&
 		    iface->conf->secondary_channel &&
 		    !acs_usable_ht40_chan(chan)) {
-			wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for HT40",
+			wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for HT40 segment",
 				   chan->chan);
 			continue;
 		}
@@ -559,7 +559,7 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 		    iface->conf->ieee80211ac &&
 		    iface->conf->vht_oper_chwidth == 1 &&
 		    !acs_usable_vht80_chan(chan)) {
-			wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for VHT80",
+			wpa_printf(MSG_DEBUG, "ACS: Channel %d: not allowed as primary channel for VHT80 segment",
 				   chan->chan);
 			continue;
 		}
@@ -568,6 +568,9 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 		if (acs_usable_chan(chan))
 			factor = chan->interference_factor;
 
+		control_chan = chan;
+		control_factor = factor;
+
 		for (j = 1; j < n_chans; j++) {
 			adj_chan = acs_find_chan(iface, chan->freq + (j * 20));
 			if (!adj_chan)
@@ -575,6 +578,13 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 
 			if (acs_usable_chan(adj_chan))
 				factor += adj_chan->interference_factor;
+
+			/* TODO handle control_chan also for 2.4 */
+			if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
+			    control_factor > adj_chan->interference_factor) {
+				control_factor = adj_chan->interference_factor;
+				control_chan = adj_chan;
+			}
 		}
 
 		if (j != n_chans) {
@@ -616,10 +626,13 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 		wpa_printf(MSG_DEBUG, "ACS:  * channel %d: total interference = %Lg",
 			   chan->chan, factor);
 
+		wpa_printf(MSG_DEBUG, "ACS:  * control_channel %d: control interference = %Lg",
+			   control_chan->chan, control_factor);
+
 		if (acs_usable_chan(chan) &&
 		    (!ideal_chan || factor < ideal_factor)) {
 			ideal_factor = factor;
-			ideal_chan = chan;
+			ideal_chan = control_chan;
 		}
 
 		/* This channel would at least be usable */
@@ -636,19 +649,55 @@  acs_find_ideal_chan(struct hostapd_iface *iface)
 	return rand_chan;
 }
 
+static void acs_adjust_vht40(struct hostapd_iface *iface)
+{
+	const int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149,
+				157, 184, 192 };
+	unsigned int i;
+
+	if (!iface->conf->secondary_channel) {
+		/* HT20 only */
+		iface->conf->vht_oper_centr_freq_seg0_idx = iface->conf->channel;
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(allowed); i++)
+		if (iface->conf->channel >= allowed[i] &&
+		    iface->conf->channel < allowed[i] + 8) {
+			if (iface->conf->channel == allowed[i])
+				iface->conf->secondary_channel = 1;
+			else
+				iface->conf->secondary_channel = -1;
+			iface->conf->vht_oper_centr_freq_seg0_idx = allowed[i] + 2;
+		}
+}
+
+static void acs_adjust_vht80(struct hostapd_iface *iface)
+{
+	const int allowed[] = { 36, 52, 100, 116, 132, 149 };
+	unsigned int i;
+
+	acs_adjust_vht40(iface);
+
+	for (i = 0; i < ARRAY_SIZE(allowed); i++)
+		if (iface->conf->channel >= allowed[i] &&
+		    iface->conf->channel < allowed[i] + 16)
+			iface->conf->vht_oper_centr_freq_seg0_idx = allowed[i] + 6;
+}
 
 static void acs_adjust_vht_center_freq(struct hostapd_iface *iface)
 {
+	if (!iface->conf->ieee80211ac)
+		return;
+
 	wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency");
 
 	switch (iface->conf->vht_oper_chwidth) {
 	case VHT_CHANWIDTH_USE_HT:
-		iface->conf->vht_oper_centr_freq_seg0_idx =
-			iface->conf->channel + 2;
+		acs_adjust_vht40(iface);
 		break;
 	case VHT_CHANWIDTH_80MHZ:
-		iface->conf->vht_oper_centr_freq_seg0_idx =
-			iface->conf->channel + 6;
+		acs_adjust_vht80(iface);
 		break;
 	default:
 		/* TODO: How can this be calculated? Adjust