[rdkb][common][bsp][Refactor and sync wifi from openwrt]
[Description]
ac60b1ff [MAC80211][misc][Add Filogic 880/860/830/820/630 Release Information]
7eb946a0 [MAC80211][WiFi7][hostapd][sync hostapd patches]
91638fc9 [MAC80211][WiFi7][mac80211][sync backports code]
8e45746b [MAC80211][WiFi7][mt76][sync mt76 patches]
1c564afa [MAC80211][WiFi7][mt76][Add Eagle BE19000 ifem default bin]
[Release-log]
Change-Id: I1d4218d3b1211700acb5937fe310cbd0bf219968
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/0020-hostapd-fix-RNR-building-for-co-location-and-MLO.patch b/recipes-wifi/hostapd/files/patches-2.10.3/0020-hostapd-fix-RNR-building-for-co-location-and-MLO.patch
new file mode 100644
index 0000000..879adf1
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/0020-hostapd-fix-RNR-building-for-co-location-and-MLO.patch
@@ -0,0 +1,748 @@
+From 8affcd80f5143fa23d3f21427b6b9f11af35ef5d Mon Sep 17 00:00:00 2001
+From: Aditya Kumar Singh <quic_adisi@quicinc.com>
+Date: Thu, 28 Mar 2024 23:46:50 +0530
+Subject: [PATCH 020/104] hostapd: fix RNR building for co-location and MLO
+
+Currently with MLO changes, RNR formation for co-location or MLO
+was not working as expected. Hence make it work as per the
+expectation.
+
+For example, during co-location, if the BSS is also its ML partner
+then there is no need to include a separate TBTT for it.
+
+Also, during co-location, if the BSS is not its partner but it is
+ML capable, then the TBTT length should be 16 bytes and it should
+include the MLD Parameters for it in the RNR.
+
+During co-location, for a given Neighbor AP (operating on a given
+channel and op-class) if it has BSSes which are ML capable as well
+as BSSes which are not, then there should be two Neighbor AP Info
+present. One indicating TBTT length as 13 bytes and one indicating
+TBTT info length as 16 bytes.
+
+Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
+---
+ src/ap/beacon.c | 12 +-
+ src/ap/ieee802_11.c | 387 ++++++++++++++++++++++++++++++++------------
+ src/ap/ieee802_11.h | 5 +-
+ 3 files changed, 290 insertions(+), 114 deletions(-)
+
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index b780d98e4..4354dfae3 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -677,7 +677,7 @@ static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
+ params->known_bss,
+ params->known_bss_len, NULL);
+ if (!params->is_ml_sta_info)
+- buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
++ buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP, true);
+ buflen += hostapd_mbo_ie_len(hapd);
+ buflen += hostapd_eid_owe_trans_len(hapd);
+ buflen += hostapd_eid_dpp_cc_len(hapd);
+@@ -797,7 +797,7 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
+ pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
+
+ if (!params->is_ml_sta_info)
+- pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP);
++ pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP, true);
+ pos = hostapd_eid_fils_indic(hapd, pos, 0);
+ pos = hostapd_get_rsnxe(hapd, pos, epos - pos);
+
+@@ -1946,7 +1946,7 @@ static u8 * hostapd_gen_fils_discovery(struct hostapd_data *hapd, size_t *len)
+ total_len += 3;
+ }
+
+- total_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_ACTION);
++ total_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_ACTION, true);
+
+ pos = hostapd_eid_fils_indic(hapd, buf, 0);
+ buf_len = pos - buf;
+@@ -2020,7 +2020,7 @@ static u8 * hostapd_gen_fils_discovery(struct hostapd_data *hapd, size_t *len)
+ /* Fill in the Length field value */
+ *length_pos = pos - (length_pos + 1);
+
+- pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_ACTION);
++ pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_ACTION, true);
+
+ /* FILS Indication element */
+ if (buf_len) {
+@@ -2126,7 +2126,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
+ hapd == hostapd_mbssid_get_tx_bss(hapd))
+ tail_len += 5; /* Multiple BSSID Configuration element */
+- tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
++ tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON, true);
+ tail_len += hostapd_mbo_ie_len(hapd);
+ tail_len += hostapd_eid_owe_trans_len(hapd);
+ tail_len += hostapd_eid_dpp_cc_len(hapd);
+@@ -2262,7 +2262,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+
+ tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
+
+- tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON);
++ tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON, true);
+ tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
+ tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos);
+ tailpos = hostapd_eid_mbssid_config(hapd, tailpos,
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 7ee18f4ae..9a23c7240 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -7273,20 +7273,21 @@ static size_t
+ hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
+ struct hostapd_data *reporting_hapd,
+ size_t *current_len,
+- struct mbssid_ie_profiles *skip_profiles)
++ struct mbssid_ie_profiles *skip_profiles,
++ bool mld_update)
+ {
+ size_t total_len = 0, len = *current_len;
+- int tbtt_count = 0;
+- size_t i, start = 0;
+- bool ap_mld = false;
++ int tbtt_count, total_tbtt_count = 0;
++ size_t i, start;
++ u8 tbtt_info_len = mld_update ? RNR_TBTT_INFO_MLD_LEN : RNR_TBTT_INFO_LEN;
+
+-#ifdef CONFIG_IEEE80211BE
+- ap_mld = !!hapd->conf->mld_ap;
+-#endif /* CONFIG_IEEE80211BE */
++repeat_rnr_len:
++ start = 0;
++ tbtt_count = 0;
+
+ while (start < hapd->iface->num_bss) {
+ if (!len ||
+- len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255 ||
++ len + RNR_TBTT_HEADER_LEN + tbtt_info_len > 255 ||
+ tbtt_count >= RNR_TBTT_INFO_COUNT_MAX) {
+ len = RNR_HEADER_LEN;
+ total_len += RNR_HEADER_LEN;
+@@ -7298,10 +7299,15 @@ hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
+
+ for (i = start; i < hapd->iface->num_bss; i++) {
+ struct hostapd_data *bss = hapd->iface->bss[i];
++ bool ap_mld = false;
+
+ if (!bss || !bss->conf || !bss->started)
+ continue;
+
++#ifdef CONFIG_IEEE80211BE
++ ap_mld = !!bss->conf->mld_ap;
++#endif /* CONFIG_IEEE80211BE */
++
+ if (bss == reporting_hapd ||
+ bss->conf->ignore_broadcast_ssid)
+ continue;
+@@ -7310,23 +7316,71 @@ hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
+ i >= skip_profiles->start && i < skip_profiles->end)
+ continue;
+
+- if (len + RNR_TBTT_INFO_LEN > 255 ||
++ /* No need to report if length is for normal TBTT and the BSS
++ * is a MLD. MLD TBTT will include this.
++ */
++ if (tbtt_info_len == RNR_TBTT_INFO_LEN && ap_mld)
++ continue;
++
++ /* No need to report if length is for MLD TBTT and the BSS
++ * is not MLD. Normal TBTT will include this.
++ */
++ if (tbtt_info_len == RNR_TBTT_INFO_MLD_LEN && !ap_mld)
++ continue;
++
++#ifdef CONFIG_IEEE80211BE
++ /* If building for co-location and they are ML partners,
++ * no need to include since the ML RNR will carry this.
++ */
++ if (!mld_update && hostapd_is_ml_partner(reporting_hapd, bss))
++ continue;
++
++ /* If building for ML RNR and they are not ML parnters,
++ * don't include.
++ */
++ if (mld_update && !hostapd_is_ml_partner(reporting_hapd, bss))
++ continue;
++#endif /* CONFIG_IEEE80211BE */
++
++ if (len + tbtt_info_len > 255 ||
+ tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
+ break;
+
+- 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;
+- }
++ len += tbtt_info_len;
++ total_len += tbtt_info_len;
+ tbtt_count++;
+ }
+ start = i;
+ }
+
+- if (!tbtt_count)
++ total_tbtt_count += tbtt_count;
++
++ /* If building for co-location, re-build again but this time include
++ * ML TBTTs.
++ */
++ if (!mld_update && tbtt_info_len == RNR_TBTT_INFO_LEN) {
++ tbtt_info_len = RNR_TBTT_INFO_MLD_LEN;
++
++ /* If no TBTT was found, then adjust the len and total_len since
++ * it would have incremented before we checked all bss.
++ */
++ if (!tbtt_count) {
++ len -= RNR_TBTT_HEADER_LEN;
++ total_len -= RNR_TBTT_HEADER_LEN;
++ }
++
++ goto repeat_rnr_len;
++ }
++
++ /* this is possible when it re-built and in that no suitable TBTT was
++ * found. Adjust the length accordingly.
++ */
++ if (!tbtt_count && total_tbtt_count) {
++ len -= RNR_TBTT_HEADER_LEN;
++ total_len -= RNR_TBTT_HEADER_LEN;
++ }
++
++ if (!total_tbtt_count)
+ total_len = 0;
+ else
+ *current_len = len;
+@@ -7375,8 +7429,8 @@ static enum colocation_mode get_colocation_mode(struct hostapd_data *hapd)
+ }
+
+
+-static size_t hostapd_eid_rnr_multi_iface_len(struct hostapd_data *hapd,
+- size_t *current_len)
++static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd,
++ size_t *current_len)
+ {
+ struct hostapd_iface *iface;
+ size_t len = 0;
+@@ -7387,34 +7441,57 @@ static size_t hostapd_eid_rnr_multi_iface_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 (hostapd_is_ml_partner(hapd, iface->bss[0]))
+- ap_mld = true;
+-#endif /* CONFIG_IEEE80211BE */
+
+- if (iface == hapd->iface ||
+- !(is_6ghz_op_class(iface->conf->op_class) || ap_mld))
++ if (!iface || iface == hapd->iface ||
++ !is_6ghz_op_class(iface->conf->op_class))
+ continue;
+
+ len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd,
+- current_len, NULL);
++ current_len, NULL, false);
+ }
+
+ return len;
+ }
+
+-
+-size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
++static size_t hostapd_eid_rnr_mlo_len(struct hostapd_data *hapd, u32 type,
++ size_t *current_len)
+ {
+- size_t total_len = 0, current_len = 0;
+- enum colocation_mode mode = get_colocation_mode(hapd);
+- bool ap_mld = false;
++ size_t len = 0;
+
+ #ifdef CONFIG_IEEE80211BE
+- ap_mld = !!hapd->conf->mld_ap;
++ struct hostapd_iface *iface;
++ size_t i;
++
++ if (!hapd->iface || !hapd->iface->interfaces)
++ return 0;
++
++ if (!hapd->conf->mld_ap)
++ return 0;
++
++ /* TODO allow for FILS/Action as well */
++ if (type != WLAN_FC_STYPE_BEACON && type != WLAN_FC_STYPE_PROBE_RESP)
++ return 0;
++
++ for (i = 0; i < hapd->iface->interfaces->count; i++) {
++ iface = hapd->iface->interfaces->iface[i];
++
++ if (!iface || iface == hapd->iface)
++ continue;
++
++ if (hapd->iface->freq == iface->freq)
++ continue;
++
++ len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd,
++ current_len, NULL, true);
++ }
+ #endif /* CONFIG_IEEE80211BE */
++ return len;
++}
++
++size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type, bool include_mld_params)
++{
++ size_t total_len = 0, current_len = 0;
++ enum colocation_mode mode = get_colocation_mode(hapd);
+
+ switch (type) {
+ case WLAN_FC_STYPE_BEACON:
+@@ -7423,29 +7500,35 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
+ /* fallthrough */
+
+ case WLAN_FC_STYPE_PROBE_RESP:
+- if (mode == COLOCATED_LOWER_BAND || ap_mld)
++ if (mode == COLOCATED_LOWER_BAND)
+ total_len +=
+- hostapd_eid_rnr_multi_iface_len(hapd,
+- ¤t_len);
++ hostapd_eid_rnr_colocation_len(hapd,
++ ¤t_len);
+
+ if (hapd->conf->rnr && hapd->iface->num_bss > 1 &&
+ !hapd->iconf->mbssid)
+ total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
+ ¤t_len,
+- NULL);
++ NULL, false);
+ break;
+
+ case WLAN_FC_STYPE_ACTION:
+ if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ)
+ total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
+ ¤t_len,
+- NULL);
++ NULL, false);
+ break;
+
+ default:
+ break;
+ }
+
++ /* For EMA Beacons, MLD neighbor repoting is added as part of mbssid rnr */
++ if (include_mld_params &&
++ (type != WLAN_FC_STYPE_BEACON ||
++ hapd->iconf->mbssid != ENHANCED_MBSSID_ENABLED))
++ total_len += hostapd_eid_rnr_mlo_len(hapd, type, ¤t_len);
++
+ return total_len;
+ }
+
+@@ -7509,13 +7592,14 @@ static bool hostapd_eid_rnr_bss(struct hostapd_data *hapd,
+ struct hostapd_data *reporting_hapd,
+ struct mbssid_ie_profiles *skip_profiles,
+ size_t i, u8 *tbtt_count, size_t *len,
+- u8 **pos)
++ u8 **pos, u8 **tbtt_count_pos, u8 tbtt_info_len,
++ u8 op_class, bool mld_update)
+ {
+ struct hostapd_iface *iface = hapd->iface;
+ struct hostapd_data *bss = iface->bss[i];
+ u8 bss_param = 0;
+- bool ap_mld = false;
+ u8 *eid = *pos;
++ bool ap_mld = false;
+
+ #ifdef CONFIG_IEEE80211BE
+ ap_mld = !!hapd->conf->mld_ap;
+@@ -7529,10 +7613,47 @@ static bool hostapd_eid_rnr_bss(struct hostapd_data *hapd,
+ && i >= skip_profiles->start && i < skip_profiles->end)
+ return false;
+
++ /* No need to report if length is for normal TBTT and the BSS
++ * is a MLD. MLD TBTT will include this.
++ */
++ if (tbtt_info_len == RNR_TBTT_INFO_LEN && ap_mld)
++ return false;
++
++ /* No need to report if length is for MLD TBTT and the BSS
++ * is not MLD. Normal TBTT will include this.
++ */
++ if (tbtt_info_len == RNR_TBTT_INFO_MLD_LEN && !ap_mld)
++ return false;
++
++#ifdef CONFIG_IEEE80211BE
++ /* If building for co-location and they are ML partners,
++ * no need to include since the ML RNR will carry this.
++ */
++ if (!mld_update && hostapd_is_ml_partner(reporting_hapd, bss))
++ return false;
++
++ /* If building for ML RNR and they are not ML parnters,
++ * don't include.
++ */
++ if (mld_update && !hostapd_is_ml_partner(reporting_hapd, bss))
++ return false;
++#endif /* CONFIG_IEEE80211BE */
++
+ if (*len + RNR_TBTT_INFO_LEN > 255 ||
+ *tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
+ return true;
+
++ if (!(*tbtt_count)) {
++ /* Add Neighbor report header info only if there is at least
++ * one tbtt info available
++ */
++ *tbtt_count_pos = eid++;
++ *eid++ = tbtt_info_len;
++ *eid++ = op_class;
++ *eid++ = bss->iconf->channel;
++ *len += RNR_TBTT_HEADER_LEN;
++ }
++
+ *eid++ = RNR_NEIGHBOR_AP_OFFSET_UNKNOWN;
+ os_memcpy(eid, bss->own_addr, ETH_ALEN);
+ eid += ETH_ALEN;
+@@ -7556,29 +7677,36 @@ static bool hostapd_eid_rnr_bss(struct hostapd_data *hapd,
+ *eid++ = bss_param;
+ *eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER;
+
+- if (!ap_mld) {
+- *len += RNR_TBTT_INFO_LEN;
+- } else {
+ #ifdef CONFIG_IEEE80211BE
+- u8 param_ch = hapd->eht_mld_bss_param_change;
+-
+- if (hostapd_is_ml_partner(bss, reporting_hapd))
+- *eid++ = 0;
+- else
+- *eid++ = hostapd_get_mld_id(hapd);
+-
+- *eid++ = hapd->mld_link_id | ((param_ch & 0xF) << 4);
+- *eid = (param_ch >> 4) & 0xF;
++ if (ap_mld) {
++ u8 param_ch = bss->eht_mld_bss_param_change;
++ bool is_partner;
++
++ /* If bss is not partner of the reporting_hapd then
++ * a) MLD ID advertised shall be 255.
++ * b) Link ID advertised shall be 15.
++ * c) BPCC advertised shall be 255
++ */
++ is_partner = hostapd_is_ml_partner(bss, reporting_hapd);
++ /* MLD ID */
++ *eid++ = is_partner ? hostapd_get_mld_id(bss) : 0xFF;
++ /* Link ID (Bit 3 to Bit 0)
++ * BPCC (Bit 4 to Bit 7)
++ */
++ *eid++ = is_partner ?
++ bss->mld_link_id | ((param_ch & 0xF) << 4) :
++ (MAX_NUM_MLD_LINKS | 0xF0);
++ /* BPCC (Bit 3 to Bit 0) */
++ *eid = is_partner ? ((param_ch & 0xF0) >> 4) : 0x0F;
+ #ifdef CONFIG_TESTING_OPTIONS
+- if (hapd->conf->mld_indicate_disabled)
++ if (bss->conf->mld_indicate_disabled)
+ *eid |= RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED;
+ #endif /* CONFIG_TESTING_OPTIONS */
+ eid++;
+-
+- *len += RNR_TBTT_INFO_MLD_LEN;
+-#endif /* CONFIG_IEEE80211BE */
+ }
++#endif /* CONFIG_IEEE80211BE */
+
++ *len += tbtt_info_len;
+ (*tbtt_count)++;
+ *pos = eid;
+
+@@ -7589,18 +7717,16 @@ static bool hostapd_eid_rnr_bss(struct hostapd_data *hapd,
+ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
+ struct hostapd_data *reporting_hapd,
+ u8 *eid, size_t *current_len,
+- struct mbssid_ie_profiles *skip_profiles)
++ struct mbssid_ie_profiles *skip_profiles,
++ bool mld_update)
+ {
+ struct hostapd_iface *iface = hapd->iface;
+- size_t i, start = 0;
++ size_t i, start;
+ size_t len = *current_len;
+- u8 *tbtt_count_pos, *eid_start = eid, *size_offset = (eid - len) + 1;
+- u8 tbtt_count = 0, op_class, channel;
+- bool ap_mld = false;
+-
+-#ifdef CONFIG_IEEE80211BE
+- ap_mld = !!hapd->conf->mld_ap;
+-#endif /* CONFIG_IEEE80211BE */
++ u8 *eid_start = eid, *size_offset = (eid - len) + 1;
++ u8 *tbtt_count_pos = size_offset + 1;
++ u8 tbtt_count, total_tbtt_count = 0, op_class, channel;
++ u8 tbtt_info_len = mld_update ? RNR_TBTT_INFO_MLD_LEN : RNR_TBTT_INFO_LEN;
+
+ if (!(iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || !iface->freq)
+ return eid;
+@@ -7612,9 +7738,12 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
+ NUM_HOSTAPD_MODES)
+ return eid;
+
++repeat_rnr:
++ start = 0;
++ tbtt_count = 0;
+ while (start < iface->num_bss) {
+ if (!len ||
+- len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255 ||
++ len + RNR_TBTT_HEADER_LEN + tbtt_info_len > 255 ||
+ tbtt_count >= RNR_TBTT_INFO_COUNT_MAX) {
+ eid_start = eid;
+ *eid++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
+@@ -7623,34 +7752,42 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
+ tbtt_count = 0;
+ }
+
+- tbtt_count_pos = eid++;
+- *eid++ = ap_mld ? RNR_TBTT_INFO_MLD_LEN : RNR_TBTT_INFO_LEN;
+- *eid++ = op_class;
+- *eid++ = hapd->iconf->channel;
+- len += RNR_TBTT_HEADER_LEN;
+-
+ for (i = start; i < iface->num_bss; i++) {
+ if (hostapd_eid_rnr_bss(hapd, reporting_hapd,
+ skip_profiles, i,
+- &tbtt_count, &len, &eid))
++ &tbtt_count, &len, &eid,
++ &tbtt_count_pos, tbtt_info_len,
++ op_class, mld_update))
+ break;
+ }
+
+ start = i;
+- *tbtt_count_pos = RNR_TBTT_INFO_COUNT(tbtt_count - 1);
+- *size_offset = (eid - size_offset) - 1;
++
++ if (tbtt_count) {
++ *tbtt_count_pos = RNR_TBTT_INFO_COUNT(tbtt_count - 1);
++ *size_offset = (eid - size_offset) - 1;
++ }
++ }
++
++ total_tbtt_count += tbtt_count;
++
++ /* If building for co-location, re-build again but this time include
++ * ML TBTTs.
++ */
++ if (!mld_update && tbtt_info_len == RNR_TBTT_INFO_LEN) {
++ tbtt_info_len = RNR_TBTT_INFO_MLD_LEN;
++ goto repeat_rnr;
+ }
+
+- if (tbtt_count == 0)
++ if (!total_tbtt_count)
+ return eid_start;
+
+ *current_len = len;
+ return eid;
+ }
+
+-
+-static u8 * hostapd_eid_rnr_multi_iface(struct hostapd_data *hapd, u8 *eid,
+- size_t *current_len)
++u8 *hostapd_eid_rnr_colocation(struct hostapd_data *hapd, u8 *eid,
++ size_t *current_len)
+ {
+ struct hostapd_iface *iface;
+ size_t i;
+@@ -7660,35 +7797,56 @@ static u8 * hostapd_eid_rnr_multi_iface(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 (hostapd_is_ml_partner(hapd, iface->bss[0]))
+- ap_mld = true;
+-#endif /* CONFIG_IEEE80211BE */
+-
+- if (iface == hapd->iface ||
+- !(is_6ghz_op_class(iface->conf->op_class) || ap_mld))
++ if (!iface || iface == hapd->iface ||
++ !is_6ghz_op_class(iface->conf->op_class))
+ continue;
+
+ eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid,
+- current_len, NULL);
++ current_len, NULL, false);
+ }
+
+ return eid;
+ }
+
++u8 *hostapd_eid_rnr_mlo(struct hostapd_data *hapd, u32 type,
++ u8 *eid, size_t *current_len)
++{
++#ifdef CONFIG_IEEE80211BE
++ struct hostapd_iface *iface;
++ size_t i;
++
++ if (!hapd->iface || !hapd->iface->interfaces)
++ return eid;
++
++ if (!hapd->conf->mld_ap)
++ return eid;
++
++ /* TODO allow for FILS/Action as well */
++ if (type != WLAN_FC_STYPE_BEACON && type != WLAN_FC_STYPE_PROBE_RESP)
++ return eid;
++
++ for (i = 0; i < hapd->iface->interfaces->count; i++) {
++ iface = hapd->iface->interfaces->iface[i];
++
++ if (!iface || iface == hapd->iface)
++ continue;
++
++ if (hapd->iface->freq == iface->freq)
++ continue;
+
+-u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
++ eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid,
++ current_len, NULL, true);
++ }
++#endif /* CONFIG_IEEE80211BE */
++ return eid;
++}
++
++u8 *hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type, bool include_mld_params)
+ {
+ 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:
+@@ -7697,26 +7855,34 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
+ /* fallthrough */
+
+ case WLAN_FC_STYPE_PROBE_RESP:
+- if (mode == COLOCATED_LOWER_BAND || ap_mld)
+- eid = hostapd_eid_rnr_multi_iface(hapd, eid,
+- ¤t_len);
++ if (mode == COLOCATED_LOWER_BAND)
++ eid = hostapd_eid_rnr_colocation(hapd, eid,
++ ¤t_len);
+
+ if (hapd->conf->rnr && hapd->iface->num_bss > 1 &&
+ !hapd->iconf->mbssid)
+ eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
+- ¤t_len, NULL);
++ ¤t_len, NULL,
++ false);
+ break;
+
+ case WLAN_FC_STYPE_ACTION:
+ if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ)
+ eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
+- ¤t_len, NULL);
++ ¤t_len, NULL,
++ false);
+ break;
+
+ default:
+ return eid_start;
+ }
+
++ /* For EMA Beacons, MLD neighbor repoting is added as part of mbssid rnr */
++ if (include_mld_params &&
++ (type != WLAN_FC_STYPE_BEACON ||
++ hapd->iconf->mbssid != ENHANCED_MBSSID_ENABLED))
++ eid = hostapd_eid_rnr_mlo(hapd, type, eid, ¤t_len);
++
+ if (eid == eid_start + 2)
+ return eid_start;
+
+@@ -7815,6 +7981,11 @@ size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
+ size_t known_bss_len, size_t *rnr_len)
+ {
+ size_t len = 0, bss_index = 1;
++ bool ap_mld = false;
++
++#ifdef CONFIG_IEEE80211BE
++ ap_mld = !!hapd->conf->mld_ap;
++#endif /* CONFIG_IEEE80211BE */
+
+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
+ (frame_type != WLAN_FC_STYPE_BEACON &&
+@@ -7847,12 +8018,12 @@ size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
+
+ *rnr_len += hostapd_eid_rnr_iface_len(
+ hapd, hostapd_mbssid_get_tx_bss(hapd),
+- &rnr_cur_len, &skip_profiles);
++ &rnr_cur_len, &skip_profiles, ap_mld);
+ }
+ }
+
+ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED && rnr_len)
+- *rnr_len += hostapd_eid_rnr_len(hapd, frame_type);
++ *rnr_len += hostapd_eid_rnr_len(hapd, frame_type, false);
+
+ return len;
+ }
+@@ -7978,7 +8149,11 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
+ {
+ size_t bss_index = 1, cur_len = 0;
+ u8 elem_index = 0, *rnr_start_eid = rnr_eid;
+- bool add_rnr;
++ bool add_rnr, ap_mld = false;
++
++#ifdef CONFIG_IEEE80211BE
++ ap_mld = !!hapd->conf->mld_ap;
++#endif /* CONFIG_IEEE80211BE */
+
+ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
+ (frame_stype != WLAN_FC_STYPE_BEACON &&
+@@ -8023,7 +8198,7 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
+ cur_len = 0;
+ rnr_eid = hostapd_eid_rnr_iface(
+ hapd, hostapd_mbssid_get_tx_bss(hapd),
+- rnr_eid, &cur_len, &skip_profiles);
++ rnr_eid, &cur_len, &skip_profiles, ap_mld);
+ }
+ }
+
+@@ -8035,8 +8210,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_multi_iface(hapd, rnr_eid,
+- &cur_len);
++ rnr_eid = hostapd_eid_rnr_colocation(hapd, rnr_eid,
++ &cur_len);
+ }
+
+ return eid;
+diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
+index 262e0ce14..078f4baf9 100644
+--- a/src/ap/ieee802_11.h
++++ b/src/ap/ieee802_11.h
+@@ -225,8 +225,9 @@ void auth_sae_process_commit(void *eloop_ctx, void *user_ctx);
+ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len);
+ u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *ext_capab_ie, size_t ext_capab_ie_len);
+-size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type);
+-u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type);
++size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type, bool include_mld_params);
++u8 *hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type,
++ bool include_mld_params);
+ int ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
+ int res, struct radius_sta *info);
+ size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd,
+--
+2.39.2
+