[PATCH 1/6] S1G: Add Support for configuring an S1G AP.
Bassem Dawood
bassem at morsemicro.com
Tue Oct 31 22:34:26 PDT 2023
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 at morsemicro.com>
---
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
More information about the Hostap
mailing list