forked from mirrors/linux
		
	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); | ||||
| 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) | ||||
| #define EXPORT_SYMBOL_IF_CFG80211_KUNIT(sym) EXPORT_SYMBOL_IF_KUNIT(sym) | ||||
| #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, | ||||
| 			   const u8 *subie, size_t subie_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) | ||||
| 
 | ||||
| /**
 | ||||
|  * 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) | ||||
| { | ||||
| 	struct cfg80211_bss_ies *ies; | ||||
|  | @ -566,7 +527,8 @@ static int cfg80211_calc_short_ssid(const struct cfg80211_bss_ies *ies, | |||
| 	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; | ||||
| 
 | ||||
|  | @ -575,6 +537,7 @@ static void cfg80211_free_coloc_ap_list(struct list_head *coloc_ap_list) | |||
| 		kfree(ap); | ||||
| 	} | ||||
| } | ||||
| EXPORT_SYMBOL_IF_KUNIT(cfg80211_free_coloc_ap_list); | ||||
| 
 | ||||
| static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry, | ||||
| 				  const u8 *pos, u8 length, | ||||
|  | @ -648,8 +611,9 @@ static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry, | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies, | ||||
| 				       struct list_head *list) | ||||
| VISIBLE_IF_CFG80211_KUNIT int | ||||
| cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies, | ||||
| 			    struct list_head *list) | ||||
| { | ||||
| 	struct ieee80211_neighbor_ap_info *ap_info; | ||||
| 	const struct element *elem, *ssid_elem; | ||||
|  | @ -746,6 +710,7 @@ static int cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies, | |||
| 	list_splice_tail(&ap_list, list); | ||||
| 	return n_coloc; | ||||
| } | ||||
| EXPORT_SYMBOL_IF_KUNIT(cfg80211_parse_colocated_ap); | ||||
| 
 | ||||
| static  void cfg80211_scan_req_add_chan(struct cfg80211_scan_request *request, | ||||
| 					struct ieee80211_channel *chan, | ||||
|  |  | |||
|  | @ -628,6 +628,172 @@ static void test_inform_bss_ml_sta(struct kunit *test) | |||
| 	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[] = { | ||||
| 	KUNIT_CASE_PARAM(test_gen_new_ie, gen_new_ie_gen_params), | ||||
| 	KUNIT_CASE(test_gen_new_ie_malformed), | ||||
|  | @ -653,3 +819,16 @@ static struct kunit_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…
	
		Reference in a new issue
	
	 Benjamin Berg
						Benjamin Berg