| // SPDX-License-Identifier: GPL-2.0-only | 
 | /* | 
 |  * KUnit tests for element parsing | 
 |  * | 
 |  * Copyright (C) 2023-2024 Intel Corporation | 
 |  */ | 
 | #include <kunit/test.h> | 
 | #include "../ieee80211_i.h" | 
 |  | 
 | MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); | 
 |  | 
 | static void mle_defrag(struct kunit *test) | 
 | { | 
 | 	struct ieee80211_elems_parse_params parse_params = { | 
 | 		.link_id = 12, | 
 | 		.from_ap = true, | 
 | 		.mode = IEEE80211_CONN_MODE_EHT, | 
 | 	}; | 
 | 	struct ieee802_11_elems *parsed; | 
 | 	struct sk_buff *skb; | 
 | 	u8 *len_mle, *len_prof; | 
 | 	int i; | 
 |  | 
 | 	skb = alloc_skb(1024, GFP_KERNEL); | 
 | 	KUNIT_ASSERT_NOT_NULL(test, skb); | 
 |  | 
 | 	if (skb_pad(skb, skb_tailroom(skb))) { | 
 | 		KUNIT_FAIL(test, "failed to pad skb"); | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	/* build a multi-link element */ | 
 | 	skb_put_u8(skb, WLAN_EID_EXTENSION); | 
 | 	len_mle = skb_put(skb, 1); | 
 | 	skb_put_u8(skb, WLAN_EID_EXT_EHT_MULTI_LINK); | 
 |  | 
 | 	put_unaligned_le16(IEEE80211_ML_CONTROL_TYPE_BASIC, | 
 | 			   skb_put(skb, 2)); | 
 | 	/* struct ieee80211_mle_basic_common_info */ | 
 | 	skb_put_u8(skb, 7); /* includes len field */ | 
 | 	skb_put_data(skb, "\x00\x00\x00\x00\x00\x00", ETH_ALEN); /* MLD addr */ | 
 |  | 
 | 	/* with a STA profile inside */ | 
 | 	skb_put_u8(skb, IEEE80211_MLE_SUBELEM_PER_STA_PROFILE); | 
 | 	len_prof = skb_put(skb, 1); | 
 | 	put_unaligned_le16(IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE | | 
 | 			   parse_params.link_id, | 
 | 			   skb_put(skb, 2)); | 
 | 	skb_put_u8(skb, 1); /* fake sta_info_len - includes itself */ | 
 | 	/* put a bunch of useless elements into it */ | 
 | 	for (i = 0; i < 20; i++) { | 
 | 		skb_put_u8(skb, WLAN_EID_SSID); | 
 | 		skb_put_u8(skb, 20); | 
 | 		skb_put(skb, 20); | 
 | 	} | 
 |  | 
 | 	/* fragment STA profile */ | 
 | 	ieee80211_fragment_element(skb, len_prof, | 
 | 				   IEEE80211_MLE_SUBELEM_FRAGMENT); | 
 | 	/* fragment MLE */ | 
 | 	ieee80211_fragment_element(skb, len_mle, WLAN_EID_FRAGMENT); | 
 |  | 
 | 	parse_params.start = skb->data; | 
 | 	parse_params.len = skb->len; | 
 | 	parsed = ieee802_11_parse_elems_full(&parse_params); | 
 | 	/* should return ERR_PTR or valid, not NULL */ | 
 | 	KUNIT_EXPECT_NOT_NULL(test, parsed); | 
 |  | 
 | 	if (IS_ERR_OR_NULL(parsed)) | 
 | 		goto free_skb; | 
 |  | 
 | 	KUNIT_EXPECT_NOT_NULL(test, parsed->ml_basic); | 
 | 	KUNIT_EXPECT_EQ(test, | 
 | 			parsed->ml_basic_len, | 
 | 			2 /* control */ + | 
 | 			7 /* common info */ + | 
 | 			2 /* sta profile element header */ + | 
 | 			3 /* sta profile header */ + | 
 | 			20 * 22 /* sta profile data */ + | 
 | 			2 /* sta profile fragment element */); | 
 | 	KUNIT_EXPECT_NOT_NULL(test, parsed->prof); | 
 | 	KUNIT_EXPECT_EQ(test, | 
 | 			parsed->sta_prof_len, | 
 | 			3 /* sta profile header */ + | 
 | 			20 * 22 /* sta profile data */); | 
 |  | 
 | 	kfree(parsed); | 
 | free_skb: | 
 | 	kfree_skb(skb); | 
 | } | 
 |  | 
 | static struct kunit_case element_parsing_test_cases[] = { | 
 | 	KUNIT_CASE(mle_defrag), | 
 | 	{} | 
 | }; | 
 |  | 
 | static struct kunit_suite element_parsing = { | 
 | 	.name = "mac80211-element-parsing", | 
 | 	.test_cases = element_parsing_test_cases, | 
 | }; | 
 |  | 
 | kunit_test_suite(element_parsing); |