From: Ilan Peer Date: Mon, 22 May 2023 19:33:37 +0000 (+0300) Subject: AP: Include an RNR element in Beacon frames for AP MLD X-Git-Tag: hostap_2_11~1148 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2b541601daae70fa2db3e4c54dbb8bbeae6e8224;p=thirdparty%2Fhostap.git AP: Include an RNR element in Beacon frames for AP MLD - Include RNR element in Beacon frames of AP MLDs. - Whenever a new interface is added to an AP MLD, reconfigure the Beacon frame templates for all other interfaces, to allow updating their RNR elements. Signed-off-by: Ilan Peer --- diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 5e9ced1e2..7ff678319 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -2194,21 +2194,29 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd) if (!iface->interfaces || iface->interfaces->count <= 1) return 0; - /* Update Beacon frames in case of 6 GHz colocation */ + /* Update Beacon frames in case of 6 GHz colocation or AP MLD */ is_6g = is_6ghz_op_class(iface->conf->op_class); for (j = 0; j < iface->interfaces->count; j++) { - struct hostapd_iface *colocated; + struct hostapd_iface *other; + bool mld_ap = false; - colocated = iface->interfaces->iface[j]; - if (colocated == iface || !colocated || !colocated->conf) + other = iface->interfaces->iface[j]; + if (other == iface || !other || !other->conf) continue; - if (is_6g == is_6ghz_op_class(colocated->conf->op_class)) +#ifdef CONFIG_IEEE80211BE + if (hapd->conf->mld_ap && other->bss[0]->conf->mld_ap && + hapd->conf->mld_id == other->bss[0]->conf->mld_id) + mld_ap = true; +#endif /* CONFIG_IEEE80211BE */ + + if (is_6g == is_6ghz_op_class(other->conf->op_class) && + !mld_ap) continue; - for (i = 0; i < colocated->num_bss; i++) { - if (colocated->bss[i] && colocated->bss[i]->started) - __ieee802_11_set_beacon(colocated->bss[i]); + for (i = 0; i < other->num_bss; i++) { + if (other->bss[i] && other->bss[i]->started) + __ieee802_11_set_beacon(other->bss[i]); } } diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index 02596dcb7..a86fc179c 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -2471,6 +2471,9 @@ dfs_offload: for (j = 0; j < iface->num_bss; j++) hostapd_neighbor_set_own_report(iface->bss[j]); + if (iface->interfaces && iface->interfaces->count > 1) + ieee802_11_set_beacons(iface); + return 0; fail: diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 93a6b4f56..a289b26af 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -6443,6 +6443,11 @@ hostapd_eid_rnr_iface_len(struct hostapd_data *hapd, size_t total_len = 0, len = *current_len; int tbtt_count = 0; size_t i, start = 0; + bool ap_mld = false; + +#ifdef CONFIG_IEEE80211BE + ap_mld = !!hapd->conf->mld_ap; +#endif /* CONFIG_IEEE80211BE */ while (start < hapd->iface->num_bss) { if (!len || @@ -6472,8 +6477,13 @@ hostapd_eid_rnr_iface_len(struct hostapd_data *hapd, tbtt_count >= RNR_TBTT_INFO_COUNT_MAX) break; - len += RNR_TBTT_INFO_LEN; - total_len += RNR_TBTT_INFO_LEN; + if (!ap_mld) { + len += RNR_TBTT_INFO_LEN; + total_len += RNR_TBTT_INFO_LEN; + } else { + len += RNR_TBTT_INFO_MLD_LEN; + total_len += RNR_TBTT_INFO_MLD_LEN; + } tbtt_count++; } start = i; @@ -6528,8 +6538,8 @@ static enum colocation_mode get_colocation_mode(struct hostapd_data *hapd) } -static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd, - size_t *current_len) +static size_t hostapd_eid_rnr_multi_iface_len(struct hostapd_data *hapd, + size_t *current_len) { struct hostapd_iface *iface; size_t len = 0; @@ -6540,9 +6550,16 @@ static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd, for (i = 0; i < hapd->iface->interfaces->count; i++) { iface = hapd->iface->interfaces->iface[i]; + bool ap_mld = false; + +#ifdef CONFIG_IEEE80211BE + if (hapd->conf->mld_ap && iface->bss[0]->conf->mld_ap && + hapd->conf->mld_id == iface->bss[0]->conf->mld_id) + ap_mld = true; +#endif /* CONFIG_IEEE80211BE */ if (iface == hapd->iface || - !is_6ghz_op_class(iface->conf->op_class)) + !(is_6ghz_op_class(iface->conf->op_class) || ap_mld)) continue; len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd, @@ -6557,6 +6574,11 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type) { size_t total_len = 0, current_len = 0; enum colocation_mode mode = get_colocation_mode(hapd); + bool ap_mld = false; + +#ifdef CONFIG_IEEE80211BE + ap_mld = !!hapd->conf->mld_ap; +#endif /* CONFIG_IEEE80211BE */ switch (type) { case WLAN_FC_STYPE_BEACON: @@ -6565,9 +6587,10 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type) /* fallthrough */ case WLAN_FC_STYPE_PROBE_RESP: - if (mode == COLOCATED_LOWER_BAND) - total_len += hostapd_eid_rnr_colocation_len( - hapd, ¤t_len); + if (mode == COLOCATED_LOWER_BAND || ap_mld) + total_len += + hostapd_eid_rnr_multi_iface_len(hapd, + ¤t_len); if (hapd->conf->rnr && hapd->iface->num_bss > 1 && !hapd->iconf->mbssid) @@ -6657,6 +6680,11 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd, size_t len = *current_len; u8 *tbtt_count_pos, *eid_start = eid, *size_offset = (eid - len) + 1; u8 tbtt_count = 0, op_class, channel, bss_param; + bool ap_mld = false; + +#ifdef CONFIG_IEEE80211BE + ap_mld = !!hapd->conf->mld_ap; +#endif /* CONFIG_IEEE80211BE */ if (!(iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || !iface->freq) return eid; @@ -6679,7 +6707,7 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd, } tbtt_count_pos = eid++; - *eid++ = RNR_TBTT_INFO_LEN; + *eid++ = ap_mld ? RNR_TBTT_INFO_MLD_LEN : RNR_TBTT_INFO_LEN; *eid++ = op_class; *eid++ = hapd->iconf->channel; len += RNR_TBTT_HEADER_LEN; @@ -6728,7 +6756,18 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd, *eid++ = bss_param; *eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER - 1; - len += RNR_TBTT_INFO_LEN; + + if (!ap_mld) { + len += RNR_TBTT_INFO_LEN; + } else { +#ifdef CONFIG_IEEE80211BE + *eid++ = hapd->conf->mld_id; + *eid++ = hapd->mld_link_id | (1 << 4); + *eid++ = 0; + len += RNR_TBTT_INFO_MLD_LEN; +#endif /* CONFIG_IEEE80211BE */ + } + tbtt_count += 1; } @@ -6745,8 +6784,8 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd, } -static u8 * hostapd_eid_rnr_colocation(struct hostapd_data *hapd, u8 *eid, - size_t *current_len) +static u8 * hostapd_eid_rnr_multi_iface(struct hostapd_data *hapd, u8 *eid, + size_t *current_len) { struct hostapd_iface *iface; size_t i; @@ -6756,9 +6795,16 @@ static u8 * hostapd_eid_rnr_colocation(struct hostapd_data *hapd, u8 *eid, for (i = 0; i < hapd->iface->interfaces->count; i++) { iface = hapd->iface->interfaces->iface[i]; + bool ap_mld = false; + +#ifdef CONFIG_IEEE80211BE + if (hapd->conf->mld_ap && iface->bss[0]->conf->mld_ap && + hapd->conf->mld_id == iface->bss[0]->conf->mld_id) + ap_mld = true; +#endif /* CONFIG_IEEE80211BE */ if (iface == hapd->iface || - !is_6ghz_op_class(iface->conf->op_class)) + !(is_6ghz_op_class(iface->conf->op_class) || ap_mld)) continue; eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid, @@ -6774,6 +6820,11 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type) u8 *eid_start = eid; size_t current_len = 0; enum colocation_mode mode = get_colocation_mode(hapd); + bool ap_mld = false; + +#ifdef CONFIG_IEEE80211BE + ap_mld = !!hapd->conf->mld_ap; +#endif /* CONFIG_IEEE80211BE */ switch (type) { case WLAN_FC_STYPE_BEACON: @@ -6782,9 +6833,9 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type) /* fallthrough */ case WLAN_FC_STYPE_PROBE_RESP: - if (mode == COLOCATED_LOWER_BAND) - eid = hostapd_eid_rnr_colocation(hapd, eid, - ¤t_len); + if (mode == COLOCATED_LOWER_BAND || ap_mld) + eid = hostapd_eid_rnr_multi_iface(hapd, eid, + ¤t_len); if (hapd->conf->rnr && hapd->iface->num_bss > 1 && !hapd->iconf->mbssid) @@ -7099,8 +7150,8 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, if (hapd->conf->rnr) rnr_eid = hostapd_eid_nr_db(hapd, rnr_eid, &cur_len); if (get_colocation_mode(hapd) == COLOCATED_LOWER_BAND) - rnr_eid = hostapd_eid_rnr_colocation(hapd, rnr_eid, - &cur_len); + rnr_eid = hostapd_eid_rnr_multi_iface(hapd, rnr_eid, + &cur_len); } return eid; diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 12789227c..b86906828 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -2454,6 +2454,7 @@ struct ieee80211_he_mu_edca_parameter_set { #define RNR_TBTT_INFO_COUNT(x) (((x) & 0xf) << 4) #define RNR_TBTT_INFO_COUNT_MAX 16 #define RNR_TBTT_INFO_LEN 13 +#define RNR_TBTT_INFO_MLD_LEN 16 #define RNR_NEIGHBOR_AP_OFFSET_UNKNOWN 255 /* Figure 9-632a - BSS Parameters subfield format */ #define RNR_BSS_PARAM_OCT_RECOMMENDED BIT(0)