blob: 3e20fd1ce49d2e27f6d2c4a0349144becadcbc8d [file] [log] [blame]
// Copyright 2020 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 <fuchsia/hardware/wlanif/c/banjo.h>
#include <zircon/errors.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/macaddr.h"
namespace wlan::brcmfmac {
namespace {
constexpr zx::duration kSimulatedClockDuration = zx::sec(10);
} // namespace
// Some default AP and association request values
constexpr wlan_channel_t kDefaultChannel = {
.primary = 9, .cbw = WLAN_CHANNEL_BANDWIDTH__20, .secondary80 = 0};
constexpr wlan_ssid_t kDefaultSsid = {.len = 15, .ssid = "Fuchsia Fake AP"};
const common::MacAddr kDefaultBssid({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc});
const common::MacAddr kSecondBssid({0x12, 0x34, 0x56, 0x78, 0x9b, 0xbd});
const common::MacAddr kMadeupClient({0xde, 0xad, 0xbe, 0xef, 0x00, 0x01});
struct ClientIfc : public SimInterface {
void OnDeauthInd(const wlanif_deauth_indication_t* ind) override;
// Once test is finished, associations and disassociations from teardowns are ignored
bool test_complete_ = false;
};
class BeaconLostTest : 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);
void Init();
void Finish();
// Move client's location in environment
void MoveClient(int32_t x, int32_t y);
protected:
// This is the interface we will use for our single client interface
ClientIfc client_ifc_;
// 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_;
};
// Ignore any deauth indications that are received during teardown
void ClientIfc::OnDeauthInd(const wlanif_deauth_indication_t* ind) {
if (!test_complete_) {
SimInterface::OnDeauthInd(ind);
}
}
// Create our device instance and hook up the callbacks
void BeaconLostTest::Init() {
ASSERT_EQ(SimTest::Init(), ZX_OK);
ASSERT_EQ(StartInterface(WLAN_INFO_MAC_ROLE_CLIENT, &client_ifc_), ZX_OK);
env_->ScheduleNotification(std::bind(&BeaconLostTest::Finish, this), kTestDuration);
}
void BeaconLostTest::Finish() {
for (auto ap : aps_) {
ap->DisableBeacon();
}
aps_.clear();
client_ifc_.test_complete_ = true;
}
// Move the client (not the test)
void BeaconLostTest::MoveClient(int32_t x, int32_t y) {
env_->MoveStation(device_->GetSim()->sim_fw->GetHardwareIfc(), x, y);
}
// Verify that deauthorization occurs if associated AP's beacons disappear
TEST_F(BeaconLostTest, NoBeaconDisassocTest) {
// Create our device instance
Init();
// Start up fake AP
simulation::FakeAp ap(env_.get(), kDefaultBssid, kDefaultSsid, kDefaultChannel);
ap.EnableBeacon(zx::msec(100));
// Associate with fake AP
client_ifc_.AssociateWith(ap, zx::msec(10));
// disable the beacon after association
env_->ScheduleNotification(std::bind(&simulation::FakeAp::DisableBeacon, &ap), zx::sec(1));
env_->Run(kSimulatedClockDuration);
// Association with fake AP should be successful
EXPECT_EQ(client_ifc_.stats_.assoc_successes, 1U);
// A disassociation should have occured due a beacon timeout
EXPECT_EQ(client_ifc_.stats_.disassoc_indications.size(), 1U);
}
// Verify that deauthorization occurs after moving away from associated AP
// such that beacon is lost
// t = 0s
// +-------------------------------------------------+
// ap-client-----------------------------------------+
// +-------------------------------------------------+
// t = 1s
// +-------------------------------------------------+
// ap1-----------------------------------------client+
// +-------------------------------------------------+
TEST_F(BeaconLostTest, BeaconTooFarDisassocTest) {
// Create our device instance
Init();
// Start up fake AP
simulation::FakeAp ap(env_.get(), kDefaultBssid, kDefaultSsid, kDefaultChannel);
ap.EnableBeacon(zx::msec(100));
aps_.push_back(&ap);
// Associate with fake AP
client_ifc_.AssociateWith(ap, zx::msec(10));
// Move away from the AP
env_->ScheduleNotification(std::bind(&BeaconLostTest::MoveClient, this, 150, 0), zx::sec(1));
env_->Run(kSimulatedClockDuration);
// Association with fake AP should be successful
EXPECT_EQ(client_ifc_.stats_.assoc_successes, 1U);
// A disassociation should have occured due to moving away from the AP
ASSERT_EQ(client_ifc_.stats_.disassoc_indications.size(), 1U);
auto disassoc_ind = *client_ifc_.stats_.disassoc_indications.begin();
EXPECT_TRUE(disassoc_ind.locally_initiated);
}
// Verify that losing a beacon from an unassociated ap does not cause any disassociation
// t = 0s
// +-------------------------------------------------+
// -------ap1------------client-------------------ap2+
// +-------------------------------------------------+
// t = 1s
// +-------------------------------------------------+
// client-ap1-------------------------------------ap2+
// +-------------------------------------------------+
TEST_F(BeaconLostTest, WrongBeaconLossTest) {
// Create our device instance
Init();
// Start up fake AP
simulation::FakeAp ap1(env_.get(), kDefaultBssid, kDefaultSsid, kDefaultChannel);
ap1.EnableBeacon(zx::msec(100));
constexpr wlan_ssid_t kWrongSsid = {.len = 14, .ssid = "Fuchsia Fake AP"};
ASSERT_NE(kDefaultSsid.len, kWrongSsid.len);
env_->MoveStation(&ap1, -50, 0);
aps_.push_back(&ap1);
simulation::FakeAp ap2(env_.get(), kSecondBssid, kWrongSsid, kDefaultChannel);
ap2.EnableBeacon(zx::msec(100));
env_->MoveStation(&ap2, 50, 0);
aps_.push_back(&ap2);
// Will associate with one AP
client_ifc_.AssociateWith(ap1, zx::msec(10));
// Move away closer to the AP we are associated to. Should not impact connection.
env_->ScheduleNotification(std::bind(&BeaconLostTest::MoveClient, this, -75, 0), zx::sec(1));
env_->Run(kSimulatedClockDuration);
// Association with fake AP should be successful
EXPECT_EQ(client_ifc_.stats_.assoc_successes, 1U);
// No disassociation should occur
EXPECT_EQ(client_ifc_.stats_.deauth_indications.size(), 0U);
}
// Verify that moving out of range of the beacon for a small duration does not cause a deauth
// t = 0s
// +-------------------------------------------------+
// ap1-client----------------------------------------+
// +-------------------------------------------------+
// t = 1s
// +-------------------------------------------------+
// ap1-------------------client----------------------+
// +-------------------------------------------------+
// t = 2s
// +-------------------------------------------------+
// ap1-client----------------------------------------+
// +-------------------------------------------------+
TEST_F(BeaconLostTest, TempBeaconLossTest) {
// Create our device instance
Init();
// Start up fake AP
simulation::FakeAp ap1(env_.get(), kDefaultBssid, kDefaultSsid, kDefaultChannel);
ap1.EnableBeacon(zx::msec(100));
constexpr wlan_ssid_t kWrongSsid = {.len = 14, .ssid = "Fuchsia Fake AP"};
ASSERT_NE(kDefaultSsid.len, kWrongSsid.len);
env_->MoveStation(&ap1, 0, 0);
aps_.push_back(&ap1);
// Will associate with one AP
client_ifc_.AssociateWith(ap1, zx::msec(10));
// Move away from the AP we are associated to.
env_->ScheduleNotification(std::bind(&BeaconLostTest::MoveClient, this, 100, 0), zx::sec(1));
// A second later, move back
env_->ScheduleNotification(std::bind(&BeaconLostTest::MoveClient, this, 0, 0), zx::sec(2));
env_->Run(kSimulatedClockDuration);
// Association with fake AP should be successful
EXPECT_EQ(client_ifc_.stats_.assoc_successes, 1U);
// No disassociation should occur
EXPECT_EQ(client_ifc_.stats_.deauth_indications.size(), 0U);
}
} // namespace wlan::brcmfmac