]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP MLD: Include BPCC only in (Re)Associtiation Response frames
authorMohan Kumar G <mkumarg@qti.qualcomm.com>
Mon, 16 Jun 2025 11:22:51 +0000 (16:52 +0530)
committerJouni Malinen <j@w1.fi>
Thu, 19 Jun 2025 20:32:44 +0000 (23:32 +0300)
Currently in ML Probe response, the per-STA Profile STA control has BSS
Parameters Change Count (BPCC) present by default for all frames.

As per IEEE P802.11be/D7.0, 9.4.2.322.2.4, AP sets this field to 1 in
(Re)Association Response frame and sets to 0 in other frames.

Hence, update this by including the BPCC present bitmask and BPCC value
in STA Info field for ML (Re)Association Response frames only. However,
since this seems to break interoperability with the current mac80211
implementation for processing Link Reconfiguration Response frames,
leave BPCC present in the Basic MLE in those frames as a workaround for
now.

Signed-off-by: Mohan Kumar G <mkumarg@qti.qualcomm.com>
Signed-off-by: Yuvarani V <yuvarani@qti.qualcomm.com>
Signed-off-by: Manish Dharanenthiran <manish.dharanenthiran@oss.qualcomm.com>
src/ap/beacon.c
src/ap/ieee802_11.c
src/ap/ieee802_11.h
src/ap/ieee802_11_eht.c

index 3bff0ae368fb6b377807f5c57372e00f36903227..fd88ec93ec6dc05292c748fbaf9f4f2edfa7019a 100644 (file)
@@ -791,7 +791,8 @@ static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
 
                if (hapd_probed != hapd && hapd_probed->conf->mld_ap)
                        buflen += hostapd_eid_eht_basic_ml_len(hapd_probed,
-                                                              NULL, true);
+                                                              NULL, true,
+                                                              false);
        }
 #endif /* CONFIG_IEEE80211BE */
 
@@ -957,7 +958,7 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
 
        if (hapd_probed != hapd && hapd_probed->conf->mld_ap)
                pos = hostapd_eid_eht_basic_ml_common(hapd_probed, pos, NULL,
-                                                     true);
+                                                     true, false);
 #endif /* CONFIG_IEEE80211BE */
 
 #ifdef CONFIG_IEEE80211AC
index 744c0b131bfdca057831b7601611cef3e98745ab..866a1c1c89bceeb411b78e572a4d1c1a4de5e33d 100644 (file)
@@ -8567,9 +8567,8 @@ static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
                 * be in the frame body */
                if (bss->conf->mld_ap &&
                    (bss != hapd || frame_type != WLAN_FC_STYPE_PROBE_RESP))
-                       nontx_profile_len += hostapd_eid_eht_basic_ml_len(bss,
-                                                                         NULL,
-                                                                         true);
+                       nontx_profile_len += hostapd_eid_eht_basic_ml_len(
+                               bss, NULL, true, false);
 #endif /* CONFIG_IEEE80211BE */
 
                if (ie_count)
@@ -8744,7 +8743,7 @@ static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
                if (bss->conf->mld_ap &&
                    (bss != hapd || frame_type != WLAN_FC_STYPE_PROBE_RESP))
                        eid = hostapd_eid_eht_basic_ml_common(bss, eid, NULL,
-                                                             true);
+                                                             true, false);
 #endif /* CONFIG_IEEE80211BE */
                if (ie_count) {
                        *eid++ = WLAN_EID_EXTENSION;
index c3c92b7a1988c1564f0a8b402b8b1f3a23c1bf76..f1230da34cc87a07670feca53dc7ccce409d7cec 100644 (file)
@@ -127,10 +127,10 @@ u8 * hostapd_eid_eht_ml_assoc(struct hostapd_data *hapd, struct sta_info *info,
                              u8 *eid);
 u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
                                     u8 *eid, struct mld_info *mld_info,
-                                    bool include_mld_id);
+                                    bool include_mld_id, bool include_bpcc);
 size_t hostapd_eid_eht_basic_ml_len(struct hostapd_data *hapd,
                                    struct sta_info *info,
-                                   bool include_mld_id);
+                                   bool include_mld_id, bool include_pbcc);
 size_t hostapd_eid_eht_ml_beacon_len(struct hostapd_data *hapd,
                                     struct mld_info *info,
                                     bool include_mld_id);
