diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 093dc4f37..fe8fcd728 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3557,6 +3557,14 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->he_oper_centr_freq_seg0_idx = atoi(pos); } else if (os_strcmp(buf, "he_oper_centr_freq_seg1_idx") == 0) { conf->he_oper_centr_freq_seg1_idx = atoi(pos); + } else if (os_strcmp(buf, "he_6ghz_max_mpdu") == 0) { + conf->he_6ghz_max_mpdu = atoi(pos); + } else if (os_strcmp(buf, "he_6ghz_max_ampdu_len_exp") == 0) { + conf->he_6ghz_max_ampdu_len_exp = atoi(pos); + } else if (os_strcmp(buf, "he_6ghz_rx_ant_pat") == 0) { + conf->he_6ghz_rx_ant_pat = atoi(pos); + } else if (os_strcmp(buf, "he_6ghz_tx_ant_pat") == 0) { + conf->he_6ghz_tx_ant_pat = atoi(pos); #endif /* CONFIG_IEEE80211AX */ } else if (os_strcmp(buf, "max_listen_interval") == 0) { bss->max_listen_interval = atoi(pos); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 6666153a7..c4482c13c 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -880,6 +880,42 @@ wmm_ac_vo_acm=0 #he_spr_srg_obss_pd_min_offset #he_spr_srg_obss_pd_max_offset +#he_6ghz_max_mpdu: Maximum MPDU Length of HE 6 GHz band capabilities. +# Indicates maximum MPDU length +# 0 = 3895 octets +# 1 = 7991 octets +# 2 = 11454 octets (default) +#he_6ghz_max_mpdu=2 +# +#he_6ghz_max_ampdu_len_exp: Maximum A-MPDU Length Exponent of HE 6 GHz band +# capabilities. Indicates the maximum length of A-MPDU pre-EOF padding that +# the STA can receive. This field is an integer in the range of 0 to 7. +# The length defined by this field is equal to +# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets +# 0 = AMPDU length of 8k +# 1 = AMPDU length of 16k +# 2 = AMPDU length of 32k +# 3 = AMPDU length of 65k +# 4 = AMPDU length of 131k +# 5 = AMPDU length of 262k +# 6 = AMPDU length of 524k +# 7 = AMPDU length of 1048k (default) +#he_6ghz_max_ampdu_len_exp=7 +# +#he_6ghz_rx_ant_pat: Rx Antenna Pattern Consistency of HE 6 GHz capability. +# Indicates the possibility of Rx antenna pattern change +# 0 = Rx antenna pattern might change during the lifetime of an association +# 1 = Rx antenna pattern does not change during the lifetime of an association +# (default) +#he_6ghz_rx_ant_pat=1 +# +#he_6ghz_tx_ant_pat: Tx Antenna Pattern Consistency of HE 6 GHz capability. +# Indicates the possibility of Tx antenna pattern change +# 0 = Tx antenna pattern might change during the lifetime of an association +# 1 = Tx antenna pattern does not change during the lifetime of an association +# (default) +#he_6ghz_tx_ant_pat=1 + ##### IEEE 802.1X-2004 related configuration ################################## # Require IEEE 802.1X authorization diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 35c0fe577..8b98e6755 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -268,6 +268,10 @@ struct hostapd_config * hostapd_config_defaults(void) conf->he_op.he_bss_color_disabled = 1; conf->he_op.he_bss_color_partial = 0; conf->he_op.he_bss_color = 1; + conf->he_6ghz_max_mpdu = 2; + conf->he_6ghz_max_ampdu_len_exp = 7; + conf->he_6ghz_rx_ant_pat = 1; + conf->he_6ghz_tx_ant_pat = 1; #endif /* CONFIG_IEEE80211AX */ /* The third octet of the country string uses an ASCII space character diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index abe58532e..0d330075d 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -1044,6 +1044,10 @@ struct hostapd_config { u8 he_oper_chwidth; u8 he_oper_centr_freq_seg0_idx; u8 he_oper_centr_freq_seg1_idx; + u8 he_6ghz_max_mpdu; + u8 he_6ghz_max_ampdu_len_exp; + u8 he_6ghz_rx_ant_pat; + u8 he_6ghz_tx_ant_pat; #endif /* CONFIG_IEEE80211AX */ /* VHT enable/disable config from CHAN_SWITCH */ diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 1b105227d..e25717464 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -1701,6 +1701,9 @@ static int setup_interface2(struct hostapd_iface *iface) return 0; } ret = hostapd_check_edmg_capab(iface); + if (ret < 0) + goto fail; + ret = hostapd_check_he_6ghz_capab(iface); if (ret < 0) goto fail; ret = hostapd_check_ht_capab(iface); diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index f6e69030d..40b7b38c3 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -732,6 +732,51 @@ int hostapd_check_edmg_capab(struct hostapd_iface *iface) } +int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface) +{ +#ifdef CONFIG_IEEE80211AX + struct he_capabilities *he_cap; + u16 hw; + + if (!iface->current_mode || !is_6ghz_freq(iface->freq)) + return 0; + + he_cap = &iface->current_mode->he_capab[IEEE80211_MODE_AP]; + hw = he_cap->he_6ghz_capa; + if (iface->conf->he_6ghz_max_mpdu > + ((hw & HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_MASK) >> + HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_SHIFT)) { + wpa_printf(MSG_ERROR, + "The driver does not support the configured HE 6 GHz Max MPDU length"); + return -1; + } + + if (iface->conf->he_6ghz_max_ampdu_len_exp > + ((hw & HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_MASK) >> + HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_SHIFT)) { + wpa_printf(MSG_ERROR, + "The driver does not support the configured HE 6 GHz Max AMPDU Length Exponent"); + return -1; + } + + if (iface->conf->he_6ghz_rx_ant_pat && + !(hw & HE_6GHZ_BAND_CAP_RX_ANTPAT_CONS)) { + wpa_printf(MSG_ERROR, + "The driver does not support the configured HE 6 GHz Rx Antenna Pattern"); + return -1; + } + + if (iface->conf->he_6ghz_tx_ant_pat && + !(hw & HE_6GHZ_BAND_CAP_TX_ANTPAT_CONS)) { + wpa_printf(MSG_ERROR, + "The driver does not support the configured HE 6 GHz Tx Antenna Pattern"); + return -1; + } +#endif /* CONFIG_IEEE80211AX */ + return 0; +} + + static int hostapd_is_usable_chan(struct hostapd_iface *iface, int frequency, int primary) { diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h index dd24f95b2..ad0ddf7ff 100644 --- a/src/ap/hw_features.h +++ b/src/ap/hw_features.h @@ -22,6 +22,7 @@ int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan); int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq); int hostapd_check_ht_capab(struct hostapd_iface *iface); int hostapd_check_edmg_capab(struct hostapd_iface *iface); +int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface); int hostapd_prepare_rates(struct hostapd_iface *iface, struct hostapd_hw_modes *mode); void hostapd_stop_setup_timers(struct hostapd_iface *iface); @@ -85,6 +86,11 @@ static inline int hostapd_hw_skip_mode(struct hostapd_iface *iface, return 0; } +static inline int hostapd_check_he_6ghz_capab(struct hostapd_iface *iface) +{ + return 0; +} + #endif /* NEED_AP_MLME */ #endif /* HW_FEATURES_H */ diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index dad68ac43..93f35855d 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -313,6 +313,7 @@ u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid) u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid) { + struct hostapd_config *conf = hapd->iface->conf; struct hostapd_hw_modes *mode = hapd->iface->current_mode; struct he_capabilities *he_cap; struct ieee80211_he_6ghz_band_cap *cap; @@ -324,8 +325,18 @@ u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid) return eid; he_cap = &mode->he_capab[IEEE80211_MODE_AP]; - capab = he_cap->he_6ghz_capa; + capab = he_cap->he_6ghz_capa & HE_6GHZ_BAND_CAP_MIN_MPDU_START; + capab |= (conf->he_6ghz_max_ampdu_len_exp << + HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_SHIFT) & + HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_MASK; + capab |= (conf->he_6ghz_max_mpdu << + HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_SHIFT) & + HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_MASK; capab |= HE_6GHZ_BAND_CAP_SMPS_DISABLED; + if (conf->he_6ghz_rx_ant_pat) + capab |= HE_6GHZ_BAND_CAP_RX_ANTPAT_CONS; + if (conf->he_6ghz_tx_ant_pat) + capab |= HE_6GHZ_BAND_CAP_TX_ANTPAT_CONS; pos = eid; *pos++ = WLAN_EID_EXTENSION;