[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,
+-								&current_len);
++				hostapd_eid_rnr_colocation_len(hapd,
++							       &current_len);
+ 
+ 		if (hapd->conf->rnr && hapd->iface->num_bss > 1 &&
+ 		    !hapd->iconf->mbssid)
+ 			total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
+ 							       &current_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,
+ 							       &current_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, &current_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,
+-							  &current_len);
++		if (mode == COLOCATED_LOWER_BAND)
++			eid = hostapd_eid_rnr_colocation(hapd, eid,
++							 &current_len);
+ 
+ 		if (hapd->conf->rnr && hapd->iface->num_bss > 1 &&
+ 		    !hapd->iconf->mbssid)
+ 			eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
+-						    &current_len, NULL);
++						    &current_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,
+-						    &current_len, NULL);
++						    &current_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, &current_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
+