]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: mac80211: clarify beacon parsing with MBSSID/EMA
authorJohannes Berg <johannes.berg@intel.com>
Fri, 29 May 2026 08:24:58 +0000 (10:24 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 3 Jun 2026 12:11:57 +0000 (14:11 +0200)
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>
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/parse.c

index 18a1017104325c03b2dcef5bdb8039c2e7073699..339faa7a0a0e26c8acd5fc2e760c1f682160fb9f 100644 (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;
 };
index f55cb376cbd517b24ecd95a8cfd09b2c9151d760..2888a382677dcd5df033b93b3227bfe20d5ea379 100644 (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);
index 2587284fa67baa9e44903b5ac3dd00fcb611cf49..c7d882ccc4c6db328acfd518fe6cfc429e99294b 100644 (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;