blob: d0d558559428a4875d917243a4385fc571e92e04 [file] [log] [blame]
// Copyright 2017 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 <wlan/common/buffer_writer.h>
#include <wlan/common/write_element.h>
#include <wlan/mlme/mac_frame.h>
#include <wlan/mlme/wlan.h>
#include <gtest/gtest.h>
#include <algorithm>
#include <cstring>
#include <memory>
#include <utility>
namespace wlan {
namespace {
class Elements : public ::testing::Test {
protected:
Elements() { buf_offset_ = buf_; }
template <typename T> void add_to_buf(const T& value) {
memcpy(buf_offset_, &value, sizeof(value));
buf_offset_ += sizeof(value);
}
uint8_t* buf_offset_;
uint8_t buf_[1024] = {};
size_t actual_ = 0;
};
TEST_F(Elements, Tspec) {
// Values are chosen randomly.
constexpr uint8_t ts_info[3] = {97, 54, 13};
constexpr uint16_t nominal_msdu_size = 1068;
constexpr uint16_t max_msdu_size = 17223;
constexpr uint32_t min_svc_interval = 3463625064;
constexpr uint32_t max_svc_interval = 1348743544;
constexpr uint32_t inactivity_interval = 3254177988;
constexpr uint32_t suspension_interval = 3114872601;
constexpr uint32_t svc_start_time = 1977490251;
constexpr uint32_t min_data_rate = 2288957164;
constexpr uint32_t mean_data_rate = 3691476893;
constexpr uint32_t peak_data_rate = 3115603983;
constexpr uint32_t burst_size = 2196032537;
constexpr uint32_t delay_bound = 4120916503;
constexpr uint32_t min_phy_rate = 4071757759;
constexpr uint32_t surplus_bw_allowance = 12936;
constexpr uint32_t medium_time = 2196;
add_to_buf(ts_info);
add_to_buf<uint16_t>(nominal_msdu_size);
add_to_buf<uint16_t>(max_msdu_size);
add_to_buf<uint32_t>(min_svc_interval);
add_to_buf<uint32_t>(max_svc_interval);
add_to_buf<uint32_t>(inactivity_interval);
add_to_buf<uint32_t>(suspension_interval);
add_to_buf<uint32_t>(svc_start_time);
add_to_buf<uint32_t>(min_data_rate);
add_to_buf<uint32_t>(mean_data_rate);
add_to_buf<uint32_t>(peak_data_rate);
add_to_buf<uint32_t>(burst_size);
add_to_buf<uint32_t>(delay_bound);
add_to_buf<uint32_t>(min_phy_rate);
add_to_buf<uint16_t>(surplus_bw_allowance);
add_to_buf<uint16_t>(medium_time);
auto element = FromBytes<Tspec>(buf_, sizeof(buf_));
ASSERT_NE(nullptr, element);
EXPECT_EQ(element->nominal_msdu_size.size(), nominal_msdu_size);
EXPECT_EQ(element->nominal_msdu_size.fixed(), 0);
EXPECT_EQ(element->max_msdu_size, max_msdu_size);
EXPECT_EQ(element->min_service_interval, min_svc_interval);
EXPECT_EQ(element->max_service_interval, max_svc_interval);
EXPECT_EQ(element->inactivity_interval, inactivity_interval);
EXPECT_EQ(element->suspension_interval, suspension_interval);
EXPECT_EQ(element->service_start_time, svc_start_time);
EXPECT_EQ(element->min_data_rate, min_data_rate);
EXPECT_EQ(element->mean_data_rate, mean_data_rate);
EXPECT_EQ(element->peak_data_rate, peak_data_rate);
EXPECT_EQ(element->burst_size, burst_size);
EXPECT_EQ(element->delay_bound, delay_bound);
EXPECT_EQ(element->min_phy_rate, min_phy_rate);
EXPECT_EQ(element->surplus_bw_allowance, surplus_bw_allowance);
EXPECT_EQ(element->medium_time, medium_time);
}
TEST_F(Elements, TsInfoAggregation) {
TsInfo ts_info;
ts_info.p1.set_access_policy(TsAccessPolicy::kHccaSpca);
EXPECT_TRUE(ts_info.IsValidAggregation());
EXPECT_TRUE(ts_info.IsScheduleReserved());
ts_info.p1.set_access_policy(TsAccessPolicy::kEdca);
EXPECT_FALSE(ts_info.IsValidAggregation());
EXPECT_FALSE(ts_info.IsScheduleReserved());
ts_info.p2.set_schedule(1);
EXPECT_TRUE(ts_info.IsValidAggregation());
}
TEST_F(Elements, TsInfoScheduleSetting) {
TsInfo ts_info;
EXPECT_EQ(ts_info.GetScheduleSetting(), TsScheduleSetting::kNoSchedule);
ts_info.p1.set_apsd(1);
EXPECT_EQ(ts_info.GetScheduleSetting(), TsScheduleSetting::kUnschedledApsd);
ts_info.p1.set_apsd(0);
ts_info.p2.set_schedule(1);
EXPECT_EQ(ts_info.GetScheduleSetting(), TsScheduleSetting::kScheduledPsmp_GcrSp);
ts_info.p1.set_apsd(1);
EXPECT_EQ(ts_info.GetScheduleSetting(), TsScheduleSetting::kScheduledApsd);
}
TEST(HtCapabilities, DdkConversion) {
wlan_ht_caps_t ddk{
.ht_capability_info = 0x016e,
.ampdu_params = 0x17,
.mcs_set.rx_mcs_head = 0x00000001000000ff,
.mcs_set.rx_mcs_tail = 0x01000000,
.mcs_set.tx_mcs = 0x00000000,
.ht_ext_capabilities = 0x1234,
.tx_beamforming_capabilities = 0x12345678,
.asel_capabilities = 0xff,
};
auto ieee = HtCapabilities::FromDdk(ddk);
EXPECT_EQ(0x016eU, ieee.ht_cap_info.val());
EXPECT_EQ(0x17U, ieee.ampdu_params.val());
EXPECT_EQ(0x00000001000000ffU, ieee.mcs_set.rx_mcs_head.val());
EXPECT_EQ(0x01000000U, ieee.mcs_set.rx_mcs_tail.val());
EXPECT_EQ(0x00000000U, ieee.mcs_set.tx_mcs.val());
EXPECT_EQ(0x1234U, ieee.ht_ext_cap.val());
EXPECT_EQ(0x12345678U, ieee.txbf_cap.val());
EXPECT_EQ(0xffU, ieee.asel_cap.val());
auto ddk2 = ieee.ToDdk();
EXPECT_EQ(ddk.ht_capability_info, ddk2.ht_capability_info);
EXPECT_EQ(ddk.ampdu_params, ddk2.ampdu_params);
EXPECT_EQ(ddk.mcs_set.rx_mcs_head, ddk2.mcs_set.rx_mcs_head);
EXPECT_EQ(ddk.mcs_set.rx_mcs_tail, ddk2.mcs_set.rx_mcs_tail);
EXPECT_EQ(ddk.mcs_set.tx_mcs, ddk2.mcs_set.tx_mcs);
EXPECT_EQ(ddk.ht_ext_capabilities, ddk2.ht_ext_capabilities);
EXPECT_EQ(ddk.tx_beamforming_capabilities, ddk2.tx_beamforming_capabilities);
EXPECT_EQ(ddk.asel_capabilities, ddk2.asel_capabilities);
}
TEST(HtOperation, DdkConversion) {
wlan_ht_op ddk{
.primary_chan = 123,
.head = 0x01020304,
.tail = 0x05,
.basic_mcs_set.rx_mcs_head = 0x00000001000000ff,
.basic_mcs_set.rx_mcs_tail = 0x01000000,
.basic_mcs_set.tx_mcs = 0x00000000,
};
auto ieee = HtOperation::FromDdk(ddk);
EXPECT_EQ(123U, ieee.primary_chan);
EXPECT_EQ(0x01020304U, ieee.head.val());
EXPECT_EQ(0x05U, ieee.tail.val());
EXPECT_EQ(0x00000001000000ffU, ieee.basic_mcs_set.rx_mcs_head.val());
EXPECT_EQ(0x01000000U, ieee.basic_mcs_set.rx_mcs_tail.val());
EXPECT_EQ(0x00000000U, ieee.basic_mcs_set.tx_mcs.val());
auto ddk2 = ieee.ToDdk();
EXPECT_EQ(ddk.primary_chan, ddk2.primary_chan);
EXPECT_EQ(ddk.head, ddk2.head);
EXPECT_EQ(ddk.tail, ddk2.tail);
EXPECT_EQ(ddk.basic_mcs_set.rx_mcs_head, ddk2.basic_mcs_set.rx_mcs_head);
EXPECT_EQ(ddk.basic_mcs_set.rx_mcs_tail, ddk2.basic_mcs_set.rx_mcs_tail);
EXPECT_EQ(ddk.basic_mcs_set.tx_mcs, ddk2.basic_mcs_set.tx_mcs);
}
TEST(VhtCapabilities, DdkConversion) {
wlan_vht_caps ddk{
.vht_capability_info = 0xaabbccdd,
.supported_vht_mcs_and_nss_set = 0x0011223344556677,
};
auto ieee = VhtCapabilities::FromDdk(ddk);
EXPECT_EQ(0xaabbccddU, ieee.vht_cap_info.val());
EXPECT_EQ(0x0011223344556677U, ieee.vht_mcs_nss.val());
auto ddk2 = ieee.ToDdk();
EXPECT_EQ(ddk.vht_capability_info, ddk2.vht_capability_info);
EXPECT_EQ(ddk.supported_vht_mcs_and_nss_set, ddk2.supported_vht_mcs_and_nss_set);
}
TEST(VhtOperation, DdkConversion) {
wlan_vht_op ddk{
.vht_cbw = 0x01,
.center_freq_seg0 = 42,
.center_freq_seg1 = 106,
.basic_mcs = 0x1122,
};
auto ieee = VhtOperation::FromDdk(ddk);
EXPECT_EQ(0x01U, ieee.vht_cbw);
EXPECT_EQ(42U, ieee.center_freq_seg0);
EXPECT_EQ(106U, ieee.center_freq_seg1);
EXPECT_EQ(0x1122U, ieee.basic_mcs.val());
auto ddk2 = ieee.ToDdk();
EXPECT_EQ(ddk.vht_cbw, ddk2.vht_cbw);
EXPECT_EQ(ddk.center_freq_seg0, ddk2.center_freq_seg0);
EXPECT_EQ(ddk.center_freq_seg1, ddk2.center_freq_seg1);
EXPECT_EQ(ddk.basic_mcs, ddk2.basic_mcs);
}
TEST(SupportedRate, Create) {
SupportedRate rate = {};
ASSERT_EQ(rate.rate(), 0);
ASSERT_EQ(rate.is_basic(), 0);
// Create a rate with basic bit set.
rate = SupportedRate(0xF9);
ASSERT_EQ(rate.rate(), 0x79);
ASSERT_EQ(rate.is_basic(), 1);
// Create a rate with basic bit set but explicitly override basic setting.
rate = SupportedRate(0xF9, false);
ASSERT_EQ(rate.rate(), 0x79);
ASSERT_EQ(rate.is_basic(), 0);
// Create a rate with explicitly setting basic bit.
rate = SupportedRate::basic(0x79);
ASSERT_EQ(rate.rate(), 0x79);
ASSERT_EQ(rate.is_basic(), 1);
}
TEST(SupportedRate, ToUint8) {
SupportedRate rate = {};
ASSERT_EQ(static_cast<uint8_t>(rate), 0);
rate = SupportedRate(0xF9);
ASSERT_EQ(static_cast<uint8_t>(rate), 0xF9);
rate = SupportedRate::basic(0x79);
ASSERT_EQ(static_cast<uint8_t>(rate), 0xF9);
}
TEST(SupportedRate, Compare) {
// Ignore basic bit when comparing rates.
SupportedRate rate1(0x79);
SupportedRate rate2(0xF9);
ASSERT_TRUE(rate1 == rate2);
ASSERT_FALSE(rate1 != rate2);
ASSERT_FALSE(rate1 < rate2);
ASSERT_FALSE(rate1 > rate2);
// Test smaller.
rate1 = SupportedRate(0x78);
rate2 = SupportedRate(0xF9);
ASSERT_FALSE(rate1 == rate2);
ASSERT_TRUE(rate1 != rate2);
ASSERT_TRUE(rate1 < rate2);
ASSERT_FALSE(rate1 > rate2);
// Test larger.
rate1 = SupportedRate(0x7A);
rate2 = SupportedRate(0xF9);
ASSERT_FALSE(rate1 == rate2);
ASSERT_TRUE(rate1 != rate2);
ASSERT_FALSE(rate1 < rate2);
ASSERT_TRUE(rate1 > rate2);
}
struct RateVector {
std::vector<SupportedRate> ap;
std::vector<SupportedRate> client;
std::vector<SupportedRate> want;
};
TEST(Intersector, IntersectRates) {
// Rates are in 0.5Mbps increment: 12 -> 6 Mbps, 11 -> 5.5 Mbps, etc.
std::vector<RateVector> list = {
{{}, {}, {}},
{{SupportedRate(12)}, {SupportedRate(12)}, {SupportedRate(12)}},
{{SupportedRate::basic(12)}, {SupportedRate(12)}, {SupportedRate::basic(12)}},
{{SupportedRate(12)}, {SupportedRate::basic(12)}, {SupportedRate(12)}},
{{SupportedRate::basic(12)}, {}, {}},
{{}, {SupportedRate::basic(12)}, {}},
{{SupportedRate(12)}, {}, {}},
{{}, {SupportedRate(12)}, {}},
{{SupportedRate::basic(12), SupportedRate(24)},
{SupportedRate::basic(24), SupportedRate(12)},
{SupportedRate::basic(12), SupportedRate(24)}},
{{SupportedRate(24), SupportedRate::basic(12)},
{SupportedRate(12), SupportedRate::basic(24)},
{SupportedRate::basic(12), SupportedRate(24)}},
{{SupportedRate(72), SupportedRate::basic(108), SupportedRate::basic(96)},
{SupportedRate(96)},
{SupportedRate::basic(96)}},
{{SupportedRate(72), SupportedRate::basic(108), SupportedRate::basic(96)},
{SupportedRate::basic(72)},
{SupportedRate(72)}},
};
for (auto vec : list) {
auto got = IntersectRatesAp(vec.ap, vec.client);
EXPECT_EQ(vec.want, got);
for (size_t i = 0; i < got.size(); ++i) {
EXPECT_EQ(vec.want[i].val(), got[i].val());
}
}
}
} // namespace
} // namespace wlan