From 387b308a6af81ada3643cc1c1658a7756f359b5a Mon Sep 17 00:00:00 2001 From: Karthikeyan Periyasamy Date: Tue, 21 Sep 2021 17:20:23 +0530 Subject: [PATCH] hostapd: Add 320 MHz support Added 320 MHz channel support in 6GHz band (EHT) as define by IEEE P802.11be/D1.1, July 2021 section 36.3.23.2. It covers channel bringup, frequency validation, channel switch and also across all channel width and frequency manipulation. Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Ramya Gnanasekar --- hostapd/ctrl_iface.c | 31 +++++++++++++++++++++++++++++++ src/ap/drv_callbacks.c | 6 ++++++ src/ap/hostapd.c | 9 +++++++++ src/ap/ieee802_11.c | 4 ++++ src/ap/ieee802_11_eht.c | 4 +++- src/ap/neighbor_db.c | 9 ++++++--- src/common/defs.h | 1 + src/common/hw_features_common.c | 3 +++ src/common/ieee802_11_common.c | 6 ++++++ src/common/ieee802_11_defs.h | 6 ++++++ src/drivers/driver.h | 1 + src/drivers/driver_common.c | 4 ++++ src/drivers/driver_nl80211.c | 5 +++++ src/drivers/driver_nl80211_capa.c | 3 +++ src/drivers/driver_nl80211_event.c | 6 ++++++ src/drivers/nl80211_copy.h | 2 ++ wpa_supplicant/ctrl_iface.c | 2 ++ 17 files changed, 98 insertions(+), 4 deletions(-) Index: b/hostapd/ctrl_iface.c =================================================================== --- a/hostapd/ctrl_iface.c 2022-08-30 18:41:54.749138965 +0530 +++ b/hostapd/ctrl_iface.c 2022-08-30 18:41:54.717139244 +0530 @@ -2637,7 +2637,7 @@ static int hostapd_ctrl_register_frame(s #ifdef NEED_AP_MLME static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) { - int idx, bw, bw_idx[] = { 20, 40, 80, 160 }; + int idx, bw, bw_idx[] = { 20, 40, 80, 160, 320 }; u32 start_freq; if (is_6ghz_freq(params->freq)) { @@ -2749,6 +2749,34 @@ static int hostapd_ctrl_check_freq_param return -1; } break; + case 320: + if (!params->center_freq1 || params->center_freq2 || + !params->sec_channel_offset) + return -1; + + switch (params->sec_channel_offset) { + case 1: + if (params->freq + 150 != params->center_freq1 && + params->freq + 70 != params->center_freq1 && + params->freq + 30 != params->center_freq1 && + params->freq - 10 != params->center_freq1 && + params->freq - 50 != params->center_freq1 && + params->freq - 130 != params->center_freq1) + return -1; + break; + case -1: + if (params->freq + 130 != params->center_freq1 && + params->freq + 50 != params->center_freq1 && + params->freq + 10 != params->center_freq1 && + params->freq - 30 != params->center_freq1 && + params->freq - 70 != params->center_freq1 && + params->freq - 150 != params->center_freq1) + return -1; + break; + default: + return -1; + } + break; default: return -1; } @@ -2872,6 +2900,9 @@ static int hostapd_ctrl_iface_chan_switc case 160: bandwidth = CHAN_WIDTH_160; break; + case 320: + bandwidth = CHAN_WIDTH_320; + break; default: bandwidth = CHAN_WIDTH_20; break; Index: b/src/ap/drv_callbacks.c =================================================================== --- a/src/ap/drv_callbacks.c 2022-08-30 18:41:54.749138965 +0530 +++ b/src/ap/drv_callbacks.c 2022-08-30 18:41:54.721139209 +0530 @@ -854,6 +854,9 @@ void hostapd_event_sta_opmode_changed(st case CHAN_WIDTH_160: txt = "160"; break; + case CHAN_WIDTH_320: + txt = "320"; + break; default: txt = NULL; break; @@ -917,6 +920,9 @@ void hostapd_event_ch_switch(struct host case CHAN_WIDTH_160: chwidth = CHANWIDTH_160MHZ; break; + case CHAN_WIDTH_320: + chwidth = CHANWIDTH_320MHZ; + break; case CHAN_WIDTH_20_NOHT: case CHAN_WIDTH_20: case CHAN_WIDTH_40: @@ -977,7 +983,8 @@ void hostapd_event_ch_switch(struct host hapd->iconf->ch_switch_eht_config = 0; if (width == CHAN_WIDTH_40 || width == CHAN_WIDTH_80 || - width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160) + width == CHAN_WIDTH_80P80 || width == CHAN_WIDTH_160 || + width == CHAN_WIDTH_320) hapd->iconf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; else if (width == CHAN_WIDTH_20 || width == CHAN_WIDTH_20_NOHT) hapd->iconf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; Index: b/src/ap/hostapd.c =================================================================== --- a/src/ap/hostapd.c 2022-08-30 18:41:54.749138965 +0530 +++ b/src/ap/hostapd.c 2022-08-30 18:41:54.725139174 +0530 @@ -3548,6 +3548,7 @@ static int hostapd_change_config_freq(st case 40: case 80: case 160: + case 320: conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; break; default: @@ -3569,6 +3570,9 @@ static int hostapd_change_config_freq(st case 160: hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ); break; + case 320: + hostapd_set_oper_chwidth(conf, CHANWIDTH_320MHZ); + break; default: return -1; } @@ -3617,6 +3621,9 @@ static int hostapd_fill_csa_settings(str case 160: bandwidth = CHANWIDTH_160MHZ; break; + case 320: + bandwidth = CHANWIDTH_320MHZ; + break; default: bandwidth = CHANWIDTH_USE_HT; break; @@ -3776,6 +3783,9 @@ hostapd_switch_channel_fallback(struct h case 160: bw = CHANWIDTH_160MHZ; break; + case 320: + bw = CHANWIDTH_320MHZ; + break; default: wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d", freq_params->bandwidth); Index: b/src/ap/ieee802_11_eht.c =================================================================== --- a/src/ap/ieee802_11_eht.c 2022-08-30 18:41:54.749138965 +0530 +++ b/src/ap/ieee802_11_eht.c 2022-08-30 18:41:54.725139174 +0530 @@ -301,7 +301,9 @@ static int check_valid_eht_mcs(struct ho u8 mcs_count = 1; switch (hapd->iface->conf->eht_oper_chwidth) { - /* TODO CHANWIDTH_320MHZ */ + case CHANWIDTH_320MHZ: + mcs_count = 3; + break; case CHANWIDTH_80P80MHZ: case CHANWIDTH_160MHZ: mcs_count = 2; Index: b/src/common/defs.h =================================================================== --- a/src/common/defs.h 2022-08-30 18:41:54.749138965 +0530 +++ b/src/common/defs.h 2022-08-30 18:41:54.725139174 +0530 @@ -430,6 +430,7 @@ enum chan_width { CHAN_WIDTH_4320, CHAN_WIDTH_6480, CHAN_WIDTH_8640, + CHAN_WIDTH_320, CHAN_WIDTH_UNKNOWN }; Index: b/src/common/hw_features_common.c =================================================================== --- a/src/common/hw_features_common.c 2022-08-30 18:41:54.749138965 +0530 +++ b/src/common/hw_features_common.c 2022-08-30 18:41:54.729139140 +0530 @@ -413,6 +413,8 @@ int hostapd_set_freq_params(struct hosta else if (oper_chwidth == CHANWIDTH_160MHZ || oper_chwidth == CHANWIDTH_80P80MHZ) data->bandwidth = 160; + else if (oper_chwidth == CHANWIDTH_320MHZ) + data->bandwidth = 320; else if (sec_channel_offset) data->bandwidth = 40; else @@ -809,6 +811,9 @@ int chan_bw_allowed(const struct hostapd case 160: bw_mask = HOSTAPD_CHAN_WIDTH_160; break; + case 320: + bw_mask = HOSTAPD_CHAN_WIDTH_320; + break; default: bw_mask = 0; break; Index: b/src/common/ieee802_11_common.c =================================================================== --- a/src/common/ieee802_11_common.c 2022-08-30 18:41:54.749138965 +0530 +++ b/src/common/ieee802_11_common.c 2022-08-30 18:41:54.729139140 +0530 @@ -1164,6 +1164,9 @@ int ieee80211_chaninfo_to_channel(unsign case CHAN_WIDTH_8640: cw = CHANWIDTH_8640MHZ; break; + case CHAN_WIDTH_320: + cw = CHANWIDTH_320MHZ; + break; } if (ieee80211_freq_to_channel_ext(freq, sec_channel, cw, op_class, @@ -2273,6 +2276,9 @@ int center_idx_to_bw_6ghz(u8 idx) /* channels 15, 47, 79...*/ if ((idx & 0x1f) == 0xf) return 3; /* 160 MHz */ + /* channels 31, 63, 95, 127, 159, 191. */ + if ((idx & 0x1f) == 0x1f) + return 4; /* 320 MHz */ return -1; } Index: b/src/common/ieee802_11_defs.h =================================================================== --- a/src/common/ieee802_11_defs.h 2022-08-30 18:41:54.749138965 +0530 +++ b/src/common/ieee802_11_defs.h 2022-08-30 18:41:54.729139140 +0530 @@ -2241,6 +2241,7 @@ enum phy_type { /* * IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information * subfields. + * IEEE P802.11be/D1.1 Table 9-322al - EHT Operation Information subfields. * Note: These definitions are not the same as other CHANWIDTH_*. */ enum nr_chan_width { Index: b/src/drivers/driver.h =================================================================== --- a/src/drivers/driver.h 2022-08-30 18:41:54.749138965 +0530 +++ b/src/drivers/driver.h 2022-08-30 18:41:54.729139140 +0530 @@ -67,6 +67,7 @@ enum hostapd_chan_width_attr { HOSTAPD_CHAN_WIDTH_40M = BIT(3), HOSTAPD_CHAN_WIDTH_80 = BIT(4), HOSTAPD_CHAN_WIDTH_160 = BIT(5), + HOSTAPD_CHAN_WIDTH_320 = BIT(6), }; /* Filter gratuitous ARP */ Index: b/src/drivers/driver_common.c =================================================================== --- a/src/drivers/driver_common.c 2022-08-30 18:41:54.749138965 +0530 +++ b/src/drivers/driver_common.c 2022-08-30 18:41:54.733139105 +0530 @@ -118,6 +118,8 @@ const char * channel_width_to_string(enu return "80+80 MHz"; case CHAN_WIDTH_160: return "160 MHz"; + case CHAN_WIDTH_320: + return "320 MHz"; default: return "unknown"; } @@ -137,6 +139,8 @@ int channel_width_to_int(enum chan_width case CHAN_WIDTH_80P80: case CHAN_WIDTH_160: return 160; + case CHAN_WIDTH_320: + return 320; default: return 0; } Index: b/src/drivers/driver_nl80211.c =================================================================== --- a/src/drivers/driver_nl80211.c 2022-08-30 18:41:54.749138965 +0530 +++ b/src/drivers/driver_nl80211.c 2022-08-30 18:41:54.737139070 +0530 @@ -215,6 +215,8 @@ enum chan_width convert2width(int width) return CHAN_WIDTH_80P80; case NL80211_CHAN_WIDTH_160: return CHAN_WIDTH_160; + case NL80211_CHAN_WIDTH_320: + return CHAN_WIDTH_320; } return CHAN_WIDTH_UNKNOWN; } @@ -5020,6 +5022,9 @@ static int nl80211_put_freq_params(struc case 160: cw = NL80211_CHAN_WIDTH_160; break; + case 320: + cw = NL80211_CHAN_WIDTH_320; + break; default: return -EINVAL; } Index: b/src/drivers/driver_nl80211_capa.c =================================================================== --- a/src/drivers/driver_nl80211_capa.c 2022-08-30 18:41:54.749138965 +0530 +++ b/src/drivers/driver_nl80211_capa.c 2022-08-30 18:41:54.737139070 +0530 @@ -1628,6 +1628,9 @@ static void phy_info_freq(struct hostapd chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_80; if (tb_freq[NL80211_FREQUENCY_ATTR_NO_160MHZ]) chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_160; + if (tb_freq[NL80211_FREQUENCY_ATTR_NO_320MHZ]) + chan->allowed_bw &= ~HOSTAPD_CHAN_WIDTH_320; + if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) { enum nl80211_dfs_state state = Index: b/src/drivers/driver_nl80211_event.c =================================================================== --- a/src/drivers/driver_nl80211_event.c 2022-08-30 18:41:54.749138965 +0530 +++ b/src/drivers/driver_nl80211_event.c 2022-08-30 18:41:54.741139036 +0530 @@ -675,6 +675,9 @@ static int calculate_chan_offset(int wid case CHAN_WIDTH_80P80: freq1 = cf1 - 30; break; + case CHAN_WIDTH_320: + freq1 = cf1 - 150; + break; case CHAN_WIDTH_UNKNOWN: case CHAN_WIDTH_2160: case CHAN_WIDTH_4320: @@ -2825,6 +2828,9 @@ static void nl80211_sta_opmode_change_ev case NL80211_CHAN_WIDTH_160: ed.sta_opmode.chan_width = CHAN_WIDTH_160; break; + case NL80211_CHAN_WIDTH_320: + ed.sta_opmode.chan_width = CHAN_WIDTH_320; + break; default: ed.sta_opmode.chan_width = CHAN_WIDTH_UNKNOWN; break; Index: b/src/drivers/nl80211_copy.h =================================================================== --- a/src/drivers/nl80211_copy.h 2022-08-30 18:41:54.749138965 +0530 +++ b/src/drivers/nl80211_copy.h 2022-08-30 18:42:13.980971726 +0530 @@ -3947,6 +3947,9 @@ enum nl80211_frequency_attr { NL80211_FREQUENCY_ATTR_4MHZ, NL80211_FREQUENCY_ATTR_8MHZ, NL80211_FREQUENCY_ATTR_16MHZ, + NL80211_FREQUENCY_ATTR_PSD, + NL80211_FREQUENCY_ATTR_NO_320MHZ, + NL80211_FREQUENCY_ATTR_NO_EHT, /* keep last */ __NL80211_FREQUENCY_ATTR_AFTER_LAST, @@ -4682,6 +4685,7 @@ enum nl80211_chan_width { NL80211_CHAN_WIDTH_4, NL80211_CHAN_WIDTH_8, NL80211_CHAN_WIDTH_16, + NL80211_CHAN_WIDTH_320, /* keep last */ __NL80211_CHAN_WIDTH_NUM, Index: b/wpa_supplicant/ctrl_iface.c =================================================================== --- a/wpa_supplicant/ctrl_iface.c 2022-08-30 18:41:54.749138965 +0530 +++ b/wpa_supplicant/ctrl_iface.c 2022-08-30 18:41:54.745139000 +0530 @@ -5993,6 +5993,8 @@ static int parse_freq(int chwidth, int f return CHANWIDTH_80MHZ; case 160: return CHANWIDTH_160MHZ; + case 320: + return CHANWIDTH_320MHZ; default: wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d", chwidth); Index: b/src/ap/ap_config.h =================================================================== --- a/src/ap/ap_config.h 2022-08-30 18:41:54.749138965 +0530 +++ b/src/ap/ap_config.h 2022-08-30 18:41:54.745139000 +0530 @@ -1186,7 +1186,8 @@ hostapd_set_oper_chwidth(struct hostapd_ conf->eht_oper_chwidth = oper_chwidth; #endif /* CONFIG_IEEE80211BE */ #ifdef CONFIG_IEEE80211AX - if (conf->ieee80211ax) + if (conf->ieee80211ax && + oper_chwidth < CHANWIDTH_320MHZ) conf->he_oper_chwidth = oper_chwidth; #endif /* CONFIG_IEEE80211AX */ conf->vht_oper_chwidth = oper_chwidth; Index: b/src/ap/ieee802_11_he.c =================================================================== --- a/src/ap/ieee802_11_he.c 2022-08-30 18:41:54.749138965 +0530 +++ b/src/ap/ieee802_11_he.c 2022-08-30 18:41:54.749138965 +0530 @@ -219,8 +219,8 @@ u8 * hostapd_eid_he_operation(struct hos pos += 6; /* skip the fixed part */ if (is_6ghz_op_class(hapd->iconf->op_class)) { - u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf); - u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf); + u8 seg0 = hapd->iface->conf->he_oper_centr_freq_seg0_idx; + u8 seg1 = hapd->iface->conf->he_oper_centr_freq_seg1_idx; if (hapd->iconf->ru_punct_bitmap) { hapd->iconf->he_oper_chwidth =