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 <ilan.peer@intel.com>
This commit is contained in:
Ilan Peer 2023-05-22 22:33:37 +03:00 committed by Jouni Malinen
parent 0c6c948047
commit 2b541601da
4 changed files with 89 additions and 26 deletions

View file

@ -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]);
}
}

View file

@ -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:

View file

@ -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, &current_len);
if (mode == COLOCATED_LOWER_BAND || ap_mld)
total_len +=
hostapd_eid_rnr_multi_iface_len(hapd,
&current_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,
&current_len);
if (mode == COLOCATED_LOWER_BAND || ap_mld)
eid = hostapd_eid_rnr_multi_iface(hapd, eid,
&current_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;

View file

@ -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)