[RFC 6/8] STA: add S1G support
Lachlan Hodges
lachlan.hodges at morsemicro.com
Wed May 27 23:38:55 PDT 2026
Introduce the ability to bring up an S1G STA. A sample config
to connect to the equivalent AP config is as follows:
```
update_config=1
country=US
pmf=2
network={
ssid="wifi_halow"
sae_password="12345678"
key_mgmt=SAE
}
```
Signed-off-by: Lachlan Hodges <lachlan.hodges at morsemicro.com>
---
src/drivers/driver.h | 23 ++++++++++++++++++++++-
wpa_supplicant/Makefile | 6 ++++++
wpa_supplicant/defconfig | 3 +++
wpa_supplicant/events.c | 13 +++++++------
wpa_supplicant/mesh.c | 3 ++-
wpa_supplicant/sme.c | 6 ++++++
wpa_supplicant/wpa_supplicant.c | 19 +++++++++++++++++--
7 files changed, 63 insertions(+), 10 deletions(-)
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index c382bf90ccf6..22fbc1b4327f 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -63,6 +63,9 @@ enum hostapd_chan_width_attr {
HOSTAPD_CHAN_WIDTH_80 = BIT(4),
HOSTAPD_CHAN_WIDTH_160 = BIT(5),
HOSTAPD_CHAN_WIDTH_320 = BIT(6),
+ HOSTAPD_CHAN_WIDTH_4 = BIT(9),
+ HOSTAPD_CHAN_WIDTH_8 = BIT(10),
+ HOSTAPD_CHAN_WIDTH_16 = BIT(11),
};
/* Filter gratuitous ARP */
@@ -332,6 +335,11 @@ struct hostapd_hw_modes {
* eht_capab - EHT (IEEE 802.11be) capabilities
*/
struct eht_capabilities eht_capab[IEEE80211_MODE_NUM];
+
+ /**
+ * s1g_capab - S1G (IEEE 802.11ah) capabilities
+ */
+ struct ieee80211_s1g_capabilities s1g_capab;
};
@@ -888,6 +896,11 @@ struct hostapd_freq_params {
*/
int he_enabled;
+ /**
+ * s1g_enabled - Whether S1G is enabled
+ */
+ int s1g_enabled;
+
/**
* center_freq1 - Segment 0 center frequency in MHz
*
@@ -910,7 +923,7 @@ struct hostapd_freq_params {
int center_freq2;
/**
- * bandwidth - Channel bandwidth in MHz (20, 40, 80, 160)
+ * bandwidth - Channel bandwidth in MHz (1, 2, 4, 8, 16, 20, 40, 80, 160)
*/
int bandwidth;
@@ -942,6 +955,13 @@ struct hostapd_freq_params {
* link_id: If >=0 indicates the link of the AP MLD to configure
*/
int link_id;
+
+ /**
+ * s1g_primary_2mhz: Determines if the S1G channel is operating as a 2MHz primary.
+ *
+ * S1G primary channels can either be 1MHz or 2MHz.
+ */
+ bool s1g_primary_2mhz;
};
/**
@@ -2856,6 +2876,7 @@ struct hostapd_sta_add_params {
const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab;
const struct ieee80211_eht_capabilities *eht_capab;
size_t eht_capab_len;
+ const struct ieee80211_s1g_capabilities *s1g_capab;
u32 flags; /* bitmask of WPA_STA_* flags */
u32 flags_mask; /* unset bits in flags */
#ifdef CONFIG_ENC_ASSOC
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 67f337df33da..23f795ff1c35 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -1063,6 +1063,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
@@ -1092,6 +1095,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 75832dbba91f..2fa0787379fa 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -698,3 +698,6 @@ CONFIG_DPP2=y
# IEEE P802.11bi/D4.0, 12.16.5 (IEEE 802.1X authentication utilizing
# Authentication frames)
#CONFIG_IEEE8021X_AUTH=y
+
+# IEEE 802.11ah (S1G) support
+#CONFIG_IEEE80211AH=y
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index f9c51994cae4..8e4991f8733c 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1455,13 +1455,14 @@ static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
}
#ifdef CONFIG_SAE
- /* When using SAE Password Identifier and when operationg on the 6 GHz
- * band, only H2E is allowed. */
+ /* When using SAE Password Identifier and when operating on 6 GHz or
+ * S1G, only H2E is allowed. */
sae_pwe = wpas_get_ssid_sae_pwe(wpa_s, ssid);
- if ((sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
- wpa_key_mgmt_only_sae_ext_key(ssid->key_mgmt) ||
- is_6ghz_freq(bss->freq) || ssid->sae_password_id) &&
- sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK &&
+ if ((is_s1ghz_freq(bss->freq) ||
+ ((sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
+ wpa_key_mgmt_only_sae_ext_key(ssid->key_mgmt) ||
+ is_6ghz_freq(bss->freq) || ssid->sae_password_id) &&
+ sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)) &&
wpa_key_mgmt_only_sae(ssid->key_mgmt) &&
!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
if (debug_print)
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 30547b19d108..ae7e66962458 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -206,12 +206,13 @@ static int wpas_mesh_update_freq_params(struct wpa_supplicant *wpa_s)
ifmsh->conf->ieee80211ac,
ifmsh->conf->ieee80211ax,
ifmsh->conf->ieee80211be,
+ 0, /* No S1G mesh support */
ifmsh->conf->secondary_channel,
hostapd_get_oper_chwidth(ifmsh->conf),
hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
ifmsh->conf->vht_capab,
- he_capab, NULL, 0)) {
+ he_capab, NULL, 0, 0, false)) {
wpa_printf(MSG_ERROR, "Error updating mesh frequency params");
wpa_supplicant_mesh_deinit(wpa_s, true);
return -1;
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 1dd1f79601b3..204a96bc603c 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -259,6 +259,12 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
if (bss && is_6ghz_freq(bss->freq) &&
sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
use_pt = 1;
+ if (bss && is_s1ghz_freq(bss->freq) &&
+ sae_pwe != SAE_PWE_HASH_TO_ELEMENT) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "SAE: Force H2E mode for S1G BSS");
+ sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
+ }
#ifdef CONFIG_SAE_PK
if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
ssid->sae_pk != SAE_PK_MODE_DISABLED &&
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index be9db6d646fd..932a0e5d3d87 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2212,6 +2212,12 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
"RSN: Enable SAE hash-to-element mode for 6 GHz BSS");
sae_pwe = SAE_PWE_BOTH;
}
+ if (bss && is_s1ghz_freq(bss->freq) &&
+ sae_pwe != SAE_PWE_HASH_TO_ELEMENT) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "RSN: hunt-and-peck not permitted with an S1G BSS");
+ sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
+ }
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe);
#ifdef CONFIG_SAE_PK
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK,
@@ -2229,6 +2235,12 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
MGMT_FRAME_PROTECTION_REQUIRED);
}
+ if (bss && is_s1ghz_freq(bss->freq) &&
+ wpas_get_ssid_pmf(wpa_s, ssid) != MGMT_FRAME_PROTECTION_REQUIRED) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Force MFPR=1 on S1GHz");
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
+ MGMT_FRAME_PROTECTION_REQUIRED);
+ }
#ifdef CONFIG_TESTING_OPTIONS
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED,
wpa_s->ft_rsnxe_used);
@@ -3531,11 +3543,11 @@ skip_80mhz:
freq->channel, ssid->enable_edmg,
ssid->edmg_channel, freq->ht_enabled,
freq->vht_enabled, freq->he_enabled,
- freq->eht_enabled,
+ freq->eht_enabled, 0, /* No S1G mesh */
freq->sec_channel_offset,
chwidth, seg0, seg1, vht_caps,
&mode->he_capab[ieee80211_mode],
- &mode->eht_capab[ieee80211_mode], 0) != 0)
+ &mode->eht_capab[ieee80211_mode], 0, 0, false) != 0)
return false;
*freq = vht_freq;
@@ -5002,6 +5014,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
#ifdef CONFIG_SAE
params.sae_pwe = wpas_get_ssid_sae_pwe(wpa_s, ssid);
+ if (bss && is_s1ghz_freq(bss->freq) &&
+ params.sae_pwe != SAE_PWE_HASH_TO_ELEMENT)
+ params.sae_pwe = SAE_PWE_HASH_TO_ELEMENT;
#endif /* CONFIG_SAE */
ret = wpa_drv_associate(wpa_s, ¶ms);
--
2.43.0
More information about the Hostap
mailing list