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 <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>
This commit is contained in:
John Crispin 2021-07-27 16:42:21 -07:00 committed by Jouni Malinen
parent a7c152d6b8
commit b2bbedcb21

View 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: