]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP: Include an RNR element in Beacon frames for AP MLD
authorIlan Peer <ilan.peer@intel.com>
Mon, 22 May 2023 19:33:37 +0000 (22:33 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 6 Jun 2023 18:13:31 +0000 (21:13 +0300)
- Include RNR element in Beacon frames of AP MLDs.
- Whenever a new interface is added to an AP MLD, reconfigure
  the Beacon frame templates for all other interfaces, to allow
  updating their RNR elements.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
src/ap/beacon.c
src/ap/hostapd.c
src/ap/ieee802_11.c
src/common/ieee802_11_defs.h

index 5e9ced1e25d80a09f881d5a7f896a94348b38254..7ff678319779f95198e434601fbb9d4b51861e4d 100644 (file)
@@ -2194,21 +2194,29 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd)
        if (!iface->interfaces || iface->interfaces->count <= 1)
                return 0;
 
-       /* Update Beacon frames in case of 6 GHz colocation */
+       /* Update Beacon frames in case of 6 GHz colocation or AP MLD */
        is_6g = is_6ghz_op_class(iface->conf->op_class);
        for (j = 0; j < iface->interfaces->count; j++) {
-               struct hostapd_iface *colocated;
+               struct hostapd_iface *other;
+               bool mld_ap = false;
 
-               colocated = iface->interfaces->iface[j];
-               if (colocated == iface || !colocated || !colocated->conf)
+               other = iface->interfaces->iface[j];
+               if (other == iface || !other || !other->conf)
                        continue;
 
-               if (is_6g == is_6ghz_op_class(colocated->conf->op_class))
+#ifdef CONFIG_IEEE80211BE
+               if (hapd->conf->mld_ap && other->bss[0]->conf->mld_ap &&
+                   hapd->conf->mld_id == other->bss[0]->conf->mld_id)
+                       mld_ap = true;
+#endif /* CONFIG_IEEE80211BE */
+
+               if (is_6g == is_6ghz_op_class(other->conf->op_class) &&
+                   !mld_ap)
                        continue;
 
-               for (i = 0; i < colocated->num_bss; i++) {
-                       if (colocated->bss[i] && colocated->bss[i]->started)
-                               __ieee802_11_set_beacon(colocated->bss[i]);
+               for (i = 0; i < other->num_bss; i++) {
+                       if (other->bss[i] && other->bss[i]->started)
+                               __ieee802_11_set_beacon(other->bss[i]);
                }
        }
 
index 02596dcb7223188c798bc628af45389deacac2c5..a86fc179c475c9f5420c4744ce62842de2c8c664 100644 (file)
@@ -2471,6 +2471,9 @@ dfs_offload:
        for (j = 0; j < iface->num_bss; j++)
                hostapd_neighbor_set_own_report(iface->bss[j]);
 
+       if (iface->interfaces && iface->interfaces->count > 1)
+               ieee802_11_set_beacons(iface);
+
        return 0;
 
 fail:
index 93a6b4f56d10dc6536eae07fcc88588b04c525a2..a289b26af2c0d058f815d124dcb863ff3bfd7f08 100644 (file)
@@ -6443,6 +6443,11 @@ hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
        size_t total_len = 0, len = *current_len;
        int tbtt_count = 0;
        size_t i, start = 0;
+       bool ap_mld = false;
+
+#ifdef CONFIG_IEEE80211BE
+       ap_mld = !!hapd->conf->mld_ap;
+#endif /* CONFIG_IEEE80211BE */
 
        while (start < hapd->iface->num_bss) {
                if (!len ||
@@ -6472,8 +6477,13 @@ hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
                            tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
                                break;
 
-                       len += RNR_TBTT_INFO_LEN;
-                       total_len += RNR_TBTT_INFO_LEN;
+                       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;
+                       }
                        tbtt_count++;
                }
                start = i;
@@ -6528,8 +6538,8 @@ static enum colocation_mode get_colocation_mode(struct hostapd_data *hapd)
 }
 
 
