diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 3f61cb625..dce65570c 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3556,6 +3556,14 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "he_mu_edca_ac_vo_timer") == 0) { conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] = atoi(pos) & 0xff; + } else if (os_strcmp(buf, "he_srp_sr_control") == 0) { + conf->spr.sr_control = atoi(pos) & 0xff; + } else if (os_strcmp(buf, "he_srp_non_srg_obss_pd_max_offset") == 0) { + conf->spr.non_srg_obss_pd_max_offset = atoi(pos); + } else if (os_strcmp(buf, "he_srp_srg_obss_pd_min_offset") == 0) { + conf->spr.srg_obss_pd_min_offset = atoi(pos); + } else if (os_strcmp(buf, "he_srp_srg_obss_pd_max_offset") == 0) { + conf->spr.srg_obss_pd_max_offset = 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 f8caa5623..2087b5233 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -825,6 +825,12 @@ wmm_ac_vo_acm=0 #he_mu_edca_ac_vo_ecwmax=15 #he_mu_edca_ac_vo_timer=255 +# Spatial Reuse Parameter Set +#he_srp_sr_control +#he_srp_non_srg_obss_pd_max_offset +#he_srp_srg_obss_pd_min_offset +#he_srp_srg_obss_pd_max_offset + ##### IEEE 802.1X-2004 related configuration ################################## # Require IEEE 802.1X authorization diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 84b6b786f..f18425224 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -740,6 +740,18 @@ struct he_operation { u16 he_rts_threshold; }; +/** + * struct spatial_reuse - Spatial reuse + */ +struct spatial_reuse { + u8 sr_control; + u8 non_srg_obss_pd_max_offset; + u8 srg_obss_pd_min_offset; + u8 srg_obss_pd_max_offset; + u8 srg_obss_color_bitmap; + u8 srg_obss_color_partial_bitmap; +}; + /** * struct hostapd_config - Per-radio interface configuration */ @@ -862,6 +874,7 @@ struct hostapd_config { struct he_phy_capabilities_info he_phy_capab; struct he_operation he_op; struct ieee80211_he_mu_edca_parameter_set he_mu_edca; + struct spatial_reuse spr; #endif /* CONFIG_IEEE80211AX */ /* VHT enable/disable config from CHAN_SWITCH */ diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 3e62991d0..8433fc3a9 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -398,7 +398,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, if (hapd->iconf->ieee80211ax) { buflen += 3 + sizeof(struct ieee80211_he_capabilities) + 3 + sizeof(struct ieee80211_he_operation) + - 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set); + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + + 3 + sizeof(struct ieee80211_spatial_reuse); } #endif /* CONFIG_IEEE80211AX */ @@ -512,6 +513,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_he_capab(hapd, pos); pos = hostapd_eid_he_operation(hapd, pos); pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos); + pos = hostapd_eid_spatial_reuse(hapd, pos); } #endif /* CONFIG_IEEE80211AX */ @@ -1088,7 +1090,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, if (hapd->iconf->ieee80211ax) { tail_len += 3 + sizeof(struct ieee80211_he_capabilities) + 3 + sizeof(struct ieee80211_he_operation) + - 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set); + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + + 3 + sizeof(struct ieee80211_spatial_reuse); } #endif /* CONFIG_IEEE80211AX */ @@ -1226,6 +1229,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_he_capab(hapd, tailpos); tailpos = hostapd_eid_he_operation(hapd, tailpos); tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos); + tailpos = hostapd_eid_spatial_reuse(hapd, tailpos); } #endif /* CONFIG_IEEE80211AX */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index db7badcff..3699246b3 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -60,6 +60,7 @@ u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid); 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); 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_he.c b/src/ap/ieee802_11_he.c index 10e5ac517..efa701335 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -127,3 +127,42 @@ u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid) return pos; } + + +u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_spatial_reuse *spr; + u8 *pos = eid, *spr_param; + u8 sz = 1; + + if (hapd->iface->conf->spr.sr_control & + SPATIAL_REUSE_NON_SRG_OFFSET_PRESENT) + sz++; + + if (hapd->iface->conf->spr.sr_control & + SPATIAL_REUSE_SRG_INFORMATION_PRESENT) + sz += 18; + + *pos++ = WLAN_EID_EXTENSION; + *pos++ = 1 + sz; + *pos++ = WLAN_EID_EXT_SPATIAL_REUSE; + + spr = (struct ieee80211_spatial_reuse *) pos; + os_memset(spr, 0, sizeof(*spr)); + + spr->sr_ctrl = hapd->iface->conf->spr.sr_control; + pos++; + spr_param = spr->params; + if (spr->sr_ctrl & SPATIAL_REUSE_NON_SRG_OFFSET_PRESENT) { + *spr_param++ = + hapd->iface->conf->spr.non_srg_obss_pd_max_offset; + pos++; + } + if (spr->sr_ctrl & SPATIAL_REUSE_SRG_INFORMATION_PRESENT) { + *spr_param++ = hapd->iface->conf->spr.srg_obss_pd_min_offset; + *spr_param++ = hapd->iface->conf->spr.srg_obss_pd_max_offset; + pos += 18; + } + + return pos; +} diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index edc7909db..90615ece6 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -468,6 +468,7 @@ #define WLAN_EID_EXT_HE_CAPABILITIES 35 #define WLAN_EID_EXT_HE_OPERATION 36 #define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38 +#define WLAN_EID_EXT_SPATIAL_REUSE 39 #define WLAN_EID_EXT_OCV_OCI 54 /* Extended Capabilities field */ @@ -2118,6 +2119,21 @@ struct ieee80211_he_operation { /* Followed by conditional MaxBSSID Indicator subfield (u8) */ } STRUCT_PACKED; +/* + * IEEE P802.11ax/D4.0, 9.4.2.246 Spatial Reuse Parameter Set element + */ +struct ieee80211_spatial_reuse { + u8 sr_ctrl; /* SR Control */ + /* Up to 19 octets of parameters: + * Non-SRG OBSS PD Max Offset[0 or 1] + * SRG OBSS PD Min Offset[0 or 1] + * SRG OBSS PD Max Offset[0 or 1] + * SRG BSS Color Bitmap[0 or 8] + * SRG Partial BSSID Bitmap[0 or 8] + */ + u8 params[19]; +} STRUCT_PACKED; + /* HE Capabilities Information defines */ #define HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX 3 #define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7)) @@ -2145,6 +2161,13 @@ struct ieee80211_he_operation { #define HE_OPERATION_BSS_COLOR_DISABLED ((u32) BIT(31)) #define HE_OPERATION_BSS_COLOR_OFFSET 24 +/* Spatial Reuse defines */ +#define SPATIAL_REUSE_SRP_DISALLOWED BIT(0) +#define SPATIAL_REUSE_NON_SRG_OBSS_PD_SR_DISALLOWED BIT(1) +#define SPATIAL_REUSE_NON_SRG_OFFSET_PRESENT BIT(2) +#define SPATIAL_REUSE_SRG_INFORMATION_PRESENT BIT(3) +#define SPATIAL_REUSE_HESIGA_SR_VAL15_ALLOWED BIT(4) + struct ieee80211_he_mu_edca_parameter_set { u8 he_qos_info; u8 he_mu_ac_be_param[3];