1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * KUnit tests for element fragmentation
4 *
5 * Copyright (C) 2023-2024 Intel Corporation
6 */
7#include <linux/ieee80211.h>
8#include <net/cfg80211.h>
9#include <kunit/test.h>
10
11static void defragment_0(struct kunit *test)
12{
13	ssize_t ret;
14	static const u8 input[] = {
15		[0] = WLAN_EID_EXTENSION,
16		[1] = 254,
17		[2] = WLAN_EID_EXT_EHT_MULTI_LINK,
18		[27] = 27,
19		[123] = 123,
20		[254 + 2] = WLAN_EID_FRAGMENT,
21		[254 + 3] = 7,
22		[254 + 3 + 7] = 0, /* for size */
23	};
24	u8 *data = kunit_kzalloc(test, sizeof(input), GFP_KERNEL);
25
26	KUNIT_ASSERT_NOT_NULL(test, data);
27
28	ret = cfg80211_defragment_element((void *)input,
29					  input, sizeof(input),
30					  NULL, 0,
31					  WLAN_EID_FRAGMENT);
32	KUNIT_EXPECT_EQ(test, ret, 253);
33	ret = cfg80211_defragment_element((void *)input,
34					  input, sizeof(input),
35					  data, ret,
36					  WLAN_EID_FRAGMENT);
37	KUNIT_EXPECT_EQ(test, ret, 253);
38	KUNIT_EXPECT_MEMEQ(test, data, input + 3, 253);
39}
40
41static void defragment_1(struct kunit *test)
42{
43	ssize_t ret;
44	static const u8 input[] = {
45		[0] = WLAN_EID_EXTENSION,
46		[1] = 255,
47		[2] = WLAN_EID_EXT_EHT_MULTI_LINK,
48		[27] = 27,
49		[123] = 123,
50		[255 + 2] = WLAN_EID_FRAGMENT,
51		[255 + 3] = 7,
52		[255 + 3 + 1] = 0xaa,
53		[255 + 3 + 8] = WLAN_EID_FRAGMENT, /* not used */
54		[255 + 3 + 9] = 1,
55		[255 + 3 + 10] = 0, /* for size */
56	};
57	u8 *data = kunit_kzalloc(test, sizeof(input), GFP_KERNEL);
58	const struct element *elem;
59	int count = 0;
60
61	KUNIT_ASSERT_NOT_NULL(test, data);
62
63	for_each_element(elem, input, sizeof(input))
64		count++;
65
66	/* check the elements are right */
67	KUNIT_ASSERT_EQ(test, count, 3);
68
69	ret = cfg80211_defragment_element((void *)input,
70					  input, sizeof(input),
71					  NULL, 0,
72					  WLAN_EID_FRAGMENT);
73	KUNIT_EXPECT_EQ(test, ret, 254 + 7);
74	ret = cfg80211_defragment_element((void *)input,
75					  input, sizeof(input),
76					  data, ret,
77					  WLAN_EID_FRAGMENT);
78	/* this means the last fragment was not used */
79	KUNIT_EXPECT_EQ(test, ret, 254 + 7);
80	KUNIT_EXPECT_MEMEQ(test, data, input + 3, 254);
81	KUNIT_EXPECT_MEMEQ(test, data + 254, input + 255 + 4, 7);
82}
83
84static void defragment_2(struct kunit *test)
85{
86	ssize_t ret;
87	static const u8 input[] = {
88		[0] = WLAN_EID_EXTENSION,
89		[1] = 255,
90		[2] = WLAN_EID_EXT_EHT_MULTI_LINK,
91		[27] = 27,
92		[123] = 123,
93
94		[257 + 0] = WLAN_EID_FRAGMENT,
95		[257 + 1] = 255,
96		[257 + 20] = 0xaa,
97
98		[2 * 257 + 0] = WLAN_EID_FRAGMENT,
99		[2 * 257 + 1] = 1,
100		[2 * 257 + 2] = 0xcc,
101		[2 * 257 + 3] = WLAN_EID_FRAGMENT, /* not used */
102		[2 * 257 + 4] = 1,
103		[2 * 257 + 5] = 0, /* for size */
104	};
105	u8 *data = kunit_kzalloc(test, sizeof(input), GFP_KERNEL);
106	const struct element *elem;
107	int count = 0;
108
109	KUNIT_ASSERT_NOT_NULL(test, data);
110
111	for_each_element(elem, input, sizeof(input))
112		count++;
113
114	/* check the elements are right */
115	KUNIT_ASSERT_EQ(test, count, 4);
116
117	ret = cfg80211_defragment_element((void *)input,
118					  input, sizeof(input),
119					  NULL, 0,
120					  WLAN_EID_FRAGMENT);
121	/* this means the last fragment was not used */
122	KUNIT_EXPECT_EQ(test, ret, 254 + 255 + 1);
123	ret = cfg80211_defragment_element((void *)input,
124					  input, sizeof(input),
125					  data, ret,
126					  WLAN_EID_FRAGMENT);
127	KUNIT_EXPECT_EQ(test, ret, 254 + 255 + 1);
128	KUNIT_EXPECT_MEMEQ(test, data, input + 3, 254);
129	KUNIT_EXPECT_MEMEQ(test, data + 254, input + 257 + 2, 255);
130	KUNIT_EXPECT_MEMEQ(test, data + 254 + 255, input + 2 * 257 + 2, 1);
131}
132
133static void defragment_at_end(struct kunit *test)
134{
135	ssize_t ret;
136	static const u8 input[] = {
137		[0] = WLAN_EID_EXTENSION,
138		[1] = 255,
139		[2] = WLAN_EID_EXT_EHT_MULTI_LINK,
140		[27] = 27,
141		[123] = 123,
142		[255 + 2] = WLAN_EID_FRAGMENT,
143		[255 + 3] = 7,
144		[255 + 3 + 7] = 0, /* for size */
145	};
146	u8 *data = kunit_kzalloc(test, sizeof(input), GFP_KERNEL);
147
148	KUNIT_ASSERT_NOT_NULL(test, data);
149
150	ret = cfg80211_defragment_element((void *)input,
151					  input, sizeof(input),
152					  NULL, 0,
153					  WLAN_EID_FRAGMENT);
154	KUNIT_EXPECT_EQ(test, ret, 254 + 7);
155	ret = cfg80211_defragment_element((void *)input,
156					  input, sizeof(input),
157					  data, ret,
158					  WLAN_EID_FRAGMENT);
159	KUNIT_EXPECT_EQ(test, ret, 254 + 7);
160	KUNIT_EXPECT_MEMEQ(test, data, input + 3, 254);
161	KUNIT_EXPECT_MEMEQ(test, data + 254, input + 255 + 4, 7);
162}
163
164static struct kunit_case element_fragmentation_test_cases[] = {
165	KUNIT_CASE(defragment_0),
166	KUNIT_CASE(defragment_1),
167	KUNIT_CASE(defragment_2),
168	KUNIT_CASE(defragment_at_end),
169	{}
170};
171
172static struct kunit_suite element_fragmentation = {
173	.name = "cfg80211-element-defragmentation",
174	.test_cases = element_fragmentation_test_cases,
175};
176
177kunit_test_suite(element_fragmentation);
178