BACKPORT: FROMLIST: cfg80211: parse RNR IE about MLD params for MBSSID feature

In order to reconstruct frame for MBSSID feature, per the description of
the Reduced Neighbor Report(RNR) element about MLD parameters subfield in
section 9.4.2.170 of Draft P802.11be_D1.4, the RNR IE is modified:
1\ If the reported AP is affiliated with the same MLD of the reporting AP,
the TBTT information is skipped;
2\ If the reported AP is affiliated with the same MLD of the nontransmitted
BSSID, the TBTT information is copied and the MLD ID is changed to 0.

Signed-off-by: Paul Zhang <quic_paulz@quicinc.com>

Bug: 231937090
Link: https://lore.kernel.org/linux-wireless/1649335871-9173-1-git-send-email-quic_paulz@quicinc.com
Change-Id: I2bae85b813a2351a62d2788f0e76f13407d11645
Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
This commit is contained in:
Paul Zhang
2022-04-07 20:51:11 +08:00
committed by Todd Kjos
parent 186398845e
commit da01931c1c
2 changed files with 149 additions and 4 deletions

View File

@@ -4282,6 +4282,17 @@ static inline bool for_each_element_completed(const struct element *element,
#define IEEE80211_TBTT_INFO_OFFSET_BSSID_BSS_PARAM 9
#define IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM 13
/*
* TBTT Information field, based on Draft P802.11be_D1.4
* section 9.4.2.170.2
*/
#define IEEE80211_TBTT_INFO_BSSID_SSID_BSS_PARAM_PSD 13
#define IEEE80211_TBTT_INFO_BSSID_SSID_BSS_PARAM_PSD_MLD_PARAM 16
#define IEEE80211_TBTT_TYPE_MASK 0xC0
#define IEEE80211_TBTT_COUNT_MASK 0x0F
/* TBTT infomation header(2) + Operating class(1) + Channel number(1) */
#define IEEE80211_NBR_AP_INFO_LEN 4
#define IEEE80211_RNR_TBTT_PARAMS_OCT_RECOMMENDED 0x01
#define IEEE80211_RNR_TBTT_PARAMS_SAME_SSID 0x02
#define IEEE80211_RNR_TBTT_PARAMS_MULTI_BSSID 0x04

View File

@@ -268,9 +268,136 @@ bool cfg80211_is_element_inherited(const struct element *elem,
}
EXPORT_SYMBOL(cfg80211_is_element_inherited);
/**
* cfg80211_handle_rnr_ie_for_mbssid() - parse and modify RNR IE for MBSSID
* feature
* @elem: The pointer to RNR IE
* @bssid_index: BSSID index from MBSSID index IE
* @pos: The buffer pointer to save the transformed RNR IE, caller is expected
* to supply a buffer that is at least as big as @elem
*
* Per the description about Neighbor AP Information field about MLD
* parameters subfield in section 9.4.2.170.2 of Draft P802.11be_D1.4.
* If the reported AP is affiliated with the same MLD of the reporting AP,
* the TBTT information is skipped; If the reported AP is affiliated with
* the same MLD of the nontransmitted BSSID, the TBTT information is copied
* and the MLD ID is changed to 0.
*
* Return: Length of the element written to @pos
*/
static size_t cfg80211_handle_rnr_ie_for_mbssid(const struct element *elem,
u8 bssid_index, u8 *pos)
{
size_t rnr_len;
const u8 *rnr, *data, *rnr_end;
u8 *rnr_new, *tbtt_info_field;
u8 tbtt_type, tbtt_len, tbtt_count;
u8 mld_pos, mld_id;
u32 i, copy_len;
/* The count of TBTT info field whose MLD ID equals to 0 in a neighbor
* AP information field.
*/
u32 tbtt_info_field_count;
/* The total bytes of TBTT info fields whose MLD ID equals to 0 in
* current RNR IE.
*/
u32 tbtt_info_field_len = 0;
rnr_new = pos;
rnr = (u8 *)elem;
rnr_len = elem->datalen;
rnr_end = rnr + rnr_len + 2;
memcpy(pos, rnr, 2);
pos += 2;
data = elem->data;
while (data < rnr_end) {
tbtt_type = u8_get_bits(data[0], IEEE80211_TBTT_TYPE_MASK);
tbtt_count = u8_get_bits(data[0], IEEE80211_TBTT_COUNT_MASK);
tbtt_len = data[1];
copy_len = tbtt_len * (tbtt_count + 1) +
IEEE80211_NBR_AP_INFO_LEN;
if (data + copy_len > rnr_end)
return 0;
if (tbtt_len >=
IEEE80211_TBTT_INFO_BSSID_SSID_BSS_PARAM_PSD_MLD_PARAM)
mld_pos =
IEEE80211_TBTT_INFO_BSSID_SSID_BSS_PARAM_PSD;
else
mld_pos = 0;
/* If MLD params do not exist, copy this neighbor AP
* information field.
* Draft P802.11be_D1.4, tbtt_type value 1, 2 and 3
* are reserved.
*/
if (mld_pos == 0 || tbtt_type != 0) {
memcpy(pos, data, copy_len);
pos += copy_len;
data += copy_len;
continue;
}
memcpy(pos, data, IEEE80211_NBR_AP_INFO_LEN);
tbtt_info_field = pos;
pos += IEEE80211_NBR_AP_INFO_LEN;
data += IEEE80211_NBR_AP_INFO_LEN;
tbtt_info_field_count = 0;
for (i = 0; i < tbtt_count + 1; i++) {
mld_id = data[mld_pos];
/* Refer to Draft P802.11be_D1.4
* 9.4.2.170.2 Neighbor AP Information field about
* MLD parameters subfield
*/
if (mld_id == 0) {
/* Skip this TBTT information since this
* reported AP is affiliated with the same MLD
* of the reporting AP who sending the frame
* carrying this element.
*/
tbtt_info_field_len += tbtt_len;
data += tbtt_len;
tbtt_info_field_count++;
} else if (mld_id == bssid_index) {
/* Copy this TBTT information and change MLD
* to 0 as this reported AP is affiliated with
* the same MLD of the nontransmitted BSSID.
*/
memcpy(pos, data, tbtt_len);
pos[mld_pos] = 0;
data += tbtt_len;
pos += tbtt_len;
} else {
memcpy(pos, data, tbtt_len);
data += tbtt_len;
pos += tbtt_len;
}
}
if (tbtt_info_field_count == (tbtt_count + 1)) {
/* If all the TBTT informations are skipped, then also
* revert the neighbor AP info which has been copied.
*/
pos -= IEEE80211_NBR_AP_INFO_LEN;
tbtt_info_field_len += IEEE80211_NBR_AP_INFO_LEN;
} else {
u8p_replace_bits(&tbtt_info_field[0],
tbtt_count - tbtt_info_field_count,
IEEE80211_TBTT_COUNT_MASK);
}
}
rnr_new[1] = rnr_len - tbtt_info_field_len;
if (rnr_new[1] == 0)
pos = rnr_new;
return pos - rnr_new;
}
static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
const u8 *subelement, size_t subie_len,
u8 *new_ie, gfp_t gfp)
u8 *new_ie, u8 bssid_index, gfp_t gfp)
{
u8 *pos, *tmp;
const u8 *tmp_old, *tmp_new;
@@ -321,8 +448,13 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
const struct element *old_elem = (void *)tmp_old;
/* ie in old ie but not in subelement */
if (cfg80211_is_element_inherited(old_elem,
non_inherit_elem)) {
if (tmp_old[0] == WLAN_EID_REDUCED_NEIGHBOR_REPORT) {
pos +=
cfg80211_handle_rnr_ie_for_mbssid(old_elem,
bssid_index,
pos);
} else if (cfg80211_is_element_inherited(old_elem,
non_inherit_elem)) {
memcpy(pos, tmp_old, tmp_old[1] + 2);
pos += tmp_old[1] + 2;
}
@@ -2079,6 +2211,7 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
u64 seen_indices = 0;
u16 capability;
struct cfg80211_bss *bss;
u8 bssid_index;
if (!non_tx_data)
return;
@@ -2145,6 +2278,7 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
non_tx_data->bssid_index = mbssid_index_ie[2];
non_tx_data->max_bssid_indicator = elem->data[0];
bssid_index = non_tx_data->bssid_index;
cfg80211_gen_new_bssid(bssid,
non_tx_data->max_bssid_indicator,
@@ -2154,7 +2288,7 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
new_ie_len = cfg80211_gen_new_ie(ie, ielen,
profile,
profile_len, new_ie,
gfp);
bssid_index, gfp);
if (!new_ie_len)
continue;