wifi: mac80211: clarify beacon parsing with MBSSID/EMA

When connected to a non-transmitting BSS of multiple BSSID
set with EMA, the correct profile for the connection isn't
always present in the beacon. Indicate this in the parser
and use the information to not check everything in beacon
processing, since the information might not be correct if
taken only from the transmitted BSS.

Link: https://patch.msgid.link/20260529102644.97527a7dfd7b.Iecd0ef578b85a5a0057538cfff5fdff41d19b7ea@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2026-05-29 10:24:58 +02:00
parent e41dc5921e
commit 32e2231985
3 changed files with 75 additions and 21 deletions

View File

@ -1898,6 +1898,15 @@ struct ieee802_11_elems {
struct ieee80211_mle_per_sta_profile *prof;
size_t sta_prof_len;
/*
* When parsing the beacon with MBSSID (from a transmitted BSS), this
* indicates that the profile the parser was instructed to look for
* (via the bss value in &struct ieee80211_elems_parse_params) couldn't
* be found (due to EMA, or perhaps broken AP) and the result cannot be
* considered complete.
*/
bool mbssid_nontx_profile_missing;
/* whether/which parse error occurred while retrieving these elements */
u8 parse_error;
};

View File

@ -7666,8 +7666,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
struct link_sta_info *link_sta;
struct sta_info *sta;
u64 changed = 0;
bool erp_valid;
u8 erp_value = 0;
u32 ncrc = 0;
u8 *bssid, *variable = mgmt->u.beacon.variable;
u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
@ -7788,6 +7786,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
if (!elems)
return;
/*
* Note: with MBSSID and an EMA (or broken) AP, we could fail to find
* the correct multi-BSSID profile for the non-transmitting AP we're
* connected to. The result's elems->mbssid_nontx_profile_missing is
* indicating that, but some things must happen regardless.
*/
if (rx_status->flag & RX_FLAG_DECRYPTED &&
ieee80211_mgd_ssid_mismatch(sdata, elems)) {
sdata_info(sdata, "SSID mismatch for AP %pM, disconnect\n",
@ -7823,6 +7828,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
}
}
/*
* P2P will almost certainly not have MBSSID, but this just
* assumes that it would at least always inherit NoA anyway
* since it's absent from the channel.
*/
if (sdata->vif.p2p ||
sdata->vif.driver_flags & IEEE80211_VIF_GET_NOA_UPDATE) {
struct ieee80211_p2p_noa_attr noa = {};
@ -7880,23 +7890,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
ieee80211_rx_bss_info(link, mgmt, len, rx_status);
/*
* This assumes that all members of a multiple BSS set must be
* switching together, so we can parse channel switch elements
* from the transmitted BSS even if our non-transmitted one is
* not present in this beacon (due to EMA.)
*/
ieee80211_sta_process_chanswitch(link, rx_status->mactime,
rx_status->device_timestamp,
elems, elems,
IEEE80211_CSA_SOURCE_BEACON);
/* note that after this elems->ml_basic can no longer be used fully */
ieee80211_mgd_check_cross_link_csa(sdata, rx_status->link_id, elems);
ieee80211_mgd_update_bss_param_ch_cnt(sdata, bss_conf, elems);
if (!sdata->u.mgd.epcs.enabled &&
!link->u.mgd.disable_wmm_tracking &&
ieee80211_sta_wmm_params(local, link, elems->wmm_param,
elems->wmm_param_len,
elems->mu_edca_param_set))
changed |= BSS_CHANGED_QOS;
/*
* If we haven't had a beacon before, tell the driver about the
* DTIM period (and beacon timing if desired) now.
@ -7913,17 +7917,53 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
ieee80211_recalc_ps_vif(sdata);
}
if (elems->erp_info) {
erp_valid = true;
erp_value = elems->erp_info[0];
} else {
erp_valid = false;
}
/* RNR isn't inside an MBSSID profile */
ieee80211_mgd_update_bss_param_ch_cnt(sdata, bss_conf, elems);
/* assume ERP would be inherited anyway */
if (!ieee80211_is_s1g_beacon(hdr->frame_control)) {
u8 erp_value = 0;
bool erp_valid;
if (elems->erp_info) {
erp_valid = true;
erp_value = elems->erp_info[0];
} else {
erp_valid = false;
}
if (!ieee80211_is_s1g_beacon(hdr->frame_control))
changed |= ieee80211_handle_bss_capability(link,
le16_to_cpu(mgmt->u.beacon.capab_info),
erp_valid, erp_value);
}
/*
* There are some other things that we can only do when the
* real non-transmitted profile was actually parsed, so exit
* here before doing those.
*/
if (elems->mbssid_nontx_profile_missing)
goto apply;
/*
* This requires multi-link element, which is from the MBSSID profile.
* Note that after this elems->ml_basic can no longer be used fully.
*
* Note also that currently the parsing is incorrect, so this will
* never actually do anything.
*/
ieee80211_mgd_check_cross_link_csa(sdata, rx_status->link_id, elems);
/*
* EDCA parameters should be the same, but perhaps ACM can differ
* between BSSes in an MBSSID set.
*/
if (!sdata->u.mgd.epcs.enabled &&
!link->u.mgd.disable_wmm_tracking &&
ieee80211_sta_wmm_params(local, link, elems->wmm_param,
elems->wmm_param_len,
elems->mu_edca_param_set))
changed |= BSS_CHANGED_QOS;
sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
if (WARN_ON(!sta)) {
@ -7969,6 +8009,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
ieee80211_process_adv_ttlm(sdata, elems,
le64_to_cpu(mgmt->u.beacon.timestamp));
apply:
ieee80211_link_info_change_notify(sdata, link, changed);
free:
kfree(elems);

View File

@ -1109,6 +1109,10 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
sub.type = params->type;
sub.link_id = params->link_id;
/* indicate to consumer whether or not profile was found */
if (params->bss->transmitted_bss && !nontx_len)
elems->mbssid_nontx_profile_missing = true;
/* consume the space used for non-transmitted profile */
elems_parse->scratch_pos += nontx_len;