blob: 218564aa229ad3d90602980c38c7532ff09a52f6 [file] [log] [blame]
// Copyright 2018 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/write_element.h>
#include <wlan/mlme/wlan.h>
#include <gtest/gtest.h>
#include "test_utils.h"
namespace wlan {
namespace common {
struct Buf {
uint8_t data[128] = {};
BufferWriter w { data };
};
static bool equal(Span<const uint8_t> a, Span<const uint8_t> b) {
return std::equal(a.begin(), a.end(), b.begin(), b.end());
}
TEST(WriteElement, Ssid) {
const uint8_t ssid[] = { 'f', 'o', 'o' };
const uint8_t expected[] = { 0, 3, 'f', 'o', 'o' };
Buf buf;
WriteSsid(&buf.w, ssid);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, SupportedRates) {
SupportedRate rates[] = { SupportedRate(5, true), SupportedRate(20), SupportedRate(30) };
const uint8_t expected[] = { 1, 3, 0x85u, 20, 30 };
Buf buf;
WriteSupportedRates(&buf.w, rates);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, DsssParamSet) {
const uint8_t expected[] = { 3, 1, 11 };
Buf buf;
WriteDsssParamSet(&buf.w, 11);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, CfParamSet) {
const uint8_t expected[] = { 4, 6, 10, 20, 0x11, 0x22, 0x33, 0x44 };
Buf buf;
WriteCfParamSet(&buf.w, { 10, 20, 0x2211, 0x4433 });
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, Tim) {
const uint8_t expected[] = { 5, 8, 1, 2, 3, 10, 20, 30, 40, 50 };
Buf buf;
std::vector<uint8_t> bmp = { 10, 20, 30, 40, 50 };
TimHeader hdr;
hdr.dtim_count = 1;
hdr.dtim_period = 2;
hdr.bmp_ctrl = BitmapControl { 3u };
WriteTim(&buf.w, hdr, bmp);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, CountryPadded) {
const uint8_t expected[] = { 7, 10, 'A', 'B', 'C', 36, 1, 17, 100, 1, 17, 0 };
Buf buf;
SubbandTriplet subbands[] = {{ 36, 1, 17 }, { 100, 1, 17 }};
WriteCountry(&buf.w, {{'A', 'B', 'C'}}, subbands);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, CountryUnpadded) {
const uint8_t expected[] = { 7, 6, 'A', 'B', 'C', 36, 1, 17 };
Buf buf;
SubbandTriplet subbands[] = {{ 36, 1, 17 }};
WriteCountry(&buf.w, {{'A', 'B', 'C'}}, subbands);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, ExtendedSupportedRates) {
SupportedRate rates[] = { SupportedRate(10), SupportedRate(20), SupportedRate(30) };
const uint8_t expected[] = { 50, 3, 10, 20, 30 };
Buf buf;
WriteExtendedSupportedRates(&buf.w, rates);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, MeshConfiguration) {
const uint8_t expected[] = { 113, 7, 1, 1, 0, 1, 1, 0xCC, 0xF0 };
Buf buf;
const MeshConfiguration mesh_config = {MeshConfiguration::kHwmp,
MeshConfiguration::kAirtime,
MeshConfiguration::kCongestCtrlInactive,
MeshConfiguration::kNeighborOffsetSync,
MeshConfiguration::kSae,
MeshConfiguration::MeshFormationInfo { 0xCC },
MeshConfiguration::MeshCapability { 0xF0 }};
WriteMeshConfiguration(&buf.w, mesh_config);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, MeshId) {
const uint8_t expected[] = { 114, 3, 'f', 'o', 'o' };
Buf buf;
const uint8_t mesh_id[] = { 'f', 'o', 'o' };
WriteMeshId(&buf.w, mesh_id);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, QosCapability) {
const uint8_t expected[] = { 46, 1, 42 };
Buf buf;
WriteQosCapability(&buf.w, QosInfo { 42 });
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, GcrGroupAddress) {
const uint8_t expected[] = { 189, 6, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
Buf buf;
common::MacAddr mac_addr { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
WriteGcrGroupAddress(&buf.w, mac_addr);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, HtCapabilities) {
const uint8_t expected[] = { 45, 26,
0xaa, 0xbb, // ht cap info
0x55, // ampdu params
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, // mcs
0xdd, 0xee, // ext caps
0x11, 0x22, 0x33, 0x44, // beamforming
0x77 }; // asel
Buf buf;
HtCapabilities ht_caps = {
.ht_cap_info = HtCapabilityInfo { 0xbbaa },
.ampdu_params = AmpduParams { 0x55 },
.mcs_set = SupportedMcsSet {
.rx_mcs_head = SupportedMcsRxMcsHead { 0x0706050403020100ul },
.rx_mcs_tail = SupportedMcsRxMcsTail { 0x0b0a0908u },
.tx_mcs = SupportedMcsTxMcs { 0x0f0e0d0cu },
},
.ht_ext_cap = HtExtCapabilities { 0xeeddu },
.txbf_cap = TxBfCapability { 0x44332211u },
.asel_cap = AselCapability { 0x77 },
};
WriteHtCapabilities(&buf.w, ht_caps);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, HtOperation) {
const uint8_t expected[] = { 61, 22, 36, 0x11, 0x22, 0x33, 0x44, 0x55,
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf };
Buf buf;
HtOperation ht_op = {
.primary_chan = 36,
.head = HtOpInfoHead { 0x44332211u },
.tail = HtOpInfoTail { 0x55 },
.basic_mcs_set = SupportedMcsSet {
.rx_mcs_head = SupportedMcsRxMcsHead { 0x0706050403020100ul },
.rx_mcs_tail = SupportedMcsRxMcsTail { 0x0b0a0908u },
.tx_mcs = SupportedMcsTxMcs { 0x0f0e0d0cu },
},
};
WriteHtOperation(&buf.w, ht_op);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, VhtCapabilities) {
const uint8_t expected[] = { 191, 12, 0xaa, 0xbb, 0xcc, 0xdd,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
Buf buf;
VhtCapabilities caps = {
.vht_cap_info = VhtCapabilitiesInfo { 0xddccbbaau },
.vht_mcs_nss = VhtMcsNss { 0x8877665544332211ul },
};
WriteVhtCapabilities(&buf.w, caps);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, VhtOperation) {
const uint8_t expected[] = { 192, 5, 1, 155, 42, 0x33, 0x55 };
Buf buf;
VhtOperation vhtop = {
.vht_cbw = VhtOperation::VHT_CBW_80_160_80P80,
.center_freq_seg0 = 155,
.center_freq_seg1 = 42,
.basic_mcs = BasicVhtMcsNss { 0x5533 },
};
WriteVhtOperation(&buf.w, vhtop);
EXPECT_TRUE(equal(expected, buf.w.WrittenData()));
}
TEST(WriteElement, MpmOpenNoPmk) {
Buf buf;
WriteMpmOpen(&buf.w, MpmHeader { MpmHeader::AMPE, 0x4433u }, nullptr);
const uint8_t expected[6] = { 117, 4, 0x01, 0x00, 0x33, 0x44 };
EXPECT_RANGES_EQ(expected, buf.w.WrittenData());
}
TEST(WriteElement, MpmOpenWithPmk) {
Buf buf;
const MpmPmk pmk = {
.data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
};
WriteMpmOpen(&buf.w, MpmHeader { MpmHeader::AMPE, 0x4433u }, &pmk);
const uint8_t expected[22] = {
117, 20,
0x01, 0x00, 0x33, 0x44,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
};
EXPECT_RANGES_EQ(expected, buf.w.WrittenData());
}
TEST(WriteElement, MpmConfirmNoPmk) {
Buf buf;
WriteMpmConfirm(&buf.w, MpmHeader { MpmHeader::AMPE, 0x4433u }, 0x6655u, nullptr);
const uint8_t expected[8] = { 117, 6, 0x01, 0x00, 0x33, 0x44, 0x55, 0x66 };
EXPECT_RANGES_EQ(expected, buf.w.WrittenData());
}
TEST(WriteElement, MpmConfirmWithPmk) {
Buf buf;
const MpmPmk pmk = {
.data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
};
WriteMpmConfirm(&buf.w, MpmHeader { MpmHeader::AMPE, 0x4433u }, 0x6655u, &pmk);
const uint8_t expected[24] = {
117, 22,
0x01, 0x00, 0x33, 0x44, 0x55, 0x66,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
};
EXPECT_RANGES_EQ(expected, buf.w.WrittenData());
}
TEST(WriteElement, PreqMinimal) {
Buf buf;
WritePreq(
&buf.w,
PreqHeader {
.flags = {},
.hop_count = 0x01,
.element_ttl = 0x02,
.path_discovery_id = 0x06050403u,
.originator_addr = MacAddr("07:08:09:0a:0b:0c"),
.originator_hwmp_seqno = 0x100f0e0du,
},
nullptr,
PreqMiddle {
.lifetime = 0x1a191817u,
.metric = 0x1e1d1c1bu,
.target_count = 0x0,
},
{});
// clang-format off
const uint8_t expected[] = {
130, 17 + 9,
0x00, // flags
0x01, // hop count
0x02, // element ttl
0x03, 0x04, 0x05, 0x06, // path discovery ID
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, // originator addr
0x0d, 0x0e, 0x0f, 0x10, // originator hwmp seqno
0x17, 0x18, 0x19, 0x1a, // lifetime
0x1b, 0x1c, 0x1d, 0x1e, // metric
// Target count
0,
};
// clang-format on
EXPECT_RANGES_EQ(expected, buf.w.WrittenData());
}
TEST(WriteElement, PreqFull) {
PreqFlags flags;
flags.set_addr_ext(true);
MacAddr ext_addr("11:12:13:14:15:16");
PreqPerTarget per_target = {
.flags = {},
.target_addr = MacAddr("21:22:23:24:25:26"),
.target_hwmp_seqno = 0x2a292827u,
};
Buf buf;
WritePreq(
&buf.w,
PreqHeader {
.flags = flags,
.hop_count = 0x01,
.element_ttl = 0x02,
.path_discovery_id = 0x06050403u,
.originator_addr = MacAddr("07:08:09:0a:0b:0c"),
.originator_hwmp_seqno = 0x100f0e0du,
},
&ext_addr,
PreqMiddle {
.lifetime = 0x1a191817u,
.metric = 0x1e1d1c1bu,
.target_count = 0x1,
},
{ &per_target, 1 });
// clang-format off
const uint8_t expected[] = {
130, 17 + 6 + 9 + 11,
0x40, // flags: ext addr present
0x01, // hop count
0x02, // element ttl
0x03, 0x04, 0x05, 0x06, // path discovery ID
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, // originator addr
0x0d, 0x0e, 0x0f, 0x10, // originator hwmp seqno
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // ext addr
0x17, 0x18, 0x19, 0x1a, // lifetime
0x1b, 0x1c, 0x1d, 0x1e, // metric
// Target count
1,
0x00, // target 1 flags
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, // target 1 address
0x27, 0x28, 0x29, 0x2a, // target 1 hwmp seqno
};
// clang-format on
EXPECT_RANGES_EQ(expected, buf.w.WrittenData());
}
TEST(WriteElement, PrepNoExtAddr) {
Buf buf;
const PrepHeader header = {
.flags = PrepFlags(0x00),
.hop_count = 0x01,
.element_ttl = 0x02,
.target_addr = MacAddr("03:04:05:06:07:08"),
.target_hwmp_seqno = 0x0c0b0a09u,
};
const PrepTail tail = {
.lifetime = 0x100f0e0du,
.metric = 0x14131211u,
.originator_addr = MacAddr("15:16:17:18:19:1a"),
.originator_hwmp_seqno = 0x1e1d1c1bu,
};
WritePrep(&buf.w, header, nullptr, tail);
// clang-format off
const uint8_t expected[33] = {
131, 31,
0x00, 0x01, 0x02, // flags, hop count, elem ttl
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // target addr
0x09, 0x0a, 0x0b, 0x0c, // target hwmp seqno
0x0d, 0x0e, 0x0f, 0x10, // lifetime
0x11, 0x12, 0x13, 0x14, // metric
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, // originator addr
0x1b, 0x1c, 0x1d, 0x1e, // originator hwmp seqno
};
// clang-format on
EXPECT_RANGES_EQ(expected, buf.w.WrittenData());
}
TEST(WriteElement, PrepWithExtAddr) {
Buf buf;
const PrepHeader header = {
.flags = PrepFlags(0x00),
.hop_count = 0x01,
.element_ttl = 0x02,
.target_addr = MacAddr("03:04:05:06:07:08"),
.target_hwmp_seqno = 0x0c0b0a09u,
};
common::MacAddr ext_addr("44:55:66:77:88:99");
const PrepTail tail = {
.lifetime = 0x100f0e0du,
.metric = 0x14131211u,
.originator_addr = MacAddr("15:16:17:18:19:1a"),
.originator_hwmp_seqno = 0x1e1d1c1bu,
};
WritePrep(&buf.w, header, &ext_addr, tail);
// clang-format off
const uint8_t expected[39] = {
131, 37,
0x00, 0x01, 0x02, // flags, hop count, elem ttl
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // target addr
0x09, 0x0a, 0x0b, 0x0c, // target hwmp seqno
0x44, 0x55, 0x66, 0x77, 0x88, 0x99, // target external addr
0x0d, 0x0e, 0x0f, 0x10, // lifetime
0x11, 0x12, 0x13, 0x14, // metric
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, // originator addr
0x1b, 0x1c, 0x1d, 0x1e, // originator hwmp seqno
};
// clang-format on
EXPECT_RANGES_EQ(expected, buf.w.WrittenData());
}
} // namespace common
} // namespace wlan