index 6c67349fcbf9e693c1be1b54cb5338f3b78e1ddf..6b844e4bfd1de0be718db8c80558f0b6d9a81b85 100644 (file)
@@ -451,13 +451,12 @@ void hostapd_get_eht_capab(struct hostapd_data *hapd,
 #define EHT_ML_COMMON_INFO_LEN 13
 /*
  * control (2) + station info length (1) + MAC address (6) +
- * beacon interval (2) + TSF offset (8) + DTIM info (2) +
- * BSS Parameters Change count(1)
+ * beacon interval (2) + TSF offset (8) + DTIM info (2)
  */
-#define EHT_ML_STA_INFO_LEN 22
+#define EHT_ML_STA_INFO_LEN 21
 u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
                                     u8 *eid, struct mld_info *mld_info,
-                                    bool include_mld_id)
+                                    bool include_mld_id, bool include_bpcc)
 {
        struct wpabuf *buf;
        u16 control;
@@ -551,10 +550,9 @@ u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
        /* Add link info for the other links */
        for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
                struct mld_link_info *link = &mld_info->links[link_id];
+               size_t sta_info_len = EHT_ML_STA_INFO_LEN;
                struct hostapd_data *link_bss;
-
-               size_t total_len = EHT_ML_STA_INFO_LEN +
-                       link->resp_sta_profile_len;
+               size_t total_len;
 
                /* Skip the local one */
                if (link_id == hapd->mld_link_id || !link->valid)
@@ -567,6 +565,13 @@ u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
                        continue;
                }
 
+               /* BSS Parameters Change Count (1) for (Re)Association Response
+                * frames */
+               if (include_bpcc)
+                       sta_info_len++;
+
+               total_len = sta_info_len + link->resp_sta_profile_len;
+
                /* Per-STA Profile subelement */
                wpabuf_put_u8(buf, EHT_ML_SUB_ELEM_PER_STA_PROFILE);
 
@@ -581,14 +586,17 @@ u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
                        EHT_PER_STA_CTRL_COMPLETE_PROFILE_MSK |
                        EHT_PER_STA_CTRL_TSF_OFFSET_PRESENT_MSK |
                        EHT_PER_STA_CTRL_BEACON_INTERVAL_PRESENT_MSK |
-                       EHT_PER_STA_CTRL_DTIM_INFO_PRESENT_MSK |
-                       EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK;
+                       EHT_PER_STA_CTRL_DTIM_INFO_PRESENT_MSK;
+
+               if (include_bpcc)
+                       control |= EHT_PER_STA_CTRL_BSS_PARAM_CNT_PRESENT_MSK;
+
                wpabuf_put_le16(buf, control);
 
                /* STA Info */
 
                /* STA Info Length */
-               wpabuf_put_u8(buf, EHT_ML_STA_INFO_LEN - 2);
+               wpabuf_put_u8(buf, sta_info_len - 2);
                wpabuf_put_data(buf, link->local_addr, ETH_ALEN);
                wpabuf_put_le16(buf, link_bss->iconf->beacon_int);
 
@@ -604,7 +612,8 @@ u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
                wpabuf_put_u8(buf, link_bss->conf->dtim_period);
 
                /* BSS Parameters Change Count */
-               wpabuf_put_u8(buf, hapd->eht_mld_bss_param_change);
+               if (include_bpcc)
+                       wpabuf_put_u8(buf, hapd->eht_mld_bss_param_change);
 
                if (!link->resp_sta_profile)
                        continue;
