From 5205496c33b432d7621ffff86df6540d6854fff2 Mon Sep 17 00:00:00 2001 From: Hari Chandrakanthan Date: Thu, 8 Sep 2022 21:10:01 +0530 Subject: [PATCH] hostapd: Add 5GHz 240MHz support 240MHz is supported in 5GHz for single band from channel 100 - 144 with right hand 80MHz puncturing in 320MHz bandwidth. EHT phy capability for advertising 320MHz support in 6GHz is reused for 5GHz as well if 320MHz is configured. EHT opertional IE is also used to advertise the bandwidth and the center frequency of the AP. Signed-off-by: Karthik M Signed-off-by: Ramya Gnanasekar Signed-off-by: Hari Chandrakanthan --- src/ap/beacon.c | 8 +++++++- src/ap/dfs.c | 19 ++++++++++++++++--- src/ap/hw_features.c | 6 +++++- src/ap/ieee802_11_eht.c | 10 +++++++--- src/common/hw_features_common.c | 16 ++++++++++++++++ src/common/ieee802_11_common.c | 7 +++++++ src/common/ieee802_11_common.h | 1 + src/common/ieee802_11_defs.h | 1 + 8 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 9536e76..e03f343 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -434,18 +434,24 @@ static u8 * hostapd_eid_ecsa(struct hostapd_data *hapd, u8 *eid) static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid) { u8 op_class, channel; + int ch_width; if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || !hapd->iface->freq) return eid; + ch_width = hostapd_get_oper_chwidth(hapd->iconf); if (ieee80211_freq_to_channel_ext(hapd->iface->freq, hapd->iconf->secondary_channel, - hostapd_get_oper_chwidth(hapd->iconf), + ch_width, &op_class, &channel) == NUM_HOSTAPD_MODES) return eid; + /*op_class for 5GHz 320MHz bw is not defined in spec. So use op_class of 160MHz*/ + if (is_5ghz_freq(hapd->iface->freq) && ch_width == CHANWIDTH_320MHZ) + op_class = 129; + *eid++ = WLAN_EID_SUPPORTED_OPERATING_CLASSES; *eid++ = 2; diff --git a/src/ap/dfs.c b/src/ap/dfs.c index f8de1c2..12e47a7 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -411,7 +411,8 @@ static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start) channel_no -= 4; /* VHT/HE */ - 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; @@ -429,6 +430,10 @@ static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start) chan_seg1 = hostapd_get_oper_centr_freq_seg1_idx( iface->conf) - 6; break; + case CHANWIDTH_320MHZ: + channel_no = hostapd_get_oper_centr_freq_seg0_idx( + iface->conf) - 30; + break; default: wpa_printf(MSG_INFO, "DFS only VHT20/40/80/160/80+80 is supported now"); @@ -722,6 +727,10 @@ static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled, n_chans = 8; frequency = cf1 - 70; break; + case CHAN_WIDTH_320: + n_chans = 16; + frequency = cf1 - 150; + break; default: wpa_printf(MSG_INFO, "DFS chan_width %d not supported", chan_width); @@ -921,13 +930,14 @@ int hostapd_handle_dfs(struct hostapd_iface *iface) hostapd_set_state(iface, HAPD_IFACE_DFS); wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq); wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START - "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds", + "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds bitmap:0x%04x", iface->freq, iface->conf->channel, iface->conf->secondary_channel, hostapd_get_oper_chwidth(iface->conf), hostapd_get_oper_centr_freq_seg0_idx(iface->conf), hostapd_get_oper_centr_freq_seg1_idx(iface->conf), - iface->dfs_cac_ms / 1000); + iface->dfs_cac_ms / 1000, + iface->conf->ru_punct_bitmap); res = hostapd_start_dfs_cac( iface, iface->conf->hw_mode, iface->freq, iface->conf->channel, @@ -1552,6 +1562,9 @@ int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width, case CHAN_WIDTH_160: half_width = 80; break; + case CHAN_WIDTH_320: + half_width = 160; + break; default: wpa_printf(MSG_WARNING, "DFS chanwidth %d not supported", width); diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index f66c649..6a7a655 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -929,7 +929,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface) static int hostapd_is_usable_ru_punct_bitmap(struct hostapd_iface *iface) { struct hostapd_config *conf = iface->conf; - u8 bw, start_chan; + int bw, start_chan; if (!conf->ru_punct_bitmap) { conf->ru_punct_ofdma = 0; @@ -971,6 +971,10 @@ static int hostapd_is_usable_ru_punct_bitmap(struct hostapd_iface *iface) bw = 160; start_chan = conf->eht_oper_centr_freq_seg0_idx - 14; break; + case 9: + bw = 320; + start_chan = conf->eht_oper_centr_freq_seg0_idx - 30; + break; default: return 0; } diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c index 8aca0de..f54fee3 100644 --- a/src/ap/ieee802_11_eht.c +++ b/src/ap/ieee802_11_eht.c @@ -74,8 +74,10 @@ static u8 ieee80211_eht_mcs_set_size(const u8 *he_phy_cap, sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS; if (eht_phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] & - EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK) + EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK) { sz += EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS; + sz += EHT_PHYCAP_MCS_NSS_LEN_160MHZ; + } return sz; } @@ -110,7 +112,7 @@ u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid, struct eht_capabilities *eht_cap; struct ieee80211_eht_capabilities *cap; size_t mcs_nss_len, ppe_thresh_len; - u8 *pos = eid, *length_pos; + u8 *pos = eid, *length_pos, chwidth; mode = hapd->iface->current_mode; if (!mode) @@ -128,8 +130,10 @@ u8 * hostapd_eid_eht_capab(struct hostapd_data *hapd, u8 *eid, os_memset(cap, 0, sizeof(*cap)); os_memcpy(cap->mac_cap, eht_cap->mac_cap, EHT_MAC_CAPAB_MAX_LEN); os_memcpy(cap->phy_cap, eht_cap->phy_cap, EHT_PHY_CAPAB_MAX_LEN); + chwidth = hapd->iconf->eht_oper_chwidth; - if (!is_6ghz_op_class(hapd->iconf->op_class)) + if (!is_6ghz_op_class(hapd->iconf->op_class) && + (chwidth != CHANWIDTH_320MHZ)) cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &= ~EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK; if (!hapd->iface->conf->eht_phy_capab.su_beamformer) diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c index 0c7607d..3381d8f 100644 --- a/src/common/hw_features_common.c +++ b/src/common/hw_features_common.c @@ -667,6 +667,22 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, return -1; } break; + case CHANWIDTH_320MHZ: + data->bandwidth = 320; + if (center_segment1) { + wpa_printf(MSG_ERROR, + "320 MHz: center segment 1 should not be set"); + return -1; + } + if (channel >= 100 && channel <= 144) { + center_segment0 = 130; + data->center_freq1 = 5650; + } else { + wpa_printf(MSG_ERROR, + "320 MHz: Configured Channel is not supported"); + return -1; + } + break; } return 0; diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 1e5c641..e68dca6 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -2284,6 +2284,13 @@ int center_idx_to_bw_6ghz(u8 idx) return -1; } +bool is_5ghz_freq(int freq) +{ + if ((freq >= 5180 && freq < 5600) || + (freq >= 5660 && freq < 5825)) + return true; + return false; +} bool is_6ghz_freq(int freq) { diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 48d66d8..e60afb3 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -268,6 +268,7 @@ u8 country_to_global_op_class(const char *country, u8 op_class); const struct oper_class_map * get_oper_class(const char *country, u8 op_class); int oper_class_bw_to_int(const struct oper_class_map *map); +bool is_5ghz_freq(int freq); int center_idx_to_bw_6ghz(u8 idx); bool is_6ghz_freq(int freq); bool is_6ghz_op_class(u8 op_class); diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index dad1435..766ec1d 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2530,6 +2530,7 @@ struct ieee80211_eht_operation { #define EHT_NSS_MAX_STREAMS 8 #define EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY 4 #define EHT_PHYCAP_MCS_NSS_LEN_20MHZ_PLUS 3 +#define EHT_PHYCAP_MCS_NSS_LEN_160MHZ 3 /* IEEE P802.11be/D1.4, May 2021, 9.4.2.295c.5 EHT PPE Thresholds field */ #define EHT_PPE_THRES_NSS_SHIFT 0 -- 2.7.4