434 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * KUnit tests for channel helper functions4 *5 * Copyright (C) 2024 Intel Corporation6 */7#include <net/mac80211.h>8#include "../mvm.h"9#include <kunit/test.h>10 11MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);12 13static struct wiphy wiphy = {14 .mtx = __MUTEX_INITIALIZER(wiphy.mtx),15};16 17static struct ieee80211_hw hw = {18 .wiphy = &wiphy,19};20 21static struct ieee80211_channel chan_5ghz = {22 .band = NL80211_BAND_5GHZ,23};24 25static struct ieee80211_channel chan_6ghz = {26 .band = NL80211_BAND_6GHZ,27};28 29static struct ieee80211_channel chan_2ghz = {30 .band = NL80211_BAND_2GHZ,31};32 33static struct cfg80211_chan_def chandef_a = {};34 35static struct cfg80211_chan_def chandef_b = {};36 37static struct iwl_mvm_phy_ctxt ctx = {};38 39static struct iwl_mvm_vif_link_info mvm_link = {40 .phy_ctxt = &ctx,41 .active = true42};43 44static struct cfg80211_bss bss = {};45 46static struct ieee80211_bss_conf link_conf = {.bss = &bss};47 48static const struct iwl_fw_cmd_version entry = {49 .group = LEGACY_GROUP,50 .cmd = BT_PROFILE_NOTIFICATION,51 .notif_ver = 452};53 54static struct iwl_fw fw = {55 .ucode_capa = {56 .n_cmd_versions = 1,57 .cmd_versions = &entry,58 },59};60 61static struct iwl_mvm mvm = {62 .hw = &hw,63 .fw = &fw,64};65 66static const struct link_grading_case {67 const char *desc;68 const struct cfg80211_chan_def chandef;69 s32 signal;70 s16 channel_util;71 int chan_load_by_us;72 unsigned int grade;73} link_grading_cases[] = {74 {75 .desc = "UHB, RSSI below range, no factors",76 .chandef = {77 .chan = &chan_6ghz,78 .width = NL80211_CHAN_WIDTH_20,79 },80 .signal = -100,81 .grade = 177,82 },83 {84 .desc = "LB, RSSI in range, no factors",85 .chandef = {86 .chan = &chan_2ghz,87 .width = NL80211_CHAN_WIDTH_20,88 },89 .signal = -84,90 .grade = 344,91 },92 {93 .desc = "HB, RSSI above range, no factors",94 .chandef = {95 .chan = &chan_5ghz,96 .width = NL80211_CHAN_WIDTH_20,97 },98 .signal = -50,99 .grade = 3442,100 },101 {102 .desc = "HB, BSS Load IE (20 percent), inactive link, no puncturing factor",103 .chandef = {104 .chan = &chan_5ghz,105 .width = NL80211_CHAN_WIDTH_20,106 },107 .signal = -66,108 .channel_util = 51,109 .grade = 1836,110 },111 {112 .desc = "LB, BSS Load IE (20 percent), active link, chan_load_by_us=10 percent. No puncturing factor",113 .chandef = {114 .chan = &chan_2ghz,115 .width = NL80211_CHAN_WIDTH_20,116 },117 .signal = -61,118 .channel_util = 51,119 .chan_load_by_us = 10,120 .grade = 2061,121 },122 {123 .desc = "UHB, BSS Load IE (40 percent), active link, chan_load_by_us=50 (invalid) percent. No puncturing factor",124 .chandef = {125 .chan = &chan_6ghz,126 .width = NL80211_CHAN_WIDTH_20,127 },128 .signal = -66,129 .channel_util = 102,130 .chan_load_by_us = 50,131 .grade = 1552,132 },133 { .desc = "HB, 80 MHz, no channel load factor, punctured percentage 0",134 .chandef = {135 .chan = &chan_5ghz,136 .width = NL80211_CHAN_WIDTH_80,137 .punctured = 0x0000138 },139 .signal = -72,140 .grade = 1750,141 },142 { .desc = "HB, 160 MHz, no channel load factor, punctured percentage 25",143 .chandef = {144 .chan = &chan_5ghz,145 .width = NL80211_CHAN_WIDTH_160,146 .punctured = 0x3147 },148 .signal = -72,149 .grade = 1312,150 },151 { .desc = "UHB, 320 MHz, no channel load factor, punctured percentage 12.5 (2/16)",152 .chandef = {153 .chan = &chan_6ghz,154 .width = NL80211_CHAN_WIDTH_320,155 .punctured = 0x3156 },157 .signal = -72,158 .grade = 1806,159 },160 { .desc = "HB, 160 MHz, channel load 20, channel load by us 10, punctured percentage 25",161 .chandef = {162 .chan = &chan_5ghz,163 .width = NL80211_CHAN_WIDTH_160,164 .punctured = 0x3165 },166 .channel_util = 51,167 .chan_load_by_us = 10,168 .signal = -72,169 .grade = 1179,170 },171};172 173KUNIT_ARRAY_PARAM_DESC(link_grading, link_grading_cases, desc)174 175static void setup_link_conf(struct kunit *test)176{177 const struct link_grading_case *params = test->param_value;178 size_t vif_size = sizeof(struct ieee80211_vif) +179 sizeof(struct iwl_mvm_vif);180 struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL);181 struct ieee80211_bss_load_elem *bss_load;182 struct element *element;183 size_t ies_size = sizeof(struct cfg80211_bss_ies) + sizeof(*bss_load) + sizeof(element);184 struct cfg80211_bss_ies *ies;185 struct iwl_mvm_vif *mvmvif;186 187 KUNIT_ASSERT_NOT_NULL(test, vif);188 189 mvmvif = iwl_mvm_vif_from_mac80211(vif);190 if (params->chan_load_by_us > 0) {191 ctx.channel_load_by_us = params->chan_load_by_us;192 mvmvif->link[0] = &mvm_link;193 }194 195 link_conf.vif = vif;196 link_conf.chanreq.oper = params->chandef;197 bss.signal = DBM_TO_MBM(params->signal);198 199 ies = kunit_kzalloc(test, ies_size, GFP_KERNEL);200 KUNIT_ASSERT_NOT_NULL(test, ies);201 ies->len = sizeof(*bss_load) + sizeof(struct element);202 203 element = (void *)ies->data;204 element->datalen = sizeof(*bss_load);205 element->id = 11;206 207 bss_load = (void *)element->data;208 bss_load->channel_util = params->channel_util;209 210 rcu_assign_pointer(bss.ies, ies);211 rcu_assign_pointer(bss.beacon_ies, ies);212}213 214static void test_link_grading(struct kunit *test)215{216 const struct link_grading_case *params = test->param_value;217 unsigned int ret;218 219 setup_link_conf(test);220 221 rcu_read_lock();222 ret = iwl_mvm_get_link_grade(&link_conf);223 rcu_read_unlock();224 225 KUNIT_EXPECT_EQ(test, ret, params->grade);226 227 kunit_kfree(test, link_conf.vif);228 RCU_INIT_POINTER(bss.ies, NULL);229}230 231static struct kunit_case link_grading_test_cases[] = {232 KUNIT_CASE_PARAM(test_link_grading, link_grading_gen_params),233 {}234};235 236static struct kunit_suite link_grading = {237 .name = "iwlmvm-link-grading",238 .test_cases = link_grading_test_cases,239};240 241kunit_test_suite(link_grading);242 243static const struct valid_link_pair_case {244 const char *desc;245 bool bt;246 struct ieee80211_channel *chan_a;247 struct ieee80211_channel *chan_b;248 enum nl80211_chan_width cw_a;249 enum nl80211_chan_width cw_b;250 s32 sig_a;251 s32 sig_b;252 bool csa_a;253 bool valid;254} valid_link_pair_cases[] = {255 {256 .desc = "HB + UHB, valid.",257 .chan_a = &chan_6ghz,258 .chan_b = &chan_5ghz,259 .valid = true,260 },261 {262 .desc = "LB + HB, no BT.",263 .chan_a = &chan_2ghz,264 .chan_b = &chan_5ghz,265 .valid = false,266 },267 {268 .desc = "LB + HB, with BT.",269 .bt = true,270 .chan_a = &chan_2ghz,271 .chan_b = &chan_5ghz,272 .valid = false,273 },274 {275 .desc = "Same band",276 .chan_a = &chan_2ghz,277 .chan_b = &chan_2ghz,278 .valid = false,279 },280 {281 .desc = "RSSI: LB, 20 MHz, low",282 .chan_a = &chan_2ghz,283 .cw_a = NL80211_CHAN_WIDTH_20,284 .sig_a = -68,285 .chan_b = &chan_5ghz,286 .valid = false,287 },288 {289 .desc = "RSSI: UHB, 20 MHz, high",290 .chan_a = &chan_6ghz,291 .cw_a = NL80211_CHAN_WIDTH_20,292 .sig_a = -66,293 .chan_b = &chan_5ghz,294 .cw_b = NL80211_CHAN_WIDTH_20,295 .valid = true,296 },297 {298 .desc = "RSSI: UHB, 40 MHz, low",299 .chan_a = &chan_6ghz,300 .cw_a = NL80211_CHAN_WIDTH_40,301 .sig_a = -65,302 .chan_b = &chan_5ghz,303 .cw_b = NL80211_CHAN_WIDTH_40,304 .valid = false,305 },306 {307 .desc = "RSSI: UHB, 40 MHz, high",308 .chan_a = &chan_6ghz,309 .cw_a = NL80211_CHAN_WIDTH_40,310 .sig_a = -63,311 .chan_b = &chan_5ghz,312 .cw_b = NL80211_CHAN_WIDTH_40,313 .valid = true,314 },315 {316 .desc = "RSSI: UHB, 80 MHz, low",317 .chan_a = &chan_6ghz,318 .cw_a = NL80211_CHAN_WIDTH_80,319 .sig_a = -62,320 .chan_b = &chan_5ghz,321 .cw_b = NL80211_CHAN_WIDTH_80,322 .valid = false,323 },324 {325 .desc = "RSSI: UHB, 80 MHz, high",326 .chan_a = &chan_6ghz,327 .cw_a = NL80211_CHAN_WIDTH_80,328 .sig_a = -60,329 .chan_b = &chan_5ghz,330 .cw_b = NL80211_CHAN_WIDTH_80,331 .valid = true,332 },333 {334 .desc = "RSSI: UHB, 160 MHz, low",335 .chan_a = &chan_6ghz,336 .cw_a = NL80211_CHAN_WIDTH_160,337 .sig_a = -59,338 .chan_b = &chan_5ghz,339 .cw_b = NL80211_CHAN_WIDTH_160,340 .valid = false,341 },342 {343 .desc = "RSSI: HB, 160 MHz, high",344 .chan_a = &chan_6ghz,345 .cw_a = NL80211_CHAN_WIDTH_160,346 .sig_a = -5,347 .chan_b = &chan_5ghz,348 .cw_b = NL80211_CHAN_WIDTH_160,349 .valid = true,350 },351 {352 .desc = "CSA active",353 .chan_a = &chan_6ghz,354 .cw_a = NL80211_CHAN_WIDTH_160,355 .sig_a = -5,356 .chan_b = &chan_5ghz,357 .cw_b = NL80211_CHAN_WIDTH_160,358 .valid = false,359 /* same as previous entry with valid=true except for CSA */360 .csa_a = true,361 },362};363 364KUNIT_ARRAY_PARAM_DESC(valid_link_pair, valid_link_pair_cases, desc)365 366static void test_valid_link_pair(struct kunit *test)367{368 const struct valid_link_pair_case *params = test->param_value;369 size_t vif_size = sizeof(struct ieee80211_vif) +370 sizeof(struct iwl_mvm_vif);371 struct ieee80211_vif *vif = kunit_kzalloc(test, vif_size, GFP_KERNEL);372 struct iwl_trans *trans = kunit_kzalloc(test, sizeof(struct iwl_trans),373 GFP_KERNEL);374 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);375 struct iwl_mvm_link_sel_data link_a = {376 .chandef = &chandef_a,377 .link_id = 1,378 .signal = params->sig_a,379 };380 struct iwl_mvm_link_sel_data link_b = {381 .chandef = &chandef_b,382 .link_id = 5,383 .signal = params->sig_b,384 };385 struct ieee80211_bss_conf *conf;386 bool result;387 388 KUNIT_ASSERT_NOT_NULL(test, vif);389 KUNIT_ASSERT_NOT_NULL(test, trans);390 391 chandef_a.chan = params->chan_a;392 chandef_b.chan = params->chan_b;393 394 chandef_a.width = params->cw_a ?: NL80211_CHAN_WIDTH_20;395 chandef_b.width = params->cw_b ?: NL80211_CHAN_WIDTH_20;396 397 mvm.trans = trans;398 399 mvm.last_bt_notif.wifi_loss_low_rssi = params->bt;400 mvmvif->mvm = &mvm;401 402 conf = kunit_kzalloc(test, sizeof(*vif->link_conf[0]), GFP_KERNEL);403 KUNIT_ASSERT_NOT_NULL(test, conf);404 conf->chanreq.oper = chandef_a;405 conf->csa_active = params->csa_a;406 vif->link_conf[link_a.link_id] = (void __rcu *)conf;407 408 conf = kunit_kzalloc(test, sizeof(*vif->link_conf[0]), GFP_KERNEL);409 KUNIT_ASSERT_NOT_NULL(test, conf);410 conf->chanreq.oper = chandef_b;411 vif->link_conf[link_b.link_id] = (void __rcu *)conf;412 413 wiphy_lock(&wiphy);414 result = iwl_mvm_mld_valid_link_pair(vif, &link_a, &link_b);415 wiphy_unlock(&wiphy);416 417 KUNIT_EXPECT_EQ(test, result, params->valid);418 419 kunit_kfree(test, vif);420 kunit_kfree(test, trans);421}422 423static struct kunit_case valid_link_pair_test_cases[] = {424 KUNIT_CASE_PARAM(test_valid_link_pair, valid_link_pair_gen_params),425 {},426};427 428static struct kunit_suite valid_link_pair = {429 .name = "iwlmvm-valid-link-pair",430 .test_cases = valid_link_pair_test_cases,431};432 433kunit_test_suite(valid_link_pair);434