@@ -617,7 +626,7 @@ u8 * hostapd_eid_eht_basic_ml_common(struct hostapd_data *hapd,
                        ptr = link->resp_sta_profile;
                        len = link->resp_sta_profile_len;
 
-                       slice_len = 255 - EHT_ML_STA_INFO_LEN;
+                       slice_len = 255 - sta_info_len;
 
                        wpabuf_put_data(buf, ptr, slice_len);
                        len -= slice_len;
@@ -680,7 +689,7 @@ out:
 
 size_t hostapd_eid_eht_basic_ml_len(struct hostapd_data *hapd,
                                    struct sta_info *info,
-                                   bool include_mld_id)
+                                   bool include_mld_id, bool include_bpcc)
 {
        int link_id;
        size_t len, num_frags;
@@ -718,6 +727,11 @@ size_t hostapd_eid_eht_basic_ml_len(struct hostapd_data *hapd,
                        continue;
                }
 
+               /* BSS Parameters Change Count (1) for (Re)Association Response
+                * frames */
+               if (include_bpcc)
+                       sta_prof_len++;
+
                /* Per-STA Profile Subelement(1), Length (1) */
                len += 2;
                len += sta_prof_len;
@@ -816,7 +830,7 @@ static u8 * hostapd_eid_eht_reconf_ml(struct hostapd_data *hapd, u8 *eid)
 
 
 static size_t hostapd_eid_eht_ml_len(struct mld_info *info,
-                                    bool include_mld_id)
+                                    bool include_mld_id, bool include_bpcc)
 {
        size_t len = 0;
        size_t eht_ml_len = 2 + EHT_ML_COMMON_INFO_LEN;
@@ -836,6 +850,11 @@ static size_t hostapd_eid_eht_ml_len(struct mld_info *info,
 
                sta_len += link->resp_sta_profile_len;
 
+               /* BSS Parameters Change Count (1) for (Re)Association Response
+                * frames */
+               if (include_bpcc)
+                       sta_len++;
+
                /* Element data and (fragmentation) headers */
                eht_ml_len += sta_len;
                eht_ml_len += 2 + sta_len / 255 * 2;
@@ -860,7 +879,8 @@ u8 * hostapd_eid_eht_ml_beacon(struct hostapd_data *hapd,
                               struct mld_info *info,
                               u8 *eid, bool include_mld_id)
 {
-       eid = hostapd_eid_eht_basic_ml_common(hapd, eid, info, include_mld_id);
+       eid = hostapd_eid_eht_basic_ml_common(hapd, eid, info, include_mld_id,
+                                             false);
        return hostapd_eid_eht_reconf_ml(hapd, eid);
 }
 
@@ -873,7 +893,7 @@ u8 * hostapd_eid_eht_ml_assoc(struct hostapd_data *hapd, struct sta_info *info,
                return eid;
 
        eid = hostapd_eid_eht_basic_ml_common(hapd, eid, &info->mld_info,
-                                             false);
+                                             false, true);
        ap_sta_free_sta_profile(&info->mld_info);
        return hostapd_eid_eht_reconf_ml(hapd, eid);
 }
@@ -883,7 +903,7 @@ size_t hostapd_eid_eht_ml_beacon_len(struct hostapd_data *hapd,
                                     struct mld_info *info,
                                     bool include_mld_id)
 {
-       return hostapd_eid_eht_ml_len(info, include_mld_id);
+       return hostapd_eid_eht_ml_len(info, include_mld_id, false);
 }
 
 
@@ -1904,7 +1924,14 @@ hostapd_send_link_reconf_resp(struct hostapd_data *hapd,
                        link->valid = true;
                        ieee80211_ml_build_assoc_resp(lhapd, link);
                }
-               mle_len = hostapd_eid_eht_ml_len(&mld, false);
+               /* TODO: Basic MLE is not supposed to include BPCC in Link
+                * Reconfiguration Response, but mac80211 implementation for
+                * processing this frame requires that to be present. For now,
+                * include that subfield as a workaround. This should be removed
+                * once mac80211 is fixed to match the standard (or this comment
+                * be removed if the standard is modified to match
+                * implementation). */
+               mle_len = hostapd_eid_eht_ml_len(&mld, false, true);
                len += mle_len;
        }
 
@@ -2000,8 +2027,15 @@ hostapd_send_link_reconf_resp(struct hostapd_data *hapd,
        if (mle_len) {
                u8 *mle_pos = pos;
 
+               /* TODO: Basic MLE is not supposed to include BPCC in Link
+                * Reconfiguration Response, but mac80211 implementation for
+                * processing this frame requires that to be present. For now,
+                * include that subfield as a workaround. This should be removed
+                * once mac80211 is fixed to match the standard (or this comment
+                * be removed if the standard is modified to match
+                * implementation). */
                mle_pos = hostapd_eid_eht_basic_ml_common(hapd, mle_pos, &mld,
-                                                         false);
+                                                         false, true);
                if ((size_t) (mle_pos - pos) != mle_len) {
                        reject_all = true;
                        goto reject_all_req;