scan.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * KUnit tests for inform_bss functions
  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. #include <kunit/skbuff.h>
  11. #include "../core.h"
  12. #include "util.h"
  13. /* mac80211 helpers for element building */
  14. #include "../../mac80211/ieee80211_i.h"
  15. MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
  16. struct test_elem {
  17. u8 id;
  18. u8 len;
  19. union {
  20. u8 data[255];
  21. struct {
  22. u8 eid;
  23. u8 edata[254];
  24. };
  25. };
  26. };
  27. static struct gen_new_ie_case {
  28. const char *desc;
  29. struct test_elem parent_ies[16];
  30. struct test_elem child_ies[16];
  31. struct test_elem result_ies[16];
  32. } gen_new_ie_cases[] = {
  33. {
  34. .desc = "ML not inherited",
  35. .parent_ies = {
  36. { .id = WLAN_EID_EXTENSION, .len = 255,
  37. .eid = WLAN_EID_EXT_EHT_MULTI_LINK },
  38. },
  39. .child_ies = {
  40. { .id = WLAN_EID_SSID, .len = 2 },
  41. },
  42. .result_ies = {
  43. { .id = WLAN_EID_SSID, .len = 2 },
  44. },
  45. },
  46. {
  47. .desc = "fragments are ignored if previous len not 255",
  48. .parent_ies = {
  49. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 254, },
  50. { .id = WLAN_EID_FRAGMENT, .len = 125, },
  51. },
  52. .child_ies = {
  53. { .id = WLAN_EID_SSID, .len = 2 },
  54. { .id = WLAN_EID_FRAGMENT, .len = 125, },
  55. },
  56. .result_ies = {
  57. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 254, },
  58. { .id = WLAN_EID_SSID, .len = 2 },
  59. },
  60. },
  61. {
  62. .desc = "fragments inherited",
  63. .parent_ies = {
  64. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
  65. { .id = WLAN_EID_FRAGMENT, .len = 125, },
  66. },
  67. .child_ies = {
  68. { .id = WLAN_EID_SSID, .len = 2 },
  69. },
  70. .result_ies = {
  71. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
  72. { .id = WLAN_EID_FRAGMENT, .len = 125, },
  73. { .id = WLAN_EID_SSID, .len = 2 },
  74. },
  75. },
  76. {
  77. .desc = "fragments copied",
  78. .parent_ies = {
  79. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
  80. { .id = WLAN_EID_FRAGMENT, .len = 125, },
  81. },
  82. .child_ies = {
  83. { .id = WLAN_EID_SSID, .len = 2 },
  84. },
  85. .result_ies = {
  86. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
  87. { .id = WLAN_EID_FRAGMENT, .len = 125, },
  88. { .id = WLAN_EID_SSID, .len = 2 },
  89. },
  90. },
  91. {
  92. .desc = "multiple elements inherit",
  93. .parent_ies = {
  94. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
  95. { .id = WLAN_EID_FRAGMENT, .len = 125, },
  96. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 123, },
  97. },
  98. .child_ies = {
  99. { .id = WLAN_EID_SSID, .len = 2 },
  100. },
  101. .result_ies = {
  102. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
  103. { .id = WLAN_EID_FRAGMENT, .len = 125, },
  104. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 123, },
  105. { .id = WLAN_EID_SSID, .len = 2 },
  106. },
  107. },
  108. {
  109. .desc = "one child element overrides",
  110. .parent_ies = {
  111. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
  112. { .id = WLAN_EID_FRAGMENT, .len = 125, },
  113. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 123, },
  114. },
  115. .child_ies = {
  116. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 127, },
  117. { .id = WLAN_EID_SSID, .len = 2 },
  118. },
  119. .result_ies = {
  120. { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 127, },
  121. { .id = WLAN_EID_SSID, .len = 2 },
  122. },
  123. },
  124. {
  125. .desc = "empty elements from parent",
  126. .parent_ies = {
  127. { .id = 0x1, .len = 0, },
  128. { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 },
  129. },
  130. .child_ies = {
  131. },
  132. .result_ies = {
  133. { .id = 0x1, .len = 0, },
  134. { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 },
  135. },
  136. },
  137. {
  138. .desc = "empty elements from child",
  139. .parent_ies = {
  140. },
  141. .child_ies = {
  142. { .id = 0x1, .len = 0, },
  143. { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 },
  144. },
  145. .result_ies = {
  146. { .id = 0x1, .len = 0, },
  147. { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 },
  148. },
  149. },
  150. {
  151. .desc = "invalid extended elements ignored",
  152. .parent_ies = {
  153. { .id = WLAN_EID_EXTENSION, .len = 0 },
  154. },
  155. .child_ies = {
  156. { .id = WLAN_EID_EXTENSION, .len = 0 },
  157. },
  158. .result_ies = {
  159. },
  160. },
  161. {
  162. .desc = "multiple extended elements",
  163. .parent_ies = {
  164. { .id = WLAN_EID_EXTENSION, .len = 3,
  165. .eid = WLAN_EID_EXT_HE_CAPABILITY },
  166. { .id = WLAN_EID_EXTENSION, .len = 5,
  167. .eid = WLAN_EID_EXT_ASSOC_DELAY_INFO },
  168. { .id = WLAN_EID_EXTENSION, .len = 7,
  169. .eid = WLAN_EID_EXT_HE_OPERATION },
  170. { .id = WLAN_EID_EXTENSION, .len = 11,
  171. .eid = WLAN_EID_EXT_FILS_REQ_PARAMS },
  172. },
  173. .child_ies = {
  174. { .id = WLAN_EID_SSID, .len = 13 },
  175. { .id = WLAN_EID_EXTENSION, .len = 17,
  176. .eid = WLAN_EID_EXT_HE_CAPABILITY },
  177. { .id = WLAN_EID_EXTENSION, .len = 11,
  178. .eid = WLAN_EID_EXT_FILS_KEY_CONFIRM },
  179. { .id = WLAN_EID_EXTENSION, .len = 19,
  180. .eid = WLAN_EID_EXT_HE_OPERATION },
  181. },
  182. .result_ies = {
  183. { .id = WLAN_EID_EXTENSION, .len = 17,
  184. .eid = WLAN_EID_EXT_HE_CAPABILITY },
  185. { .id = WLAN_EID_EXTENSION, .len = 5,
  186. .eid = WLAN_EID_EXT_ASSOC_DELAY_INFO },
  187. { .id = WLAN_EID_EXTENSION, .len = 19,
  188. .eid = WLAN_EID_EXT_HE_OPERATION },
  189. { .id = WLAN_EID_EXTENSION, .len = 11,
  190. .eid = WLAN_EID_EXT_FILS_REQ_PARAMS },
  191. { .id = WLAN_EID_SSID, .len = 13 },
  192. { .id = WLAN_EID_EXTENSION, .len = 11,
  193. .eid = WLAN_EID_EXT_FILS_KEY_CONFIRM },
  194. },
  195. },
  196. {
  197. .desc = "non-inherit element",
  198. .parent_ies = {
  199. { .id = 0x1, .len = 7, },
  200. { .id = 0x2, .len = 11, },
  201. { .id = 0x3, .len = 13, },
  202. { .id = WLAN_EID_EXTENSION, .len = 17, .eid = 0x10 },
  203. { .id = WLAN_EID_EXTENSION, .len = 19, .eid = 0x11 },
  204. { .id = WLAN_EID_EXTENSION, .len = 23, .eid = 0x12 },
  205. { .id = WLAN_EID_EXTENSION, .len = 29, .eid = 0x14 },
  206. },
  207. .child_ies = {
  208. { .id = WLAN_EID_EXTENSION,
  209. .eid = WLAN_EID_EXT_NON_INHERITANCE,
  210. .len = 10,
  211. .edata = { 0x3, 0x1, 0x2, 0x3,
  212. 0x4, 0x10, 0x11, 0x13, 0x14 } },
  213. { .id = WLAN_EID_SSID, .len = 2 },
  214. },
  215. .result_ies = {
  216. { .id = WLAN_EID_EXTENSION, .len = 23, .eid = 0x12 },
  217. { .id = WLAN_EID_SSID, .len = 2 },
  218. },
  219. },
  220. };
  221. KUNIT_ARRAY_PARAM_DESC(gen_new_ie, gen_new_ie_cases, desc)
  222. static void test_gen_new_ie(struct kunit *test)
  223. {
  224. const struct gen_new_ie_case *params = test->param_value;
  225. struct sk_buff *parent = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
  226. struct sk_buff *child = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
  227. struct sk_buff *reference = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
  228. u8 *out = kunit_kzalloc(test, IEEE80211_MAX_DATA_LEN, GFP_KERNEL);
  229. size_t len;
  230. int i;
  231. KUNIT_ASSERT_NOT_NULL(test, parent);
  232. KUNIT_ASSERT_NOT_NULL(test, child);
  233. KUNIT_ASSERT_NOT_NULL(test, reference);
  234. KUNIT_ASSERT_NOT_NULL(test, out);
  235. for (i = 0; i < ARRAY_SIZE(params->parent_ies); i++) {
  236. if (params->parent_ies[i].len != 0) {
  237. skb_put_u8(parent, params->parent_ies[i].id);
  238. skb_put_u8(parent, params->parent_ies[i].len);
  239. skb_put_data(parent, params->parent_ies[i].data,
  240. params->parent_ies[i].len);
  241. }
  242. if (params->child_ies[i].len != 0) {
  243. skb_put_u8(child, params->child_ies[i].id);
  244. skb_put_u8(child, params->child_ies[i].len);
  245. skb_put_data(child, params->child_ies[i].data,
  246. params->child_ies[i].len);
  247. }
  248. if (params->result_ies[i].len != 0) {
  249. skb_put_u8(reference, params->result_ies[i].id);
  250. skb_put_u8(reference, params->result_ies[i].len);
  251. skb_put_data(reference, params->result_ies[i].data,
  252. params->result_ies[i].len);
  253. }
  254. }
  255. len = cfg80211_gen_new_ie(parent->data, parent->len,
  256. child->data, child->len,
  257. out, IEEE80211_MAX_DATA_LEN);
  258. KUNIT_EXPECT_EQ(test, len, reference->len);
  259. KUNIT_EXPECT_MEMEQ(test, out, reference->data, reference->len);
  260. memset(out, 0, IEEE80211_MAX_DATA_LEN);
  261. /* Exactly enough space */
  262. len = cfg80211_gen_new_ie(parent->data, parent->len,
  263. child->data, child->len,
  264. out, reference->len);
  265. KUNIT_EXPECT_EQ(test, len, reference->len);
  266. KUNIT_EXPECT_MEMEQ(test, out, reference->data, reference->len);
  267. memset(out, 0, IEEE80211_MAX_DATA_LEN);
  268. /* Not enough space (or expected zero length) */
  269. len = cfg80211_gen_new_ie(parent->data, parent->len,
  270. child->data, child->len,
  271. out, reference->len - 1);
  272. KUNIT_EXPECT_EQ(test, len, 0);
  273. }
  274. static void test_gen_new_ie_malformed(struct kunit *test)
  275. {
  276. struct sk_buff *malformed = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
  277. u8 *out = kunit_kzalloc(test, IEEE80211_MAX_DATA_LEN, GFP_KERNEL);
  278. size_t len;
  279. KUNIT_ASSERT_NOT_NULL(test, malformed);
  280. KUNIT_ASSERT_NOT_NULL(test, out);
  281. skb_put_u8(malformed, WLAN_EID_SSID);
  282. skb_put_u8(malformed, 3);
  283. skb_put(malformed, 3);
  284. skb_put_u8(malformed, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
  285. skb_put_u8(malformed, 10);
  286. skb_put(malformed, 9);
  287. len = cfg80211_gen_new_ie(malformed->data, malformed->len,
  288. out, 0,
  289. out, IEEE80211_MAX_DATA_LEN);
  290. KUNIT_EXPECT_EQ(test, len, 5);
  291. len = cfg80211_gen_new_ie(out, 0,
  292. malformed->data, malformed->len,
  293. out, IEEE80211_MAX_DATA_LEN);
  294. KUNIT_EXPECT_EQ(test, len, 5);
  295. }
  296. struct inform_bss {
  297. struct kunit *test;
  298. int inform_bss_count;
  299. };
  300. static void inform_bss_inc_counter(struct wiphy *wiphy,
  301. struct cfg80211_bss *bss,
  302. const struct cfg80211_bss_ies *ies,
  303. void *drv_data)
  304. {
  305. struct inform_bss *ctx = t_wiphy_ctx(wiphy);
  306. ctx->inform_bss_count++;
  307. rcu_read_lock();
  308. KUNIT_EXPECT_PTR_EQ(ctx->test, drv_data, ctx);
  309. KUNIT_EXPECT_PTR_EQ(ctx->test, ies, rcu_dereference(bss->ies));
  310. rcu_read_unlock();
  311. }
  312. static void test_inform_bss_ssid_only(struct kunit *test)
  313. {
  314. struct inform_bss ctx = {
  315. .test = test,
  316. };
  317. struct wiphy *wiphy = T_WIPHY(test, ctx);
  318. struct t_wiphy_priv *w_priv = wiphy_priv(wiphy);
  319. struct cfg80211_inform_bss inform_bss = {
  320. .signal = 50,
  321. .drv_data = &ctx,
  322. };
  323. const u8 bssid[ETH_ALEN] = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x66 };
  324. u64 tsf = 0x1000000000000000ULL;
  325. int beacon_int = 100;
  326. u16 capability = 0x1234;
  327. static const u8 input[] = {
  328. [0] = WLAN_EID_SSID,
  329. [1] = 4,
  330. [2] = 'T', 'E', 'S', 'T'
  331. };
  332. struct cfg80211_bss *bss, *other;
  333. const struct cfg80211_bss_ies *ies;
  334. w_priv->ops->inform_bss = inform_bss_inc_counter;
  335. inform_bss.chan = ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(2412));
  336. KUNIT_ASSERT_NOT_NULL(test, inform_bss.chan);
  337. bss = cfg80211_inform_bss_data(wiphy, &inform_bss,
  338. CFG80211_BSS_FTYPE_PRESP, bssid, tsf,
  339. capability, beacon_int,
  340. input, sizeof(input),
  341. GFP_KERNEL);
  342. KUNIT_EXPECT_NOT_NULL(test, bss);
  343. KUNIT_EXPECT_EQ(test, ctx.inform_bss_count, 1);
  344. /* Check values in returned bss are correct */
  345. KUNIT_EXPECT_EQ(test, bss->signal, inform_bss.signal);
  346. KUNIT_EXPECT_EQ(test, bss->beacon_interval, beacon_int);
  347. KUNIT_EXPECT_EQ(test, bss->capability, capability);
  348. KUNIT_EXPECT_EQ(test, bss->bssid_index, 0);
  349. KUNIT_EXPECT_PTR_EQ(test, bss->channel, inform_bss.chan);
  350. KUNIT_EXPECT_MEMEQ(test, bssid, bss->bssid, sizeof(bssid));
  351. /* Check the IEs have the expected value */
  352. rcu_read_lock();
  353. ies = rcu_dereference(bss->ies);
  354. KUNIT_EXPECT_NOT_NULL(test, ies);
  355. KUNIT_EXPECT_EQ(test, ies->tsf, tsf);
  356. KUNIT_EXPECT_EQ(test, ies->len, sizeof(input));
  357. KUNIT_EXPECT_MEMEQ(test, ies->data, input, sizeof(input));
  358. rcu_read_unlock();
  359. /* Check we can look up the BSS - by SSID */
  360. other = cfg80211_get_bss(wiphy, NULL, NULL, "TEST", 4,
  361. IEEE80211_BSS_TYPE_ANY,
  362. IEEE80211_PRIVACY_ANY);
  363. KUNIT_EXPECT_PTR_EQ(test, bss, other);
  364. cfg80211_put_bss(wiphy, other);
  365. /* Check we can look up the BSS - by BSSID */
  366. other = cfg80211_get_bss(wiphy, NULL, bssid, NULL, 0,
  367. IEEE80211_BSS_TYPE_ANY,
  368. IEEE80211_PRIVACY_ANY);
  369. KUNIT_EXPECT_PTR_EQ(test, bss, other);
  370. cfg80211_put_bss(wiphy, other);
  371. cfg80211_put_bss(wiphy, bss);
  372. }
  373. static struct inform_bss_ml_sta_case {
  374. const char *desc;
  375. int mld_id;
  376. bool sta_prof_vendor_elems;
  377. bool include_oper_class;
  378. bool nstr;
  379. } inform_bss_ml_sta_cases[] = {
  380. {
  381. .desc = "zero_mld_id",
  382. .mld_id = 0,
  383. .sta_prof_vendor_elems = false,
  384. }, {
  385. .desc = "zero_mld_id_with_oper_class",
  386. .mld_id = 0,
  387. .sta_prof_vendor_elems = false,
  388. .include_oper_class = true,
  389. }, {
  390. .desc = "mld_id_eq_1",
  391. .mld_id = 1,
  392. .sta_prof_vendor_elems = true,
  393. }, {
  394. .desc = "mld_id_eq_1_with_oper_class",
  395. .mld_id = 1,
  396. .sta_prof_vendor_elems = true,
  397. .include_oper_class = true,
  398. }, {
  399. .desc = "nstr",
  400. .mld_id = 0,
  401. .nstr = true,
  402. },
  403. };
  404. KUNIT_ARRAY_PARAM_DESC(inform_bss_ml_sta, inform_bss_ml_sta_cases, desc)
  405. static void test_inform_bss_ml_sta(struct kunit *test)
  406. {
  407. const struct inform_bss_ml_sta_case *params = test->param_value;
  408. struct inform_bss ctx = {
  409. .test = test,
  410. };
  411. struct wiphy *wiphy = T_WIPHY(test, ctx);
  412. struct t_wiphy_priv *w_priv = wiphy_priv(wiphy);
  413. struct cfg80211_inform_bss inform_bss = {
  414. .signal = 50,
  415. .drv_data = &ctx,
  416. };
  417. struct cfg80211_bss *bss, *link_bss;
  418. const struct cfg80211_bss_ies *ies;
  419. /* sending station */
  420. const u8 bssid[ETH_ALEN] = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x66 };
  421. u64 tsf = 0x1000000000000000ULL;
  422. int beacon_int = 100;
  423. u16 capability = 0x1234;
  424. /* Building the frame *************************************************/
  425. struct sk_buff *input = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
  426. u8 *len_mle, *len_prof;
  427. u8 link_id = 2;
  428. struct {
  429. struct ieee80211_neighbor_ap_info info;
  430. struct ieee80211_tbtt_info_ge_11 ap;
  431. } __packed rnr_normal = {
  432. .info = {
  433. .tbtt_info_hdr = u8_encode_bits(0, IEEE80211_AP_INFO_TBTT_HDR_COUNT),
  434. .tbtt_info_len = sizeof(struct ieee80211_tbtt_info_ge_11),
  435. .op_class = 81,
  436. .channel = 11,
  437. },
  438. .ap = {
  439. .tbtt_offset = 0xff,
  440. .bssid = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x67 },
  441. .short_ssid = 0, /* unused */
  442. .bss_params = 0,
  443. .psd_20 = 0,
  444. .mld_params.mld_id = params->mld_id,
  445. .mld_params.params =
  446. le16_encode_bits(link_id,
  447. IEEE80211_RNR_MLD_PARAMS_LINK_ID),
  448. }
  449. };
  450. struct {
  451. struct ieee80211_neighbor_ap_info info;
  452. struct ieee80211_rnr_mld_params mld_params;
  453. } __packed rnr_nstr = {
  454. .info = {
  455. .tbtt_info_hdr =
  456. u8_encode_bits(0, IEEE80211_AP_INFO_TBTT_HDR_COUNT) |
  457. u8_encode_bits(IEEE80211_TBTT_INFO_TYPE_MLD,
  458. IEEE80211_AP_INFO_TBTT_HDR_TYPE),
  459. .tbtt_info_len = sizeof(struct ieee80211_rnr_mld_params),
  460. .op_class = 81,
  461. .channel = 11,
  462. },
  463. .mld_params = {
  464. .mld_id = params->mld_id,
  465. .params =
  466. le16_encode_bits(link_id,
  467. IEEE80211_RNR_MLD_PARAMS_LINK_ID),
  468. }
  469. };
  470. size_t rnr_len = params->nstr ? sizeof(rnr_nstr) : sizeof(rnr_normal);
  471. void *rnr = params->nstr ? (void *)&rnr_nstr : (void *)&rnr_normal;
  472. struct {
  473. __le16 control;
  474. u8 var_len;
  475. u8 mld_mac_addr[ETH_ALEN];
  476. u8 link_id_info;
  477. u8 params_change_count;
  478. __le16 mld_caps_and_ops;
  479. u8 mld_id;
  480. __le16 ext_mld_caps_and_ops;
  481. } __packed mle_basic_common_info = {
  482. .control =
  483. cpu_to_le16(IEEE80211_ML_CONTROL_TYPE_BASIC |
  484. IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT |
  485. IEEE80211_MLC_BASIC_PRES_LINK_ID |
  486. (params->mld_id ? IEEE80211_MLC_BASIC_PRES_MLD_ID : 0) |
  487. IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP),
  488. .mld_id = params->mld_id,
  489. .mld_caps_and_ops = cpu_to_le16(0x0102),
  490. .ext_mld_caps_and_ops = cpu_to_le16(0x0304),
  491. .var_len = sizeof(mle_basic_common_info) - 2 -
  492. (params->mld_id ? 0 : 1),
  493. .mld_mac_addr = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x60 },
  494. };
  495. struct {
  496. __le16 control;
  497. u8 var_len;
  498. u8 bssid[ETH_ALEN];
  499. __le16 beacon_int;
  500. __le64 tsf_offset;
  501. __le16 capabilities; /* already part of payload */
  502. } __packed sta_prof = {
  503. .control =
  504. cpu_to_le16(IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE |
  505. IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT |
  506. IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT |
  507. IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT |
  508. u16_encode_bits(link_id,
  509. IEEE80211_MLE_STA_CONTROL_LINK_ID)),
  510. .var_len = sizeof(sta_prof) - 2 - 2,
  511. .bssid = { *rnr_normal.ap.bssid },
  512. .beacon_int = cpu_to_le16(101),
  513. .tsf_offset = cpu_to_le64(-123ll),
  514. .capabilities = cpu_to_le16(0xdead),
  515. };
  516. KUNIT_ASSERT_NOT_NULL(test, input);
  517. w_priv->ops->inform_bss = inform_bss_inc_counter;
  518. inform_bss.chan = ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(2412));
  519. KUNIT_ASSERT_NOT_NULL(test, inform_bss.chan);
  520. skb_put_u8(input, WLAN_EID_SSID);
  521. skb_put_u8(input, 4);
  522. skb_put_data(input, "TEST", 4);
  523. if (params->include_oper_class) {
  524. skb_put_u8(input, WLAN_EID_SUPPORTED_REGULATORY_CLASSES);
  525. skb_put_u8(input, 1);
  526. skb_put_u8(input, 81);
  527. }
  528. skb_put_u8(input, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
  529. skb_put_u8(input, rnr_len);
  530. skb_put_data(input, rnr, rnr_len);
  531. /* build a multi-link element */
  532. skb_put_u8(input, WLAN_EID_EXTENSION);
  533. len_mle = skb_put(input, 1);
  534. skb_put_u8(input, WLAN_EID_EXT_EHT_MULTI_LINK);
  535. skb_put_data(input, &mle_basic_common_info, sizeof(mle_basic_common_info));
  536. if (!params->mld_id)
  537. t_skb_remove_member(input, typeof(mle_basic_common_info), mld_id);
  538. /* with a STA profile inside */
  539. skb_put_u8(input, IEEE80211_MLE_SUBELEM_PER_STA_PROFILE);
  540. len_prof = skb_put(input, 1);
  541. skb_put_data(input, &sta_prof, sizeof(sta_prof));
  542. if (params->sta_prof_vendor_elems) {
  543. /* Put two (vendor) element into sta_prof */
  544. skb_put_u8(input, WLAN_EID_VENDOR_SPECIFIC);
  545. skb_put_u8(input, 160);
  546. skb_put(input, 160);
  547. skb_put_u8(input, WLAN_EID_VENDOR_SPECIFIC);
  548. skb_put_u8(input, 165);
  549. skb_put(input, 165);
  550. }
  551. /* fragment STA profile */
  552. ieee80211_fragment_element(input, len_prof,
  553. IEEE80211_MLE_SUBELEM_FRAGMENT);
  554. /* fragment MLE */
  555. ieee80211_fragment_element(input, len_mle, WLAN_EID_FRAGMENT);
  556. /* Put a (vendor) element after the ML element */
  557. skb_put_u8(input, WLAN_EID_VENDOR_SPECIFIC);
  558. skb_put_u8(input, 155);
  559. skb_put(input, 155);
  560. /* Submit *************************************************************/
  561. bss = cfg80211_inform_bss_data(wiphy, &inform_bss,
  562. CFG80211_BSS_FTYPE_PRESP, bssid, tsf,
  563. capability, beacon_int,
  564. input->data, input->len,
  565. GFP_KERNEL);
  566. KUNIT_EXPECT_NOT_NULL(test, bss);
  567. KUNIT_EXPECT_EQ(test, ctx.inform_bss_count, 2);
  568. /* Check link_bss *****************************************************/
  569. link_bss = __cfg80211_get_bss(wiphy, NULL, sta_prof.bssid, NULL, 0,
  570. IEEE80211_BSS_TYPE_ANY,
  571. IEEE80211_PRIVACY_ANY,
  572. 0);
  573. KUNIT_ASSERT_NOT_NULL(test, link_bss);
  574. KUNIT_EXPECT_EQ(test, link_bss->signal, 0);
  575. KUNIT_EXPECT_EQ(test, link_bss->beacon_interval,
  576. le16_to_cpu(sta_prof.beacon_int));
  577. KUNIT_EXPECT_EQ(test, link_bss->capability,
  578. le16_to_cpu(sta_prof.capabilities));
  579. KUNIT_EXPECT_EQ(test, link_bss->bssid_index, 0);
  580. KUNIT_EXPECT_PTR_EQ(test, link_bss->channel,
  581. ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(2462)));
  582. /* Test wiphy does not set WIPHY_FLAG_SUPPORTS_NSTR_NONPRIMARY */
  583. if (params->nstr) {
  584. KUNIT_EXPECT_EQ(test, link_bss->use_for, 0);
  585. KUNIT_EXPECT_EQ(test, link_bss->cannot_use_reasons,
  586. NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY);
  587. KUNIT_EXPECT_NULL(test,
  588. cfg80211_get_bss(wiphy, NULL, sta_prof.bssid,
  589. NULL, 0,
  590. IEEE80211_BSS_TYPE_ANY,
  591. IEEE80211_PRIVACY_ANY));
  592. } else {
  593. KUNIT_EXPECT_EQ(test, link_bss->use_for,
  594. NL80211_BSS_USE_FOR_ALL);
  595. KUNIT_EXPECT_EQ(test, link_bss->cannot_use_reasons, 0);
  596. }
  597. rcu_read_lock();
  598. ies = rcu_dereference(link_bss->ies);
  599. KUNIT_EXPECT_NOT_NULL(test, ies);
  600. KUNIT_EXPECT_EQ(test, ies->tsf, tsf + le64_to_cpu(sta_prof.tsf_offset));
  601. /* Resulting length should be:
  602. * SSID (inherited) + RNR (inherited) + vendor element(s) +
  603. * operating class (if requested) +
  604. * generated RNR (if MLD ID == 0 and not NSTR) +
  605. * MLE common info + MLE header and control
  606. */
  607. if (params->sta_prof_vendor_elems)
  608. KUNIT_EXPECT_EQ(test, ies->len,
  609. 6 + 2 + rnr_len + 2 + 160 + 2 + 165 +
  610. (params->include_oper_class ? 3 : 0) +
  611. (!params->mld_id && !params->nstr ? 22 : 0) +
  612. mle_basic_common_info.var_len + 5);
  613. else
  614. KUNIT_EXPECT_EQ(test, ies->len,
  615. 6 + 2 + rnr_len + 2 + 155 +
  616. (params->include_oper_class ? 3 : 0) +
  617. (!params->mld_id && !params->nstr ? 22 : 0) +
  618. mle_basic_common_info.var_len + 5);
  619. rcu_read_unlock();
  620. cfg80211_put_bss(wiphy, bss);
  621. cfg80211_put_bss(wiphy, link_bss);
  622. }
  623. static struct cfg80211_parse_colocated_ap_case {
  624. const char *desc;
  625. u8 op_class;
  626. u8 channel;
  627. struct ieee80211_neighbor_ap_info info;
  628. union {
  629. struct ieee80211_tbtt_info_ge_11 tbtt_long;
  630. struct ieee80211_tbtt_info_7_8_9 tbtt_short;
  631. };
  632. bool add_junk;
  633. bool same_ssid;
  634. bool valid;
  635. } cfg80211_parse_colocated_ap_cases[] = {
  636. {
  637. .desc = "wrong_band",
  638. .info.op_class = 81,
  639. .info.channel = 11,
  640. .tbtt_long = {
  641. .bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
  642. .bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
  643. },
  644. .valid = false,
  645. },
  646. {
  647. .desc = "wrong_type",
  648. /* IEEE80211_AP_INFO_TBTT_HDR_TYPE is in the least significant bits */
  649. .info.tbtt_info_hdr = IEEE80211_TBTT_INFO_TYPE_MLD,
  650. .tbtt_long = {
  651. .bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
  652. .bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
  653. },
  654. .valid = false,
  655. },
  656. {
  657. .desc = "colocated_invalid_len_short",
  658. .info.tbtt_info_len = 6,
  659. .tbtt_short = {
  660. .bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
  661. .bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP |
  662. IEEE80211_RNR_TBTT_PARAMS_SAME_SSID,
  663. },
  664. .valid = false,
  665. },
  666. {
  667. .desc = "colocated_invalid_len_short_mld",
  668. .info.tbtt_info_len = 10,
  669. .tbtt_long = {
  670. .bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
  671. .bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
  672. },
  673. .valid = false,
  674. },
  675. {
  676. .desc = "colocated_non_mld",
  677. .info.tbtt_info_len = sizeof(struct ieee80211_tbtt_info_7_8_9),
  678. .tbtt_short = {
  679. .bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
  680. .bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP |
  681. IEEE80211_RNR_TBTT_PARAMS_SAME_SSID,
  682. },
  683. .same_ssid = true,
  684. .valid = true,
  685. },
  686. {
  687. .desc = "colocated_non_mld_invalid_bssid",
  688. .info.tbtt_info_len = sizeof(struct ieee80211_tbtt_info_7_8_9),
  689. .tbtt_short = {
  690. .bssid = { 0xff, 0x11, 0x22, 0x33, 0x44, 0x55 },
  691. .bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP |
  692. IEEE80211_RNR_TBTT_PARAMS_SAME_SSID,
  693. },
  694. .same_ssid = true,
  695. .valid = false,
  696. },
  697. {
  698. .desc = "colocated_mld",
  699. .tbtt_long = {
  700. .bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
  701. .bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
  702. },
  703. .valid = true,
  704. },
  705. {
  706. .desc = "colocated_mld",
  707. .tbtt_long = {
  708. .bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
  709. .bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
  710. },
  711. .add_junk = true,
  712. .valid = false,
  713. },
  714. {
  715. .desc = "colocated_disabled_mld",
  716. .tbtt_long = {
  717. .bssid = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 },
  718. .bss_params = IEEE80211_RNR_TBTT_PARAMS_COLOC_AP,
  719. .mld_params.params = cpu_to_le16(IEEE80211_RNR_MLD_PARAMS_DISABLED_LINK),
  720. },
  721. .valid = false,
  722. },
  723. };
  724. KUNIT_ARRAY_PARAM_DESC(cfg80211_parse_colocated_ap, cfg80211_parse_colocated_ap_cases, desc)
  725. static void test_cfg80211_parse_colocated_ap(struct kunit *test)
  726. {
  727. const struct cfg80211_parse_colocated_ap_case *params = test->param_value;
  728. struct sk_buff *input = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
  729. struct cfg80211_bss_ies *ies;
  730. struct ieee80211_neighbor_ap_info info;
  731. LIST_HEAD(coloc_ap_list);
  732. int count;
  733. KUNIT_ASSERT_NOT_NULL(test, input);
  734. info = params->info;
  735. /* Reasonable values for a colocated AP */
  736. if (!info.tbtt_info_len)
  737. info.tbtt_info_len = sizeof(params->tbtt_long);
  738. if (!info.op_class)
  739. info.op_class = 131;
  740. if (!info.channel)
  741. info.channel = 33;
  742. /* Zero is the correct default for .btt_info_hdr (one entry, TBTT type) */
  743. skb_put_u8(input, WLAN_EID_SSID);
  744. skb_put_u8(input, 4);
  745. skb_put_data(input, "TEST", 4);
  746. skb_put_u8(input, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
  747. skb_put_u8(input, sizeof(info) + info.tbtt_info_len + (params->add_junk ? 3 : 0));
  748. skb_put_data(input, &info, sizeof(info));
  749. skb_put_data(input, &params->tbtt_long, info.tbtt_info_len);
  750. if (params->add_junk)
  751. skb_put_data(input, "123", 3);
  752. ies = kunit_kzalloc(test, struct_size(ies, data, input->len), GFP_KERNEL);
  753. KUNIT_ASSERT_NOT_NULL(test, ies);
  754. ies->len = input->len;
  755. memcpy(ies->data, input->data, input->len);
  756. count = cfg80211_parse_colocated_ap(ies, &coloc_ap_list);
  757. KUNIT_EXPECT_EQ(test, count, params->valid);
  758. KUNIT_EXPECT_EQ(test, list_count_nodes(&coloc_ap_list), params->valid);
  759. if (params->valid && !list_empty(&coloc_ap_list)) {
  760. struct cfg80211_colocated_ap *ap;
  761. ap = list_first_entry(&coloc_ap_list, typeof(*ap), list);
  762. if (info.tbtt_info_len <= sizeof(params->tbtt_short))
  763. KUNIT_EXPECT_MEMEQ(test, ap->bssid, params->tbtt_short.bssid, ETH_ALEN);
  764. else
  765. KUNIT_EXPECT_MEMEQ(test, ap->bssid, params->tbtt_long.bssid, ETH_ALEN);
  766. if (params->same_ssid) {
  767. KUNIT_EXPECT_EQ(test, ap->ssid_len, 4);
  768. KUNIT_EXPECT_MEMEQ(test, ap->ssid, "TEST", 4);
  769. } else {
  770. KUNIT_EXPECT_EQ(test, ap->ssid_len, 0);
  771. }
  772. }
  773. cfg80211_free_coloc_ap_list(&coloc_ap_list);
  774. }
  775. static struct kunit_case gen_new_ie_test_cases[] = {
  776. KUNIT_CASE_PARAM(test_gen_new_ie, gen_new_ie_gen_params),
  777. KUNIT_CASE(test_gen_new_ie_malformed),
  778. {}
  779. };
  780. static struct kunit_suite gen_new_ie = {
  781. .name = "cfg80211-ie-generation",
  782. .test_cases = gen_new_ie_test_cases,
  783. };
  784. kunit_test_suite(gen_new_ie);
  785. static struct kunit_case inform_bss_test_cases[] = {
  786. KUNIT_CASE(test_inform_bss_ssid_only),
  787. KUNIT_CASE_PARAM(test_inform_bss_ml_sta, inform_bss_ml_sta_gen_params),
  788. {}
  789. };
  790. static struct kunit_suite inform_bss = {
  791. .name = "cfg80211-inform-bss",
  792. .test_cases = inform_bss_test_cases,
  793. };
  794. kunit_test_suite(inform_bss);
  795. static struct kunit_case scan_6ghz_cases[] = {
  796. KUNIT_CASE_PARAM(test_cfg80211_parse_colocated_ap,
  797. cfg80211_parse_colocated_ap_gen_params),
  798. {}
  799. };
  800. static struct kunit_suite scan_6ghz = {
  801. .name = "cfg80211-scan-6ghz",
  802. .test_cases = scan_6ghz_cases,
  803. };
  804. kunit_test_suite(scan_6ghz);