From b2bbedcb2149d2ed7e73fa6113b921ab05486454 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 27 Jul 2021 16:42:21 -0700 Subject: [PATCH] RNR: Add co-located BSSes 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 Co-developed-by: Pradeep Kumar Chitrapu Signed-off-by: Pradeep Kumar Chitrapu Co-developed-by: Muna Sinada Signed-off-by: Muna Sinada Co-developed-by: Aloka Dixit Signed-off-by: Aloka Dixit --- src/ap/ieee802_11.c | 146 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 52df06d29..404f243af 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -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, ¤t_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, + ¤t_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, ¤t_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, + ¤t_len); break; default: