From 19cb10a62d2cd4507cbe28bf36a1522fd8d5870a Mon Sep 17 00:00:00 2001 From: Karthik M Date: Fri, 24 Jun 2022 10:28:31 +0530 Subject: [PATCH] hostapd: Add ACS and DFS support for 5GHz BW240MHZ ACS dynamically punctures the channels based on the noise levels. Incase of 5G 240MHZ bandwidth, we need to use static punturing bitmap. In case of radar, We have only one channel in 240MHz. The bandwidth should downgrade to 160MHz and choose a channel. Signed-off-by: Karthik M --- src/ap/acs.c | 19 +++++++++++++++---- src/ap/dfs.c | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 8 deletions(-) Index: b/src/ap/acs.c =================================================================== --- a/src/ap/acs.c 2022-09-19 10:33:57.084303028 +0530 +++ b/src/ap/acs.c 2022-09-19 10:33:57.076303097 +0530 @@ -420,7 +420,7 @@ static int acs_usable_bw160_chan(const s static int acs_usable_bw320_chan(const struct hostapd_channel_data *chan) { /* Allow start of overlapping 320MHz channels */ - const int allowed[] = { 5955, 6115, 6275, 6435, 6595, 6755 }; + const int allowed[] = { 5500, 5955, 6115, 6275, 6435, 6595, 6755 }; unsigned int i; for (i = 0; i < ARRAY_SIZE(allowed); i++) @@ -657,6 +657,8 @@ static int is_common_24ghz_chan(int chan #define ACS_24GHZ_PREFER_1_6_11 0.8 #endif /* ACS_24GHZ_PREFER_1_6_11 */ +#define PUNCTURING_PATTERN_5G_320MHZ 0XF000 + static void acs_update_puncturing_bitmap(struct hostapd_iface *iface, struct hostapd_hw_modes *mode, u32 bw, int n_chans, @@ -669,14 +671,32 @@ static void acs_update_puncturing_bitmap struct hostapd_config *conf = iface->conf; long double threshold = factor * conf->ru_punct_acs_threshold / 100; + if (is_24ghz_mode(mode->mode) || (bw < 80)) + return; + + /* + * 5GHz 320Mhz operates with static punturing bitmap. Overiding the dynammic + * bitmap calculation + */ + + if (!is_6ghz_op_class(iface->conf->op_class) && bw == 320) { + if ((conf->ru_punct_bitmap & PUNCTURING_PATTERN_5G_320MHZ) == + PUNCTURING_PATTERN_5G_320MHZ) { + chan->ru_punct_bitmap = conf->ru_punct_bitmap; + goto bitmap_selected; + } else { + wpa_printf(MSG_DEBUG, "ACS : Invalid ru_punct_bitmap for 5G %X", + conf->ru_punct_bitmap); + return; + } + } + /* * If threshold is 0 or user configured puncturing pattern is * available then don't add additional puncturing. */ - if (!conf->ru_punct_acs_threshold || conf->ru_punct_bitmap) - return; - if (is_24ghz_mode(mode->mode) || (bw < 80)) + if (!conf->ru_punct_acs_threshold || conf->ru_punct_bitmap) return; for (i = 0; i < n_chans; i++) { @@ -701,6 +721,11 @@ static void acs_update_puncturing_bitmap chan->ru_punct_bitmap |= BIT(i); } +bitmap_selected: + wpa_printf(MSG_DEBUG, + "ACS: Calculated ru_punct_bitmap is %X and ru_punct_ofdma is %X", + chan->ru_punct_bitmap,conf->ru_punct_ofdma); + if (!is_ru_punct_bitmap_valid(bw, (chan->freq - first_chan->freq) / 20, chan->ru_punct_bitmap, @@ -919,6 +944,11 @@ acs_find_ideal_chan_mode(struct hostapd_ factor = chan->interference_factor; total_weight = 1; + /* 5GHz is supported for 240Mhz and so reducing number of channels*/ + if(!is_6ghz_op_class(iface->conf->op_class) && + hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_320MHZ) + n_chans = n_chans - 4; + for (j = 1; j < n_chans; j++) { adj_chan = acs_find_chan(iface, chan->freq + (j * 20)); if (!adj_chan) @@ -1018,7 +1048,7 @@ acs_find_ideal_chan_mode(struct hostapd_ *ideal_factor = factor; *ideal_chan = chan; - if (iface->conf->ieee80211ax) + if (iface->conf->ieee80211ax || iface->conf->ieee80211be) acs_update_puncturing_bitmap(iface, mode, bw, n_chans, chan, factor, 0); @@ -1075,7 +1105,9 @@ acs_find_ideal_chan(struct hostapd_iface case CHANWIDTH_160MHZ: n_chans = 8; break; - /* 320 is supported only in 6GHz 11be mode */ + case CHANWIDTH_320MHZ: + n_chans = 16; + break; } } Index: b/src/ap/dfs.c =================================================================== --- a/src/ap/dfs.c 2022-09-19 10:33:57.084303028 +0530 +++ b/src/ap/dfs.c 2022-09-19 10:42:06.192255486 +0530 @@ -20,7 +20,6 @@ #include "beacon.h" #include "eloop.h" - static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) { int n_chans = 1; @@ -30,7 +29,8 @@ static int dfs_get_used_n_chans(struct h if (iface->conf->ieee80211n && iface->conf->secondary_channel) n_chans = 2; - if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) { + if (iface->conf->ieee80211ac || iface->conf->ieee80211ax || + iface->conf->ieee80211be) { switch (hostapd_get_oper_chwidth(iface->conf)) { case CHANWIDTH_USE_HT: break; @@ -44,6 +44,9 @@ static int dfs_get_used_n_chans(struct h n_chans = 4; *seg1 = 4; break; + case CHANWIDTH_320MHZ: + n_chans = 12; + break; default: break; } @@ -94,6 +97,12 @@ static int dfs_is_chan_allowed(struct ho * 50, 114, 163 */ int allowed_160[] = { 36, 100, 149 }; + /* + * EHT320 valid channels based on center frequency: + * 100 + */ + int allowed_320[] = {100}; + int *allowed = allowed_40; unsigned int i, allowed_no = 0; @@ -110,6 +119,10 @@ static int dfs_is_chan_allowed(struct ho allowed = allowed_160; allowed_no = ARRAY_SIZE(allowed_160); break; + case 16: + allowed = allowed_320; + allowed_no = ARRAY_SIZE(allowed_320); + break; default: wpa_printf(MSG_DEBUG, "Unknown width for %d channels", n_chans); break; @@ -337,7 +350,8 @@ static void dfs_adjust_center_freq(struc u8 *oper_centr_freq_seg0_idx, u8 *oper_centr_freq_seg1_idx) { - if (!iface->conf->ieee80211ac && !iface->conf->ieee80211ax) + if (!iface->conf->ieee80211ac && !iface->conf->ieee80211ax && + !iface->conf->ieee80211be) return; if (!chan) @@ -364,6 +378,9 @@ static void dfs_adjust_center_freq(struc *oper_centr_freq_seg0_idx = chan->chan + 6; *oper_centr_freq_seg1_idx = sec_chan_idx_80p80 + 6; break; + case CHANWIDTH_320MHZ: + *oper_centr_freq_seg0_idx = chan->chan + 30; + break; default: wpa_printf(MSG_INFO, @@ -711,7 +728,7 @@ static int set_dfs_state(struct hostapd_ frequency = cf1 - 70; break; case CHAN_WIDTH_320: - n_chans = 16; + n_chans = 12; frequency = cf1 - 150; break; default: @@ -775,6 +792,10 @@ static int dfs_are_channels_overlapped(s radar_n_chans = 8; frequency = cf1 - 70; break; + case CHAN_WIDTH_320: + radar_n_chans = 12; + frequency = cf1 - 150; + break; default: wpa_printf(MSG_INFO, "DFS chan_width %d not supported", chan_width); @@ -1021,6 +1042,7 @@ dfs_downgrade_bandwidth(struct hostapd_i u8 *oper_centr_freq_seg1_idx, int *skip_radar) { struct hostapd_channel_data *channel; + int oper_chwidth; for (;;) { channel = dfs_get_valid_channel(iface, secondary_channel, @@ -1036,7 +1058,6 @@ dfs_downgrade_bandwidth(struct hostapd_i if (*skip_radar) { *skip_radar = 0; } else { - int oper_chwidth; oper_chwidth = hostapd_get_oper_chwidth(iface->conf); if (oper_chwidth == CHANWIDTH_USE_HT) { @@ -1047,9 +1068,13 @@ dfs_downgrade_bandwidth(struct hostapd_i iface->conf->secondary_channel = 0; *skip_radar = 1; continue; + } else if (oper_chwidth == CHANWIDTH_320MHZ) { + oper_chwidth = oper_chwidth - 7; + } else { + oper_chwidth = oper_chwidth - 1; } *skip_radar = 1; - hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1); + hostapd_set_oper_chwidth(iface->conf, oper_chwidth); } } Index: b/src/common/hw_features_common.c =================================================================== --- a/src/common/hw_features_common.c 2022-09-19 10:33:57.084303028 +0530 +++ b/src/common/hw_features_common.c 2022-09-19 10:33:57.080303063 +0530 @@ -794,6 +794,7 @@ u32 num_chan_to_bw(int num_chans) case 2: case 4: case 8: + case 16: return num_chans * 20; default: return 20;