blob: 879adf14dfca6ba8af03e7ebd2624760d3ccdb72 [file] [log] [blame]
developer66e89bc2024-04-23 14:50:01 +08001From 8affcd80f5143fa23d3f21427b6b9f11af35ef5d Mon Sep 17 00:00:00 2001
2From: Aditya Kumar Singh <quic_adisi@quicinc.com>
3Date: Thu, 28 Mar 2024 23:46:50 +0530
4Subject: [PATCH 020/104] hostapd: fix RNR building for co-location and MLO
5
6Currently with MLO changes, RNR formation for co-location or MLO
7was not working as expected. Hence make it work as per the
8expectation.
9
10For example, during co-location, if the BSS is also its ML partner
11then there is no need to include a separate TBTT for it.
12
13Also, during co-location, if the BSS is not its partner but it is
14ML capable, then the TBTT length should be 16 bytes and it should
15include the MLD Parameters for it in the RNR.
16
17During co-location, for a given Neighbor AP (operating on a given
18channel and op-class) if it has BSSes which are ML capable as well
19as BSSes which are not, then there should be two Neighbor AP Info
20present. One indicating TBTT length as 13 bytes and one indicating
21TBTT info length as 16 bytes.
22
23Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
24---
25 src/ap/beacon.c | 12 +-
26 src/ap/ieee802_11.c | 387 ++++++++++++++++++++++++++++++++------------
27 src/ap/ieee802_11.h | 5 +-
28 3 files changed, 290 insertions(+), 114 deletions(-)
29
30diff --git a/src/ap/beacon.c b/src/ap/beacon.c
31index b780d98e4..4354dfae3 100644
32--- a/src/ap/beacon.c
33+++ b/src/ap/beacon.c
34@@ -677,7 +677,7 @@ static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
35 params->known_bss,
36 params->known_bss_len, NULL);
37 if (!params->is_ml_sta_info)
38- buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
39+ buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP, true);
40 buflen += hostapd_mbo_ie_len(hapd);
41 buflen += hostapd_eid_owe_trans_len(hapd);
42 buflen += hostapd_eid_dpp_cc_len(hapd);
43@@ -797,7 +797,7 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
44 pos = hostapd_eid_wb_chsw_wrapper(hapd, pos);
45
46 if (!params->is_ml_sta_info)
47- pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP);
48+ pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_PROBE_RESP, true);
49 pos = hostapd_eid_fils_indic(hapd, pos, 0);
50 pos = hostapd_get_rsnxe(hapd, pos, epos - pos);
51
52@@ -1946,7 +1946,7 @@ static u8 * hostapd_gen_fils_discovery(struct hostapd_data *hapd, size_t *len)
53 total_len += 3;
54 }
55
56- total_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_ACTION);
57+ total_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_ACTION, true);
58
59 pos = hostapd_eid_fils_indic(hapd, buf, 0);
60 buf_len = pos - buf;
61@@ -2020,7 +2020,7 @@ static u8 * hostapd_gen_fils_discovery(struct hostapd_data *hapd, size_t *len)
62 /* Fill in the Length field value */
63 *length_pos = pos - (length_pos + 1);
64
65- pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_ACTION);
66+ pos = hostapd_eid_rnr(hapd, pos, WLAN_FC_STYPE_ACTION, true);
67
68 /* FILS Indication element */
69 if (buf_len) {
70@@ -2126,7 +2126,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
71 if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
72 hapd == hostapd_mbssid_get_tx_bss(hapd))
73 tail_len += 5; /* Multiple BSSID Configuration element */
74- tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
75+ tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON, true);
76 tail_len += hostapd_mbo_ie_len(hapd);
77 tail_len += hostapd_eid_owe_trans_len(hapd);
78 tail_len += hostapd_eid_dpp_cc_len(hapd);
79@@ -2262,7 +2262,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
80
81 tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos);
82
83- tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON);
84+ tailpos = hostapd_eid_rnr(hapd, tailpos, WLAN_FC_STYPE_BEACON, true);
85 tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0);
86 tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos);
87 tailpos = hostapd_eid_mbssid_config(hapd, tailpos,
88diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
89index 7ee18f4ae..9a23c7240 100644
90--- a/src/ap/ieee802_11.c
91+++ b/src/ap/ieee802_11.c
92@@ -7273,20 +7273,21 @@ static size_t
93 hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
94 struct hostapd_data *reporting_hapd,
95 size_t *current_len,
96- struct mbssid_ie_profiles *skip_profiles)
97+ struct mbssid_ie_profiles *skip_profiles,
98+ bool mld_update)
99 {
100 size_t total_len = 0, len = *current_len;
101- int tbtt_count = 0;
102- size_t i, start = 0;
103- bool ap_mld = false;
104+ int tbtt_count, total_tbtt_count = 0;
105+ size_t i, start;
106+ u8 tbtt_info_len = mld_update ? RNR_TBTT_INFO_MLD_LEN : RNR_TBTT_INFO_LEN;
107
108-#ifdef CONFIG_IEEE80211BE
109- ap_mld = !!hapd->conf->mld_ap;
110-#endif /* CONFIG_IEEE80211BE */
111+repeat_rnr_len:
112+ start = 0;
113+ tbtt_count = 0;
114
115 while (start < hapd->iface->num_bss) {
116 if (!len ||
117- len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255 ||
118+ len + RNR_TBTT_HEADER_LEN + tbtt_info_len > 255 ||
119 tbtt_count >= RNR_TBTT_INFO_COUNT_MAX) {
120 len = RNR_HEADER_LEN;
121 total_len += RNR_HEADER_LEN;
122@@ -7298,10 +7299,15 @@ hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
123
124 for (i = start; i < hapd->iface->num_bss; i++) {
125 struct hostapd_data *bss = hapd->iface->bss[i];
126+ bool ap_mld = false;
127
128 if (!bss || !bss->conf || !bss->started)
129 continue;
130
131+#ifdef CONFIG_IEEE80211BE
132+ ap_mld = !!bss->conf->mld_ap;
133+#endif /* CONFIG_IEEE80211BE */
134+
135 if (bss == reporting_hapd ||
136 bss->conf->ignore_broadcast_ssid)
137 continue;
138@@ -7310,23 +7316,71 @@ hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
139 i >= skip_profiles->start && i < skip_profiles->end)
140 continue;
141
142- if (len + RNR_TBTT_INFO_LEN > 255 ||
143+ /* No need to report if length is for normal TBTT and the BSS
144+ * is a MLD. MLD TBTT will include this.
145+ */
146+ if (tbtt_info_len == RNR_TBTT_INFO_LEN && ap_mld)
147+ continue;
148+
149+ /* No need to report if length is for MLD TBTT and the BSS
150+ * is not MLD. Normal TBTT will include this.
151+ */
152+ if (tbtt_info_len == RNR_TBTT_INFO_MLD_LEN && !ap_mld)
153+ continue;
154+
155+#ifdef CONFIG_IEEE80211BE
156+ /* If building for co-location and they are ML partners,
157+ * no need to include since the ML RNR will carry this.
158+ */
159+ if (!mld_update && hostapd_is_ml_partner(reporting_hapd, bss))
160+ continue;
161+
162+ /* If building for ML RNR and they are not ML parnters,
163+ * don't include.
164+ */
165+ if (mld_update && !hostapd_is_ml_partner(reporting_hapd, bss))
166+ continue;
167+#endif /* CONFIG_IEEE80211BE */
168+
169+ if (len + tbtt_info_len > 255 ||
170 tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
171 break;
172
173- if (!ap_mld) {
174- len += RNR_TBTT_INFO_LEN;
175- total_len += RNR_TBTT_INFO_LEN;
176- } else {
177- len += RNR_TBTT_INFO_MLD_LEN;
178- total_len += RNR_TBTT_INFO_MLD_LEN;
179- }
180+ len += tbtt_info_len;
181+ total_len += tbtt_info_len;
182 tbtt_count++;
183 }
184 start = i;
185 }
186
187- if (!tbtt_count)
188+ total_tbtt_count += tbtt_count;
189+
190+ /* If building for co-location, re-build again but this time include
191+ * ML TBTTs.
192+ */
193+ if (!mld_update && tbtt_info_len == RNR_TBTT_INFO_LEN) {
194+ tbtt_info_len = RNR_TBTT_INFO_MLD_LEN;
195+
196+ /* If no TBTT was found, then adjust the len and total_len since
197+ * it would have incremented before we checked all bss.
198+ */
199+ if (!tbtt_count) {
200+ len -= RNR_TBTT_HEADER_LEN;
201+ total_len -= RNR_TBTT_HEADER_LEN;
202+ }
203+
204+ goto repeat_rnr_len;
205+ }
206+
207+ /* this is possible when it re-built and in that no suitable TBTT was
208+ * found. Adjust the length accordingly.
209+ */
210+ if (!tbtt_count && total_tbtt_count) {
211+ len -= RNR_TBTT_HEADER_LEN;
212+ total_len -= RNR_TBTT_HEADER_LEN;
213+ }
214+
215+ if (!total_tbtt_count)
216 total_len = 0;
217 else
218 *current_len = len;
219@@ -7375,8 +7429,8 @@ static enum colocation_mode get_colocation_mode(struct hostapd_data *hapd)
220 }
221
222
223-static size_t hostapd_eid_rnr_multi_iface_len(struct hostapd_data *hapd,
224- size_t *current_len)
225+static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd,
226+ size_t *current_len)
227 {
228 struct hostapd_iface *iface;
229 size_t len = 0;
230@@ -7387,34 +7441,57 @@ static size_t hostapd_eid_rnr_multi_iface_len(struct hostapd_data *hapd,
231
232 for (i = 0; i < hapd->iface->interfaces->count; i++) {
233 iface = hapd->iface->interfaces->iface[i];
234- bool ap_mld = false;
235-
236-#ifdef CONFIG_IEEE80211BE
237- if (hostapd_is_ml_partner(hapd, iface->bss[0]))
238- ap_mld = true;
239-#endif /* CONFIG_IEEE80211BE */
240
241- if (iface == hapd->iface ||
242- !(is_6ghz_op_class(iface->conf->op_class) || ap_mld))
243+ if (!iface || iface == hapd->iface ||
244+ !is_6ghz_op_class(iface->conf->op_class))
245 continue;
246
247 len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd,
248- current_len, NULL);
249+ current_len, NULL, false);
250 }
251
252 return len;
253 }
254
255-
256-size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
257+static size_t hostapd_eid_rnr_mlo_len(struct hostapd_data *hapd, u32 type,
258+ size_t *current_len)
259 {
260- size_t total_len = 0, current_len = 0;
261- enum colocation_mode mode = get_colocation_mode(hapd);
262- bool ap_mld = false;
263+ size_t len = 0;
264
265 #ifdef CONFIG_IEEE80211BE
266- ap_mld = !!hapd->conf->mld_ap;
267+ struct hostapd_iface *iface;
268+ size_t i;
269+
270+ if (!hapd->iface || !hapd->iface->interfaces)
271+ return 0;
272+
273+ if (!hapd->conf->mld_ap)
274+ return 0;
275+
276+ /* TODO allow for FILS/Action as well */
277+ if (type != WLAN_FC_STYPE_BEACON && type != WLAN_FC_STYPE_PROBE_RESP)
278+ return 0;
279+
280+ for (i = 0; i < hapd->iface->interfaces->count; i++) {
281+ iface = hapd->iface->interfaces->iface[i];
282+
283+ if (!iface || iface == hapd->iface)
284+ continue;
285+
286+ if (hapd->iface->freq == iface->freq)
287+ continue;
288+
289+ len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd,
290+ current_len, NULL, true);
291+ }
292 #endif /* CONFIG_IEEE80211BE */
293+ return len;
294+}
295+
296+size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type, bool include_mld_params)
297+{
298+ size_t total_len = 0, current_len = 0;
299+ enum colocation_mode mode = get_colocation_mode(hapd);
300
301 switch (type) {
302 case WLAN_FC_STYPE_BEACON:
303@@ -7423,29 +7500,35 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
304 /* fallthrough */
305
306 case WLAN_FC_STYPE_PROBE_RESP:
307- if (mode == COLOCATED_LOWER_BAND || ap_mld)
308+ if (mode == COLOCATED_LOWER_BAND)
309 total_len +=
310- hostapd_eid_rnr_multi_iface_len(hapd,
311- &current_len);
312+ hostapd_eid_rnr_colocation_len(hapd,
313+ &current_len);
314
315 if (hapd->conf->rnr && hapd->iface->num_bss > 1 &&
316 !hapd->iconf->mbssid)
317 total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
318 &current_len,
319- NULL);
320+ NULL, false);
321 break;
322
323 case WLAN_FC_STYPE_ACTION:
324 if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ)
325 total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
326 &current_len,
327- NULL);
328+ NULL, false);
329 break;
330
331 default:
332 break;
333 }
334
335+ /* For EMA Beacons, MLD neighbor repoting is added as part of mbssid rnr */
336+ if (include_mld_params &&
337+ (type != WLAN_FC_STYPE_BEACON ||
338+ hapd->iconf->mbssid != ENHANCED_MBSSID_ENABLED))
339+ total_len += hostapd_eid_rnr_mlo_len(hapd, type, &current_len);
340+
341 return total_len;
342 }
343
344@@ -7509,13 +7592,14 @@ static bool hostapd_eid_rnr_bss(struct hostapd_data *hapd,
345 struct hostapd_data *reporting_hapd,
346 struct mbssid_ie_profiles *skip_profiles,
347 size_t i, u8 *tbtt_count, size_t *len,
348- u8 **pos)
349+ u8 **pos, u8 **tbtt_count_pos, u8 tbtt_info_len,
350+ u8 op_class, bool mld_update)
351 {
352 struct hostapd_iface *iface = hapd->iface;
353 struct hostapd_data *bss = iface->bss[i];
354 u8 bss_param = 0;
355- bool ap_mld = false;
356 u8 *eid = *pos;
357+ bool ap_mld = false;
358
359 #ifdef CONFIG_IEEE80211BE
360 ap_mld = !!hapd->conf->mld_ap;
361@@ -7529,10 +7613,47 @@ static bool hostapd_eid_rnr_bss(struct hostapd_data *hapd,
362 && i >= skip_profiles->start && i < skip_profiles->end)
363 return false;
364
365+ /* No need to report if length is for normal TBTT and the BSS
366+ * is a MLD. MLD TBTT will include this.
367+ */
368+ if (tbtt_info_len == RNR_TBTT_INFO_LEN && ap_mld)
369+ return false;
370+
371+ /* No need to report if length is for MLD TBTT and the BSS
372+ * is not MLD. Normal TBTT will include this.
373+ */
374+ if (tbtt_info_len == RNR_TBTT_INFO_MLD_LEN && !ap_mld)
375+ return false;
376+
377+#ifdef CONFIG_IEEE80211BE
378+ /* If building for co-location and they are ML partners,
379+ * no need to include since the ML RNR will carry this.
380+ */
381+ if (!mld_update && hostapd_is_ml_partner(reporting_hapd, bss))
382+ return false;
383+
384+ /* If building for ML RNR and they are not ML parnters,
385+ * don't include.
386+ */
387+ if (mld_update && !hostapd_is_ml_partner(reporting_hapd, bss))
388+ return false;
389+#endif /* CONFIG_IEEE80211BE */
390+
391 if (*len + RNR_TBTT_INFO_LEN > 255 ||
392 *tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
393 return true;
394
395+ if (!(*tbtt_count)) {
396+ /* Add Neighbor report header info only if there is at least
397+ * one tbtt info available
398+ */
399+ *tbtt_count_pos = eid++;
400+ *eid++ = tbtt_info_len;
401+ *eid++ = op_class;
402+ *eid++ = bss->iconf->channel;
403+ *len += RNR_TBTT_HEADER_LEN;
404+ }
405+
406 *eid++ = RNR_NEIGHBOR_AP_OFFSET_UNKNOWN;
407 os_memcpy(eid, bss->own_addr, ETH_ALEN);
408 eid += ETH_ALEN;
409@@ -7556,29 +7677,36 @@ static bool hostapd_eid_rnr_bss(struct hostapd_data *hapd,
410 *eid++ = bss_param;
411 *eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER;
412
413- if (!ap_mld) {
414- *len += RNR_TBTT_INFO_LEN;
415- } else {
416 #ifdef CONFIG_IEEE80211BE
417- u8 param_ch = hapd->eht_mld_bss_param_change;
418-
419- if (hostapd_is_ml_partner(bss, reporting_hapd))
420- *eid++ = 0;
421- else
422- *eid++ = hostapd_get_mld_id(hapd);
423-
424- *eid++ = hapd->mld_link_id | ((param_ch & 0xF) << 4);
425- *eid = (param_ch >> 4) & 0xF;
426+ if (ap_mld) {
427+ u8 param_ch = bss->eht_mld_bss_param_change;
428+ bool is_partner;
429+
430+ /* If bss is not partner of the reporting_hapd then
431+ * a) MLD ID advertised shall be 255.
432+ * b) Link ID advertised shall be 15.
433+ * c) BPCC advertised shall be 255
434+ */
435+ is_partner = hostapd_is_ml_partner(bss, reporting_hapd);
436+ /* MLD ID */
437+ *eid++ = is_partner ? hostapd_get_mld_id(bss) : 0xFF;
438+ /* Link ID (Bit 3 to Bit 0)
439+ * BPCC (Bit 4 to Bit 7)
440+ */
441+ *eid++ = is_partner ?
442+ bss->mld_link_id | ((param_ch & 0xF) << 4) :
443+ (MAX_NUM_MLD_LINKS | 0xF0);
444+ /* BPCC (Bit 3 to Bit 0) */
445+ *eid = is_partner ? ((param_ch & 0xF0) >> 4) : 0x0F;
446 #ifdef CONFIG_TESTING_OPTIONS
447- if (hapd->conf->mld_indicate_disabled)
448+ if (bss->conf->mld_indicate_disabled)
449 *eid |= RNR_TBTT_INFO_MLD_PARAM2_LINK_DISABLED;
450 #endif /* CONFIG_TESTING_OPTIONS */
451 eid++;
452-
453- *len += RNR_TBTT_INFO_MLD_LEN;
454-#endif /* CONFIG_IEEE80211BE */
455 }
456+#endif /* CONFIG_IEEE80211BE */
457
458+ *len += tbtt_info_len;
459 (*tbtt_count)++;
460 *pos = eid;
461
462@@ -7589,18 +7717,16 @@ static bool hostapd_eid_rnr_bss(struct hostapd_data *hapd,
463 static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
464 struct hostapd_data *reporting_hapd,
465 u8 *eid, size_t *current_len,
466- struct mbssid_ie_profiles *skip_profiles)
467+ struct mbssid_ie_profiles *skip_profiles,
468+ bool mld_update)
469 {
470 struct hostapd_iface *iface = hapd->iface;
471- size_t i, start = 0;
472+ size_t i, start;
473 size_t len = *current_len;
474- u8 *tbtt_count_pos, *eid_start = eid, *size_offset = (eid - len) + 1;
475- u8 tbtt_count = 0, op_class, channel;
476- bool ap_mld = false;
477-
478-#ifdef CONFIG_IEEE80211BE
479- ap_mld = !!hapd->conf->mld_ap;
480-#endif /* CONFIG_IEEE80211BE */
481+ u8 *eid_start = eid, *size_offset = (eid - len) + 1;
482+ u8 *tbtt_count_pos = size_offset + 1;
483+ u8 tbtt_count, total_tbtt_count = 0, op_class, channel;
484+ u8 tbtt_info_len = mld_update ? RNR_TBTT_INFO_MLD_LEN : RNR_TBTT_INFO_LEN;
485
486 if (!(iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || !iface->freq)
487 return eid;
488@@ -7612,9 +7738,12 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
489 NUM_HOSTAPD_MODES)
490 return eid;
491
492+repeat_rnr:
493+ start = 0;
494+ tbtt_count = 0;
495 while (start < iface->num_bss) {
496 if (!len ||
497- len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255 ||
498+ len + RNR_TBTT_HEADER_LEN + tbtt_info_len > 255 ||
499 tbtt_count >= RNR_TBTT_INFO_COUNT_MAX) {
500 eid_start = eid;
501 *eid++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
502@@ -7623,34 +7752,42 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
503 tbtt_count = 0;
504 }
505
506- tbtt_count_pos = eid++;
507- *eid++ = ap_mld ? RNR_TBTT_INFO_MLD_LEN : RNR_TBTT_INFO_LEN;
508- *eid++ = op_class;
509- *eid++ = hapd->iconf->channel;
510- len += RNR_TBTT_HEADER_LEN;
511-
512 for (i = start; i < iface->num_bss; i++) {
513 if (hostapd_eid_rnr_bss(hapd, reporting_hapd,
514 skip_profiles, i,
515- &tbtt_count, &len, &eid))
516+ &tbtt_count, &len, &eid,
517+ &tbtt_count_pos, tbtt_info_len,
518+ op_class, mld_update))
519 break;
520 }
521
522 start = i;
523- *tbtt_count_pos = RNR_TBTT_INFO_COUNT(tbtt_count - 1);
524- *size_offset = (eid - size_offset) - 1;
525+
526+ if (tbtt_count) {
527+ *tbtt_count_pos = RNR_TBTT_INFO_COUNT(tbtt_count - 1);
528+ *size_offset = (eid - size_offset) - 1;
529+ }
530+ }
531+
532+ total_tbtt_count += tbtt_count;
533+
534+ /* If building for co-location, re-build again but this time include
535+ * ML TBTTs.
536+ */
537+ if (!mld_update && tbtt_info_len == RNR_TBTT_INFO_LEN) {
538+ tbtt_info_len = RNR_TBTT_INFO_MLD_LEN;
539+ goto repeat_rnr;
540 }
541
542- if (tbtt_count == 0)
543+ if (!total_tbtt_count)
544 return eid_start;
545
546 *current_len = len;
547 return eid;
548 }
549
550-
551-static u8 * hostapd_eid_rnr_multi_iface(struct hostapd_data *hapd, u8 *eid,
552- size_t *current_len)
553+u8 *hostapd_eid_rnr_colocation(struct hostapd_data *hapd, u8 *eid,
554+ size_t *current_len)
555 {
556 struct hostapd_iface *iface;
557 size_t i;
558@@ -7660,35 +7797,56 @@ static u8 * hostapd_eid_rnr_multi_iface(struct hostapd_data *hapd, u8 *eid,
559
560 for (i = 0; i < hapd->iface->interfaces->count; i++) {
561 iface = hapd->iface->interfaces->iface[i];
562- bool ap_mld = false;
563
564-#ifdef CONFIG_IEEE80211BE
565- if (hostapd_is_ml_partner(hapd, iface->bss[0]))
566- ap_mld = true;
567-#endif /* CONFIG_IEEE80211BE */
568-
569- if (iface == hapd->iface ||
570- !(is_6ghz_op_class(iface->conf->op_class) || ap_mld))
571+ if (!iface || iface == hapd->iface ||
572+ !is_6ghz_op_class(iface->conf->op_class))
573 continue;
574
575 eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid,
576- current_len, NULL);
577+ current_len, NULL, false);
578 }
579
580 return eid;
581 }
582
583+u8 *hostapd_eid_rnr_mlo(struct hostapd_data *hapd, u32 type,
584+ u8 *eid, size_t *current_len)
585+{
586+#ifdef CONFIG_IEEE80211BE
587+ struct hostapd_iface *iface;
588+ size_t i;
589+
590+ if (!hapd->iface || !hapd->iface->interfaces)
591+ return eid;
592+
593+ if (!hapd->conf->mld_ap)
594+ return eid;
595+
596+ /* TODO allow for FILS/Action as well */
597+ if (type != WLAN_FC_STYPE_BEACON && type != WLAN_FC_STYPE_PROBE_RESP)
598+ return eid;
599+
600+ for (i = 0; i < hapd->iface->interfaces->count; i++) {
601+ iface = hapd->iface->interfaces->iface[i];
602+
603+ if (!iface || iface == hapd->iface)
604+ continue;
605+
606+ if (hapd->iface->freq == iface->freq)
607+ continue;
608
609-u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
610+ eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid,
611+ current_len, NULL, true);
612+ }
613+#endif /* CONFIG_IEEE80211BE */
614+ return eid;
615+}
616+
617+u8 *hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type, bool include_mld_params)
618 {
619 u8 *eid_start = eid;
620 size_t current_len = 0;
621 enum colocation_mode mode = get_colocation_mode(hapd);
622- bool ap_mld = false;
623-
624-#ifdef CONFIG_IEEE80211BE
625- ap_mld = !!hapd->conf->mld_ap;
626-#endif /* CONFIG_IEEE80211BE */
627
628 switch (type) {
629 case WLAN_FC_STYPE_BEACON:
630@@ -7697,26 +7855,34 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
631 /* fallthrough */
632
633 case WLAN_FC_STYPE_PROBE_RESP:
634- if (mode == COLOCATED_LOWER_BAND || ap_mld)
635- eid = hostapd_eid_rnr_multi_iface(hapd, eid,
636- &current_len);
637+ if (mode == COLOCATED_LOWER_BAND)
638+ eid = hostapd_eid_rnr_colocation(hapd, eid,
639+ &current_len);
640
641 if (hapd->conf->rnr && hapd->iface->num_bss > 1 &&
642 !hapd->iconf->mbssid)
643 eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
644- &current_len, NULL);
645+ &current_len, NULL,
646+ false);
647 break;
648
649 case WLAN_FC_STYPE_ACTION:
650 if (hapd->iface->num_bss > 1 && mode == STANDALONE_6GHZ)
651 eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
652- &current_len, NULL);
653+ &current_len, NULL,
654+ false);
655 break;
656
657 default:
658 return eid_start;
659 }
660
661+ /* For EMA Beacons, MLD neighbor repoting is added as part of mbssid rnr */
662+ if (include_mld_params &&
663+ (type != WLAN_FC_STYPE_BEACON ||
664+ hapd->iconf->mbssid != ENHANCED_MBSSID_ENABLED))
665+ eid = hostapd_eid_rnr_mlo(hapd, type, eid, &current_len);
666+
667 if (eid == eid_start + 2)
668 return eid_start;
669
670@@ -7815,6 +7981,11 @@ size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
671 size_t known_bss_len, size_t *rnr_len)
672 {
673 size_t len = 0, bss_index = 1;
674+ bool ap_mld = false;
675+
676+#ifdef CONFIG_IEEE80211BE
677+ ap_mld = !!hapd->conf->mld_ap;
678+#endif /* CONFIG_IEEE80211BE */
679
680 if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
681 (frame_type != WLAN_FC_STYPE_BEACON &&
682@@ -7847,12 +8018,12 @@ size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
683
684 *rnr_len += hostapd_eid_rnr_iface_len(
685 hapd, hostapd_mbssid_get_tx_bss(hapd),
686- &rnr_cur_len, &skip_profiles);
687+ &rnr_cur_len, &skip_profiles, ap_mld);
688 }
689 }
690
691 if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED && rnr_len)
692- *rnr_len += hostapd_eid_rnr_len(hapd, frame_type);
693+ *rnr_len += hostapd_eid_rnr_len(hapd, frame_type, false);
694
695 return len;
696 }
697@@ -7978,7 +8149,11 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
698 {
699 size_t bss_index = 1, cur_len = 0;
700 u8 elem_index = 0, *rnr_start_eid = rnr_eid;
701- bool add_rnr;
702+ bool add_rnr, ap_mld = false;
703+
704+#ifdef CONFIG_IEEE80211BE
705+ ap_mld = !!hapd->conf->mld_ap;
706+#endif /* CONFIG_IEEE80211BE */
707
708 if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
709 (frame_stype != WLAN_FC_STYPE_BEACON &&
710@@ -8023,7 +8198,7 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
711 cur_len = 0;
712 rnr_eid = hostapd_eid_rnr_iface(
713 hapd, hostapd_mbssid_get_tx_bss(hapd),
714- rnr_eid, &cur_len, &skip_profiles);
715+ rnr_eid, &cur_len, &skip_profiles, ap_mld);
716 }
717 }
718
719@@ -8035,8 +8210,8 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
720 if (hapd->conf->rnr)
721 rnr_eid = hostapd_eid_nr_db(hapd, rnr_eid, &cur_len);
722 if (get_colocation_mode(hapd) == COLOCATED_LOWER_BAND)
723- rnr_eid = hostapd_eid_rnr_multi_iface(hapd, rnr_eid,
724- &cur_len);
725+ rnr_eid = hostapd_eid_rnr_colocation(hapd, rnr_eid,
726+ &cur_len);
727 }
728
729 return eid;
730diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
731index 262e0ce14..078f4baf9 100644
732--- a/src/ap/ieee802_11.h
733+++ b/src/ap/ieee802_11.h
734@@ -225,8 +225,9 @@ void auth_sae_process_commit(void *eloop_ctx, void *user_ctx);
735 u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len);
736 u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
737 const u8 *ext_capab_ie, size_t ext_capab_ie_len);
738-size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type);
739-u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type);
740+size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type, bool include_mld_params);
741+u8 *hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type,
742+ bool include_mld_params);
743 int ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
744 int res, struct radius_sta *info);
745 size_t hostapd_eid_eht_capab_len(struct hostapd_data *hapd,
746--
7472.39.2
748