]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
RNR: Add co-located BSSes
authorJohn Crispin <john@phrozen.org>
Tue, 27 Jul 2021 23:42:21 +0000 (16:42 -0700)
committerJouni Malinen <j@w1.fi>
Mon, 8 Nov 2021 22:21:29 +0000 (00:21 +0200)
Calculate the length and include data for the BSSes active on the same
radio as the reporting BSS in the Reduced Neighbor Report element. This
element is included in Beacon and Probe Response frames.

Signed-off-by: John Crispin <john@phrozen.org>
Co-developed-by: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
Signed-off-by: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
Co-developed-by: Muna Sinada <msinada@codeaurora.org>
Signed-off-by: Muna Sinada <msinada@codeaurora.org>
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
src/ap/ieee802_11.c

index 52df06d299c3473449f66c1d2def6f822f48522e..404f243af05d09dff12c1e168adb28bd7661b4db 100644 (file)
@@ -7102,6 +7102,54 @@ static size_t hostapd_eid_nr_db_len(struct hostapd_data *hapd,
 }
 
 
+static size_t hostapd_eid_rnr_iface_len(struct hostapd_data *hapd,
+                                       struct hostapd_data *reporting_hapd,
+                                       size_t *current_len)
+{
+       size_t total_len = 0, len = *current_len;
+       int tbtt_count = 0;
+       size_t i, start = 0;
+
+       while (start < hapd->iface->num_bss) {
+               if (!len ||
+                   len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255) {
+                       len = RNR_HEADER_LEN;
+                       total_len += RNR_HEADER_LEN;
+               }
+
+               len += RNR_TBTT_HEADER_LEN;
+               total_len += RNR_TBTT_HEADER_LEN;
+
+               for (i = start; i < hapd->iface->num_bss; i++) {
+                       struct hostapd_data *bss = hapd->iface->bss[i];
+
+                       if (!bss || !bss->conf || !bss->started)
+                               continue;
+
+                       if (bss == reporting_hapd ||
+                           bss->conf->ignore_broadcast_ssid)
+                               continue;
+
+                       if (len + RNR_TBTT_INFO_LEN > 255 ||
+                           tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
+                               break;
+
+                       len += RNR_TBTT_INFO_LEN;
+                       total_len += RNR_TBTT_INFO_LEN;
+                       tbtt_count++;
+               }
+               start = i;
+       }
+
+       if (!tbtt_count)
+               total_len = 0;
+       else
+               *current_len = len;
+
+       return total_len;
+}
+
+
 size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
 {
        size_t total_len = 0, current_len = 0;
@@ -7110,6 +7158,12 @@ size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type)
        case WLAN_FC_STYPE_BEACON:
                if (hapd->conf->rnr)
                        total_len += hostapd_eid_nr_db_len(hapd, &current_len);
+               /* fallthrough */
+
+       case WLAN_FC_STYPE_PROBE_RESP:
+               if (hapd->conf->rnr && hapd->iface->num_bss > 1)
+                       total_len += hostapd_eid_rnr_iface_len(hapd, hapd,
+                                                              &current_len);
                break;
 
        default:
@@ -7175,6 +7229,92 @@ static u8 * hostapd_eid_nr_db(struct hostapd_data *hapd, u8 *eid,
 }
 
 
+static u8 * hostapd_eid_rnr_iface(struct hostapd_data *hapd,
+                                 struct hostapd_data *reporting_hapd,
+                                 u8 *eid, size_t *current_len)
+{
+       struct hostapd_data *bss;
+       struct hostapd_iface *iface = hapd->iface;
+       size_t i, start = 0;
+       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;
+
+       if (!(iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || !iface->freq)
+               return eid;
+
+       if (ieee80211_freq_to_channel_ext(iface->freq,
+                                         hapd->iconf->secondary_channel,
+                                         hostapd_get_oper_chwidth(hapd->iconf),
+                                         &op_class, &channel) ==
+           NUM_HOSTAPD_MODES)
+               return eid;
+
+       while (start < iface->num_bss) {
+               if (!len ||
+                   len + RNR_TBTT_HEADER_LEN + RNR_TBTT_INFO_LEN > 255) {
+                       eid_start = eid;
+                       *eid++ = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
+                       size_offset = eid++;
+                       len = RNR_HEADER_LEN;
+                       tbtt_count = 0;
+               }
+
+               tbtt_count_pos = eid++;
+               *eid++ = RNR_TBTT_INFO_LEN;
+               *eid++ = op_class;
+               *eid++ = hapd->iconf->channel;
+               len += RNR_TBTT_HEADER_LEN;
+
+               for (i = start; i < iface->num_bss; i++) {
+                       bss_param = 0;
+                       bss = iface->bss[i];
+                       if (!bss || !bss->conf || !bss->started)
+                               continue;
+
+                       if (bss == reporting_hapd ||
+                           bss->conf->ignore_broadcast_ssid)
+                               continue;
+
+                       if (len + RNR_TBTT_INFO_LEN > 255 ||
+                           tbtt_count >= RNR_TBTT_INFO_COUNT_MAX)
+                               break;
+
+                       *eid++ = RNR_NEIGHBOR_AP_OFFSET_UNKNOWN;
+                       os_memcpy(eid, bss->conf->bssid, ETH_ALEN);
+                       eid += ETH_ALEN;
+                       os_memcpy(eid, &bss->conf->ssid.short_ssid, 4);
+                       eid += 4;
+                       if (bss->conf->ssid.short_ssid ==
+                           reporting_hapd->conf->ssid.short_ssid)
+                               bss_param |= RNR_BSS_PARAM_SAME_SSID;
+
+                       if (is_6ghz_op_class(hapd->iconf->op_class) &&
+                           bss->conf->unsol_bcast_probe_resp_interval)
+                               bss_param |=
+                                       RNR_BSS_PARAM_UNSOLIC_PROBE_RESP_ACTIVE;
+
+                       bss_param |= RNR_BSS_PARAM_CO_LOCATED;
+
+                       *eid++ = bss_param;
+                       *eid++ = RNR_20_MHZ_PSD_MAX_TXPOWER - 1;
+                       len += RNR_TBTT_INFO_LEN;
+                       tbtt_count += 1;
+               }
+
+               start = i;
+               *tbtt_count_pos = RNR_TBTT_INFO_COUNT(tbtt_count - 1);
+               *size_offset = (eid - size_offset) - 1;
+       }
+
+       if (tbtt_count == 0)
+               return eid_start;
+
+       *current_len = len;
+       return eid;
+}
+
+
 u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
 {
        u8 *eid_start = eid;
@@ -7184,6 +7324,12 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
        case WLAN_FC_STYPE_BEACON:
                if (hapd->conf->rnr)
                        eid = hostapd_eid_nr_db(hapd, eid, &current_len);
+               /* fallthrough */
+
+       case WLAN_FC_STYPE_PROBE_RESP:
+               if (hapd->conf->rnr && hapd->iface->num_bss > 1)
+                       eid = hostapd_eid_rnr_iface(hapd, hapd, eid,
+                                                   &current_len);
                break;
 
        default: