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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'wireless-next-2024-01-03' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next

Johannes Berg says:

====================
Just a couple of more things over the holidays:

- first kunit tests for both cfg80211 and mac80211
- a few multi-link fixes
- DSCP mapping update
- RCU fix

* tag 'wireless-next-2024-01-03' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next:
wifi: mac80211: remove redundant ML element check
wifi: cfg80211: parse all ML elements in an ML probe response
wifi: cfg80211: correct comment about MLD ID
wifi: cfg80211: Update the default DSCP-to-UP mapping
wifi: cfg80211: tests: add some scanning related tests
wifi: mac80211: kunit: extend MFP tests
wifi: mac80211: kunit: generalize public action test
wifi: mac80211: add kunit tests for public action handling
kunit: add a convenience allocation wrapper for SKBs
kunit: add parameter generation macro using description from array
wifi: mac80211: fix spelling typo in comment
wifi: cfg80211: fix RCU dereference in __cfg80211_bss_update
====================

Link: https://lore.kernel.org/r/20240103144423.52269-3-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1244 -52
+4 -8
Documentation/dev-tools/kunit/usage.rst
··· 566 566 }, 567 567 }; 568 568 569 - // Need a helper function to generate a name for each test case. 570 - static void case_to_desc(const struct sha1_test_case *t, char *desc) 571 - { 572 - strcpy(desc, t->str); 573 - } 574 - // Creates `sha1_gen_params()` to iterate over `cases`. 575 - KUNIT_ARRAY_PARAM(sha1, cases, case_to_desc); 569 + // Creates `sha1_gen_params()` to iterate over `cases` while using 570 + // the struct member `str` for the case description. 571 + KUNIT_ARRAY_PARAM_DESC(sha1, cases, str); 576 572 577 573 // Looks no different from a normal test. 578 574 static void sha1_test(struct kunit *test) ··· 584 588 } 585 589 586 590 // Instead of KUNIT_CASE, we use KUNIT_CASE_PARAM and pass in the 587 - // function declared by KUNIT_ARRAY_PARAM. 591 + // function declared by KUNIT_ARRAY_PARAM or KUNIT_ARRAY_PARAM_DESC. 588 592 static struct kunit_case sha1_test_cases[] = { 589 593 KUNIT_CASE_PARAM(sha1_test, sha1_gen_params), 590 594 {}
+56
include/kunit/skbuff.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * KUnit resource management helpers for SKBs (skbuff). 4 + * 5 + * Copyright (C) 2023 Intel Corporation 6 + */ 7 + 8 + #ifndef _KUNIT_SKBUFF_H 9 + #define _KUNIT_SKBUFF_H 10 + 11 + #include <kunit/resource.h> 12 + #include <linux/skbuff.h> 13 + 14 + static void kunit_action_kfree_skb(void *p) 15 + { 16 + kfree_skb((struct sk_buff *)p); 17 + } 18 + 19 + /** 20 + * kunit_zalloc_skb() - Allocate and initialize a resource managed skb. 21 + * @test: The test case to which the skb belongs 22 + * @len: size to allocate 23 + * 24 + * Allocate a new struct sk_buff with GFP_KERNEL, zero fill the give length 25 + * and add it as a resource to the kunit test for automatic cleanup. 26 + * 27 + * Returns: newly allocated SKB, or %NULL on error 28 + */ 29 + static inline struct sk_buff *kunit_zalloc_skb(struct kunit *test, int len, 30 + gfp_t gfp) 31 + { 32 + struct sk_buff *res = alloc_skb(len, GFP_KERNEL); 33 + 34 + if (!res || skb_pad(res, len)) 35 + return NULL; 36 + 37 + if (kunit_add_action_or_reset(test, kunit_action_kfree_skb, res)) 38 + return NULL; 39 + 40 + return res; 41 + } 42 + 43 + /** 44 + * kunit_kfree_skb() - Like kfree_skb except for allocations managed by KUnit. 45 + * @test: The test case to which the resource belongs. 46 + * @skb: The SKB to free. 47 + */ 48 + static inline void kunit_kfree_skb(struct kunit *test, struct sk_buff *skb) 49 + { 50 + if (!skb) 51 + return; 52 + 53 + kunit_release_action(test, kunit_action_kfree_skb, (void *)skb); 54 + } 55 + 56 + #endif /* _KUNIT_SKBUFF_H */
+19
include/kunit/test.h
··· 1514 1514 return NULL; \ 1515 1515 } 1516 1516 1517 + /** 1518 + * KUNIT_ARRAY_PARAM_DESC() - Define test parameter generator from an array. 1519 + * @name: prefix for the test parameter generator function. 1520 + * @array: array of test parameters. 1521 + * @desc_member: structure member from array element to use as description 1522 + * 1523 + * Define function @name_gen_params which uses @array to generate parameters. 1524 + */ 1525 + #define KUNIT_ARRAY_PARAM_DESC(name, array, desc_member) \ 1526 + static const void *name##_gen_params(const void *prev, char *desc) \ 1527 + { \ 1528 + typeof((array)[0]) *__next = prev ? ((typeof(__next)) prev) + 1 : (array); \ 1529 + if (__next - (array) < ARRAY_SIZE((array))) { \ 1530 + strscpy(desc, __next->desc_member, KUNIT_PARAM_DESC_SIZE); \ 1531 + return __next; \ 1532 + } \ 1533 + return NULL; \ 1534 + } 1535 + 1517 1536 // TODO(dlatypov@google.com): consider eventually migrating users to explicitly 1518 1537 // include resource.h themselves if they need it. 1519 1538 #include <kunit/resource.h>
+1 -1
net/mac80211/debugfs_sta.c
··· 16 16 #include "sta_info.h" 17 17 #include "driver-ops.h" 18 18 19 - /* sta attributtes */ 19 + /* sta attributes */ 20 20 21 21 #define STA_READ(name, field, format_string) \ 22 22 static ssize_t sta_ ##name## _read(struct file *file, \
+10
net/mac80211/ieee80211_i.h
··· 2608 2608 void ieee80211_add_wbrf(struct ieee80211_local *local, struct cfg80211_chan_def *chandef); 2609 2609 void ieee80211_remove_wbrf(struct ieee80211_local *local, struct cfg80211_chan_def *chandef); 2610 2610 2611 + #if IS_ENABLED(CONFIG_MAC80211_KUNIT_TEST) 2612 + #define EXPORT_SYMBOL_IF_MAC80211_KUNIT(sym) EXPORT_SYMBOL_IF_KUNIT(sym) 2613 + #define VISIBLE_IF_MAC80211_KUNIT 2614 + ieee80211_rx_result 2615 + ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx); 2616 + #else 2617 + #define EXPORT_SYMBOL_IF_MAC80211_KUNIT(sym) 2618 + #define VISIBLE_IF_MAC80211_KUNIT static 2619 + #endif 2620 + 2611 2621 #endif /* IEEE80211_I_H */
+10 -19
net/mac80211/mlme.c
··· 5407 5407 } 5408 5408 5409 5409 if (ieee80211_vif_is_mld(&sdata->vif)) { 5410 + struct ieee80211_mle_basic_common_info *common; 5411 + 5410 5412 if (!elems->ml_basic) { 5411 5413 sdata_info(sdata, 5412 - "MLO association with %pM but no multi-link element in response!\n", 5414 + "MLO association with %pM but no (basic) multi-link element in response!\n", 5413 5415 assoc_data->ap_addr); 5414 5416 goto abandon_assoc; 5415 5417 } 5416 5418 5417 - if (le16_get_bits(elems->ml_basic->control, 5418 - IEEE80211_ML_CONTROL_TYPE) != 5419 - IEEE80211_ML_CONTROL_TYPE_BASIC) { 5419 + common = (void *)elems->ml_basic->variable; 5420 + 5421 + if (memcmp(assoc_data->ap_addr, 5422 + common->mld_mac_addr, ETH_ALEN)) { 5420 5423 sdata_info(sdata, 5421 - "bad multi-link element (control=0x%x)\n", 5422 - le16_to_cpu(elems->ml_basic->control)); 5424 + "AP MLD MAC address mismatch: got %pM expected %pM\n", 5425 + common->mld_mac_addr, 5426 + assoc_data->ap_addr); 5423 5427 goto abandon_assoc; 5424 - } else { 5425 - struct ieee80211_mle_basic_common_info *common; 5426 - 5427 - common = (void *)elems->ml_basic->variable; 5428 - 5429 - if (memcmp(assoc_data->ap_addr, 5430 - common->mld_mac_addr, ETH_ALEN)) { 5431 - sdata_info(sdata, 5432 - "AP MLD MAC address mismatch: got %pM expected %pM\n", 5433 - common->mld_mac_addr, 5434 - assoc_data->ap_addr); 5435 - goto abandon_assoc; 5436 - } 5437 5428 } 5438 5429 } 5439 5430
+3 -1
net/mac80211/rx.c
··· 19 19 #include <linux/export.h> 20 20 #include <linux/kcov.h> 21 21 #include <linux/bitops.h> 22 + #include <kunit/visibility.h> 22 23 #include <net/mac80211.h> 23 24 #include <net/ieee80211_radiotap.h> 24 25 #include <asm/unaligned.h> ··· 2415 2414 return 0; 2416 2415 } 2417 2416 2418 - static ieee80211_rx_result 2417 + VISIBLE_IF_MAC80211_KUNIT ieee80211_rx_result 2419 2418 ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) 2420 2419 { 2421 2420 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); ··· 2494 2493 2495 2494 return RX_CONTINUE; 2496 2495 } 2496 + EXPORT_SYMBOL_IF_MAC80211_KUNIT(ieee80211_drop_unencrypted_mgmt); 2497 2497 2498 2498 static ieee80211_rx_result 2499 2499 __ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
+1 -1
net/mac80211/tests/Makefile
··· 1 - mac80211-tests-y += module.o elems.o 1 + mac80211-tests-y += module.o elems.o mfp.o 2 2 3 3 obj-$(CONFIG_MAC80211_KUNIT_TEST) += mac80211-tests.o
+286
net/mac80211/tests/mfp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * KUnit tests for management frame acceptance 4 + * 5 + * Copyright (C) 2023 Intel Corporation 6 + */ 7 + #include <kunit/test.h> 8 + #include <kunit/skbuff.h> 9 + #include "../ieee80211_i.h" 10 + #include "../sta_info.h" 11 + 12 + MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING); 13 + 14 + static const struct mfp_test_case { 15 + const char *desc; 16 + bool sta, mfp, decrypted, unicast, assoc; 17 + u8 category; 18 + u8 stype; 19 + u8 action; 20 + ieee80211_rx_result result; 21 + } accept_mfp_cases[] = { 22 + /* regular public action */ 23 + { 24 + .desc = "public action: accept unicast from unknown peer", 25 + .stype = IEEE80211_STYPE_ACTION, 26 + .category = WLAN_CATEGORY_PUBLIC, 27 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 28 + .unicast = true, 29 + .result = RX_CONTINUE, 30 + }, 31 + { 32 + .desc = "public action: accept multicast from unknown peer", 33 + .stype = IEEE80211_STYPE_ACTION, 34 + .category = WLAN_CATEGORY_PUBLIC, 35 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 36 + .unicast = false, 37 + .result = RX_CONTINUE, 38 + }, 39 + { 40 + .desc = "public action: accept unicast without MFP", 41 + .stype = IEEE80211_STYPE_ACTION, 42 + .category = WLAN_CATEGORY_PUBLIC, 43 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 44 + .unicast = true, 45 + .sta = true, 46 + .result = RX_CONTINUE, 47 + }, 48 + { 49 + .desc = "public action: accept multicast without MFP", 50 + .stype = IEEE80211_STYPE_ACTION, 51 + .category = WLAN_CATEGORY_PUBLIC, 52 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 53 + .unicast = false, 54 + .sta = true, 55 + .result = RX_CONTINUE, 56 + }, 57 + { 58 + .desc = "public action: drop unicast with MFP", 59 + .stype = IEEE80211_STYPE_ACTION, 60 + .category = WLAN_CATEGORY_PUBLIC, 61 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 62 + .unicast = true, 63 + .sta = true, 64 + .mfp = true, 65 + .result = RX_DROP_U_UNPROT_UNICAST_PUB_ACTION, 66 + }, 67 + { 68 + .desc = "public action: accept multicast with MFP", 69 + .stype = IEEE80211_STYPE_ACTION, 70 + .category = WLAN_CATEGORY_PUBLIC, 71 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 72 + .unicast = false, 73 + .sta = true, 74 + .mfp = true, 75 + .result = RX_CONTINUE, 76 + }, 77 + /* protected dual of public action */ 78 + { 79 + .desc = "protected dual: drop unicast from unknown peer", 80 + .stype = IEEE80211_STYPE_ACTION, 81 + .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION, 82 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 83 + .unicast = true, 84 + .result = RX_DROP_U_UNPROT_DUAL, 85 + }, 86 + { 87 + .desc = "protected dual: drop multicast from unknown peer", 88 + .stype = IEEE80211_STYPE_ACTION, 89 + .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION, 90 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 91 + .unicast = false, 92 + .result = RX_DROP_U_UNPROT_DUAL, 93 + }, 94 + { 95 + .desc = "protected dual: drop unicast without MFP", 96 + .stype = IEEE80211_STYPE_ACTION, 97 + .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION, 98 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 99 + .unicast = true, 100 + .sta = true, 101 + .result = RX_DROP_U_UNPROT_DUAL, 102 + }, 103 + { 104 + .desc = "protected dual: drop multicast without MFP", 105 + .stype = IEEE80211_STYPE_ACTION, 106 + .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION, 107 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 108 + .unicast = false, 109 + .sta = true, 110 + .result = RX_DROP_U_UNPROT_DUAL, 111 + }, 112 + { 113 + .desc = "protected dual: drop undecrypted unicast with MFP", 114 + .stype = IEEE80211_STYPE_ACTION, 115 + .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION, 116 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 117 + .unicast = true, 118 + .sta = true, 119 + .mfp = true, 120 + .result = RX_DROP_U_UNPROT_DUAL, 121 + }, 122 + { 123 + .desc = "protected dual: drop undecrypted multicast with MFP", 124 + .stype = IEEE80211_STYPE_ACTION, 125 + .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION, 126 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 127 + .unicast = false, 128 + .sta = true, 129 + .mfp = true, 130 + .result = RX_DROP_U_UNPROT_DUAL, 131 + }, 132 + { 133 + .desc = "protected dual: accept unicast with MFP", 134 + .stype = IEEE80211_STYPE_ACTION, 135 + .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION, 136 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 137 + .decrypted = true, 138 + .unicast = true, 139 + .sta = true, 140 + .mfp = true, 141 + .result = RX_CONTINUE, 142 + }, 143 + { 144 + .desc = "protected dual: accept multicast with MFP", 145 + .stype = IEEE80211_STYPE_ACTION, 146 + .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION, 147 + .action = WLAN_PUB_ACTION_DSE_ENABLEMENT, 148 + .decrypted = true, 149 + .unicast = false, 150 + .sta = true, 151 + .mfp = true, 152 + .result = RX_CONTINUE, 153 + }, 154 + /* deauth/disassoc before keys are set */ 155 + { 156 + .desc = "deauth: accept unicast with MFP but w/o key", 157 + .stype = IEEE80211_STYPE_DEAUTH, 158 + .sta = true, 159 + .mfp = true, 160 + .unicast = true, 161 + .result = RX_CONTINUE, 162 + }, 163 + { 164 + .desc = "disassoc: accept unicast with MFP but w/o key", 165 + .stype = IEEE80211_STYPE_DEAUTH, 166 + .sta = true, 167 + .mfp = true, 168 + .unicast = true, 169 + .result = RX_CONTINUE, 170 + }, 171 + /* non-public robust action frame ... */ 172 + { 173 + .desc = "BA action: drop unicast before assoc", 174 + .stype = IEEE80211_STYPE_ACTION, 175 + .category = WLAN_CATEGORY_BACK, 176 + .unicast = true, 177 + .sta = true, 178 + .result = RX_DROP_U_UNPROT_ROBUST_ACTION, 179 + }, 180 + { 181 + .desc = "BA action: drop unprotected after assoc", 182 + .stype = IEEE80211_STYPE_ACTION, 183 + .category = WLAN_CATEGORY_BACK, 184 + .unicast = true, 185 + .sta = true, 186 + .mfp = true, 187 + .result = RX_DROP_U_UNPROT_UCAST_MGMT, 188 + }, 189 + { 190 + .desc = "BA action: accept unprotected without MFP", 191 + .stype = IEEE80211_STYPE_ACTION, 192 + .category = WLAN_CATEGORY_BACK, 193 + .unicast = true, 194 + .sta = true, 195 + .assoc = true, 196 + .mfp = false, 197 + .result = RX_CONTINUE, 198 + }, 199 + { 200 + .desc = "BA action: drop unprotected with MFP", 201 + .stype = IEEE80211_STYPE_ACTION, 202 + .category = WLAN_CATEGORY_BACK, 203 + .unicast = true, 204 + .sta = true, 205 + .mfp = true, 206 + .result = RX_DROP_U_UNPROT_UCAST_MGMT, 207 + }, 208 + }; 209 + 210 + KUNIT_ARRAY_PARAM_DESC(accept_mfp, accept_mfp_cases, desc); 211 + 212 + static void accept_mfp(struct kunit *test) 213 + { 214 + static struct sta_info sta; 215 + const struct mfp_test_case *params = test->param_value; 216 + struct ieee80211_rx_data rx = { 217 + .sta = params->sta ? &sta : NULL, 218 + }; 219 + struct ieee80211_rx_status *status; 220 + struct ieee80211_hdr_3addr hdr = { 221 + .frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 222 + params->stype), 223 + .addr1 = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 224 + .addr2 = { 0x12, 0x22, 0x33, 0x44, 0x55, 0x66 }, 225 + /* A3/BSSID doesn't matter here */ 226 + }; 227 + 228 + memset(&sta, 0, sizeof(sta)); 229 + 230 + if (!params->sta) { 231 + KUNIT_ASSERT_FALSE(test, params->mfp); 232 + KUNIT_ASSERT_FALSE(test, params->decrypted); 233 + } 234 + 235 + if (params->mfp) 236 + set_sta_flag(&sta, WLAN_STA_MFP); 237 + 238 + if (params->assoc) 239 + set_bit(WLAN_STA_ASSOC, &sta._flags); 240 + 241 + rx.skb = kunit_zalloc_skb(test, 128, GFP_KERNEL); 242 + KUNIT_ASSERT_NOT_NULL(test, rx.skb); 243 + status = IEEE80211_SKB_RXCB(rx.skb); 244 + 245 + if (params->decrypted) { 246 + status->flag |= RX_FLAG_DECRYPTED; 247 + if (params->unicast) 248 + hdr.frame_control |= 249 + cpu_to_le16(IEEE80211_FCTL_PROTECTED); 250 + } 251 + 252 + if (params->unicast) 253 + hdr.addr1[0] = 0x02; 254 + 255 + skb_put_data(rx.skb, &hdr, sizeof(hdr)); 256 + 257 + switch (params->stype) { 258 + case IEEE80211_STYPE_ACTION: 259 + skb_put_u8(rx.skb, params->category); 260 + skb_put_u8(rx.skb, params->action); 261 + break; 262 + case IEEE80211_STYPE_DEAUTH: 263 + case IEEE80211_STYPE_DISASSOC: { 264 + __le16 reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); 265 + 266 + skb_put_data(rx.skb, &reason, sizeof(reason)); 267 + } 268 + break; 269 + } 270 + 271 + KUNIT_EXPECT_EQ(test, 272 + (__force u32)ieee80211_drop_unencrypted_mgmt(&rx), 273 + (__force u32)params->result); 274 + } 275 + 276 + static struct kunit_case mfp_test_cases[] = { 277 + KUNIT_CASE_PARAM(accept_mfp, accept_mfp_gen_params), 278 + {} 279 + }; 280 + 281 + static struct kunit_suite mfp = { 282 + .name = "mac80211-mfp", 283 + .test_cases = mfp_test_cases, 284 + }; 285 + 286 + kunit_test_suite(mfp);
+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 */
+38 -20
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) ··· 1867 1864 &hidden->hidden_list); 1868 1865 hidden->refcount++; 1869 1866 1870 - ies = (void *)rcu_dereference(new->pub.beacon_ies); 1867 + ies = (void *)rcu_access_pointer(new->pub.beacon_ies); 1871 1868 rcu_assign_pointer(new->pub.beacon_ies, 1872 1869 hidden->pub.beacon_ies); 1873 1870 if (ies) ··· 2617 2614 return 0; 2618 2615 } 2619 2616 2620 - static void cfg80211_parse_ml_sta_data(struct wiphy *wiphy, 2621 - struct cfg80211_inform_single_bss_data *tx_data, 2622 - struct cfg80211_bss *source_bss, 2623 - gfp_t gfp) 2617 + static void 2618 + cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy, 2619 + struct cfg80211_inform_single_bss_data *tx_data, 2620 + struct cfg80211_bss *source_bss, 2621 + const struct element *elem, 2622 + gfp_t gfp) 2624 2623 { 2625 2624 struct cfg80211_inform_single_bss_data data = { 2626 2625 .drv_data = tx_data->drv_data, ··· 2631 2626 .bss_source = BSS_SOURCE_STA_PROFILE, 2632 2627 }; 2633 2628 struct ieee80211_multi_link_elem *ml_elem; 2634 - const struct element *elem; 2635 2629 struct cfg80211_mle *mle; 2636 2630 u16 control; 2637 2631 u8 ml_common_len; ··· 2641 2637 const u8 *pos; 2642 2638 u8 i; 2643 2639 2644 - if (!source_bss) 2645 - return; 2646 - 2647 - if (tx_data->ftype != CFG80211_BSS_FTYPE_PRESP) 2648 - return; 2649 - 2650 - elem = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_MULTI_LINK, 2651 - tx_data->ie, tx_data->ielen); 2652 - if (!elem || !ieee80211_mle_size_ok(elem->data + 1, elem->datalen - 1)) 2640 + if (!ieee80211_mle_size_ok(elem->data + 1, elem->datalen - 1)) 2653 2641 return; 2654 2642 2655 2643 ml_elem = (void *)elem->data + 1; ··· 2669 2673 /* MLD capabilities and operations */ 2670 2674 pos += 2; 2671 2675 2672 - /* Not included when the (nontransmitted) AP is responding itself, 2673 - * but defined to zero then (Draft P802.11be_D3.0, 9.4.2.170.2) 2676 + /* 2677 + * The MLD ID of the reporting AP is always zero. It is set if the AP 2678 + * is part of an MBSSID set and will be non-zero for ML Elements 2679 + * relating to a nontransmitted BSS (matching the Multi-BSSID Index, 2680 + * Draft P802.11be_D3.2, 35.3.4.2) 2674 2681 */ 2675 2682 if (u16_get_bits(control, IEEE80211_MLC_BASIC_PRES_MLD_ID)) { 2676 2683 mld_id = *pos; ··· 2814 2815 out: 2815 2816 kfree(new_ie); 2816 2817 kfree(mle); 2818 + } 2819 + 2820 + static void cfg80211_parse_ml_sta_data(struct wiphy *wiphy, 2821 + struct cfg80211_inform_single_bss_data *tx_data, 2822 + struct cfg80211_bss *source_bss, 2823 + gfp_t gfp) 2824 + { 2825 + const struct element *elem; 2826 + 2827 + if (!source_bss) 2828 + return; 2829 + 2830 + if (tx_data->ftype != CFG80211_BSS_FTYPE_PRESP) 2831 + return; 2832 + 2833 + for_each_element_extid(elem, WLAN_EID_EXT_EHT_MULTI_LINK, 2834 + tx_data->ie, tx_data->ielen) 2835 + cfg80211_parse_ml_elem_sta_data(wiphy, tx_data, source_bss, 2836 + elem, gfp); 2817 2837 } 2818 2838 2819 2839 struct cfg80211_bss *
+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 */
+56
net/wireless/util.c
··· 980 980 } 981 981 } 982 982 983 + /* The default mapping as defined Section 2.3 in RFC8325: The three 984 + * Most Significant Bits (MSBs) of the DSCP are used as the 985 + * corresponding L2 markings. 986 + */ 983 987 ret = dscp >> 5; 988 + 989 + /* Handle specific DSCP values for which the default mapping (as 990 + * described above) doesn't adhere to the intended usage of the DSCP 991 + * value. See section 4 in RFC8325. Specifically, for the following 992 + * Diffserv Service Classes no update is needed: 993 + * - Standard: DF 994 + * - Low Priority Data: CS1 995 + * - Multimedia Streaming: AF31, AF32, AF33 996 + * - Multimedia Conferencing: AF41, AF42, AF43 997 + * - Network Control Traffic: CS7 998 + * - Real-Time Interactive: CS4 999 + */ 1000 + switch (dscp >> 2) { 1001 + case 10: 1002 + case 12: 1003 + case 14: 1004 + /* High throughput data: AF11, AF12, AF13 */ 1005 + ret = 0; 1006 + break; 1007 + case 16: 1008 + /* Operations, Administration, and Maintenance and Provisioning: 1009 + * CS2 1010 + */ 1011 + ret = 0; 1012 + break; 1013 + case 18: 1014 + case 20: 1015 + case 22: 1016 + /* Low latency data: AF21, AF22, AF23 */ 1017 + ret = 3; 1018 + break; 1019 + case 24: 1020 + /* Broadcasting video: CS3 */ 1021 + ret = 4; 1022 + break; 1023 + case 40: 1024 + /* Signaling: CS5 */ 1025 + ret = 5; 1026 + break; 1027 + case 44: 1028 + /* Voice Admit: VA */ 1029 + ret = 6; 1030 + break; 1031 + case 46: 1032 + /* Telephony traffic: EF */ 1033 + ret = 6; 1034 + break; 1035 + case 48: 1036 + /* Network Control Traffic: CS6 */ 1037 + ret = 7; 1038 + break; 1039 + } 984 1040 out: 985 1041 return array_index_nospec(ret, IEEE80211_NUM_TIDS); 986 1042 }