|  | // 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); |