From 2ec71488b5a380d7c1e4e733ebc408246671baff Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 16 Apr 2019 14:34:01 +0200 Subject: [PATCH] HE: Add Spatial Reuse Parameter Set element to the Beacon frames SPR allows us to detect OBSS overlaps and allows us to do adaptive CCA thresholds. For this to work the AP needs to broadcast the element first. Signed-off-by: Shashidhar Lakkavalli Signed-off-by: John Crispin --- hostapd/config_file.c | 8 ++++++++ hostapd/hostapd.conf | 6 ++++++ src/ap/ap_config.h | 13 ++++++++++++ src/ap/beacon.c | 8 ++++++-- src/ap/ieee802_11.h | 1 + src/ap/ieee802_11_he.c | 39 ++++++++++++++++++++++++++++++++++++ src/common/ieee802_11_defs.h | 23 +++++++++++++++++++++ 7 files changed, 96 insertions(+), 2 deletions(-) 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];