Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

wifi: cfg80211: tests: add some scanning related tests

This adds some scanning related tests, mainly exercising the ML element
parsing and inheritance.

Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Link: https://msgid.link/20231220151952.415232-7-benjamin@sipsolutions.net
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Benjamin Berg and committed by
Johannes Berg
9d027a35 bbd97bbe

+766 -5
+12 -1
net/wireless/core.h
··· 3 3 * Wireless configuration interface internals. 4 4 * 5 5 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> 6 - * Copyright (C) 2018-2022 Intel Corporation 6 + * Copyright (C) 2018-2023 Intel Corporation 7 7 */ 8 8 #ifndef __NET_WIRELESS_CORE_H 9 9 #define __NET_WIRELESS_CORE_H ··· 548 548 int cfg80211_remove_virtual_intf(struct cfg80211_registered_device *rdev, 549 549 struct wireless_dev *wdev); 550 550 void cfg80211_wdev_release_link_bsses(struct wireless_dev *wdev, u16 link_mask); 551 + 552 + #if IS_ENABLED(CONFIG_CFG80211_KUNIT_TEST) 553 + #define EXPORT_SYMBOL_IF_CFG80211_KUNIT(sym) EXPORT_SYMBOL_IF_KUNIT(sym) 554 + #define VISIBLE_IF_CFG80211_KUNIT 555 + size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen, 556 + const u8 *subie, size_t subie_len, 557 + u8 *new_ie, size_t new_ie_len); 558 + #else 559 + #define EXPORT_SYMBOL_IF_CFG80211_KUNIT(sym) 560 + #define VISIBLE_IF_CFG80211_KUNIT static 561 + #endif /* IS_ENABLED(CONFIG_CFG80211_KUNIT_TEST) */ 551 562 552 563 #endif /* __NET_WIRELESS_CORE_H */
+6 -3
net/wireless/scan.c
··· 20 20 #include <net/cfg80211.h> 21 21 #include <net/cfg80211-wext.h> 22 22 #include <net/iw_handler.h> 23 + #include <kunit/visibility.h> 23 24 #include "core.h" 24 25 #include "nl80211.h" 25 26 #include "wext-compat.h" ··· 304 303 return *pos - buf; 305 304 } 306 305 307 - static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen, 308 - const u8 *subie, size_t subie_len, 309 - u8 *new_ie, size_t new_ie_len) 306 + VISIBLE_IF_CFG80211_KUNIT size_t 307 + cfg80211_gen_new_ie(const u8 *ie, size_t ielen, 308 + const u8 *subie, size_t subie_len, 309 + u8 *new_ie, size_t new_ie_len) 310 310 { 311 311 const struct element *non_inherit_elem, *parent, *sub; 312 312 u8 *pos = new_ie; ··· 415 413 416 414 return pos - new_ie; 417 415 } 416 + EXPORT_SYMBOL_IF_CFG80211_KUNIT(cfg80211_gen_new_ie); 418 417 419 418 static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, 420 419 const u8 *ssid, size_t ssid_len)
+1 -1
net/wireless/tests/Makefile
··· 1 - cfg80211-tests-y += module.o fragmentation.o 1 + cfg80211-tests-y += module.o fragmentation.o scan.o util.o 2 2 3 3 obj-$(CONFIG_CFG80211_KUNIT_TEST) += cfg80211-tests.o
+625
net/wireless/tests/scan.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * KUnit tests for inform_bss functions 4 + * 5 + * Copyright (C) 2023 Intel Corporation 6 + */ 7 + #include <linux/ieee80211.h> 8 + #include <net/cfg80211.h> 9 + #include <kunit/test.h> 10 + #include <kunit/skbuff.h> 11 + #include "../core.h" 12 + #include "util.h" 13 + 14 + /* mac80211 helpers for element building */ 15 + #include "../../mac80211/ieee80211_i.h" 16 + 17 + MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); 18 + 19 + struct test_elem { 20 + u8 id; 21 + u8 len; 22 + union { 23 + u8 data[255]; 24 + struct { 25 + u8 eid; 26 + u8 edata[254]; 27 + }; 28 + }; 29 + }; 30 + 31 + static struct gen_new_ie_case { 32 + const char *desc; 33 + struct test_elem parent_ies[16]; 34 + struct test_elem child_ies[16]; 35 + struct test_elem result_ies[16]; 36 + } gen_new_ie_cases[] = { 37 + { 38 + .desc = "ML not inherited", 39 + .parent_ies = { 40 + { .id = WLAN_EID_EXTENSION, .len = 255, 41 + .eid = WLAN_EID_EXT_EHT_MULTI_LINK }, 42 + }, 43 + .child_ies = { 44 + { .id = WLAN_EID_SSID, .len = 2 }, 45 + }, 46 + .result_ies = { 47 + { .id = WLAN_EID_SSID, .len = 2 }, 48 + }, 49 + }, 50 + { 51 + .desc = "fragments are ignored if previous len not 255", 52 + .parent_ies = { 53 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 254, }, 54 + { .id = WLAN_EID_FRAGMENT, .len = 125, }, 55 + }, 56 + .child_ies = { 57 + { .id = WLAN_EID_SSID, .len = 2 }, 58 + { .id = WLAN_EID_FRAGMENT, .len = 125, }, 59 + }, 60 + .result_ies = { 61 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 254, }, 62 + { .id = WLAN_EID_SSID, .len = 2 }, 63 + }, 64 + }, 65 + { 66 + .desc = "fragments inherited", 67 + .parent_ies = { 68 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, }, 69 + { .id = WLAN_EID_FRAGMENT, .len = 125, }, 70 + }, 71 + .child_ies = { 72 + { .id = WLAN_EID_SSID, .len = 2 }, 73 + }, 74 + .result_ies = { 75 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, }, 76 + { .id = WLAN_EID_FRAGMENT, .len = 125, }, 77 + { .id = WLAN_EID_SSID, .len = 2 }, 78 + }, 79 + }, 80 + { 81 + .desc = "fragments copied", 82 + .parent_ies = { 83 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, }, 84 + { .id = WLAN_EID_FRAGMENT, .len = 125, }, 85 + }, 86 + .child_ies = { 87 + { .id = WLAN_EID_SSID, .len = 2 }, 88 + }, 89 + .result_ies = { 90 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, }, 91 + { .id = WLAN_EID_FRAGMENT, .len = 125, }, 92 + { .id = WLAN_EID_SSID, .len = 2 }, 93 + }, 94 + }, 95 + { 96 + .desc = "multiple elements inherit", 97 + .parent_ies = { 98 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, }, 99 + { .id = WLAN_EID_FRAGMENT, .len = 125, }, 100 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 123, }, 101 + }, 102 + .child_ies = { 103 + { .id = WLAN_EID_SSID, .len = 2 }, 104 + }, 105 + .result_ies = { 106 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, }, 107 + { .id = WLAN_EID_FRAGMENT, .len = 125, }, 108 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 123, }, 109 + { .id = WLAN_EID_SSID, .len = 2 }, 110 + }, 111 + }, 112 + { 113 + .desc = "one child element overrides", 114 + .parent_ies = { 115 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, }, 116 + { .id = WLAN_EID_FRAGMENT, .len = 125, }, 117 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 123, }, 118 + }, 119 + .child_ies = { 120 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 127, }, 121 + { .id = WLAN_EID_SSID, .len = 2 }, 122 + }, 123 + .result_ies = { 124 + { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 127, }, 125 + { .id = WLAN_EID_SSID, .len = 2 }, 126 + }, 127 + }, 128 + { 129 + .desc = "empty elements from parent", 130 + .parent_ies = { 131 + { .id = 0x1, .len = 0, }, 132 + { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 }, 133 + }, 134 + .child_ies = { 135 + }, 136 + .result_ies = { 137 + { .id = 0x1, .len = 0, }, 138 + { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 }, 139 + }, 140 + }, 141 + { 142 + .desc = "empty elements from child", 143 + .parent_ies = { 144 + }, 145 + .child_ies = { 146 + { .id = 0x1, .len = 0, }, 147 + { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 }, 148 + }, 149 + .result_ies = { 150 + { .id = 0x1, .len = 0, }, 151 + { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 }, 152 + }, 153 + }, 154 + { 155 + .desc = "invalid extended elements ignored", 156 + .parent_ies = { 157 + { .id = WLAN_EID_EXTENSION, .len = 0 }, 158 + }, 159 + .child_ies = { 160 + { .id = WLAN_EID_EXTENSION, .len = 0 }, 161 + }, 162 + .result_ies = { 163 + }, 164 + }, 165 + { 166 + .desc = "multiple extended elements", 167 + .parent_ies = { 168 + { .id = WLAN_EID_EXTENSION, .len = 3, 169 + .eid = WLAN_EID_EXT_HE_CAPABILITY }, 170 + { .id = WLAN_EID_EXTENSION, .len = 5, 171 + .eid = WLAN_EID_EXT_ASSOC_DELAY_INFO }, 172 + { .id = WLAN_EID_EXTENSION, .len = 7, 173 + .eid = WLAN_EID_EXT_HE_OPERATION }, 174 + { .id = WLAN_EID_EXTENSION, .len = 11, 175 + .eid = WLAN_EID_EXT_FILS_REQ_PARAMS }, 176 + }, 177 + .child_ies = { 178 + { .id = WLAN_EID_SSID, .len = 13 }, 179 + { .id = WLAN_EID_EXTENSION, .len = 17, 180 + .eid = WLAN_EID_EXT_HE_CAPABILITY }, 181 + { .id = WLAN_EID_EXTENSION, .len = 11, 182 + .eid = WLAN_EID_EXT_FILS_KEY_CONFIRM }, 183 + { .id = WLAN_EID_EXTENSION, .len = 19, 184 + .eid = WLAN_EID_EXT_HE_OPERATION }, 185 + }, 186 + .result_ies = { 187 + { .id = WLAN_EID_EXTENSION, .len = 17, 188 + .eid = WLAN_EID_EXT_HE_CAPABILITY }, 189 + { .id = WLAN_EID_EXTENSION, .len = 5, 190 + .eid = WLAN_EID_EXT_ASSOC_DELAY_INFO }, 191 + { .id = WLAN_EID_EXTENSION, .len = 19, 192 + .eid = WLAN_EID_EXT_HE_OPERATION }, 193 + { .id = WLAN_EID_EXTENSION, .len = 11, 194 + .eid = WLAN_EID_EXT_FILS_REQ_PARAMS }, 195 + { .id = WLAN_EID_SSID, .len = 13 }, 196 + { .id = WLAN_EID_EXTENSION, .len = 11, 197 + .eid = WLAN_EID_EXT_FILS_KEY_CONFIRM }, 198 + }, 199 + }, 200 + { 201 + .desc = "non-inherit element", 202 + .parent_ies = { 203 + { .id = 0x1, .len = 7, }, 204 + { .id = 0x2, .len = 11, }, 205 + { .id = 0x3, .len = 13, }, 206 + { .id = WLAN_EID_EXTENSION, .len = 17, .eid = 0x10 }, 207 + { .id = WLAN_EID_EXTENSION, .len = 19, .eid = 0x11 }, 208 + { .id = WLAN_EID_EXTENSION, .len = 23, .eid = 0x12 }, 209 + { .id = WLAN_EID_EXTENSION, .len = 29, .eid = 0x14 }, 210 + }, 211 + .child_ies = { 212 + { .id = WLAN_EID_EXTENSION, 213 + .eid = WLAN_EID_EXT_NON_INHERITANCE, 214 + .len = 10, 215 + .edata = { 0x3, 0x1, 0x2, 0x3, 216 + 0x4, 0x10, 0x11, 0x13, 0x14 } }, 217 + { .id = WLAN_EID_SSID, .len = 2 }, 218 + }, 219 + .result_ies = { 220 + { .id = WLAN_EID_EXTENSION, .len = 23, .eid = 0x12 }, 221 + { .id = WLAN_EID_SSID, .len = 2 }, 222 + }, 223 + }, 224 + }; 225 + KUNIT_ARRAY_PARAM_DESC(gen_new_ie, gen_new_ie_cases, desc) 226 + 227 + static void test_gen_new_ie(struct kunit *test) 228 + { 229 + const struct gen_new_ie_case *params = test->param_value; 230 + struct sk_buff *parent = kunit_zalloc_skb(test, 1024, GFP_KERNEL); 231 + struct sk_buff *child = kunit_zalloc_skb(test, 1024, GFP_KERNEL); 232 + struct sk_buff *reference = kunit_zalloc_skb(test, 1024, GFP_KERNEL); 233 + u8 *out = kunit_kzalloc(test, IEEE80211_MAX_DATA_LEN, GFP_KERNEL); 234 + size_t len; 235 + int i; 236 + 237 + KUNIT_ASSERT_NOT_NULL(test, parent); 238 + KUNIT_ASSERT_NOT_NULL(test, child); 239 + KUNIT_ASSERT_NOT_NULL(test, reference); 240 + KUNIT_ASSERT_NOT_NULL(test, out); 241 + 242 + for (i = 0; i < ARRAY_SIZE(params->parent_ies); i++) { 243 + if (params->parent_ies[i].len != 0) { 244 + skb_put_u8(parent, params->parent_ies[i].id); 245 + skb_put_u8(parent, params->parent_ies[i].len); 246 + skb_put_data(parent, params->parent_ies[i].data, 247 + params->parent_ies[i].len); 248 + } 249 + 250 + if (params->child_ies[i].len != 0) { 251 + skb_put_u8(child, params->child_ies[i].id); 252 + skb_put_u8(child, params->child_ies[i].len); 253 + skb_put_data(child, params->child_ies[i].data, 254 + params->child_ies[i].len); 255 + } 256 + 257 + if (params->result_ies[i].len != 0) { 258 + skb_put_u8(reference, params->result_ies[i].id); 259 + skb_put_u8(reference, params->result_ies[i].len); 260 + skb_put_data(reference, params->result_ies[i].data, 261 + params->result_ies[i].len); 262 + } 263 + } 264 + 265 + len = cfg80211_gen_new_ie(parent->data, parent->len, 266 + child->data, child->len, 267 + out, IEEE80211_MAX_DATA_LEN); 268 + KUNIT_EXPECT_EQ(test, len, reference->len); 269 + KUNIT_EXPECT_MEMEQ(test, out, reference->data, reference->len); 270 + memset(out, 0, IEEE80211_MAX_DATA_LEN); 271 + 272 + /* Exactly enough space */ 273 + len = cfg80211_gen_new_ie(parent->data, parent->len, 274 + child->data, child->len, 275 + out, reference->len); 276 + KUNIT_EXPECT_EQ(test, len, reference->len); 277 + KUNIT_EXPECT_MEMEQ(test, out, reference->data, reference->len); 278 + memset(out, 0, IEEE80211_MAX_DATA_LEN); 279 + 280 + /* Not enough space (or expected zero length) */ 281 + len = cfg80211_gen_new_ie(parent->data, parent->len, 282 + child->data, child->len, 283 + out, reference->len - 1); 284 + KUNIT_EXPECT_EQ(test, len, 0); 285 + } 286 + 287 + static void test_gen_new_ie_malformed(struct kunit *test) 288 + { 289 + struct sk_buff *malformed = kunit_zalloc_skb(test, 1024, GFP_KERNEL); 290 + u8 *out = kunit_kzalloc(test, IEEE80211_MAX_DATA_LEN, GFP_KERNEL); 291 + size_t len; 292 + 293 + KUNIT_ASSERT_NOT_NULL(test, malformed); 294 + KUNIT_ASSERT_NOT_NULL(test, out); 295 + 296 + skb_put_u8(malformed, WLAN_EID_SSID); 297 + skb_put_u8(malformed, 3); 298 + skb_put(malformed, 3); 299 + skb_put_u8(malformed, WLAN_EID_REDUCED_NEIGHBOR_REPORT); 300 + skb_put_u8(malformed, 10); 301 + skb_put(malformed, 9); 302 + 303 + len = cfg80211_gen_new_ie(malformed->data, malformed->len, 304 + out, 0, 305 + out, IEEE80211_MAX_DATA_LEN); 306 + KUNIT_EXPECT_EQ(test, len, 5); 307 + 308 + len = cfg80211_gen_new_ie(out, 0, 309 + malformed->data, malformed->len, 310 + out, IEEE80211_MAX_DATA_LEN); 311 + KUNIT_EXPECT_EQ(test, len, 5); 312 + } 313 + 314 + struct inform_bss { 315 + struct kunit *test; 316 + 317 + int inform_bss_count; 318 + }; 319 + 320 + static void inform_bss_inc_counter(struct wiphy *wiphy, 321 + struct cfg80211_bss *bss, 322 + const struct cfg80211_bss_ies *ies, 323 + void *drv_data) 324 + { 325 + struct inform_bss *ctx = t_wiphy_ctx(wiphy); 326 + 327 + ctx->inform_bss_count++; 328 + 329 + rcu_read_lock(); 330 + KUNIT_EXPECT_PTR_EQ(ctx->test, drv_data, ctx); 331 + KUNIT_EXPECT_PTR_EQ(ctx->test, ies, rcu_dereference(bss->ies)); 332 + rcu_read_unlock(); 333 + } 334 + 335 + static void test_inform_bss_ssid_only(struct kunit *test) 336 + { 337 + struct inform_bss ctx = { 338 + .test = test, 339 + }; 340 + struct wiphy *wiphy = T_WIPHY(test, ctx); 341 + struct t_wiphy_priv *w_priv = wiphy_priv(wiphy); 342 + struct cfg80211_inform_bss inform_bss = { 343 + .signal = 50, 344 + .drv_data = &ctx, 345 + }; 346 + const u8 bssid[ETH_ALEN] = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x66 }; 347 + u64 tsf = 0x1000000000000000ULL; 348 + int beacon_int = 100; 349 + u16 capability = 0x1234; 350 + static const u8 input[] = { 351 + [0] = WLAN_EID_SSID, 352 + [1] = 4, 353 + [2] = 'T', 'E', 'S', 'T' 354 + }; 355 + struct cfg80211_bss *bss, *other; 356 + const struct cfg80211_bss_ies *ies; 357 + 358 + w_priv->ops->inform_bss = inform_bss_inc_counter; 359 + 360 + inform_bss.chan = ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(2412)); 361 + KUNIT_ASSERT_NOT_NULL(test, inform_bss.chan); 362 + 363 + bss = cfg80211_inform_bss_data(wiphy, &inform_bss, 364 + CFG80211_BSS_FTYPE_PRESP, bssid, tsf, 365 + capability, beacon_int, 366 + input, sizeof(input), 367 + GFP_KERNEL); 368 + KUNIT_EXPECT_NOT_NULL(test, bss); 369 + KUNIT_EXPECT_EQ(test, ctx.inform_bss_count, 1); 370 + 371 + /* Check values in returned bss are correct */ 372 + KUNIT_EXPECT_EQ(test, bss->signal, inform_bss.signal); 373 + KUNIT_EXPECT_EQ(test, bss->beacon_interval, beacon_int); 374 + KUNIT_EXPECT_EQ(test, bss->capability, capability); 375 + KUNIT_EXPECT_EQ(test, bss->bssid_index, 0); 376 + KUNIT_EXPECT_PTR_EQ(test, bss->channel, inform_bss.chan); 377 + KUNIT_EXPECT_MEMEQ(test, bssid, bss->bssid, sizeof(bssid)); 378 + 379 + /* Check the IEs have the expected value */ 380 + rcu_read_lock(); 381 + ies = rcu_dereference(bss->ies); 382 + KUNIT_EXPECT_NOT_NULL(test, ies); 383 + KUNIT_EXPECT_EQ(test, ies->tsf, tsf); 384 + KUNIT_EXPECT_EQ(test, ies->len, sizeof(input)); 385 + KUNIT_EXPECT_MEMEQ(test, ies->data, input, sizeof(input)); 386 + rcu_read_unlock(); 387 + 388 + /* Check we can look up the BSS - by SSID */ 389 + other = cfg80211_get_bss(wiphy, NULL, NULL, "TEST", 4, 390 + IEEE80211_BSS_TYPE_ANY, 391 + IEEE80211_PRIVACY_ANY); 392 + KUNIT_EXPECT_PTR_EQ(test, bss, other); 393 + cfg80211_put_bss(wiphy, other); 394 + 395 + /* Check we can look up the BSS - by BSSID */ 396 + other = cfg80211_get_bss(wiphy, NULL, bssid, NULL, 0, 397 + IEEE80211_BSS_TYPE_ANY, 398 + IEEE80211_PRIVACY_ANY); 399 + KUNIT_EXPECT_PTR_EQ(test, bss, other); 400 + cfg80211_put_bss(wiphy, other); 401 + 402 + cfg80211_put_bss(wiphy, bss); 403 + } 404 + 405 + static struct inform_bss_ml_sta_case { 406 + const char *desc; 407 + int mld_id; 408 + bool sta_prof_vendor_elems; 409 + } inform_bss_ml_sta_cases[] = { 410 + { .desc = "no_mld_id", .mld_id = 0, .sta_prof_vendor_elems = false }, 411 + { .desc = "mld_id_eq_1", .mld_id = 1, .sta_prof_vendor_elems = true }, 412 + }; 413 + KUNIT_ARRAY_PARAM_DESC(inform_bss_ml_sta, inform_bss_ml_sta_cases, desc) 414 + 415 + static void test_inform_bss_ml_sta(struct kunit *test) 416 + { 417 + const struct inform_bss_ml_sta_case *params = test->param_value; 418 + struct inform_bss ctx = { 419 + .test = test, 420 + }; 421 + struct wiphy *wiphy = T_WIPHY(test, ctx); 422 + struct t_wiphy_priv *w_priv = wiphy_priv(wiphy); 423 + struct cfg80211_inform_bss inform_bss = { 424 + .signal = 50, 425 + .drv_data = &ctx, 426 + }; 427 + struct cfg80211_bss *bss, *link_bss; 428 + const struct cfg80211_bss_ies *ies; 429 + 430 + /* sending station */ 431 + const u8 bssid[ETH_ALEN] = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x66 }; 432 + u64 tsf = 0x1000000000000000ULL; 433 + int beacon_int = 100; 434 + u16 capability = 0x1234; 435 + 436 + /* Building the frame *************************************************/ 437 + struct sk_buff *input = kunit_zalloc_skb(test, 1024, GFP_KERNEL); 438 + u8 *len_mle, *len_prof; 439 + u8 link_id = 2; 440 + struct { 441 + struct ieee80211_neighbor_ap_info info; 442 + struct ieee80211_tbtt_info_ge_11 ap; 443 + } __packed rnr = { 444 + .info = { 445 + .tbtt_info_hdr = u8_encode_bits(0, IEEE80211_AP_INFO_TBTT_HDR_COUNT), 446 + .tbtt_info_len = sizeof(struct ieee80211_tbtt_info_ge_11), 447 + .op_class = 81, 448 + .channel = 11, 449 + }, 450 + .ap = { 451 + .tbtt_offset = 0xff, 452 + .bssid = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x67 }, 453 + .short_ssid = 0, /* unused */ 454 + .bss_params = 0, 455 + .psd_20 = 0, 456 + .mld_params.mld_id = params->mld_id, 457 + .mld_params.params = 458 + le16_encode_bits(link_id, 459 + IEEE80211_RNR_MLD_PARAMS_LINK_ID), 460 + } 461 + }; 462 + struct { 463 + __le16 control; 464 + u8 var_len; 465 + u8 mld_mac_addr[ETH_ALEN]; 466 + u8 link_id_info; 467 + u8 params_change_count; 468 + __le16 mld_caps_and_ops; 469 + u8 mld_id; 470 + __le16 ext_mld_caps_and_ops; 471 + } __packed mle_basic_common_info = { 472 + .control = 473 + cpu_to_le16(IEEE80211_ML_CONTROL_TYPE_BASIC | 474 + IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT | 475 + IEEE80211_MLC_BASIC_PRES_LINK_ID | 476 + (params->mld_id ? IEEE80211_MLC_BASIC_PRES_MLD_ID : 0) | 477 + IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP), 478 + .mld_id = params->mld_id, 479 + .mld_caps_and_ops = cpu_to_le16(0x0102), 480 + .ext_mld_caps_and_ops = cpu_to_le16(0x0304), 481 + .var_len = sizeof(mle_basic_common_info) - 2 - 482 + (params->mld_id ? 0 : 1), 483 + .mld_mac_addr = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x60 }, 484 + }; 485 + struct { 486 + __le16 control; 487 + u8 var_len; 488 + u8 bssid[ETH_ALEN]; 489 + __le16 beacon_int; 490 + __le64 tsf_offset; 491 + __le16 capabilities; /* already part of payload */ 492 + } __packed sta_prof = { 493 + .control = 494 + cpu_to_le16(IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE | 495 + IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT | 496 + IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT | 497 + IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT | 498 + u16_encode_bits(link_id, 499 + IEEE80211_MLE_STA_CONTROL_LINK_ID)), 500 + .var_len = sizeof(sta_prof) - 2 - 2, 501 + .bssid = { *rnr.ap.bssid }, 502 + .beacon_int = cpu_to_le16(101), 503 + .tsf_offset = cpu_to_le64(-123ll), 504 + .capabilities = cpu_to_le16(0xdead), 505 + }; 506 + 507 + KUNIT_ASSERT_NOT_NULL(test, input); 508 + 509 + w_priv->ops->inform_bss = inform_bss_inc_counter; 510 + 511 + inform_bss.chan = ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(2412)); 512 + KUNIT_ASSERT_NOT_NULL(test, inform_bss.chan); 513 + 514 + skb_put_u8(input, WLAN_EID_SSID); 515 + skb_put_u8(input, 4); 516 + skb_put_data(input, "TEST", 4); 517 + 518 + skb_put_u8(input, WLAN_EID_REDUCED_NEIGHBOR_REPORT); 519 + skb_put_u8(input, sizeof(rnr)); 520 + skb_put_data(input, &rnr, sizeof(rnr)); 521 + 522 + /* build a multi-link element */ 523 + skb_put_u8(input, WLAN_EID_EXTENSION); 524 + len_mle = skb_put(input, 1); 525 + skb_put_u8(input, WLAN_EID_EXT_EHT_MULTI_LINK); 526 + skb_put_data(input, &mle_basic_common_info, sizeof(mle_basic_common_info)); 527 + if (!params->mld_id) 528 + t_skb_remove_member(input, typeof(mle_basic_common_info), mld_id); 529 + /* with a STA profile inside */ 530 + skb_put_u8(input, IEEE80211_MLE_SUBELEM_PER_STA_PROFILE); 531 + len_prof = skb_put(input, 1); 532 + skb_put_data(input, &sta_prof, sizeof(sta_prof)); 533 + 534 + if (params->sta_prof_vendor_elems) { 535 + /* Put two (vendor) element into sta_prof */ 536 + skb_put_u8(input, WLAN_EID_VENDOR_SPECIFIC); 537 + skb_put_u8(input, 160); 538 + skb_put(input, 160); 539 + 540 + skb_put_u8(input, WLAN_EID_VENDOR_SPECIFIC); 541 + skb_put_u8(input, 165); 542 + skb_put(input, 165); 543 + } 544 + 545 + /* fragment STA profile */ 546 + ieee80211_fragment_element(input, len_prof, 547 + IEEE80211_MLE_SUBELEM_FRAGMENT); 548 + /* fragment MLE */ 549 + ieee80211_fragment_element(input, len_mle, WLAN_EID_FRAGMENT); 550 + 551 + /* Put a (vendor) element after the ML element */ 552 + skb_put_u8(input, WLAN_EID_VENDOR_SPECIFIC); 553 + skb_put_u8(input, 155); 554 + skb_put(input, 155); 555 + 556 + /* Submit *************************************************************/ 557 + bss = cfg80211_inform_bss_data(wiphy, &inform_bss, 558 + CFG80211_BSS_FTYPE_PRESP, bssid, tsf, 559 + capability, beacon_int, 560 + input->data, input->len, 561 + GFP_KERNEL); 562 + KUNIT_EXPECT_NOT_NULL(test, bss); 563 + KUNIT_EXPECT_EQ(test, ctx.inform_bss_count, 2); 564 + 565 + /* Check link_bss *****************************************************/ 566 + link_bss = cfg80211_get_bss(wiphy, NULL, sta_prof.bssid, NULL, 0, 567 + IEEE80211_BSS_TYPE_ANY, 568 + IEEE80211_PRIVACY_ANY); 569 + KUNIT_ASSERT_NOT_NULL(test, link_bss); 570 + KUNIT_EXPECT_EQ(test, link_bss->signal, 0); 571 + KUNIT_EXPECT_EQ(test, link_bss->beacon_interval, 572 + le16_to_cpu(sta_prof.beacon_int)); 573 + KUNIT_EXPECT_EQ(test, link_bss->capability, 574 + le16_to_cpu(sta_prof.capabilities)); 575 + KUNIT_EXPECT_EQ(test, link_bss->bssid_index, 0); 576 + KUNIT_EXPECT_PTR_EQ(test, link_bss->channel, 577 + ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(2462))); 578 + 579 + rcu_read_lock(); 580 + ies = rcu_dereference(link_bss->ies); 581 + KUNIT_EXPECT_NOT_NULL(test, ies); 582 + KUNIT_EXPECT_EQ(test, ies->tsf, tsf + le64_to_cpu(sta_prof.tsf_offset)); 583 + /* Resulting length should be: 584 + * SSID (inherited) + RNR (inherited) + vendor element(s) + 585 + * MLE common info + MLE header and control 586 + */ 587 + if (params->sta_prof_vendor_elems) 588 + KUNIT_EXPECT_EQ(test, ies->len, 589 + 6 + 2 + sizeof(rnr) + 2 + 160 + 2 + 165 + 590 + mle_basic_common_info.var_len + 5); 591 + else 592 + KUNIT_EXPECT_EQ(test, ies->len, 593 + 6 + 2 + sizeof(rnr) + 2 + 155 + 594 + mle_basic_common_info.var_len + 5); 595 + rcu_read_unlock(); 596 + 597 + cfg80211_put_bss(wiphy, bss); 598 + cfg80211_put_bss(wiphy, link_bss); 599 + } 600 + 601 + static struct kunit_case gen_new_ie_test_cases[] = { 602 + KUNIT_CASE_PARAM(test_gen_new_ie, gen_new_ie_gen_params), 603 + KUNIT_CASE(test_gen_new_ie_malformed), 604 + {} 605 + }; 606 + 607 + static struct kunit_suite gen_new_ie = { 608 + .name = "cfg80211-ie-generation", 609 + .test_cases = gen_new_ie_test_cases, 610 + }; 611 + 612 + kunit_test_suite(gen_new_ie); 613 + 614 + static struct kunit_case inform_bss_test_cases[] = { 615 + KUNIT_CASE(test_inform_bss_ssid_only), 616 + KUNIT_CASE_PARAM(test_inform_bss_ml_sta, inform_bss_ml_sta_gen_params), 617 + {} 618 + }; 619 + 620 + static struct kunit_suite inform_bss = { 621 + .name = "cfg80211-inform-bss", 622 + .test_cases = inform_bss_test_cases, 623 + }; 624 + 625 + kunit_test_suite(inform_bss);
+56
net/wireless/tests/util.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * KUnit fixture to have a (configurable) wiphy 4 + * 5 + * Copyright (C) 2023 Intel Corporation 6 + */ 7 + #include <linux/ieee80211.h> 8 + #include <net/cfg80211.h> 9 + #include <kunit/test.h> 10 + #include <kunit/test-bug.h> 11 + #include "util.h" 12 + 13 + int t_wiphy_init(struct kunit_resource *resource, void *ctx) 14 + { 15 + struct kunit *test = kunit_get_current_test(); 16 + struct cfg80211_ops *ops; 17 + struct wiphy *wiphy; 18 + struct t_wiphy_priv *priv; 19 + 20 + ops = kzalloc(sizeof(*ops), GFP_KERNEL); 21 + KUNIT_ASSERT_NOT_NULL(test, ops); 22 + 23 + wiphy = wiphy_new_nm(ops, sizeof(*priv), "kunit"); 24 + KUNIT_ASSERT_NOT_NULL(test, wiphy); 25 + 26 + priv = wiphy_priv(wiphy); 27 + priv->ctx = ctx; 28 + priv->ops = ops; 29 + 30 + /* Initialize channels, feel free to add more here channels/bands */ 31 + memcpy(priv->channels_2ghz, channels_2ghz, sizeof(channels_2ghz)); 32 + wiphy->bands[NL80211_BAND_2GHZ] = &priv->band_2ghz; 33 + priv->band_2ghz.channels = priv->channels_2ghz; 34 + priv->band_2ghz.n_channels = ARRAY_SIZE(channels_2ghz); 35 + 36 + resource->data = wiphy; 37 + resource->name = "wiphy"; 38 + 39 + return 0; 40 + } 41 + 42 + void t_wiphy_exit(struct kunit_resource *resource) 43 + { 44 + struct t_wiphy_priv *priv; 45 + struct cfg80211_ops *ops; 46 + 47 + priv = wiphy_priv(resource->data); 48 + ops = priv->ops; 49 + 50 + /* Should we ensure anything about the state here? 51 + * e.g. full destruction or no calls to any ops on destruction? 52 + */ 53 + 54 + wiphy_free(resource->data); 55 + kfree(ops); 56 + }
+66
net/wireless/tests/util.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Utilities for cfg80211 unit testing 4 + * 5 + * Copyright (C) 2023 Intel Corporation 6 + */ 7 + #ifndef __CFG80211_UTILS_H 8 + #define __CFG80211_UTILS_H 9 + 10 + #define CHAN2G(_freq) { \ 11 + .band = NL80211_BAND_2GHZ, \ 12 + .center_freq = (_freq), \ 13 + .hw_value = (_freq), \ 14 + } 15 + 16 + static const struct ieee80211_channel channels_2ghz[] = { 17 + CHAN2G(2412), /* Channel 1 */ 18 + CHAN2G(2417), /* Channel 2 */ 19 + CHAN2G(2422), /* Channel 3 */ 20 + CHAN2G(2427), /* Channel 4 */ 21 + CHAN2G(2432), /* Channel 5 */ 22 + CHAN2G(2437), /* Channel 6 */ 23 + CHAN2G(2442), /* Channel 7 */ 24 + CHAN2G(2447), /* Channel 8 */ 25 + CHAN2G(2452), /* Channel 9 */ 26 + CHAN2G(2457), /* Channel 10 */ 27 + CHAN2G(2462), /* Channel 11 */ 28 + CHAN2G(2467), /* Channel 12 */ 29 + CHAN2G(2472), /* Channel 13 */ 30 + CHAN2G(2484), /* Channel 14 */ 31 + }; 32 + 33 + struct t_wiphy_priv { 34 + struct kunit *test; 35 + struct cfg80211_ops *ops; 36 + 37 + void *ctx; 38 + 39 + struct ieee80211_supported_band band_2ghz; 40 + struct ieee80211_channel channels_2ghz[ARRAY_SIZE(channels_2ghz)]; 41 + }; 42 + 43 + #define T_WIPHY(test, ctx) ({ \ 44 + struct wiphy *__wiphy = \ 45 + kunit_alloc_resource(test, t_wiphy_init, \ 46 + t_wiphy_exit, \ 47 + GFP_KERNEL, &(ctx)); \ 48 + \ 49 + KUNIT_ASSERT_NOT_NULL(test, __wiphy); \ 50 + __wiphy; \ 51 + }) 52 + #define t_wiphy_ctx(wiphy) (((struct t_wiphy_priv *)wiphy_priv(wiphy))->ctx) 53 + 54 + int t_wiphy_init(struct kunit_resource *resource, void *data); 55 + void t_wiphy_exit(struct kunit_resource *resource); 56 + 57 + #define t_skb_remove_member(skb, type, member) do { \ 58 + memmove((skb)->data + (skb)->len - sizeof(type) + \ 59 + offsetof(type, member), \ 60 + (skb)->data + (skb)->len - sizeof(type) + \ 61 + offsetofend(type, member), \ 62 + offsetofend(type, member)); \ 63 + skb_trim(skb, (skb)->len - sizeof_field(type, member)); \ 64 + } while (0) 65 + 66 + #endif /* __CFG80211_UTILS_H */