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 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap