| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <ddk/protocol/wlanif.h> |
| |
| #include "src/connectivity/wlan/drivers/testing/lib/sim-fake-ap/sim-fake-ap.h" |
| #include "src/connectivity/wlan/drivers/third_party/broadcom/brcmfmac/sim/sim.h" |
| #include "src/connectivity/wlan/drivers/third_party/broadcom/brcmfmac/sim/test/sim_test.h" |
| #include "src/connectivity/wlan/lib/common/cpp/include/wlan/common/status_code.h" |
| |
| namespace wlan::brcmfmac { |
| |
| // Some default AP and association request values |
| constexpr uint16_t kDefaultCh = 149; |
| constexpr wlan_channel_t kDefaultChannel = { |
| .primary = kDefaultCh, .cbw = WLAN_CHANNEL_BANDWIDTH__20, .secondary80 = 0}; |
| // Chanspec value corresponding to kDefaultChannel with current d11 encoder. |
| constexpr uint16_t kDefaultChanspec = 53397; |
| constexpr uint16_t kTestChanspec = 0xd0a5; |
| constexpr uint16_t kTest1Chanspec = 0xd095; |
| constexpr simulation::WlanTxInfo kDefaultTxInfo = {.channel = kDefaultChannel}; |
| constexpr wlan_ssid_t kDefaultSsid = {.len = 15, .ssid = "Fuchsia Fake AP"}; |
| const common::MacAddr kDefaultBssid({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc}); |
| const common::MacAddr kFakeMac({0xde, 0xad, 0xbe, 0xef, 0x00, 0x02}); |
| |
| class DynamicIfTest : public SimTest { |
| public: |
| // How long an individual test will run for. We need an end time because tests run until no more |
| // events remain and so we need to stop aps from beaconing to drain the event queue. |
| static constexpr zx::duration kTestDuration = zx::sec(100); |
| DynamicIfTest() = default; |
| void Init(); |
| void Finish(); |
| |
| zx_status_t CreateInterface(wlan_info_mac_role_t role, |
| std::optional<common::MacAddr> mac_addr = std::nullopt); |
| void DeleteInterface(wlan_info_mac_role_t role); |
| uint32_t DeviceCount(); |
| void StartSoftAP(); |
| void StopSoftAP(); |
| void InjectStopAPError(); |
| // Run through the join => auth => assoc flow |
| void StartAssoc(); |
| |
| void ChannelCheck(); |
| void TxAuthandAssocReq(); |
| |
| void VerifyAssocWithSoftAP(); |
| void VerifyClientDisassoc(bool exp_value); |
| |
| // Query for wlanphy info |
| void Query(wlanphy_impl_info_t* out_info); |
| |
| // Interfaces to set and get chanspec iovar in sim-fw |
| void SetChanspec(bool is_ap_iface, uint16_t* chanspec, zx_status_t expect_result); |
| uint16_t GetChanspec(bool is_ap_iface, zx_status_t expect_result); |
| |
| protected: |
| struct AssocContext { |
| // Information about the BSS we are attempting to associate with. Used to generate the |
| // appropriate MLME calls (Join => Auth => Assoc). |
| wlan_channel_t channel = kDefaultChannel; |
| common::MacAddr bssid = kDefaultBssid; |
| wlan_ssid_t ssid = kDefaultSsid; |
| |
| // There should be one result for each association response received |
| std::list<wlan_assoc_result_t> expected_results; |
| |
| // Track number of association responses |
| size_t assoc_resp_count; |
| }; |
| |
| struct AssocRespInfo { |
| wlan_channel_t channel; |
| common::MacAddr src; |
| common::MacAddr dst; |
| uint16_t status; |
| }; |
| |
| SimInterface client_ifc_; |
| SimInterface softap_ifc_; |
| |
| AssocContext context_; |
| // Keep track of the APs that are in operation so we can easily disable beaconing on all of them |
| // at the end of each test. |
| std::list<simulation::FakeAp*> aps_; |
| |
| // All of the association responses seen in the environment |
| std::list<AssocRespInfo> assoc_responses_; |
| |
| bool deauth_ind_recv_ = false; |
| |
| private: |
| bool auth_ind_recv_ = false; |
| bool assoc_ind_recv_ = false; |
| uint16_t new_channel_; |
| bool chan_ind_recv_ = false; |
| // StationIfc overrides |
| void Rx(std::shared_ptr<const simulation::SimFrame> frame, |
| std::shared_ptr<const simulation::WlanRxInfo> info) override; |
| |
| // SME callbacks |
| static wlanif_impl_ifc_protocol_ops_t sme_ops_; |
| wlanif_impl_ifc_protocol sme_protocol_ = {.ops = &sme_ops_, .ctx = this}; |
| |
| // Event handlers |
| void OnJoinConf(const wlanif_join_confirm_t* resp); |
| void OnAuthConf(const wlanif_auth_confirm_t* resp); |
| void OnAssocConf(const wlanif_assoc_confirm_t* resp); |
| void OnAuthInd(const wlanif_auth_ind_t* ind); |
| void OnDeauthInd(const wlanif_deauth_indication_t* ind); |
| void OnAssocInd(const wlanif_assoc_ind_t* ind); |
| void OnChannelSwitch(const wlanif_channel_switch_info_t* info); |
| }; |
| |
| // Since we're acting as wlanif, we need handlers for any protocol calls we may receive |
| wlanif_impl_ifc_protocol_ops_t DynamicIfTest::sme_ops_ = { |
| .join_conf = |
| [](void* cookie, const wlanif_join_confirm_t* resp) { |
| static_cast<DynamicIfTest*>(cookie)->OnJoinConf(resp); |
| }, |
| .auth_conf = |
| [](void* cookie, const wlanif_auth_confirm_t* resp) { |
| static_cast<DynamicIfTest*>(cookie)->OnAuthConf(resp); |
| }, |
| .auth_ind = |
| [](void* cookie, const wlanif_auth_ind_t* ind) { |
| static_cast<DynamicIfTest*>(cookie)->OnAuthInd(ind); |
| }, |
| .deauth_ind = |
| [](void* cookie, const wlanif_deauth_indication_t* ind) { |
| static_cast<DynamicIfTest*>(cookie)->OnDeauthInd(ind); |
| }, |
| .assoc_conf = |
| [](void* cookie, const wlanif_assoc_confirm_t* resp) { |
| static_cast<DynamicIfTest*>(cookie)->OnAssocConf(resp); |
| }, |
| .assoc_ind = |
| [](void* cookie, const wlanif_assoc_ind_t* ind) { |
| static_cast<DynamicIfTest*>(cookie)->OnAssocInd(ind); |
| }, |
| .disassoc_ind = [](void* cookie, const wlanif_disassoc_indication_t* ind) {}, |
| .start_conf = |
| [](void* cookie, const wlanif_start_confirm_t* resp) { |
| ASSERT_EQ(resp->result_code, WLAN_START_RESULT_SUCCESS); |
| }, |
| .stop_conf = |
| [](void* cookie, const wlanif_stop_confirm_t* resp) { |
| ASSERT_EQ(resp->result_code, WLAN_STOP_RESULT_SUCCESS); |
| }, |
| .on_channel_switch = |
| [](void* cookie, const wlanif_channel_switch_info_t* info) { |
| static_cast<DynamicIfTest*>(cookie)->OnChannelSwitch(info); |
| }, |
| .signal_report = [](void* cookie, const wlanif_signal_report_indication* ind) {}, |
| }; |
| |
| zx_status_t DynamicIfTest::CreateInterface(wlan_info_mac_role_t role, |
| std::optional<common::MacAddr> mac_addr) { |
| if (role == WLAN_INFO_MAC_ROLE_CLIENT) { |
| return SimTest::StartInterface(role, &client_ifc_, &sme_protocol_, mac_addr); |
| } else { |
| return SimTest::StartInterface(role, &softap_ifc_, &sme_protocol_, mac_addr); |
| } |
| } |
| |
| void DynamicIfTest::DeleteInterface(wlan_info_mac_role_t role) { |
| uint32_t iface_id; |
| |
| if (role == WLAN_INFO_MAC_ROLE_CLIENT) |
| iface_id = client_ifc_.iface_id_; |
| else |
| iface_id = softap_ifc_.iface_id_; |
| SimTest::DeleteInterface(iface_id); |
| } |
| |
| void DynamicIfTest::Query(wlanphy_impl_info_t* out_info) { |
| zx_status_t status; |
| status = device_->WlanphyImplQuery(out_info); |
| ASSERT_EQ(status, ZX_OK); |
| } |
| |
| uint32_t DynamicIfTest::DeviceCount() { return (dev_mgr_->DeviceCount()); } |
| |
| void DynamicIfTest::StartSoftAP() { |
| wlanif_start_req_t start_req = { |
| .ssid = {.len = 6, .data = "Sim_AP"}, |
| .bss_type = WLAN_BSS_TYPE_INFRASTRUCTURE, |
| .beacon_period = 100, |
| .dtim_period = 100, |
| .channel = kDefaultCh, |
| }; |
| softap_ifc_.if_impl_ops_->start_req(softap_ifc_.if_impl_ctx_, &start_req); |
| } |
| |
| void DynamicIfTest::StopSoftAP() { |
| wlanif_stop_req_t stop_req{ |
| .ssid = {.len = 6, .data = "Sim_AP"}, |
| }; |
| softap_ifc_.if_impl_ops_->stop_req(softap_ifc_.if_impl_ctx_, &stop_req); |
| } |
| |
| void DynamicIfTest::InjectStopAPError() { |
| brcmf_simdev* sim = device_->GetSim(); |
| sim->sim_fw->err_inj_.AddErrInjIovar("bss", ZX_ERR_IO, softap_ifc_.iface_id_); |
| } |
| |
| void DynamicIfTest::ChannelCheck() { |
| uint16_t softap_chanspec = GetChanspec(true, ZX_OK); |
| uint16_t client_chanspec = GetChanspec(false, ZX_OK); |
| EXPECT_EQ(softap_chanspec, client_chanspec); |
| brcmf_simdev* sim = device_->GetSim(); |
| wlan_channel_t chan; |
| sim->sim_fw->convert_chanspec_to_channel(softap_chanspec, &chan); |
| EXPECT_EQ(chan.primary, new_channel_); |
| } |
| |
| void DynamicIfTest::Rx(std::shared_ptr<const simulation::SimFrame> frame, |
| std::shared_ptr<const simulation::WlanRxInfo> info) { |
| ASSERT_EQ(frame->FrameType(), simulation::SimFrame::FRAME_TYPE_MGMT); |
| |
| auto mgmt_frame = std::static_pointer_cast<const simulation::SimManagementFrame>(frame); |
| if (mgmt_frame->MgmtFrameType() == simulation::SimManagementFrame::FRAME_TYPE_ASSOC_RESP) { |
| auto assoc_resp = std::static_pointer_cast<const simulation::SimAssocRespFrame>(mgmt_frame); |
| AssocRespInfo resp_info = {.channel = info->channel, |
| .src = assoc_resp->src_addr_, |
| .dst = assoc_resp->dst_addr_, |
| .status = assoc_resp->status_}; |
| assoc_responses_.push_back(resp_info); |
| } |
| } |
| |
| // Create our device instance and hook up the callbacks |
| void DynamicIfTest::Init() { |
| ASSERT_EQ(SimTest::Init(), ZX_OK); |
| context_.assoc_resp_count = 0; |
| // Schedule an event to stop the test. This is needed to stop any beaconing APs, since the test |
| // won't end until all events are processed. |
| SCHEDULE_CALL(kTestDuration, &DynamicIfTest::Finish, this); |
| } |
| |
| void DynamicIfTest::Finish() { |
| for (auto ap : aps_) { |
| ap->DisableBeacon(); |
| } |
| aps_.clear(); |
| } |
| |
| void DynamicIfTest::OnJoinConf(const wlanif_join_confirm_t* resp) { |
| // Send auth request |
| wlanif_auth_req_t auth_req; |
| std::memcpy(auth_req.peer_sta_address, context_.bssid.byte, ETH_ALEN); |
| auth_req.auth_type = WLAN_AUTH_TYPE_OPEN_SYSTEM; |
| auth_req.auth_failure_timeout = 1000; // ~1s (although value is ignored for now) |
| client_ifc_.if_impl_ops_->auth_req(client_ifc_.if_impl_ctx_, &auth_req); |
| } |
| |
| void DynamicIfTest::OnAuthConf(const wlanif_auth_confirm_t* resp) { |
| // Send assoc request |
| wlanif_assoc_req_t assoc_req = {.rsne_len = 0, .vendor_ie_len = 0}; |
| memcpy(assoc_req.peer_sta_address, context_.bssid.byte, ETH_ALEN); |
| client_ifc_.if_impl_ops_->assoc_req(client_ifc_.if_impl_ctx_, &assoc_req); |
| } |
| |
| void DynamicIfTest::OnAssocConf(const wlanif_assoc_confirm_t* resp) { |
| context_.assoc_resp_count++; |
| EXPECT_EQ(resp->result_code, context_.expected_results.front()); |
| context_.expected_results.pop_front(); |
| } |
| |
| void DynamicIfTest::StartAssoc() { |
| // Send join request |
| wlanif_join_req join_req = {}; |
| std::memcpy(join_req.selected_bss.bssid, context_.bssid.byte, ETH_ALEN); |
| join_req.selected_bss.ssid.len = context_.ssid.len; |
| memcpy(join_req.selected_bss.ssid.data, context_.ssid.ssid, WLAN_MAX_SSID_LEN); |
| join_req.selected_bss.chan = context_.channel; |
| client_ifc_.if_impl_ops_->join_req(client_ifc_.if_impl_ctx_, &join_req); |
| } |
| |
| void DynamicIfTest::TxAuthandAssocReq() { |
| // Get the mac address of the SoftAP |
| common::MacAddr soft_ap_mac; |
| softap_ifc_.GetMacAddr(&soft_ap_mac); |
| wlan_ssid_t ssid = {.len = 6, .ssid = "Sim_AP"}; |
| // Pass the auth stop for softAP iface before assoc. |
| simulation::SimAuthFrame auth_req_frame(kFakeMac, soft_ap_mac, 1, simulation::AUTH_TYPE_OPEN, |
| WLAN_STATUS_CODE_SUCCESS); |
| env_->Tx(auth_req_frame, kDefaultTxInfo, this); |
| simulation::SimAssocReqFrame assoc_req_frame(kFakeMac, soft_ap_mac, ssid); |
| env_->Tx(assoc_req_frame, kDefaultTxInfo, this); |
| } |
| |
| void DynamicIfTest::OnAssocInd(const wlanif_assoc_ind_t* ind) { |
| ASSERT_EQ(std::memcmp(ind->peer_sta_address, kFakeMac.byte, ETH_ALEN), 0); |
| assoc_ind_recv_ = true; |
| } |
| |
| void DynamicIfTest::OnChannelSwitch(const wlanif_channel_switch_info_t* info) { |
| new_channel_ = info->new_channel; |
| chan_ind_recv_ = true; |
| } |
| |
| void DynamicIfTest::OnAuthInd(const wlanif_auth_ind_t* ind) { |
| ASSERT_EQ(std::memcmp(ind->peer_sta_address, kFakeMac.byte, ETH_ALEN), 0); |
| auth_ind_recv_ = true; |
| } |
| |
| void DynamicIfTest::OnDeauthInd(const wlanif_deauth_indication_t* ind) { deauth_ind_recv_ = true; } |
| |
| void DynamicIfTest::VerifyAssocWithSoftAP() { |
| // Verify the event indications were received and |
| // the number of clients |
| ASSERT_EQ(assoc_ind_recv_, true); |
| ASSERT_EQ(auth_ind_recv_, true); |
| brcmf_simdev* sim = device_->GetSim(); |
| uint16_t num_clients = sim->sim_fw->GetNumClients(softap_ifc_.iface_id_); |
| ASSERT_EQ(num_clients, 1U); |
| } |
| |
| void DynamicIfTest::VerifyClientDisassoc(bool exp_value) { ASSERT_EQ(deauth_ind_recv_, exp_value); } |
| |
| void DynamicIfTest::SetChanspec(bool is_ap_iface, uint16_t* chanspec, zx_status_t expect_result) { |
| brcmf_simdev* sim = device_->GetSim(); |
| zx_status_t err = |
| sim->sim_fw->IovarsSet(is_ap_iface ? softap_ifc_.iface_id_ : client_ifc_.iface_id_, |
| "chanspec", chanspec, sizeof(uint16_t)); |
| EXPECT_EQ(err, expect_result); |
| } |
| |
| uint16_t DynamicIfTest::GetChanspec(bool is_ap_iface, zx_status_t expect_result) { |
| brcmf_simdev* sim = device_->GetSim(); |
| uint16_t chanspec; |
| zx_status_t err = |
| sim->sim_fw->IovarsGet(is_ap_iface ? softap_ifc_.iface_id_ : client_ifc_.iface_id_, |
| "chanspec", &chanspec, sizeof(uint16_t)); |
| EXPECT_EQ(err, expect_result); |
| return chanspec; |
| } |
| |
| TEST_F(DynamicIfTest, CreateDestroy) { |
| Init(); |
| ASSERT_EQ(CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT), ZX_OK); |
| DeleteInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| EXPECT_EQ(DeviceCount(), static_cast<size_t>(1)); |
| |
| ASSERT_EQ(CreateInterface(WLAN_INFO_MAC_ROLE_AP, kDefaultBssid), ZX_OK); |
| // Verify whether the default bssid is correctly set to sim-fw when creating softAP iface. |
| common::MacAddr soft_ap_mac; |
| softap_ifc_.GetMacAddr(&soft_ap_mac); |
| EXPECT_EQ(soft_ap_mac, kDefaultBssid); |
| |
| DeleteInterface(WLAN_INFO_MAC_ROLE_AP); |
| EXPECT_EQ(DeviceCount(), static_cast<size_t>(1)); |
| } |
| |
| // This test case verifies that starting an AP iface using the same MAC address as the existing |
| // client iface will return an error. |
| TEST_F(DynamicIfTest, CreateAPwithSameMacAsClient) { |
| Init(); |
| ASSERT_EQ(CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT), ZX_OK); |
| common::MacAddr client_mac; |
| client_ifc_.GetMacAddr(&client_mac); |
| |
| // Create AP iface with the same mac addr. |
| EXPECT_EQ(CreateInterface(WLAN_INFO_MAC_ROLE_AP, client_mac), ZX_ERR_ALREADY_EXISTS); |
| EXPECT_EQ(DeviceCount(), static_cast<size_t>(2)); |
| DeleteInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| EXPECT_EQ(DeviceCount(), static_cast<size_t>(1)); |
| } |
| |
| // This test verifies that if we want to create an client iface with the same MAC address as the |
| // pre-set one, no error will be returned. |
| TEST_F(DynamicIfTest, CreateClientwithPreAllocMac) { |
| Init(); |
| common::MacAddr pre_set_mac; |
| brcmf_simdev* sim = device_->GetSim(); |
| sim->sim_fw->IovarsGet(0, "cur_etheraddr", pre_set_mac.byte, ETH_ALEN); |
| EXPECT_EQ(CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT, pre_set_mac), ZX_OK); |
| EXPECT_EQ(DeviceCount(), static_cast<size_t>(2)); |
| DeleteInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| EXPECT_EQ(DeviceCount(), static_cast<size_t>(1)); |
| } |
| |
| TEST_F(DynamicIfTest, DualInterfaces) { |
| Init(); |
| CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| CreateInterface(WLAN_INFO_MAC_ROLE_AP); |
| EXPECT_EQ(DeviceCount(), static_cast<size_t>(3)); |
| |
| DeleteInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| DeleteInterface(WLAN_INFO_MAC_ROLE_AP); |
| EXPECT_EQ(DeviceCount(), static_cast<size_t>(1)); |
| } |
| |
| TEST_F(DynamicIfTest, QueryInfo) { |
| Init(); |
| CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| wlanphy_impl_info_t info = {}; |
| // Test brcmfmac supports simutaneous client ap operation |
| Query(&info); |
| EXPECT_NE(info.wlan_info.caps & WLAN_INFO_HARDWARE_CAPABILITY_SIMULTANEOUS_CLIENT_AP, |
| static_cast<size_t>(0)); |
| } |
| |
| // Start both client and SoftAP interfaces simultaneously and check if |
| // the client can associate to a FakeAP and a fake client can associate to the |
| // SoftAP. |
| TEST_F(DynamicIfTest, ConnectBothInterfaces) { |
| // Create our device instances |
| Init(); |
| CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| CreateInterface(WLAN_INFO_MAC_ROLE_AP); |
| |
| // Start our SoftAP |
| StartSoftAP(); |
| |
| // Start up our fake AP |
| simulation::FakeAp ap(env_.get(), kDefaultBssid, kDefaultSsid, kDefaultChannel); |
| ap.EnableBeacon(zx::msec(100)); |
| aps_.push_back(&ap); |
| |
| context_.expected_results.push_front(WLAN_ASSOC_RESULT_SUCCESS); |
| |
| // Associate to FakeAp |
| SCHEDULE_CALL(zx::msec(10), &DynamicIfTest::StartAssoc, this); |
| // Associate to SoftAP |
| SCHEDULE_CALL(zx::msec(100), &DynamicIfTest::TxAuthandAssocReq, this); |
| |
| env_->Run(); |
| |
| // Check if the client's assoc with FakeAP succeeded |
| EXPECT_EQ(context_.assoc_resp_count, 1U); |
| // Verify Assoc with SoftAP succeeded |
| VerifyAssocWithSoftAP(); |
| // TODO(karthikrish) Will add disassoc once support in SIM FW is available |
| } |
| |
| // Start both client and SoftAP interfaces simultaneously and check if |
| // stopping the AP, does not affect the client. |
| TEST_F(DynamicIfTest, StopAPDoesntAffectClientIF) { |
| // Create our device instances |
| Init(); |
| CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| CreateInterface(WLAN_INFO_MAC_ROLE_AP); |
| |
| // Start our SoftAP |
| StartSoftAP(); |
| |
| // Start up our fake AP |
| simulation::FakeAp ap(env_.get(), kDefaultBssid, kDefaultSsid, kDefaultChannel); |
| ap.EnableBeacon(zx::msec(100)); |
| aps_.push_back(&ap); |
| |
| context_.expected_results.push_front(WLAN_ASSOC_RESULT_SUCCESS); |
| |
| // Associate to FakeAp |
| SCHEDULE_CALL(zx::msec(10), &DynamicIfTest::StartAssoc, this); |
| // Associate to SoftAP |
| SCHEDULE_CALL(zx::msec(100), &DynamicIfTest::TxAuthandAssocReq, this); |
| |
| // Verify Assoc with SoftAP succeeded |
| SCHEDULE_CALL(zx::msec(150), &DynamicIfTest::VerifyAssocWithSoftAP, this); |
| SCHEDULE_CALL(zx::msec(160), &DynamicIfTest::StopSoftAP, this); |
| SCHEDULE_CALL(zx::msec(170), &DynamicIfTest::VerifyClientDisassoc, this, false); |
| env_->Run(); |
| |
| // Check if the client's assoc with FakeAP succeeded |
| EXPECT_EQ(context_.assoc_resp_count, 1U); |
| // Disassoc and other assoc scenarios are covered in assoc_test.cc |
| } |
| |
| // Start both client and SoftAP interfaces simultaneously and check if |
| // stopping the AP with iovar bss fail, brings down the client as well |
| // because C_DOWN is issued |
| TEST_F(DynamicIfTest, UsingCdownDisconnectsClient) { |
| // Create our device instances |
| Init(); |
| CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| CreateInterface(WLAN_INFO_MAC_ROLE_AP); |
| |
| // Start our SoftAP |
| StartSoftAP(); |
| |
| // Start up our fake AP |
| simulation::FakeAp ap(env_.get(), kDefaultBssid, kDefaultSsid, kDefaultChannel); |
| ap.EnableBeacon(zx::msec(100)); |
| aps_.push_back(&ap); |
| |
| context_.expected_results.push_front(WLAN_ASSOC_RESULT_SUCCESS); |
| InjectStopAPError(); |
| // Associate to FakeAp |
| SCHEDULE_CALL(zx::msec(10), &DynamicIfTest::StartAssoc, this); |
| // Associate to SoftAP |
| SCHEDULE_CALL(zx::msec(100), &DynamicIfTest::TxAuthandAssocReq, this); |
| |
| // Verify Assoc with SoftAP succeeded |
| SCHEDULE_CALL(zx::msec(150), &DynamicIfTest::VerifyAssocWithSoftAP, this); |
| SCHEDULE_CALL(zx::msec(200), &DynamicIfTest::StopSoftAP, this); |
| SCHEDULE_CALL(zx::msec(300), &DynamicIfTest::VerifyClientDisassoc, this, true); |
| env_->Run(); |
| |
| // Check if the client's assoc with FakeAP succeeded |
| EXPECT_EQ(context_.assoc_resp_count, 1U); |
| // Disassoc and other assoc scenarios are covered in assoc_test.cc |
| } |
| |
| TEST_F(DynamicIfTest, SetClientChanspecAfterAPStarted) { |
| // Create our device instances |
| Init(); |
| |
| uint16_t chanspec; |
| // Create softAP iface and start |
| CreateInterface(WLAN_INFO_MAC_ROLE_AP); |
| StartSoftAP(); |
| |
| // The chanspec of softAP iface should be set to default one. |
| chanspec = GetChanspec(true, ZX_OK); |
| EXPECT_EQ(chanspec, kDefaultChanspec); |
| |
| // After creating client iface and setting a different chanspec to it, chanspec of softAP will |
| // change as a result of this operation. |
| CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| chanspec = kTestChanspec; |
| SetChanspec(false, &chanspec, ZX_OK); |
| |
| // Confirm chanspec of AP is same as client |
| chanspec = GetChanspec(true, ZX_OK); |
| EXPECT_EQ(chanspec, kTestChanspec); |
| } |
| |
| TEST_F(DynamicIfTest, SetAPChanspecAfterClientCreated) { |
| // Create our device instances |
| Init(); |
| |
| // Create client iface and set chanspec |
| uint16_t chanspec = kTestChanspec; |
| CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| SetChanspec(false, &chanspec, ZX_OK); |
| |
| // Create and start softAP iface to and set another chanspec |
| CreateInterface(WLAN_INFO_MAC_ROLE_AP); |
| StartSoftAP(); |
| // When we call StartSoftAP, the kDefaultCh will be transformed into chanspec(in this case the |
| // value is 53397) and set to soffAP iface, but since there is already a client iface activated, |
| // that input chanspec will be ignored and set to client's chanspec. |
| chanspec = GetChanspec(true, ZX_OK); |
| EXPECT_EQ(chanspec, kTestChanspec); |
| |
| // Now if we set chanspec again to softAP when it already have a chanspec, this operation is |
| // silently rejected |
| chanspec = kTest1Chanspec; |
| SetChanspec(true, &chanspec, ZX_OK); |
| } |
| |
| // Start SoftAP after client assoc. SoftAP's channel should get set to |
| // client's channel |
| TEST_F(DynamicIfTest, CheckSoftAPChannel) { |
| // Create our device instances |
| Init(); |
| CreateInterface(WLAN_INFO_MAC_ROLE_CLIENT); |
| CreateInterface(WLAN_INFO_MAC_ROLE_AP); |
| |
| // Start up our fake AP |
| simulation::FakeAp ap(env_.get(), kDefaultBssid, kDefaultSsid, kDefaultChannel); |
| ap.EnableBeacon(zx::msec(100)); |
| aps_.push_back(&ap); |
| |
| context_.expected_results.push_front(WLAN_ASSOC_RESULT_SUCCESS); |
| |
| zx::duration delay = zx::msec(10); |
| // Associate to FakeAp |
| SCHEDULE_CALL(delay, &DynamicIfTest::StartAssoc, this); |
| // Start our SoftAP |
| delay += zx::msec(10); |
| SCHEDULE_CALL(delay, &DynamicIfTest::StartSoftAP, this); |
| |
| // Wait until SIM FW sends AP Start confirmation. This is set as a |
| // scheduled event to ensure test runs until AP Start confirmation is |
| // received. |
| delay += kStartAPConfDelay + zx::msec(10); |
| SCHEDULE_CALL(delay, &DynamicIfTest::ChannelCheck, this); |
| env_->Run(); |
| // ChannelCheck(); |
| } |
| } // namespace wlan::brcmfmac |