Add user configuration for options for configuring an S1G AP. Users will achieve this using a combination of the channel, s1g_op_class, and global op_class. S1G channels numbers are indexed within a regulatory domain. This diverges from traditional 802.11 channelling. S1G channels numbers are derived as a index from the regulatory domains start frequency instead of being allocated an absolute frequency. This means a channel number to frequency mapping will vary in different regulatory domains. Helper functions have been added to support this configuration. Signed-off-by: Bassem Dawood <bassem@xxxxxxxxxxxxxx> --- hostapd/Android.mk | 4 + hostapd/config_file.c | 12 ++ hostapd/defconfig | 3 + hostapd/hostapd.conf | 51 +++++++- src/ap/Makefile | 1 + src/ap/ap_config.h | 13 ++ src/ap/hostapd.c | 7 + src/ap/ieee802_11.h | 2 + src/ap/ieee802_11_s1g.c | 269 ++++++++++++++++++++++++++++++++++++++ wpa_supplicant/Android.mk | 3 + wpa_supplicant/Makefile | 6 + wpa_supplicant/defconfig | 3 + 12 files changed, 370 insertions(+), 4 deletions(-) create mode 100644 src/ap/ieee802_11_s1g.c diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 3a243d13b..48e96fff1 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -1053,6 +1053,10 @@ ifdef CONFIG_IEEE80211AX OBJS += src/ap/ieee802_11_he.c endif +ifdef CONFIG_IEEE80211AH +OBJS += ../src/ap/ieee802_11_ah.c +endif + ifdef CONFIG_P2P_MANAGER L_CFLAGS += -DCONFIG_P2P_MANAGER OBJS += src/ap/p2p_hostapd.c diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 4f3050841..6be294ed3 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3654,6 +3654,18 @@ static int hostapd_config_fill(struct hostapd_config *conf, } conf->mbssid = mbssid; #endif /* CONFIG_IEEE80211AX */ +#ifdef CONFIG_IEEE80211AH + } else if (os_strcmp(buf, "ieee80211ah") == 0) { + conf->ieee80211ah = atoi(pos); + } else if (os_strcmp(buf, "s1g_start_freq") == 0) { + conf->s1g_start_freq = atoi(pos); + } else if (os_strcmp(buf, "s1g_oper_chwidth") == 0) { + conf->s1g_oper_chwidth = atoi(pos); + } else if (os_strcmp(buf, "s1g_op_class") == 0) { + conf->s1g_op_class = atoi(pos); + } else if (os_strcmp(buf, "s1g_basic_mcs_nss_set") == 0) { + conf->s1g_basic_mcs_nss_set = atoi(pos); +#endif /* CONFIG_IEEE80211AH */ } else if (os_strcmp(buf, "max_listen_interval") == 0) { bss->max_listen_interval = atoi(pos); } else if (os_strcmp(buf, "disable_pmksa_caching") == 0) { diff --git a/hostapd/defconfig b/hostapd/defconfig index a9eab4d9c..3ad6e6ac7 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -155,6 +155,9 @@ CONFIG_IPV6=y # IEEE 802.11ac (Very High Throughput) support #CONFIG_IEEE80211AC=y +# IEEE 802.11ah (S1G) support +#CONFIG_IEEE80211AH=y + # IEEE 802.11ax HE support #CONFIG_IEEE80211AX=y diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index f02cd9274..d2ab4ffa6 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -147,10 +147,10 @@ ssid=test # g = IEEE 802.11g (2.4 GHz), ad = IEEE 802.11ad (60 GHz); a/g options are used # with IEEE 802.11n (HT), too, to specify band). For IEEE 802.11ac (VHT), this # needs to be set to hw_mode=a. For IEEE 802.11ax (HE) on 6 GHz this needs -# to be set to hw_mode=a. When using ACS (see channel parameter), a -# special value "any" can be used to indicate that any support band can be used. -# This special case is currently supported only with drivers with which -# offloaded ACS is used. +# to be set to hw_mode=a. For IEEE 802.11ah (S1G) this needs to be set to +# hw_mode=a. When using ACS (see channel parameter), a special value "any" can +# be used to indicate that any support band can be used. This special case is +#currently supported only with drivers with which offloaded ACS is used. # Default: IEEE 802.11b hw_mode=g @@ -1053,6 +1053,49 @@ wmm_ac_vo_acm=0 # as the AP MLD MAC address. If not set, the current interface hardware address # will be used as the AP MLD MAC address. #mld_addr=02:03:04:05:06:07 +# +##### IEEE 802.11ah related configuration ################################ + +# IEEE 802.11ah (S1G) supported. +# 0 = disabled (default) +# 1 = enabled +#ieee80211ah=1 + +# S1G operating class (IEEE 802.11, Annex E, Table E-5) +# This option allows hostapd to specify the S1G operating class of the channel +# configured with the channel parameter. channel and s1g_op_class together can +# uniquely identify channels in the S1G band. +#s1g_op_class=5 + +# Sub-1 GHz start frequency in kHz. The starting frequency varies per regulatory +# domain. This value, used with the channel value can specify the operating +# frequency. This is calculated as: +# S1G center frequency(MHz) = s1g_start_freq + (500 * channel) +#s1g_start_freq=902000 + +# Sub-1 GHz operating channel bandwidth. +# 0 = 1 MHz +# 1 = 2 MHz +# 2 = 4 MHz +# 3 = 8 MHz +# 4 = 16 MHz +#s1g_oper_chwidth=2 + +#S1G Basic NSS/MCS set +# 16-bits consisting of 8-bits for Max S1G_MCS and 8-bits for Min S1G_MCS. +# Max S1G_MCS: 2-bit values for 1..4 SS; each 2-bit +# value having the following meaning: +# 0 = S1G-MCS 2 for n SS +# 1 = S1G-MCS 7 for n SS +# 2 = S1G-MCS 9 for n SS +# 3 = n SS is not supported +# Min S1G_MCS: 2-bit values for 1..4 SS; each 2-bit +# value having the following meaning: +# 0 = no minimum MCS restriction for n SS +# 1 = S1G-MCS 0 for n SS is not recommended +# 2 = S1G-MCS 0 and 1 for n SS is no recommended +# 3 = Reserved +#s1g_basic_mcs_nss_set=14 ##### IEEE 802.1X-2004 related configuration ################################## diff --git a/src/ap/Makefile b/src/ap/Makefile index a1e9b7c44..d0b476469 100644 --- a/src/ap/Makefile +++ b/src/ap/Makefile @@ -34,6 +34,7 @@ LIB_OBJS= \ ieee802_11.o \ ieee802_11_ht.o \ ieee802_11_shared.o \ + ieee802_11_s1g.o \ ieee802_11_vht.o \ ieee802_1x.o \ neighbor_db.o \ diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 5699a6be1..2901d2b86 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -1140,6 +1140,15 @@ struct hostapd_config { bool require_he; #endif /* CONFIG_IEEE80211AX */ + int ieee80211ah; +#ifdef CONFIG_IEEE80211AH + u32 s1g_start_freq; + u8 s1g_op_class; + u8 s1g_oper_centr_freq_idx; + u8 s1g_oper_chwidth; + u16 s1g_basic_mcs_nss_set; +#endif /* CONFIG_IEEE80211AH */ + /* VHT enable/disable config from CHAN_SWITCH */ #define CH_SWITCH_VHT_ENABLED BIT(0) #define CH_SWITCH_VHT_DISABLED BIT(1) @@ -1199,6 +1208,10 @@ hostapd_get_oper_chwidth(struct hostapd_config *conf) if (conf->ieee80211ax) return conf->he_oper_chwidth; #endif /* CONFIG_IEEE80211AX */ +#ifdef CONFIG_IEEE80211AH + if (conf->ieee80211ah) + return (1 << conf->s1g_oper_chwidth); +#endif return conf->vht_oper_chwidth; } diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 966030d57..f949a431f 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -1944,6 +1944,13 @@ static int setup_interface2(struct hostapd_iface *iface) * feature data. */ } else { int ret; +#ifdef CONFIG_IEEE80211AH + if (iface->bss[0]->iconf->ieee80211ah) { + ret = hostapd_s1g_get_oper_config(iface); + if (ret < 0) + goto fail; + } +#endif /* CONFIG_IEEE80211AH */ if (iface->conf->acs) { iface->freq = 0; diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 4e7d8fbe8..c23ffe365 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -137,6 +137,8 @@ int hostapd_update_time_adv(struct hostapd_data *hapd); void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr); u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid); +u32 hostapd_s1g_get_oper_config(struct hostapd_iface *iface); + int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta); #ifdef CONFIG_SAE void sae_clear_retransmit_timer(struct hostapd_data *hapd, diff --git a/src/ap/ieee802_11_s1g.c b/src/ap/ieee802_11_s1g.c new file mode 100644 index 000000000..34078a7f5 --- /dev/null +++ b/src/ap/ieee802_11_s1g.c @@ -0,0 +1,269 @@ +/* + * hostapd / IEEE 802.11ah S1G + * Copyright (c) 2022, Morse Micro + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "hostapd.h" +#include "ap_config.h" +#include "sta_info.h" +#include "beacon.h" +#include "ieee802_11.h" + + +static u8 hostapd_s1g_get_oper_class_s1g(u16 s1g_op, + struct hostapd_iface *iface) { + u8 bw; + unsigned start_freq; + + /* S1G op class conversions to channel start frequency (kHz) and + * channel bw (MHz) retrieved from IEEE Std 802.11-2020: Table E-5 */ + switch (s1g_op) { + case 1: + bw = 0; + start_freq = 902000; + break; + case 2: + bw = 1; + start_freq = 902000; + break; + case 3: + bw = 2; + start_freq = 902000; + break; + case 4: + bw = 3; + start_freq = 902000; + break; + case 5: + bw = 4; + start_freq = 902000; + break; + case 6: + bw = 0; + start_freq = 863000; + break; + case 8: + bw = 0; + start_freq = 916500; + break; + case 14: + bw = 0; + start_freq = 917500; + break; + case 15: + bw = 1; + start_freq = 917500; + break; + case 16: + bw = 2; + start_freq = 917500; + break; + case 17: + bw = 0; + start_freq = 863000; + break; + case 18: + bw = 0; + start_freq = 902000; + break; + case 19: + bw = 1; + start_freq = 863000; + break; + case 20: + bw = 1; + start_freq = 902000; + break; + case 21: + bw = 2; + start_freq = 902000; + break; + case 22: + bw = 0; + start_freq = 902000; + break; + case 23: + bw = 1; + start_freq = 902000; + break; + case 24: + bw = 2; + start_freq = 902000; + break; + case 25: + bw = 3; + start_freq = 902000; + break; + case 26: + bw = 0; + start_freq = 902000; + break; + case 27: + bw = 1; + start_freq = 902000; + break; + case 28: + bw = 2; + start_freq = 902000; + break; + case 29: + bw = 3; + start_freq = 902000; + break; + case 30: + bw = 0; + start_freq = 901400; + break; + default: + return -1; + } + + iface->conf->s1g_oper_chwidth = bw; + iface->conf->s1g_op_class = s1g_op; + /* + * From IEEE Std 802.11-2020: 23.3.14 - Channelization. + * ChannelCenterFrequency = ChannelStartingFrequency + separation * + * ChannelCenterFrequencyIndex + */ + iface->freq_khz = start_freq + 500 * iface->conf->channel; + return 0; +} + + +static u8 hostapd_s1g_get_oper_global(u16 glob_op, + char *cc, + struct hostapd_iface *iface) { + /* Mappings of global operating class to S1G operating class + * retrieved from IEEE Std 802.11-2020: Table E-5 */ + switch(glob_op) { + case 66: + if (!strncmp(cc, "EU", 2)) { + return hostapd_s1g_get_oper_class_s1g(6, iface); + } else if (!strncmp(cc, "SG", 2)) { + return hostapd_s1g_get_oper_class_s1g(17, iface); + } else { + return -1; + } + case 67: + if (!strncmp(cc, "SG", 2)) { + return hostapd_s1g_get_oper_class_s1g(19, iface); + } else { + return -1; + } + case 68: + if (!strncmp(cc, "US", 2)) { + return hostapd_s1g_get_oper_class_s1g(1, iface); + } else if (!strncmp(cc, "SG", 2)) { + return hostapd_s1g_get_oper_class_s1g(18, iface); + } else if (!strncmp(cc, "AU", 2)) { + return hostapd_s1g_get_oper_class_s1g(22, iface); + } else if (!strncmp(cc, "NZ", 2)) { + return hostapd_s1g_get_oper_class_s1g(26, iface); + } else { + return -1; + } + case 69: + if (!strncmp(cc, "US", 2)) { + return hostapd_s1g_get_oper_class_s1g(2, iface); + } else if (!strncmp(cc, "SG", 2)) { + return hostapd_s1g_get_oper_class_s1g(20, iface); + } else if (!strncmp(cc, "AU", 2)) { + return hostapd_s1g_get_oper_class_s1g(23, iface); + } else if (!strncmp(cc, "NZ", 2)) { + return hostapd_s1g_get_oper_class_s1g(27, iface); + } else { + return -1; + } + case 70: + if (!strncmp(cc, "US", 2)) { + return hostapd_s1g_get_oper_class_s1g(3, iface); + } else if (!strncmp(cc, "SG", 2)) { + return hostapd_s1g_get_oper_class_s1g(21, iface); + } else if (!strncmp(cc, "AU", 2)) { + return hostapd_s1g_get_oper_class_s1g(24, iface); + } else if (!strncmp(cc, "NZ", 2)) { + return hostapd_s1g_get_oper_class_s1g(28, iface); + } else { + return -1; + } + case 71: + if (!strncmp(cc, "US", 2)) { + return hostapd_s1g_get_oper_class_s1g(4, iface); + } else if (!strncmp(cc, "AU", 2)) { + return hostapd_s1g_get_oper_class_s1g(25, iface); + } else if (!strncmp(cc, "NZ", 2)) { + return hostapd_s1g_get_oper_class_s1g(29, iface); + } else { + return -1; + } + case 72: + if (!strncmp(cc, "US", 2)) { + return hostapd_s1g_get_oper_class_s1g(5, iface); + } else { + return -1; + } + case 73: + if (!strncmp(cc, "JP", 2)) { + return hostapd_s1g_get_oper_class_s1g(8, iface); + } else { + return -1; + } + case 74: + if (!strncmp(cc, "KR", 2)) { + return hostapd_s1g_get_oper_class_s1g(14, iface); + } else { + return -1; + } + case 75: + if (!strncmp(cc, "KR", 2)) { + return hostapd_s1g_get_oper_class_s1g(15, iface); + } else { + return -1; + } + case 76: + if (!strncmp(cc, "KR", 2)) { + return hostapd_s1g_get_oper_class_s1g(16, iface); + } else { + return -1; + } + case 77: + if (!strncmp(cc, "EU", 2)) { + return hostapd_s1g_get_oper_class_s1g(30, iface); + } else { + return -1; + } + } + return 0; +} + + +u32 hostapd_s1g_get_oper_config(struct hostapd_iface *iface) { + int ret; + + /* If channel is 0 we will do ACS */ + if (iface->conf->channel == 0) + return 0; + + if (iface->conf->s1g_op_class) { + ret = hostapd_s1g_get_oper_class_s1g(iface->conf->s1g_op_class, + iface); + if (ret < 0) + return -1; + } else if (iface->conf->op_class && iface->conf->country) { + ret = hostapd_s1g_get_oper_global(iface->conf->op_class, + iface->conf->country, + iface); + if (ret < 0) + return -1; + } else { + return -1; + } + return 0; +} diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index 5b0ca2e3b..a77fa6a24 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -917,6 +917,9 @@ endif ifdef CONFIG_IEEE80211BE OBJS += src/ap/ieee802_11_eht.c endif +ifdef CONFIG_IEEE80211AH +OBJS += ../src/ap/ieee802_11_ah.c +endif ifdef CONFIG_WNM_AP L_CFLAGS += -DCONFIG_WNM_AP OBJS += src/ap/wnm_ap.c diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 57620fe79..1f5558138 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -962,6 +962,9 @@ endif ifdef CONFIG_IEEE80211BE OBJS += ../src/ap/ieee802_11_eht.o endif +ifdef CONFIG_IEEE80211AH +OBJS += ../src/ap/ieee802_11_s1g.o +endif ifdef CONFIG_WNM_AP CFLAGS += -DCONFIG_WNM_AP OBJS += ../src/ap/wnm_ap.o @@ -991,6 +994,9 @@ endif ifdef CONFIG_IEEE80211AX CFLAGS += -DCONFIG_IEEE80211AX endif +ifdef CONFIG_IEEE80211AH +CFLAGS += -DCONFIG_IEEE80211AH +endif ifdef NEED_AP_MLME OBJS += ../src/ap/wmm.o diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index a4f20d439..7a0ddb9fe 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -483,6 +483,9 @@ CONFIG_DEBUG_SYSLOG=y # IEEE 802.11ac (Very High Throughput) support (mainly for AP mode) CONFIG_IEEE80211AC=y +# IEEE 802.11ah (S1G) support (mainly for AP mode) +#CONFIG_IEEE80211AH=y + # IEEE 802.11ax HE support (mainly for AP mode) CONFIG_IEEE80211AX=y -- 2.25.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap