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 New
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(-)

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