[PATCH 4/6] S1G: Add support for S1G Manangement frames
Bassem Dawood
bassem at morsemicro.com
Tue Oct 31 22:34:29 PDT 2023
S1G beacons use the new extention frame format introduced in the ieee80211
specification to support 802.11ah. The new features included in this
commit are:
- S1G short beacon
- extention frame format
This commit additional adds support for the following new information
elements:
- s1g_capabilities
- s1g_operation
- s1g_short_beacon_interval
- s1g_aid_response
---
hostapd/config_file.c | 9 ++
src/ap/ap_config.h | 1 +
src/ap/beacon.c | 94 +++++++++++++++++++--
src/ap/hw_features.c | 3 +-
src/ap/ieee802_11.c | 25 +++++-
src/ap/ieee802_11.h | 5 ++
src/ap/ieee802_11_s1g.c | 131 ++++++++++++++++++++++++++++++
src/ap/ieee802_11_shared.c | 14 ++++
src/common/ieee802_11_defs.h | 42 ++++++++++
src/drivers/driver.h | 16 +++-
src/drivers/driver_nl80211.c | 2 +
src/drivers/driver_nl80211_capa.c | 20 +++++
src/drivers/nl80211_copy.h | 2 +
13 files changed, 351 insertions(+), 13 deletions(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 6be294ed3..110de53c4 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3216,6 +3216,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
return 1;
}
bss->dtim_period = val;
+ } else if (os_strcmp(buf, "short_beacon_int") == 0) {
+ int val = atoi(pos);
+
+ if (val < 1 || val > 65535) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid short_beacon_int %d",
+ line, val);
+ return 1;
+ }
+ bss->short_beacon_int = val;
} else if (os_strcmp(buf, "bss_load_update_period") == 0) {
int val = atoi(pos);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 2901d2b86..74b3ef1bd 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -294,6 +294,7 @@ struct hostapd_bss_config {
int max_num_sta; /* maximum number of STAs in station table */
int dtim_period;
+ int short_beacon_int;
unsigned int bss_load_update_period;
unsigned int chan_util_avg_period;
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index b8431e4a9..a6e70cdd6 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -616,6 +616,13 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
}
#endif /* CONFIG_IEEE80211BE */
+#ifdef CONFIG_IEEE80211AH
+ if (hapd->iconf->ieee80211ah) {
+ buflen += 2 + sizeof(struct ieee80211_s1g_capabilities) +
+ 2 + sizeof(struct ieee80211_s1g_operation);
+ }
+#endif /* CONFIG_IEEE80211AH */
+
buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
known_bss, known_bss_len, NULL);
buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
@@ -775,6 +782,14 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_eid_vendor_vht(hapd, pos);
#endif /* CONFIG_IEEE80211AC */
+#ifdef CONFIG_IEEE80211AH
+ if (hapd->iconf->ieee80211ah) {
+ pos = hostapd_eid_s1g_capab(hapd, pos);
+ pos = hostapd_eid_s1g_oper(hapd, pos);
+ pos = hostapd_eid_s1g_short_beacon_int(hapd, pos);
+ }
+#endif /* CONFIG_IEEE80211AH */
+
/* WPA / OSEN */
pos = hostapd_get_wpa_ie(hapd, pos, epos - pos);
pos = hostapd_get_osen_ie(hapd, pos, epos - pos);
@@ -1072,7 +1087,7 @@ void handle_probe_req(struct hostapd_data *hapd,
return;
}
- if ((!elems.ssid || !elems.supp_rates)) {
+ if ((!elems.ssid || (!elems.supp_rates && !elems.s1g_capab))) {
wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
"without SSID or supported rates element",
MAC2STR(mgmt->sa));
@@ -1708,10 +1723,15 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
struct wpa_driver_ap_params *params)
{
struct ieee80211_mgmt *head = NULL;
+ struct ieee80211_ext *ext_head = NULL;
u8 *tail = NULL;
size_t head_len = 0, tail_len = 0;
u8 *resp = NULL;
size_t resp_len = 0;
+#ifdef CONFIG_IEEE80211AH
+ u8 bss_bw;
+#endif
+
#ifdef NEED_AP_MLME
u16 capab_info;
u8 *pos, *tailpos, *tailend, *csa_pos;
@@ -1724,6 +1744,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
#define BEACON_HEAD_BUF_SIZE 256
#define BEACON_TAIL_BUF_SIZE 512
head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+ ext_head = os_zalloc(BEACON_HEAD_BUF_SIZE);
tail_len = BEACON_TAIL_BUF_SIZE;
#ifdef CONFIG_WPS
if (hapd->conf->wps_state && hapd->wps_beacon_ie)
@@ -1782,6 +1803,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
}
#endif /* CONFIG_IEEE80211BE */
+#ifdef CONFIG_IEEE80211AH
+ if (hapd->iconf->ieee80211ah) {
+ tail_len += 2 + sizeof(struct ieee80211_s1g_operation) +
+ 2 + sizeof(struct ieee80211_s1g_capabilities);
+ }
+#endif /* CONFIG_IEEE80211AH */
+
if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
hapd == hostapd_mbssid_get_tx_bss(hapd))
tail_len += 5; /* Multiple BSSID Configuration element */
@@ -1799,12 +1827,43 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
}
tailend = tail + tail_len;
- head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_BEACON);
+ if (hapd->iconf->ieee80211ah) {
+ ext_head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_EXT, WLAN_FC_STYPE_S1G_BEACON);
+#ifdef CONFIG_IEEE80211AH
+ /* For the time being we are supporting only 2 MHz as the minimum BW */
+ switch (hapd->iconf->s1g_oper_chwidth) {
+ case 0:
+ /* No support in the spec for Maximum BSS BW for 1 MHz */
+ bss_bw = 0;
+ break;
+ case 1:
+ bss_bw = 0;
+ break;
+ case 2:
+ bss_bw = 3;
+ break;
+ case 3:
+ bss_bw = 5;
+ break;
+ case 4:
+ bss_bw = 7;
+ break;
+ default:
+ /* An S1G AP should always support the minimum bss_bw */
+ bss_bw = 0;
+ break;
+ }
+ ext_head->frame_control |= bss_bw << 11;
+#endif /* CONFIG_IEEE80211AH */
+ } else
+ head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_BEACON);
+
head->duration = host_to_le16(0);
+ ext_head->duration = host_to_le16(0);
os_memset(head->da, 0xff, ETH_ALEN);
os_memcpy(head->sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(ext_head->sa, hapd->own_addr, ETH_ALEN);
os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN);
head->u.beacon.beacon_int =
host_to_le16(hapd->iconf->beacon_int);
@@ -1812,7 +1871,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
/* hardware or low-level driver will setup seq_ctrl and timestamp */
capab_info = hostapd_own_capab_info(hapd);
head->u.beacon.capab_info = host_to_le16(capab_info);
- pos = &head->u.beacon.variable[0];
+
+ if (hapd->iconf->ieee80211ah)
+ pos = &ext_head->u.beacon.variable[0];
+ else
+ pos = &head->u.beacon.variable[0];
/* SSID */
*pos++ = WLAN_EID_SSID;
@@ -1834,9 +1897,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
pos = hostapd_eid_supp_rates(hapd, pos);
/* DS Params */
- pos = hostapd_eid_ds_params(hapd, pos);
+ if (!hapd->iconf->ieee80211ah)
+ pos = hostapd_eid_ds_params(hapd, pos);
- head_len = pos - (u8 *) head;
+ if (hapd->iconf->ieee80211ah)
+ head_len = pos - (u8 *) ext_head;
+ else
+ head_len = pos - (u8 *) head;
tailpos = hostapd_eid_country(hapd, tailpos, tailend - tailpos);
@@ -1963,6 +2030,15 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
#endif /* CONFIG_IEEE80211AC */
+#ifdef CONFIG_IEEE80211AH
+ if (hapd->iconf->ieee80211ah) {
+ tailpos = hostapd_eid_s1g_beacon_compat(hapd, tailpos);
+ tailpos = hostapd_eid_s1g_capab(hapd, tailpos);
+ tailpos = hostapd_eid_s1g_oper(hapd, tailpos);
+ tailpos = hostapd_eid_s1g_short_beacon_int(hapd, tailpos);
+ }
+#endif /* CONFIG_IEEE80211AH */
+
/* WPA / OSEN */
tailpos = hostapd_get_wpa_ie(hapd, tailpos, tailend - tailpos);
tailpos = hostapd_get_osen_ie(hapd, tailpos, tailend - tailpos);
@@ -2011,7 +2087,10 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
resp = hostapd_probe_resp_offloads(hapd, &resp_len);
#endif /* NEED_AP_MLME */
- params->head = (u8 *) head;
+ if (hapd->iconf->ieee80211ah)
+ params->head = (u8 *) ext_head;
+ else
+ params->head = (u8 *) head;
params->head_len = head_len;
params->tail = tail;
params->tail_len = tail_len;
@@ -2021,6 +2100,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
params->beacon_int = hapd->iconf->beacon_int;
params->basic_rates = hapd->iface->basic_rates;
params->beacon_rate = hapd->iconf->beacon_rate;
+ params->short_beacon_int = hapd->conf->short_beacon_int;
params->rate_type = hapd->iconf->rate_type;
params->ssid = hapd->conf->ssid.ssid;
params->ssid_len = hapd->conf->ssid.ssid_len;
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 963c3d45b..0009a19e5 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -242,7 +242,8 @@ int hostapd_prepare_rates(struct hostapd_iface *iface,
}
if ((iface->num_rates == 0 || num_basic_rates == 0) &&
- (!iface->conf->ieee80211n || !iface->conf->require_ht)) {
+ (!iface->conf->ieee80211n || !iface->conf->require_ht) &&
+ !iface->conf->ieee80211ah) {
wpa_printf(MSG_ERROR, "No rates remaining in supported/basic "
"rate sets (%d,%d).",
iface->num_rates, num_basic_rates);
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index a9b3e8c60..9abac5867 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -111,6 +111,10 @@ u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
if (hapd->iface->current_rates == NULL)
return eid;
+ /* 802.11ah does not need to include the support rates element */
+ if (hapd->iconf->ieee80211ah)
+ return eid;
+
*pos++ = WLAN_EID_SUPP_RATES;
num = hapd->iface->num_rates;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
@@ -3452,8 +3456,9 @@ static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
struct ieee802_11_elems *elems)
{
/* Supported rates not used in IEEE 802.11ad/DMG */
- if (hapd->iface->current_mode &&
- hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD)
+ if ((hapd->iface->current_mode &&
+ hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) ||
+ hapd->iconf->ieee80211ah)
return WLAN_STATUS_SUCCESS;
if (!elems->supp_rates) {
@@ -4710,6 +4715,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
size_t buflen;
struct ieee80211_mgmt *reply;
u8 *p;
+ le16 aid = 0;
u16 res = WLAN_STATUS_SUCCESS;
const u8 *sa = hapd->own_addr;
@@ -4767,8 +4773,11 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
host_to_le16(hostapd_own_capab_info(hapd));
reply->u.assoc_resp.status_code = host_to_le16(status_code);
- reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) |
- BIT(14) | BIT(15));
+ aid = host_to_le16((sta ? sta->aid : 0) |
+ BIT(14) | BIT(15));
+ if (!hapd->iconf->ieee80211ah)
+ reply->u.assoc_resp.aid = aid;
+
/* Supported rates */
p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
/* Extended supported rates */
@@ -4862,6 +4871,14 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
}
#endif /* CONFIG_IEEE80211AX */
+#ifdef CONFIG_IEEE80211AH
+ if (hapd->iconf->ieee80211ah) {
+ p = hostapd_eid_aid_response(hapd, p, aid);
+ p = hostapd_eid_s1g_capab(hapd, p);
+ p = hostapd_eid_s1g_oper(hapd, p);
+ }
+#endif /* CONFIG_IEEE80211AH */
+
p = hostapd_eid_ext_capab(hapd, p, false);
p = hostapd_eid_bss_max_idle_period(hapd, p);
if (sta && sta->qos_map_enabled)
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index c23ffe365..201fc3d49 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -67,6 +67,11 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_s1g_oper(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_s1g_capab(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_s1g_beacon_compat(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_s1g_short_beacon_int(struct hostapd_data *hapd, u8 *eid);
+u8 * hostapd_eid_aid_response(struct hostapd_data *hapd, u8 *eid, le16 aid);
int hostapd_ht_operation_update(struct hostapd_iface *iface);
void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
diff --git a/src/ap/ieee802_11_s1g.c b/src/ap/ieee802_11_s1g.c
index 34078a7f5..8f635de43 100644
--- a/src/ap/ieee802_11_s1g.c
+++ b/src/ap/ieee802_11_s1g.c
@@ -16,6 +16,137 @@
#include "beacon.h"
#include "ieee802_11.h"
+u8 * hostapd_eid_s1g_oper(struct hostapd_data *hapd, u8 *eid)
+{
+ struct ieee80211_s1g_operation *cap;
+ u8 max_mcs_nss_set;
+ u8 s1g_supp_oper_chwidth_mask = 0;
+ u8 s1g_prim_chwidth = 0;
+ u16 s1g_basic_min_max_mcs_nss_ie = 0;
+ u8 *pos = eid;
+
+ *pos++ = WLAN_EID_S1G_OPERATION;
+ *pos++ = sizeof(*cap);
+
+ cap = (struct ieee80211_s1g_operation *) pos;
+ os_memset(cap, 0, sizeof(*cap));
+
+ switch(hapd->iconf->s1g_oper_chwidth) {
+ case 0:
+ s1g_supp_oper_chwidth_mask = 0;
+ s1g_prim_chwidth = 1;
+ cap->primary_ch = hapd->iconf->channel;
+ break;
+ case 1:
+ s1g_supp_oper_chwidth_mask = 1;
+ s1g_prim_chwidth = 0;
+ cap->primary_ch = hapd->iconf->channel;
+ break;
+ case 2:
+ s1g_supp_oper_chwidth_mask = 3;
+ s1g_prim_chwidth = 0;
+ cap->primary_ch = hapd->iconf->channel - 2;
+ break;
+ case 3:
+ s1g_supp_oper_chwidth_mask = 7;
+ s1g_prim_chwidth = 0;
+ cap->primary_ch = hapd->iconf->channel - 6;
+ break;
+ case 4:
+ s1g_supp_oper_chwidth_mask = 15;
+ s1g_prim_chwidth = 0;
+ cap->primary_ch = hapd->iconf->channel - 14;
+ break;
+ }
+
+ cap->primary_ch = hapd->iconf->channel;
+ cap->ch_width |= (s1g_prim_chwidth &
+ S1G_OPER_IE_CHANWIDTH_PRIM_CH_MASK);
+ cap->ch_width |= ((s1g_supp_oper_chwidth_mask << 1) &
+ S1G_OPER_IE_CHANWIDTH_OPER_CH_MASK);
+ cap->ch_width |= S1G_OPER_IE_CHANWIDTH_PRIM_OFFSET;
+
+ cap->oper_class = hapd->iconf->s1g_op_class;
+
+ cap->oper_ch = hapd->iconf->channel;
+
+ max_mcs_nss_set = hapd->iconf->s1g_basic_mcs_nss_set;
+
+ s1g_basic_min_max_mcs_nss_ie = (max_mcs_nss_set & 0x3) <<
+ S1G_OPER_IE_MAX_MCS_1_NSS_SHIFT |
+ ((max_mcs_nss_set >> 2) & 0x3) <<
+ S1G_OPER_IE_MAX_MCS_2_NSS_SHIFT |
+ ((max_mcs_nss_set >> 4) & 0x3) <<
+ S1G_OPER_IE_MAX_MCS_3_NSS_SHIFT |
+ ((max_mcs_nss_set >> 6) & 0x3) <<
+ S1G_OPER_IE_MAX_MCS_4_NSS_SHIFT;
+ cap->basic_mcs_nss |= s1g_basic_min_max_mcs_nss_ie & 0xff;
+ cap->basic_mcs_nss |= (s1g_basic_min_max_mcs_nss_ie >> 8);
+
+ pos += sizeof(*cap);
+ return pos;
+}
+
+u8 * hostapd_eid_s1g_capab(struct hostapd_data *hapd, u8 *eid)
+{
+ struct ieee80211_s1g_capabilities *cap;
+ u8 *pos = eid;
+
+ *pos++ = WLAN_EID_S1G_CAPABILITIES;
+ *pos++ = sizeof(*cap);
+
+ cap = (struct ieee80211_s1g_capabilities *) pos;
+ os_memset(cap, 0, sizeof(*cap));
+
+ os_memcpy(cap->capab_info,
+ hapd->iface->current_mode->s1g_capab,
+ sizeof(cap->capab_info));
+ os_memcpy(cap->supp_mcs_nss,
+ hapd->iface->current_mode->s1g_mcs,
+ sizeof(cap->supp_mcs_nss));
+
+ pos += sizeof(*cap);
+ return pos;
+}
+
+
+u8 * hostapd_eid_s1g_beacon_compat(struct hostapd_data *hapd, u8 *eid)
+{
+ u8 *pos = eid;
+ u16 beacon_int;
+
+ beacon_int = hapd->conf->short_beacon_int * hapd->iconf->beacon_int;
+
+ *pos++ = WLAN_EID_S1G_BCN_COMPAT;
+ *pos++ = 8;
+ *pos++ = WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY;;
+ *pos++ = 0;
+
+ *pos++ = beacon_int & 0xff;
+ *pos++ = (beacon_int >> 8) & 0xff;
+
+ /* Last 4 octets will be filled in by the driver to contain the 4
+ MSB of the TSF timer at time of generation */
+ *pos++ = 0;
+ *pos++ = 0;
+ *pos++ = 0;
+ *pos++ = 0;
+ return pos;
+}
+
+
+u8 * hostapd_eid_s1g_short_beacon_int(struct hostapd_data *hapd, u8 *eid)
+{
+ u8 *pos = eid;
+
+ *pos++ = WLAN_EID_S1G_SHORT_BCN_INTERVAL;
+ *pos++ = 2;
+ *pos++ = hapd->iconf->beacon_int & 0xff;
+ *pos++ = (hapd->iconf->beacon_int >> 8) & 0xff;
+
+ return pos;
+}
+
static u8 hostapd_s1g_get_oper_class_s1g(u16 s1g_op,
struct hostapd_iface *iface) {
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 31dfb6254..0ad374491 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -455,6 +455,20 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx,
}
}
+u8 * hostapd_eid_aid_response(struct hostapd_data *hapd, u8 *eid, le16 aid)
+{
+ u8 *pos = eid;
+ const u8 len = 5;
+
+ *pos++ = WLAN_EID_AID_RESPONSE;
+ *pos++ = len;
+
+ *pos++ = aid;
+
+ memset(pos, 0, sizeof(*pos));
+
+ return pos;
+}
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid,
bool mbssid_complete)
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 1dafba93a..ea519e680 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -36,6 +36,7 @@
#define WLAN_FC_TYPE_MGMT 0
#define WLAN_FC_TYPE_CTRL 1
#define WLAN_FC_TYPE_DATA 2
+#define WLAN_FC_TYPE_EXT 3
/* management */
#define WLAN_FC_STYPE_ASSOC_REQ 0
@@ -77,6 +78,9 @@
#define WLAN_FC_STYPE_QOS_CFPOLL 14
#define WLAN_FC_STYPE_QOS_CFACKPOLL 15
+/* extension */
+#define WLAN_FC_STYPE_S1G_BEACON 1
+
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
#define WLAN_AUTH_SHARED_KEY 1
@@ -448,7 +452,10 @@
#define WLAN_EID_DEVICE_LOCATION 204
#define WLAN_EID_WHITE_SPACE_MAP 205
#define WLAN_EID_FTM_PARAMETERS 206
+#define WLAN_EID_AID_REQUEST 210
+#define WLAN_EID_AID_RESPONSE 211
#define WLAN_EID_S1G_BCN_COMPAT 213
+#define WLAN_EID_S1G_SHORT_BCN_INTERVAL 214
#define WLAN_EID_TWT 216
#define WLAN_EID_S1G_CAPABILITIES 217
#define WLAN_EID_VENDOR_SPECIFIC 221
@@ -1113,6 +1120,18 @@ struct ieee80211_mgmt {
} u;
} STRUCT_PACKED;
+struct ieee80211_ext {
+ le16 frame_control;
+ le16 duration;
+ u8 sa[6];
+ union {
+ struct {
+ u8 timestamp[4];
+ u8 change_seq;
+ u8 variable[];
+ } STRUCT_PACKED beacon;
+ } u;
+} STRUCT_PACKED;
#define IEEE80211_MAX_MMPDU_SIZE 2304
@@ -2446,6 +2465,29 @@ struct ieee80211_he_mu_edca_parameter_set {
/* B7: Reserved if sent by an AP; More Data Ack if sent by a non-AP STA */
#define HE_QOS_INFO_MORE_DATA_ACK ((u8) (BIT(7)))
+struct ieee80211_s1g_capabilities {
+ u8 capab_info[10];
+ u8 supp_mcs_nss[5];
+} STRUCT_PACKED;
+
+struct ieee80211_s1g_operation {
+ u8 ch_width;
+ u8 oper_class;
+ u8 primary_ch;
+ u8 oper_ch;
+ le16 basic_mcs_nss;
+} STRUCT_PACKED;
+
+#define S1G_OPER_IE_CHANWIDTH_PRIM_CH_MASK (BIT(0))
+#define S1G_OPER_IE_CHANWIDTH_OPER_CH_MASK (BIT(1) | BIT(2) | \
+ BIT(3) | BIT(4))
+#define S1G_OPER_IE_CHANWIDTH_PRIM_OFFSET (BIT(5))
+#define S1G_OPER_IE_MAX_MCS_1_NSS_SHIFT (2)
+#define S1G_OPER_IE_MAX_MCS_2_NSS_SHIFT (6)
+#define S1G_OPER_IE_MAX_MCS_3_NSS_SHIFT (10)
+#define S1G_OPER_IE_MAX_MCS_4_NSS_SHIFT (14)
+
+
/*
* IEEE Std 802.11-2020 and IEEE Std 802.11ax-2021
* 9.4.2.170 Reduced Neighbor Report element
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 7825dfca3..707764d70 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -318,6 +318,16 @@ 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
+ */
+ u8 s1g_capab[10];
+
+ /**
+ * s1g_mcs - S1G (IEEE 802 11ah) supported MCS and NSS params
+ */
+ u8 s1g_mcs[5];
};
@@ -1395,6 +1405,11 @@ struct wpa_driver_ap_params {
*/
int beacon_int;
+ /**
+ * short_beacon_int - S1G short beacons per S1G beacon
+ */
+ int short_beacon_int;
+
/**
* basic_rates: -1 terminated array of basic rates in 100 kbps
*
@@ -6570,7 +6585,6 @@ union wpa_event_data {
*/
struct acs_selected_channels {
unsigned int pri_freq;
- unsigned int pri_freq_khz;
unsigned int sec_freq;
u8 edmg_channel;
u8 vht_seg0_center_ch;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 582eddd98..4427cff03 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5066,6 +5066,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
nl80211_put_beacon_rate(msg, drv->capa.flags, drv->capa.flags2,
params) ||
nl80211_put_dtim_period(msg, params->dtim_period) ||
+ nla_put_u32(msg, NL80211_ATTR_SHORT_BEACON_PERIOD,
+ params->short_beacon_int) ||
nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
goto fail;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 1ae381e49..81eeae358 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1613,6 +1613,24 @@ static void phy_info_vht_capa(struct hostapd_hw_modes *mode,
}
+static void phy_info_s1g_capa(struct hostapd_hw_modes *mode,
+ struct nlattr *capability,
+ struct nlattr *mcs_nss_set)
+{
+ if (capability && nla_len(capability) >= 10) {
+ u8 *capa;
+ capa = nla_data(capability);
+ os_memcpy(mode->s1g_capab, capa, 10);
+ }
+
+ if (mcs_nss_set && nla_len(mcs_nss_set) >= 5) {
+ u8 *mcs_nss;
+ mcs_nss = nla_data(mcs_nss_set);
+ os_memcpy(mode->s1g_mcs, mcs_nss, 5);
+ }
+}
+
+
static int phy_info_edmg_capa(struct hostapd_hw_modes *mode,
struct nlattr *bw_config,
struct nlattr *channels)
@@ -2088,6 +2106,8 @@ static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band)
tb_band[NL80211_BAND_ATTR_HT_MCS_SET]);
phy_info_vht_capa(mode, tb_band[NL80211_BAND_ATTR_VHT_CAPA],
tb_band[NL80211_BAND_ATTR_VHT_MCS_SET]);
+ phy_info_s1g_capa(mode, tb_band[NL80211_BAND_ATTR_S1G_CAPA],
+ tb_band[NL80211_BAND_ATTR_S1G_MCS_NSS_SET]);
ret = phy_info_edmg_capa(mode,
tb_band[NL80211_BAND_ATTR_EDMG_BW_CONFIG],
tb_band[NL80211_BAND_ATTR_EDMG_CHANNELS]);
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index c59fec406..759dfe968 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -3341,6 +3341,8 @@ enum nl80211_attrs {
NL80211_ATTR_EMA_RNR_ELEMS,
+ NL80211_ATTR_SHORT_BEACON_PERIOD,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
--
2.25.1
More information about the Hostap
mailing list