[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