-static size_t hostapd_eid_rnr_colocation_len(struct hostapd_data *hapd,
-                                            size_t *current_len)
+static size_t hostapd_eid_rnr_multi_iface_len(struct hostapd_data *hapd,
+                                             size_t *current_len)
 {
        struct hostapd_iface *iface;
        size_t len = 0;
@@ -6540,9 +6550,16 @@ static size_t hostapd_eid_rnr_colocation_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 (hapd->conf->mld_ap && iface->bss[0]->conf->mld_ap &&
+                   hapd->conf->mld_id == iface->bss[0]->conf->mld_id)
+                       ap_mld = true;
+#endif /* CONFIG_IEEE80211BE */
 
                if (iface == hapd->iface ||
-                   !is_6ghz_op_class(iface->conf->op_class))
+                   !(is_6ghz_op_class(iface->conf->op_class) || ap_mld))
                        continue;
 
                len += hostapd_eid_rnr_iface_len(iface->bss[0], hapd,
@@ -6557,6 +6574,11 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
 {
        size_t total_len = 0, 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:
@@ -6565,9 +6587,10 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
                /* fallthrough */
 
        case WLAN_FC_STYPE_PROBE_RESP:
-               if (mode == COLOCATED_LOWER_BAND)
-                       total_len += hostapd_eid_rnr_colocation_len(
-                               hapd, &current_len);
+               if (mode == COLOCATED_LOWER_BAND || ap_mld)
+                       total_len +=
+                               hostapd_eid_rnr_multi_iface_len(hapd,
+                                                               &current_len);
 
                if (hapd->conf->rnr && hapd->iface->num_bss > 1 &&
                    !hapd->iconf->mbssid)
@@ -6657,6 +6680,11 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
        size_t len = *current_len;
        u8 *tbtt_count_pos, *eid_start = eid, *size_offset = (eid - len) + 1;
        u8 tbtt_count = 0, op_class, channel, bss_param;
+       bool ap_mld = false;
+
+#ifdef CONFIG_IEEE80211BE
+       ap_mld = !!hapd->conf->mld_ap;
+#endif /* CONFIG_IEEE80211BE */
 
        if (!(iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || !iface->freq)
                return eid;
@@ -6679,7 +6707,7 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
                }
 
                tbtt_count_pos = eid++;
-               *eid++ = RNR_TBTT_INFO_LEN;
+               *eid++ = ap_mld ? RNR_TBTT_INFO_MLD_LEN : RNR_TBTT_INFO_LEN;
                *eid++ = op_class;
                *eid++ = hapd->iconf->channel;
                len += RNR_TBTT_HEADER_LEN;
@@ -6728,7 +6756,18 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
 
                        *eid++ = bss_param;
                        *eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER - 1;
-                       len += RNR_TBTT_INFO_LEN;
+
+                       if (!ap_mld) {
+                               len += RNR_TBTT_INFO_LEN;
+                       } else {
+#ifdef CONFIG_IEEE80211BE
+                               *eid++ = hapd->conf->mld_id;
+                               *eid++ = hapd->mld_link_id | (1 << 4);
+                               *eid++ = 0;
+                               len += RNR_TBTT_INFO_MLD_LEN;
+#endif /* CONFIG_IEEE80211BE */
+                       }
+
                        tbtt_count += 1;
                }
 
@@ -6745,8 +6784,8 @@ static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
 }
 
 
-static u8 * hostapd_eid_rnr_colocation(struct hostapd_data *hapd, u8 *eid,
-                                      size_t *current_len)
+static u8 * hostapd_eid_rnr_multi_iface(struct hostapd_data *hapd, u8 *eid,
+                                       size_t *current_len)
 {
        struct hostapd_iface *iface;
        size_t i;
@@ -6756,9 +6795,16 @@ static u8 * hostapd_eid_rnr_colocation(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 (hapd->conf->mld_ap && iface->bss[0]->conf->mld_ap &&
+                   hapd->conf->mld_id == iface->bss[0]->conf->mld_id)
+                       ap_mld = true;
+#endif /* CONFIG_IEEE80211BE */
 
                if (iface == hapd->iface ||
-                   !is_6ghz_op_class(iface->conf->op_class))
+                   !(is_6ghz_op_class(iface->conf->op_class) || ap_mld))
                        continue;
 
                eid = hostapd_eid_rnr_iface(iface->bss[0], hapd, eid,
@@ -6774,6 +6820,11 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
        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:
@@ -6782,9 +6833,9 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
                /* fallthrough */
 
        case WLAN_FC_STYPE_PROBE_RESP:
-               if (mode == COLOCATED_LOWER_BAND)
-                       eid = hostapd_eid_rnr_colocation(hapd, eid,
-                                                        &current_len);
+               if (mode == COLOCATED_LOWER_BAND || ap_mld)
+                       eid = hostapd_eid_rnr_multi_iface(hapd, eid,
+                                                         &current_len);
 
                if (hapd->conf->rnr && hapd->iface->num_bss > 1 &&
                    !hapd->iconf->mbssid)
@@ -7099,8 +7150,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_colocation(hapd, rnr_eid,
-                                                            &cur_len);
+                       rnr_eid = hostapd_eid_rnr_multi_iface(hapd, rnr_eid,
+                                                             &cur_len);
        }
 
        return eid;
index 12789227c4c9379303030b1ccb0caf30a9e8aa74..b86906828271af0bf55352187caa711090bca648 100644 (file)
@@ -2454,6 +2454,7 @@ struct ieee80211_he_mu_edca_parameter_set {
 #define RNR_TBTT_INFO_COUNT(x)                      (((x) & 0xf) << 4)
 #define RNR_TBTT_INFO_COUNT_MAX                     16
 #define RNR_TBTT_INFO_LEN                           13
+#define RNR_TBTT_INFO_MLD_LEN                       16
 #define RNR_NEIGHBOR_AP_OFFSET_UNKNOWN              255
 /* Figure 9-632a - BSS Parameters subfield format */
 #define RNR_BSS_PARAM_OCT_RECOMMENDED               BIT(0)