wifi: cfg80211: add a kunit test for 6 GHz colocated AP parsing
Test a few things around parsing of 6 GHz colocated APs to e.g. ensure that we are not going to scan for a disabled (affiliated) AP. Signed-off-by: Benjamin Berg <benjamin.berg@intel.com> Link: https://msgid.link/20240129220918.079dc50ab43b.Ide898d9f1d4c26d7e774d6fd0ec57766967d6572@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
ce1fa3adc0
commit
45d43937a4
3 changed files with 230 additions and 42 deletions
|
@ -550,9 +550,53 @@ int cfg80211_remove_virtual_intf(struct cfg80211_registered_device *rdev,
|
||||||
struct wireless_dev *wdev);
|
struct wireless_dev *wdev);
|
||||||
void cfg80211_wdev_release_link_bsses(struct wireless_dev *wdev, u16 link_mask);
|
void cfg80211_wdev_release_link_bsses(struct wireless_dev *wdev, u16 link_mask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct cfg80211_colocated_ap - colocated AP information
|
||||||
|
*
|
||||||
|
* @list: linked list to all colocated APs
|
||||||
|
* @bssid: BSSID of the reported AP
|
||||||
|
* @ssid: SSID of the reported AP
|
||||||
|
* @ssid_len: length of the ssid
|
||||||
|
* @center_freq: frequency the reported AP is on
|
||||||
|
* @unsolicited_probe: the reported AP is part of an ESS, where all the APs
|
||||||
|
* that operate in the same channel as the reported AP and that might be
|
||||||
|
* detected by a STA receiving this frame, are transmitting unsolicited
|
||||||
|
* Probe Response frames every 20 TUs
|
||||||
|
* @oct_recommended: OCT is recommended to exchange MMPDUs with the reported AP
|
||||||
|
* @same_ssid: the reported AP has the same SSID as the reporting AP
|
||||||
|
* @multi_bss: the reported AP is part of a multiple BSSID set
|
||||||
|
* @transmitted_bssid: the reported AP is the transmitting BSSID
|
||||||
|
* @colocated_ess: all the APs that share the same ESS as the reported AP are
|
||||||
|
* colocated and can be discovered via legacy bands.
|
||||||
|
* @short_ssid_valid: short_ssid is valid and can be used
|
||||||
|
* @short_ssid: the short SSID for this SSID
|
||||||
|
* @psd_20: The 20MHz PSD EIRP of the primary 20MHz channel for the reported AP
|
||||||
|
*/
|
||||||
|
struct cfg80211_colocated_ap {
|
||||||
|
struct list_head list;
|
||||||
|
u8 bssid[ETH_ALEN];
|
||||||
|
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||||
|
size_t ssid_len;
|
||||||
|
u32 short_ssid;
|
||||||
|
u32 center_freq;
|
||||||
|
u8 unsolicited_probe:1,
|
||||||
|
oct_recommended:1,
|
||||||
|
same_ssid:1,
|
||||||
|
multi_bss:1,
|
||||||
|
transmitted_bssid:1,
|
||||||
|
colocated_ess:1,
|
||||||
|
short_ssid_valid:1;
|
||||||
|
s8 psd_20;
|
||||||
|
};
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_CFG80211_KUNIT_TEST)
|
#if IS_ENABLED(CONFIG_CFG80211_KUNIT_TEST)
|
||||||
#define EXPORT_SYMBOL_IF_CFG80211_KUNIT(sym) EXPORT_SYMBOL_IF_KUNIT(sym)
|
#define EXPORT_SYMBOL_IF_CFG80211_KUNIT(sym) EXPORT_SYMBOL_IF_KUNIT(sym)
|
||||||
#define VISIBLE_IF_CFG80211_KUNIT
|
#define VISIBLE_IF_CFG80211_KUNIT
|
||||||
|
void cfg80211_free_coloc_ap_list(struct list_head *coloc_ap_list);
|
||||||
|
|
||||||
|
int cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies,
|
||||||
|
struct list_head *list);
|
||||||
|
|
||||||
size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
|
size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
|
||||||
const u8 *subie, size_t subie_len,
|
const u8 *subie, size_t subie_len,
|
||||||
u8 *new_ie, size_t new_ie_len);
|
u8 *new_ie, size_t new_ie_len);
|
||||||
|
|
|
@ -77,45 +77,6 @@ MODULE_PARM_DESC(bss_entries_limit,
|
||||||
|
|
||||||
#define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
|
#define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
|
||||||
|
|
||||||
/**
|
|
||||||
* struct cfg80211_colocated_ap - colocated AP information
|
|
||||||
*
|
|
||||||
* @list: linked list to all colocated aPS
|
|
||||||
* @bssid: BSSID of the reported AP
|
|
||||||
* @ssid: SSID of the reported AP
|
|
||||||
* @ssid_len: length of the ssid
|
|
||||||
* @center_freq: frequency the reported AP is on
|
|
||||||
* @unsolicited_probe: the reported AP is part of an ESS, where all the APs
|
|
||||||
* that operate in the same channel as the reported AP and that might be
|
|
||||||
* detected by a STA receiving this frame, are transmitting unsolicited
|
|
||||||
* Probe Response frames every 20 TUs
|
|
||||||
* @oct_recommended: OCT is recommended to exchange MMPDUs with the reported AP
|
|
||||||
* @same_ssid: the reported AP has the same SSID as the reporting AP
|
|
||||||
* @multi_bss: the reported AP is part of a multiple BSSID set
|
|
||||||
* @transmitted_bssid: the reported AP is the transmitting BSSID
|
|
||||||
* @colocated_ess: all the APs that share the same ESS as the reported AP are
|
|
||||||
* colocated and can be discovered via legacy bands.
|
|
||||||
* @short_ssid_valid: short_ssid is valid and can be used
|
|
||||||
* @short_ssid: the short SSID for this SSID
|
|
||||||
* @psd_20: The 20MHz PSD EIRP of the primary 20MHz channel for the reported AP
|
|
||||||
*/
|
|
||||||
struct cfg80211_colocated_ap {
|
|
||||||
struct list_head list;
|
|
||||||
u8 bssid[ETH_ALEN];
|
|
||||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
|
||||||
size_t ssid_len;
|
|
||||||
u32 short_ssid;
|
|
||||||
u32 center_freq;
|
|
||||||
u8 unsolicited_probe:1,
|
|
||||||
oct_recommended:1,
|
|
||||||
same_ssid:1,
|
|
||||||
multi_bss:1,
|
|
||||||
transmitted_bssid:1,
|
|
||||||
colocated_ess:1,
|
|
||||||
short_ssid_valid:1;
|
|
||||||
s8 psd_20;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void bss_free(struct cfg80211_internal_bss *bss)
|
static void bss_free(struct cfg80211_internal_bss *bss)
|
||||||
{
|
{
|
||||||
struct cfg80211_bss_ies *ies;
|
struct cfg80211_bss_ies *ies;
|
||||||
|
@ -566,7 +527,8 @@ static int cfg80211_calc_short_ssid(const struct cfg80211_bss_ies *ies,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cfg80211_free_coloc_ap_list(struct list_head *coloc_ap_list)
|
VISIBLE_IF_CFG80211_KUNIT void
|
||||||
|
cfg80211_free_coloc_ap_list(struct list_head *coloc_ap_list)
|
||||||
{
|
{
|
||||||
struct cfg80211_colocated_ap *ap, *tmp_ap;
|
struct cfg80211_colocated_ap *ap, *tmp_ap;
|
||||||
|
|
||||||
|
@ -575,6 +537,7 @@ static void cfg80211_free_coloc_ap_list(struct list_head *coloc_ap_list)
|
||||||
kfree(ap);
|
kfree(ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_IF_KUNIT(cfg80211_free_coloc_ap_list);
|
||||||
|
|
||||||
static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry,
|
static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry,
|
||||||
const u8 *pos, u8 length,
|
const u8 *pos, u8 length,
|
||||||
|
@ -648,8 +611,9 @@ static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies,
|
VISIBLE_IF_CFG80211_KUNIT int
|
||||||
struct list_head *list)
|
cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies,
|
||||||
|
struct list_head *list)
|
||||||
{
|
{
|
||||||
struct ieee80211_neighbor_ap_info *ap_info;
|
struct ieee80211_neighbor_ap_info *ap_info;
|
||||||
const struct element *elem, *ssid_elem;
|
const struct element *elem, *ssid_elem;
|
||||||
|
@ -746,6 +710,7 @@ error:
|
||||||
list_splice_tail(&ap_list, list);
|
list_splice_tail(&ap_list, list);
|
||||||
return n_coloc;
|
return n_coloc;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_IF_KUNIT(cfg80211_parse_colocated_ap);
|
||||||
|
|
||||||
static void cfg80211_scan_req_add_chan(struct cfg80211_scan_request *request,
|
static void cfg80211_scan_req_add_chan(struct cfg80211_scan_request *request,
|
||||||
struct ieee80211_channel *chan,
|
struct ieee80211_channel *chan,
|
||||||
|
|
|
@ -628,6 +628,172 @@ static void test_inform_bss_ml_sta(struct kunit *test)
|
||||||
cfg80211_put_bss(wiphy, link_bss);
|
cfg80211_put_bss(wiphy, link_bss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct cfg80211_parse_colocated_ap_case {
|
||||||
|
const char *desc;
|
||||||
|
u8 op_class;
|
||||||
|
u8 channel;
|
||||||
|
struct ieee80211_neighbor_ap_info info;
|
||||||
|
union {
|
||||||
|
struct ieee80211_tbtt_info_ge_11 tbtt_long;
|
||||||
|
struct ieee80211_tbtt_info_7_8_9 tbtt_short;
|
||||||
|
};
|
||||||
|
bool add_junk;
|
||||||
|
bool same_ssid;
|
||||||
|
bool valid;
|
||||||
|
} cfg80211_parse_colocated_ap_cases[] = {
|
||||||
|
{
|
||||||
|
.desc = "wrong_band",
|
||||||
|
.info.op_class = 81,
|
||||||
|
.info.channel = 11,
|
||||||
|
.tbtt_long = {
|
||||||
|
.bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
|
||||||
|
.bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
|
||||||
|
},
|
||||||
|
.valid = false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "wrong_type",
|
||||||
|
/* IEEE80211_AP_INFO_TBTT_HDR_TYPE is in the least significant bits */
|
||||||
|
.info.tbtt_info_hdr = IEEE80211_TBTT_INFO_TYPE_MLD,
|
||||||
|
.tbtt_long = {
|
||||||
|
.bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
|
||||||
|
.bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
|
||||||
|
},
|
||||||
|
.valid = false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "colocated_invalid_len_short",
|
||||||
|
.info.tbtt_info_len = 6,
|
||||||
|
.tbtt_short = {
|
||||||
|
.bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
|
||||||
|
.bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP |
|
||||||
|
IEEE80211_RNR_TBTT_PARAMS_SAME_SSID,
|
||||||
|
},
|
||||||
|
.valid = false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "colocated_invalid_len_short_mld",
|
||||||
|
.info.tbtt_info_len = 10,
|
||||||
|
.tbtt_long = {
|
||||||
|
.bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
|
||||||
|
.bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
|
||||||
|
},
|
||||||
|
.valid = false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "colocated_non_mld",
|
||||||
|
.info.tbtt_info_len = sizeof(struct ieee80211_tbtt_info_7_8_9),
|
||||||
|
.tbtt_short = {
|
||||||
|
.bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
|
||||||
|
.bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP |
|
||||||
|
IEEE80211_RNR_TBTT_PARAMS_SAME_SSID,
|
||||||
|
},
|
||||||
|
.same_ssid = true,
|
||||||
|
.valid = true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "colocated_non_mld_invalid_bssid",
|
||||||
|
.info.tbtt_info_len = sizeof(struct ieee80211_tbtt_info_7_8_9),
|
||||||
|
.tbtt_short = {
|
||||||
|
.bssid = { 0xff, 0x11, 0x22, 0x33, 0x44, 0x55 },
|
||||||
|
.bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP |
|
||||||
|
IEEE80211_RNR_TBTT_PARAMS_SAME_SSID,
|
||||||
|
},
|
||||||
|
.same_ssid = true,
|
||||||
|
.valid = false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "colocated_mld",
|
||||||
|
.tbtt_long = {
|
||||||
|
.bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
|
||||||
|
.bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
|
||||||
|
},
|
||||||
|
.valid = true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "colocated_mld",
|
||||||
|
.tbtt_long = {
|
||||||
|
.bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
|
||||||
|
.bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
|
||||||
|
},
|
||||||
|
.add_junk = true,
|
||||||
|
.valid = false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.desc = "colocated_disabled_mld",
|
||||||
|
.tbtt_long = {
|
||||||
|
.bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
|
||||||
|
.bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
|
||||||
|
.mld_params.params = cpu_to_le16(IEEE80211_RNR_MLD_PARAMS_DISABLED_LINK),
|
||||||
|
},
|
||||||
|
.valid = false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
KUNIT_ARRAY_PARAM_DESC(cfg80211_parse_colocated_ap, cfg80211_parse_colocated_ap_cases, desc)
|
||||||
|
|
||||||
|
static void test_cfg80211_parse_colocated_ap(struct kunit *test)
|
||||||
|
{
|
||||||
|
const struct cfg80211_parse_colocated_ap_case *params = test->param_value;
|
||||||
|
struct sk_buff *input = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
|
||||||
|
struct cfg80211_bss_ies *ies;
|
||||||
|
struct ieee80211_neighbor_ap_info info;
|
||||||
|
LIST_HEAD(coloc_ap_list);
|
||||||
|
int count;
|
||||||
|
|
||||||
|
KUNIT_ASSERT_NOT_NULL(test, input);
|
||||||
|
|
||||||
|
info = params->info;
|
||||||
|
|
||||||
|
/* Reasonable values for a colocated AP */
|
||||||
|
if (!info.tbtt_info_len)
|
||||||
|
info.tbtt_info_len = sizeof(params->tbtt_long);
|
||||||
|
if (!info.op_class)
|
||||||
|
info.op_class = 131;
|
||||||
|
if (!info.channel)
|
||||||
|
info.channel = 33;
|
||||||
|
/* Zero is the correct default for .btt_info_hdr (one entry, TBTT type) */
|
||||||
|
|
||||||
|
skb_put_u8(input, WLAN_EID_SSID);
|
||||||
|
skb_put_u8(input, 4);
|
||||||
|
skb_put_data(input, "TEST", 4);
|
||||||
|
|
||||||
|
skb_put_u8(input, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
|
||||||
|
skb_put_u8(input, sizeof(info) + info.tbtt_info_len + (params->add_junk ? 3 : 0));
|
||||||
|
skb_put_data(input, &info, sizeof(info));
|
||||||
|
skb_put_data(input, ¶ms->tbtt_long, info.tbtt_info_len);
|
||||||
|
|
||||||
|
if (params->add_junk)
|
||||||
|
skb_put_data(input, "123", 3);
|
||||||
|
|
||||||
|
ies = kunit_kzalloc(test, struct_size(ies, data, input->len), GFP_KERNEL);
|
||||||
|
ies->len = input->len;
|
||||||
|
memcpy(ies->data, input->data, input->len);
|
||||||
|
|
||||||
|
count = cfg80211_parse_colocated_ap(ies, &coloc_ap_list);
|
||||||
|
|
||||||
|
KUNIT_EXPECT_EQ(test, count, params->valid);
|
||||||
|
KUNIT_EXPECT_EQ(test, list_count_nodes(&coloc_ap_list), params->valid);
|
||||||
|
|
||||||
|
if (params->valid && !list_empty(&coloc_ap_list)) {
|
||||||
|
struct cfg80211_colocated_ap *ap;
|
||||||
|
|
||||||
|
ap = list_first_entry(&coloc_ap_list, typeof(*ap), list);
|
||||||
|
if (info.tbtt_info_len <= sizeof(params->tbtt_short))
|
||||||
|
KUNIT_EXPECT_MEMEQ(test, ap->bssid, params->tbtt_short.bssid, ETH_ALEN);
|
||||||
|
else
|
||||||
|
KUNIT_EXPECT_MEMEQ(test, ap->bssid, params->tbtt_long.bssid, ETH_ALEN);
|
||||||
|
|
||||||
|
if (params->same_ssid) {
|
||||||
|
KUNIT_EXPECT_EQ(test, ap->ssid_len, 4);
|
||||||
|
KUNIT_EXPECT_MEMEQ(test, ap->ssid, "TEST", 4);
|
||||||
|
} else {
|
||||||
|
KUNIT_EXPECT_EQ(test, ap->ssid_len, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg80211_free_coloc_ap_list(&coloc_ap_list);
|
||||||
|
}
|
||||||
|
|
||||||
static struct kunit_case gen_new_ie_test_cases[] = {
|
static struct kunit_case gen_new_ie_test_cases[] = {
|
||||||
KUNIT_CASE_PARAM(test_gen_new_ie, gen_new_ie_gen_params),
|
KUNIT_CASE_PARAM(test_gen_new_ie, gen_new_ie_gen_params),
|
||||||
KUNIT_CASE(test_gen_new_ie_malformed),
|
KUNIT_CASE(test_gen_new_ie_malformed),
|
||||||
|
@ -653,3 +819,16 @@ static struct kunit_suite inform_bss = {
|
||||||
};
|
};
|
||||||
|
|
||||||
kunit_test_suite(inform_bss);
|
kunit_test_suite(inform_bss);
|
||||||
|
|
||||||
|
static struct kunit_case scan_6ghz_cases[] = {
|
||||||
|
KUNIT_CASE_PARAM(test_cfg80211_parse_colocated_ap,
|
||||||
|
cfg80211_parse_colocated_ap_gen_params),
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct kunit_suite scan_6ghz = {
|
||||||
|
.name = "cfg80211-scan-6ghz",
|
||||||
|
.test_cases = scan_6ghz_cases,
|
||||||
|
};
|
||||||
|
|
||||||
|
kunit_test_suite(scan_6ghz);
|
||||||
|
|
Loading…
Add table
Reference in a new issue