mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 19:03:39 +00:00
264 lines
8.2 KiB
Diff
264 lines
8.2 KiB
Diff
From 856937cfab895f6a20e1fd9d919ad5710077745c Mon Sep 17 00:00:00 2001
|
|
From: Hari Chandrakanthan <quic_haric@quicinc.com>
|
|
Date: Wed, 28 Sep 2022 17:48:40 +0530
|
|
Subject: [PATCH] hostapd : add awgn support for 320MHz bw in 6GHz band
|
|
|
|
Add support for awgn handling of 320MHz bw in 6GHz band.
|
|
|
|
Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
|
|
---
|
|
src/ap/interference.c | 147 ++++++++++++++++++++++++++++++++++----------------
|
|
1 file changed, 100 insertions(+), 47 deletions(-)
|
|
|
|
diff --git a/src/ap/interference.c b/src/ap/interference.c
|
|
index c51a4bf..4148489 100644
|
|
--- a/src/ap/interference.c
|
|
+++ b/src/ap/interference.c
|
|
@@ -62,6 +62,7 @@ static int intf_awgn_chan_range_available(struct hostapd_hw_modes *mode,
|
|
int allowed_80_6g[] = {1, 17, 33, 49, 65, 81, 97, 113, 129, 145, 161, 177,
|
|
193, 209};
|
|
int allowed_160_6g[] = {1, 33, 65, 97, 129, 161, 193};
|
|
+ int allowed_320_6g[] = {1, 65, 129, 33, 97, 161};
|
|
int chan_idx_match = 0;
|
|
int i;
|
|
|
|
@@ -97,6 +98,13 @@ static int intf_awgn_chan_range_available(struct hostapd_hw_modes *mode,
|
|
break;
|
|
}
|
|
}
|
|
+ } else if (num_chans == 16) { /* 320Mhz channel */
|
|
+ for (i = 0; i < ARRAY_SIZE(allowed_320_6g); i++) {
|
|
+ if (first_chan->chan == allowed_320_6g[i]) {
|
|
+ chan_idx_match = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
if (chan_idx_match == 1)
|
|
@@ -114,6 +122,42 @@ static int is_in_chanlist(struct hostapd_iface *iface,
|
|
return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
|
|
}
|
|
|
|
+#define BASE_6G_FREQ 5950
|
|
+
|
|
+int get_centre_freq_6g(int chan_idx, int chan_width, int *centre_freq)
|
|
+{
|
|
+ if (!centre_freq)
|
|
+ return -1;
|
|
+
|
|
+ *centre_freq = 0;
|
|
+
|
|
+ switch (chan_width) {
|
|
+ case CHAN_WIDTH_40:
|
|
+ if (chan_idx >= 1 && chan_idx <= 229)
|
|
+ *centre_freq = ((chan_idx / 8) * 8 + 3) * 5 + BASE_6G_FREQ;
|
|
+ break;
|
|
+ case CHAN_WIDTH_80:
|
|
+ if (chan_idx >= 1 && chan_idx <= 221)
|
|
+ *centre_freq = ((chan_idx / 16) * 16 + 7) * 5 + BASE_6G_FREQ;
|
|
+ break;
|
|
+ case CHAN_WIDTH_160:
|
|
+ if (chan_idx >= 1 && chan_idx <= 221)
|
|
+ *centre_freq = ((chan_idx / 32) * 32 + 15) * 5 + BASE_6G_FREQ;
|
|
+ break;
|
|
+ case CHAN_WIDTH_320:
|
|
+ if (chan_idx >= 1 && chan_idx <= 221)
|
|
+ *centre_freq = ((chan_idx /64) * 64 + 31) * 5 + BASE_6G_FREQ;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (*centre_freq == 0)
|
|
+ return -1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
/*
|
|
*intf_awgn_find_channel - find the channel that can operate with bandwidth chan_width.
|
|
If idx doesn't match with index of any of the existing channel, then the api
|
|
@@ -123,11 +167,13 @@ static int is_in_chanlist(struct hostapd_iface *iface,
|
|
*/
|
|
static int intf_awgn_find_channel(struct hostapd_iface *iface,
|
|
struct hostapd_channel_data **ret_chan,
|
|
- int idx, int chan_width)
|
|
+ int idx, int chan_width, int cs1)
|
|
{
|
|
struct hostapd_hw_modes *mode = iface->current_mode;
|
|
struct hostapd_channel_data *chan;
|
|
int i, channel_idx = 0, n_chans;
|
|
+ int temp_centre_freq;
|
|
+ int ret;
|
|
|
|
switch (chan_width) {
|
|
case CHAN_WIDTH_20_NOHT:
|
|
@@ -144,6 +190,9 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface,
|
|
case CHAN_WIDTH_160:
|
|
n_chans = 8;
|
|
break;
|
|
+ case CHAN_WIDTH_320:
|
|
+ n_chans = 16;
|
|
+ break;
|
|
default:
|
|
n_chans = 1;
|
|
break;
|
|
@@ -167,6 +216,24 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface,
|
|
continue;
|
|
}
|
|
|
|
+ if (chan_width == CHAN_WIDTH_320) {
|
|
+ ret = get_centre_freq_6g(chan->chan, CHAN_WIDTH_320,
|
|
+ &temp_centre_freq);
|
|
+ if (ret) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
+ "AWGN : couldn't find centre freq for chan : %d"
|
|
+ " chan_width : %d", chan->chan, CHAN_WIDTH_320);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (abs(temp_centre_freq - cs1) < 320) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "AWGN: channel %d is a overlapping channel so skipping",
|
|
+ chan->freq);
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (ret_chan && idx == channel_idx) {
|
|
wpa_printf(MSG_DEBUG, "AWGN: Selected channel %d (%d)",
|
|
chan->freq, chan->chan);
|
|
@@ -182,50 +249,27 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface,
|
|
}
|
|
|
|
enum chan_seg {
|
|
- SEG_PRI20 = 0x1,
|
|
- SEG_SEC20 = 0x2,
|
|
- SEG_SEC40_LOWER = 0x4,
|
|
- SEG_SEC40_UPPER = 0x8,
|
|
- SEG_SEC40 = 0xC,
|
|
- SEG_SEC80_LOWER = 0x10,
|
|
- SEG_SEC80_LOWER_UPPER = 0x20,
|
|
- SEG_SEC80_UPPER_LOWER = 0x40,
|
|
- SEG_SEC80_UPPER = 0x80,
|
|
- SEG_SEC80 = 0xF0,
|
|
+ SEG_PRI20 = 0x1,
|
|
+ SEG_SEC20 = 0x2,
|
|
+ SEG_SEC40_LOW = 0x4,
|
|
+ SEG_SEC40_UP = 0x8,
|
|
+ SEG_SEC40 = 0xC,
|
|
+ SEG_SEC80_LOW = 0x10,
|
|
+ SEG_SEC80_LOW_UP = 0x20,
|
|
+ SEG_SEC80_UP_LOW = 0x40,
|
|
+ SEG_SEC80_UP = 0x80,
|
|
+ SEG_SEC80 = 0xF0,
|
|
+ SEG_SEC160_LOW = 0x0100,
|
|
+ SEG_SEC160_LOW_UP = 0x0200,
|
|
+ SEG_SEC160_LOW_UP_UP = 0x0400,
|
|
+ SEG_SEC160_LOW_UP_UP_UP = 0x0800,
|
|
+ SEG_SEC160_UP_LOW_LOW_LOW = 0x1000,
|
|
+ SEG_SEC160_UP_LOW_LOW = 0x2000,
|
|
+ SEG_SEC160_UP_LOW = 0x4000,
|
|
+ SEG_SEC160_UP = 0x8000,
|
|
+ SEG_SEC160 = 0xFF00,
|
|
};
|
|
|
|
-#define BASE_6G_FREQ 5950
|
|
-
|
|
-int get_centre_freq_6g(int chan_idx, int chan_width, int *centre_freq)
|
|
-{
|
|
- if (!centre_freq)
|
|
- return -1;
|
|
-
|
|
- *centre_freq = 0;
|
|
-
|
|
- switch (chan_width) {
|
|
- case CHAN_WIDTH_40:
|
|
- if (chan_idx >= 1 && chan_idx <= 229)
|
|
- *centre_freq = ((chan_idx / 8) * 8 + 3) * 5 + BASE_6G_FREQ;
|
|
- break;
|
|
- case CHAN_WIDTH_80:
|
|
- if (chan_idx >= 1 && chan_idx <= 221)
|
|
- *centre_freq = ((chan_idx / 16) * 16 + 7) * 5 + BASE_6G_FREQ;
|
|
- break;
|
|
- case CHAN_WIDTH_160:
|
|
- if (chan_idx >= 1 && chan_idx <= 221)
|
|
- *centre_freq = ((chan_idx / 32) * 32 + 15) * 5 + BASE_6G_FREQ;
|
|
- break;
|
|
- default:
|
|
- break;
|
|
- }
|
|
-
|
|
- if (*centre_freq == 0)
|
|
- return -1;
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
/*
|
|
* hostapd_intf_awgn_detected - awgn interference is detected in the operating channel.
|
|
* The interference channel information is available as a
|
|
@@ -269,7 +313,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
|
|
if (channel_switch) {
|
|
/* Find a random channel to be switched */
|
|
num_available_chandefs = intf_awgn_find_channel(iface, NULL, 0,
|
|
- chan_width);
|
|
+ chan_width, cf1);
|
|
if (num_available_chandefs == 0) {
|
|
wpa_printf(MSG_ERROR, "AWGN: no available_chandefs");
|
|
return 0;
|
|
@@ -281,7 +325,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
|
|
}
|
|
|
|
chan_idx = _rand % num_available_chandefs;
|
|
- intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width);
|
|
+ intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width, cf1);
|
|
|
|
if (!chan_data) {
|
|
wpa_printf(MSG_ERROR, "AWGN: no random channel found, chan idx : %d",
|
|
@@ -295,7 +339,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
|
|
*/
|
|
chan_data = NULL;
|
|
chan_idx = (chan_idx + 1) % num_available_chandefs;
|
|
- intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width);
|
|
+ intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width, cf1);
|
|
if (!chan_data) {
|
|
wpa_printf(MSG_ERROR,
|
|
"AWGN: random channel not found, chan idx : %d",
|
|
@@ -319,7 +363,12 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
|
|
return 0;
|
|
}
|
|
|
|
- if ((chan_width > CHAN_WIDTH_80) &&
|
|
+ if ((chan_width > CHAN_WIDTH_160) &&
|
|
+ !(chan_bw_interference_bitmap & SEG_SEC80) &&
|
|
+ !(chan_bw_interference_bitmap & SEG_SEC40) &&
|
|
+ !(chan_bw_interference_bitmap & SEG_SEC20))
|
|
+ new_chan_width = CHAN_WIDTH_160;
|
|
+ else if ((chan_width > CHAN_WIDTH_80) &&
|
|
!(chan_bw_interference_bitmap & SEG_SEC40) &&
|
|
!(chan_bw_interference_bitmap & SEG_SEC20))
|
|
new_chan_width = CHAN_WIDTH_80;
|
|
@@ -358,6 +407,9 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
|
|
case CHAN_WIDTH_160:
|
|
settings.freq_params.bandwidth = 160;
|
|
break;
|
|
+ case CHAN_WIDTH_320:
|
|
+ settings.freq_params.bandwidth = 320;
|
|
+ break;
|
|
default:
|
|
settings.freq_params.bandwidth = 20;
|
|
break;
|
|
@@ -367,6 +419,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
|
|
settings.freq_params.ht_enabled = iface->conf->ieee80211n;
|
|
settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
|
|
settings.freq_params.he_enabled = iface->conf->ieee80211ax;
|
|
+ settings.freq_params.eht_enabled= iface->conf->ieee80211be;
|
|
|
|
for (i = 0; i < iface->num_bss; i++) {
|
|
/* Save CHAN_SWITCH VHT and HE config */
|
|
--
|
|
2.7.4
|
|
|