diff --git a/hostapd/config_file.c b/hostapd/config_file.c index ac66d8bd4..eaf190b86 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -1220,6 +1220,32 @@ static u8 set_he_cap(int val, u8 mask) return (u8) (mask & (val << find_bit_offset(mask))); } + +static int hostapd_parse_he_srg_bitmap(u8 *bitmap, char *val) +{ + int bitpos; + char *pos, *end; + + os_memset(bitmap, 0, 8); + pos = val; + while (*pos != '\0') { + end = os_strchr(pos, ' '); + if (end) + *end = '\0'; + + bitpos = atoi(pos); + if (bitpos < 0 || bitpos > 64) + return -1; + + bitmap[bitpos / 8] |= BIT(bitpos % 8); + if (!end) + break; + pos = end + 1; + } + + return 0; +} + #endif /* CONFIG_IEEE80211AX */ @@ -3554,13 +3580,29 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->he_mu_edca.he_mu_ac_vo_param[HE_MU_AC_PARAM_TIMER_IDX] = atoi(pos) & 0xff; } else if (os_strcmp(buf, "he_spr_sr_control") == 0) { - conf->spr.sr_control = atoi(pos) & 0xff; + conf->spr.sr_control = atoi(pos) & 0x1f; } else if (os_strcmp(buf, "he_spr_non_srg_obss_pd_max_offset") == 0) { conf->spr.non_srg_obss_pd_max_offset = atoi(pos); } else if (os_strcmp(buf, "he_spr_srg_obss_pd_min_offset") == 0) { conf->spr.srg_obss_pd_min_offset = atoi(pos); } else if (os_strcmp(buf, "he_spr_srg_obss_pd_max_offset") == 0) { conf->spr.srg_obss_pd_max_offset = atoi(pos); + } else if (os_strcmp(buf, "he_spr_srg_bss_colors") == 0) { + if (hostapd_parse_he_srg_bitmap( + conf->spr.srg_bss_color_bitmap, pos)) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid srg bss colors list '%s'", + line, pos); + return 1; + } + } else if (os_strcmp(buf, "he_spr_srg_partial_bssid") == 0) { + if (hostapd_parse_he_srg_bitmap( + conf->spr.srg_partial_bssid_bitmap, pos)) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid srg partial bssid list '%s'", + line, pos); + return 1; + } } else if (os_strcmp(buf, "he_oper_chwidth") == 0) { conf->he_oper_chwidth = atoi(pos); } else if (os_strcmp(buf, "he_oper_centr_freq_seg0_idx") == 0) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 8553338fd..769fab66a 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -881,7 +881,22 @@ wmm_ac_vo_acm=0 #he_spr_non_srg_obss_pd_max_offset #he_spr_srg_obss_pd_min_offset #he_spr_srg_obss_pd_max_offset - +# +# SPR SRG BSS Color +# This config represents SRG BSS Color Bitmap field of Spatial Reuse Parameter +# Set element that indicates the BSS color values used by members of the +# SRG of which the transmitting STA is a member. The value is in range of 0-63. +#he_spr_srg_bss_colors=1 2 10 63 +# +# SPR SRG Partial BSSID +# This config represents SRG Partial BSSID Bitmap field of Spatial Reuse +# Parameter Set element that indicates the Partial BSSID values used by members +# of the SRG of which the transmitting STA is a member. The value range +# corresponds to one of the 64 possible values of BSSID[39:44], where the lowest +# numbered bit corresponds to Partial BSSID value 0 and the highest numbered bit +# corresponds to Partial BSSID value 63. +#he_spr_srg_partial_bssid=0 1 3 63 +# #he_6ghz_max_mpdu: Maximum MPDU Length of HE 6 GHz band capabilities. # Indicates maximum MPDU length # 0 = 3895 octets diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 0d330075d..cb2bf9b24 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -908,8 +908,8 @@ struct spatial_reuse { 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; + u8 srg_bss_color_bitmap[8]; + u8 srg_partial_bssid_bitmap[8]; }; /** diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 16f1e96c0..477caa494 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -1497,11 +1497,17 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd) params.assocresp_ies = assocresp; params.reenable = hapd->reenable_beacon; #ifdef CONFIG_IEEE80211AX - params.he_spr = !!hapd->iface->conf->spr.sr_control; + params.he_spr_ctrl = hapd->iface->conf->spr.sr_control; + params.he_spr_non_srg_obss_pd_max_offset = + hapd->iface->conf->spr.non_srg_obss_pd_max_offset; params.he_spr_srg_obss_pd_min_offset = hapd->iface->conf->spr.srg_obss_pd_min_offset; params.he_spr_srg_obss_pd_max_offset = hapd->iface->conf->spr.srg_obss_pd_max_offset; + os_memcpy(params.he_spr_bss_color_bitmap, + hapd->iface->conf->spr.srg_bss_color_bitmap, 8); + os_memcpy(params.he_spr_partial_bssid_bitmap, + hapd->iface->conf->spr.srg_partial_bssid_bitmap, 8); params.he_bss_color_disabled = hapd->iface->conf->he_op.he_bss_color_disabled; params.he_bss_color_partial = diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index 93f35855d..c27bb1fcd 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -304,6 +304,11 @@ u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid) 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; + os_memcpy(spr_param, + hapd->iface->conf->spr.srg_bss_color_bitmap, 8); + spr_param += 8; + os_memcpy(spr_param, + hapd->iface->conf->spr.srg_partial_bssid_bitmap, 8); pos += 18; } diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 1e1f11372..1a42381d7 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1483,19 +1483,36 @@ struct wpa_driver_ap_params { const struct wpabuf *civic; /** - * he_spr - Whether Spatial Reuse is enabled + * he_spr_ctrl - Spatial Reuse control field of SPR element */ - int he_spr; + u8 he_spr_ctrl; + + /** + * he_spr_non_srg_obss_pd_max_offset - Non-SRG Maximum TX power offset + */ + u8 he_spr_non_srg_obss_pd_max_offset; /** * he_spr_srg_obss_pd_min_offset - Minimum TX power offset */ - int he_spr_srg_obss_pd_min_offset; + u8 he_spr_srg_obss_pd_min_offset; /** * he_spr_srg_obss_pd_max_offset - Maximum TX power offset */ - int he_spr_srg_obss_pd_max_offset; + u8 he_spr_srg_obss_pd_max_offset; + + /** + * he_spr_bss_color_bitmap - BSS color values used by members of the + * SRG. + */ + u8 he_spr_bss_color_bitmap[8]; + + /** + * he_spr_partial_bssid_bitmap - Partial BSSID values used by members + * of the SRG. + */ + u8 he_spr_partial_bssid_bitmap[8]; /** * he_bss_color - Whether the BSS Color is disabled diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 9e5ee5441..c258557db 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4606,17 +4606,34 @@ static int wpa_driver_nl80211_set_ap(void *priv, } #ifdef CONFIG_IEEE80211AX - if (params->he_spr) { + if (params->he_spr_ctrl) { struct nlattr *spr; spr = nla_nest_start(msg, NL80211_ATTR_HE_OBSS_PD); - wpa_printf(MSG_DEBUG, "nl80211: he_spr=%d", params->he_spr); + wpa_printf(MSG_DEBUG, "nl80211: he_spr_ctrl=0x%x", + params->he_spr_ctrl); if (!spr || - nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, - params->he_spr_srg_obss_pd_min_offset) || - nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET, - params->he_spr_srg_obss_pd_max_offset)) + nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_SR_CTRL, + params->he_spr_ctrl) || + ((params->he_spr_ctrl & + SPATIAL_REUSE_NON_SRG_OFFSET_PRESENT) && + nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET, + params->he_spr_non_srg_obss_pd_max_offset))) + goto fail; + + if ((params->he_spr_ctrl & + SPATIAL_REUSE_SRG_INFORMATION_PRESENT) && + (nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, + params->he_spr_srg_obss_pd_min_offset) || + nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET, + params->he_spr_srg_obss_pd_max_offset) || + nla_put(msg, NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP, + sizeof(params->he_spr_bss_color_bitmap), + params->he_spr_bss_color_bitmap) || + nla_put(msg, NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP, + sizeof(params->he_spr_partial_bssid_bitmap), + params->he_spr_partial_bssid_bitmap))) goto fail; nla_nest_end(msg, spr);