projects/linux·blob master · refs

408 lines · 9.2 KiB

1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * KUnit tests for channel helper functions
4 *
5 * Copyright (C) 2023-2024, 2026 Intel Corporation
6 */
7#include <net/cfg80211.h>
8#include <kunit/test.h>
9
10MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
11
12static struct ieee80211_channel chan_2ghz_1 = {
13 .band = NL80211_BAND_2GHZ,
14 .center_freq = 2412,
15};
16
17static struct ieee80211_channel chan_6ghz_1 = {
18 .band = NL80211_BAND_6GHZ,
19 .center_freq = 5955,
20};
21
22static struct ieee80211_channel chan_6ghz_5 = {
23 .band = NL80211_BAND_6GHZ,
24 .center_freq = 5975,
25};
26
27static struct ieee80211_channel chan_6ghz_105 = {
28 .band = NL80211_BAND_6GHZ,
29 .center_freq = 6475,
30};
31
32static const struct chandef_compat_case {
33 const char *desc;
34 /* leave c1 empty for tests for identical */
35 struct cfg80211_chan_def c1, c2;
36 /* we test both ways around, so c2 should always be the compat one */
37 bool compat;
38} chandef_compat_cases[] = {
39 {
40 .desc = "identical non-HT",
41 .c2 = {
42 .width = NL80211_CHAN_WIDTH_20_NOHT,
43 .chan = &chan_6ghz_1,
44 .center_freq1 = 5955,
45 },
46 .compat = true,
47 },
48 {
49 .desc = "identical 20 MHz",
50 .c2 = {
51 .width = NL80211_CHAN_WIDTH_20,
52 .chan = &chan_6ghz_1,
53 .center_freq1 = 5955,
54 },
55 .compat = true,
56 },
57 {
58 .desc = "identical 40 MHz",
59 .c2 = {
60 .width = NL80211_CHAN_WIDTH_40,
61 .chan = &chan_6ghz_1,
62 .center_freq1 = 5955 + 10,
63 },
64 .compat = true,
65 },
66 {
67 .desc = "identical 80 MHz",
68 .c2 = {
69 .width = NL80211_CHAN_WIDTH_80,
70 .chan = &chan_6ghz_1,
71 .center_freq1 = 5955 + 10 + 20,
72 },
73 .compat = true,
74 },
75 {
76 .desc = "identical 160 MHz",
77 .c2 = {
78 .width = NL80211_CHAN_WIDTH_160,
79 .chan = &chan_6ghz_1,
80 .center_freq1 = 5955 + 10 + 20 + 40,
81 },
82 .compat = true,
83 },
84 {
85 .desc = "identical 320 MHz",
86 .c2 = {
87 .width = NL80211_CHAN_WIDTH_320,
88 .chan = &chan_6ghz_1,
89 .center_freq1 = 5955 + 10 + 20 + 40 + 80,
90 },
91 .compat = true,
92 },
93 {
94 .desc = "20 MHz in 320 MHz\n",
95 .c1 = {
96 .width = NL80211_CHAN_WIDTH_20,
97 .chan = &chan_6ghz_1,
98 .center_freq1 = 5955,
99 },
100 .c2 = {
101 .width = NL80211_CHAN_WIDTH_320,
102 .chan = &chan_6ghz_1,
103 .center_freq1 = 5955 + 10 + 20 + 40 + 80,
104 },
105 .compat = true,
106 },
107 {
108 .desc = "different 20 MHz",
109 .c1 = {
110 .width = NL80211_CHAN_WIDTH_20,
111 .chan = &chan_6ghz_1,
112 .center_freq1 = 5955,
113 },
114 .c2 = {
115 .width = NL80211_CHAN_WIDTH_20,
116 .chan = &chan_6ghz_5,
117 .center_freq1 = 5975,
118 },
119 },
120 {
121 .desc = "different primary 320 MHz",
122 .c1 = {
123 .width = NL80211_CHAN_WIDTH_320,
124 .chan = &chan_6ghz_105,
125 .center_freq1 = 6475 + 110,
126 },
127 .c2 = {
128 .width = NL80211_CHAN_WIDTH_320,
129 .chan = &chan_6ghz_105,
130 .center_freq1 = 6475 - 50,
131 },
132 },
133 {
134 /* similar to previous test but one has lower BW */
135 .desc = "matching primary 160 MHz",
136 .c1 = {
137 .width = NL80211_CHAN_WIDTH_160,
138 .chan = &chan_6ghz_105,
139 .center_freq1 = 6475 + 30,
140 },
141 .c2 = {
142 .width = NL80211_CHAN_WIDTH_320,
143 .chan = &chan_6ghz_105,
144 .center_freq1 = 6475 - 50,
145 },
146 .compat = true,
147 },
148 {
149 .desc = "matching primary 160 MHz & punctured secondary 160 Mhz",
150 .c1 = {
151 .width = NL80211_CHAN_WIDTH_160,
152 .chan = &chan_6ghz_105,
153 .center_freq1 = 6475 + 30,
154 },
155 .c2 = {
156 .width = NL80211_CHAN_WIDTH_320,
157 .chan = &chan_6ghz_105,
158 .center_freq1 = 6475 - 50,
159 .punctured = 0xf,
160 },
161 .compat = true,
162 },
163 {
164 .desc = "matching primary 160 MHz & punctured matching",
165 .c1 = {
166 .width = NL80211_CHAN_WIDTH_160,
167 .chan = &chan_6ghz_105,
168 .center_freq1 = 6475 + 30,
169 .punctured = 0xc0,
170 },
171 .c2 = {
172 .width = NL80211_CHAN_WIDTH_320,
173 .chan = &chan_6ghz_105,
174 .center_freq1 = 6475 - 50,
175 .punctured = 0xc000,
176 },
177 .compat = true,
178 },
179 {
180 .desc = "matching primary 160 MHz & punctured not matching",
181 .c1 = {
182 .width = NL80211_CHAN_WIDTH_160,
183 .chan = &chan_6ghz_105,
184 .center_freq1 = 6475 + 30,
185 .punctured = 0x80,
186 },
187 .c2 = {
188 .width = NL80211_CHAN_WIDTH_320,
189 .chan = &chan_6ghz_105,
190 .center_freq1 = 6475 - 50,
191 .punctured = 0xc000,
192 },
193 },
194};
195
196KUNIT_ARRAY_PARAM_DESC(chandef_compat, chandef_compat_cases, desc)
197
198static void test_chandef_compat(struct kunit *test)
199{
200 const struct chandef_compat_case *params = test->param_value;
201 const struct cfg80211_chan_def *ret, *expect;
202 struct cfg80211_chan_def c1 = params->c1;
203
204 /* tests with identical ones */
205 if (!params->c1.chan)
206 c1 = params->c2;
207
208 KUNIT_EXPECT_EQ(test, cfg80211_chandef_valid(&c1), true);
209 KUNIT_EXPECT_EQ(test, cfg80211_chandef_valid(&params->c2), true);
210
211 expect = params->compat ? &params->c2 : NULL;
212
213 ret = cfg80211_chandef_compatible(&c1, &params->c2);
214 KUNIT_EXPECT_PTR_EQ(test, ret, expect);
215
216 if (!params->c1.chan)
217 expect = &c1;
218
219 ret = cfg80211_chandef_compatible(&params->c2, &c1);
220 KUNIT_EXPECT_PTR_EQ(test, ret, expect);
221}
222
223static const struct chandef_dbe_case {
224 const char *desc;
225 struct cfg80211_chan_def c;
226 u8 dbe[3];
227 bool fails;
228 u16 cf1;
229} chandef_dbe_cases[] = {
230 {
231 .desc = "non-HT failure",
232 .c = {
233 .width = NL80211_CHAN_WIDTH_20_NOHT,
234 .chan = &chan_6ghz_1,
235 .center_freq1 = 5955,
236 },
237 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_40,
238 .fails = true,
239 },
240 {
241 .desc = "2.4 GHz fails",
242 .c = {
243 .width = NL80211_CHAN_WIDTH_20,
244 .chan = &chan_2ghz_1,
245 .center_freq1 = 2412,
246 },
247 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_40,
248 .fails = true,
249 },
250 {
251 .desc = "DBE narrower",
252 .c = {
253 .width = NL80211_CHAN_WIDTH_320,
254 .chan = &chan_6ghz_1,
255 .center_freq1 = 5955 + 10 + 20 + 40 + 80,
256 },
257 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_160,
258 .fails = true,
259 },
260 {
261 .desc = "DBE to 320-1",
262 .c = {
263 .width = NL80211_CHAN_WIDTH_160,
264 .chan = &chan_6ghz_105,
265 .center_freq1 = 6475 + 30,
266 },
267 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_320_1,
268 .cf1 = 6425,
269 },
270 {
271 .desc = "DBE to 320-2",
272 .c = {
273 .width = NL80211_CHAN_WIDTH_160,
274 .chan = &chan_6ghz_105,
275 .center_freq1 = 6475 + 30,
276 },
277 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_320_2,
278 .cf1 = 6585,
279 },
280 {
281 .desc = "bad disabled subchannel bitmap - not enough in BSS (1)",
282 .c = {
283 .width = NL80211_CHAN_WIDTH_160,
284 .chan = &chan_6ghz_105,
285 .center_freq1 = 6475 + 30,
286 .punctured = 0x0001,
287 },
288 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_320_1 |
289 IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES,
290 /* DBE disabled subchannel bitmap == 0 */
291 .fails = true,
292 },
293 {
294 .desc = "bad disabled subchannel bitmap - too much in BSS (1)",
295 .c = {
296 .width = NL80211_CHAN_WIDTH_160,
297 .chan = &chan_6ghz_105,
298 .center_freq1 = 6475 + 30,
299 .punctured = 0x0001,
300 },
301 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_320_1 |
302 IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES,
303 /* DBE disabled subchannel bitmap == 0x0300 */
304 .dbe[2] = 0x03,
305 .fails = true,
306 },
307 {
308 .desc = "bad disabled subchannel bitmap - not enough in BSS (2)",
309 .c = {
310 .width = NL80211_CHAN_WIDTH_160,
311 .chan = &chan_6ghz_105,
312 .center_freq1 = 6475 + 30,
313 .punctured = 0x0001,
314 },
315 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_320_2 |
316 IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES,
317 /* DBE disabled subchannel bitmap == 0 */
318 .fails = true,
319 },
320 {
321 .desc = "bad disabled subchannel bitmap - too much in BSS (2)",
322 .c = {
323 .width = NL80211_CHAN_WIDTH_160,
324 .chan = &chan_6ghz_105,
325 .center_freq1 = 6475 + 30,
326 .punctured = 0x0001,
327 },
328 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_320_2 |
329 IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES,
330 /* DBE disabled subchannel bitmap == 0x03 */
331 .dbe[1] = 0x03,
332 .fails = true,
333 },
334 {
335 .desc = "bad disabled subchannel bitmap - bad bitmap",
336 .c = {
337 .width = NL80211_CHAN_WIDTH_160,
338 .chan = &chan_6ghz_105,
339 .center_freq1 = 6475 + 30,
340 .punctured = 0x0001,
341 },
342 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_320_1 |
343 IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES,
344 /* DBE disabled subchannel bitmap == 0x1100 */
345 .dbe[2] = 0x11,
346 .fails = true,
347 },
348 {
349 .desc = "good disabled subchannel bitmap (1)",
350 .c = {
351 .width = NL80211_CHAN_WIDTH_160,
352 .chan = &chan_6ghz_105,
353 .center_freq1 = 6475 + 30,
354 .punctured = 0x0003,
355 },
356 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_320_1 |
357 IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES,
358 /* DBE disabled subchannel bitmap == 0x0300 */
359 .dbe[2] = 0x03,
360 .cf1 = 6425,
361 },
362 {
363 .desc = "good disabled subchannel bitmap (2)",
364 .c = {
365 .width = NL80211_CHAN_WIDTH_160,
366 .chan = &chan_6ghz_105,
367 .center_freq1 = 6475 + 30,
368 .punctured = 0x0003,
369 },
370 .dbe[0] = IEEE80211_UHR_DBE_OPER_BW_320_2 |
371 IEEE80211_UHR_DBE_OPER_DIS_SUBCHANNEL_BITMAP_PRES,
372 /* DBE disabled subchannel bitmap == 0x0003 */
373 .dbe[1] = 0x03,
374 .cf1 = 6585,
375 },
376};
377
378KUNIT_ARRAY_PARAM_DESC(chandef_dbe, chandef_dbe_cases, desc)
379
380static void test_chandef_dbe(struct kunit *test)
381{
382 const struct chandef_dbe_case *params = test->param_value;
383 struct cfg80211_chan_def c = params->c;
384 int ret;
385
386 KUNIT_EXPECT_EQ(test, cfg80211_chandef_valid(&params->c), true);
387
388 ret = cfg80211_chandef_add_dbe(&c, (void *)params->dbe);
389 KUNIT_EXPECT_EQ(test, ret != 0, params->fails);
390
391 if (params->fails)
392 return;
393
394 KUNIT_EXPECT_EQ(test, c.center_freq1, params->cf1);
395}
396
397static struct kunit_case chandef_test_cases[] = {
398 KUNIT_CASE_PARAM(test_chandef_compat, chandef_compat_gen_params),
399 KUNIT_CASE_PARAM(test_chandef_dbe, chandef_dbe_gen_params),
400 {}
401};
402
403static struct kunit_suite chandef = {
404 .name = "cfg80211-chandef",
405 .test_cases = chandef_test_cases,
406};
407
408kunit_test_suite(chandef);