diff options
author | Kai Shi <kaishi@google.com> | 2020-02-11 22:13:36 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-02-11 22:13:36 +0000 |
commit | 83baec8531a4d5b7870190b71d2cceaad61d538b (patch) | |
tree | 0e39930ccec985b91c0e1ae97e579672cd67f144 | |
parent | 413d7e3aaf017a055f79f9066f8cc4a85cf4f1f6 (diff) | |
parent | 731bd94be0770dd9f6e84f3e573486c6e40e020d (diff) | |
download | wificond-83baec8531a4d5b7870190b71d2cceaad61d538b.tar.gz |
Merge "Parse nl80211 PHY attributes"
-rw-r--r-- | net/netlink_utils.cpp | 162 | ||||
-rw-r--r-- | net/netlink_utils.h | 25 | ||||
-rw-r--r-- | tests/netlink_utils_unittest.cpp | 71 |
3 files changed, 255 insertions, 3 deletions
diff --git a/net/netlink_utils.cpp b/net/netlink_utils.cpp index 41bb34e..b7d5ebb 100644 --- a/net/netlink_utils.cpp +++ b/net/netlink_utils.cpp @@ -37,6 +37,7 @@ using std::make_pair; using std::make_unique; using std::map; using std::move; +using std::pair; using std::string; using std::unique_ptr; using std::vector; @@ -57,6 +58,16 @@ uint32_t k5GHzFrequencyUpperBound = 5850; uint32_t k6GHzFrequencyLowerBound = 5925; uint32_t k6GHzFrequencyUpperBound = 7125; +constexpr uint8_t kHtMcsSetNumByte = 16; +constexpr uint8_t kVhtMcsSetNumByte = 8; +constexpr uint8_t kHeMcsSetNumByteMin = 4; +constexpr uint8_t kMaxStreams = 8; +constexpr uint8_t kVht160MhzBitMask = 0x4; +constexpr uint8_t kVht80p80MhzBitMask = 0x8; +constexpr uint8_t kHeCapPhyNumByte = 11; +constexpr uint8_t kHe160MhzBitMask = 0x8; +constexpr uint8_t kHe80p80MhzBitMask = 0x10; + bool IsExtFeatureFlagSet( const std::vector<uint8_t>& ext_feature_flags_bytes, enum nl80211_ext_feature_index ext_feature_flag) { @@ -421,7 +432,6 @@ bool NetlinkUtils::ParseBandInfo(const NL80211Packet* const packet, } *out_band_info = BandInfo(); - //TODO: b/144576344: Need to get also channel width, and #streams for (auto& band : bands) { NL80211NestedAttr freqs_attr(0); if (band.GetAttribute(NL80211_BAND_ATTR_FREQS, &freqs_attr)) { @@ -441,6 +451,7 @@ bool NetlinkUtils::ParseBandInfo(const NL80211Packet* const packet, out_band_info->is_80211ax_supported = true; } } + ParsePhyCapabilities(band, out_band_info); } return true; @@ -498,6 +509,155 @@ void NetlinkUtils::handleBandFreqAttributes(const NL80211NestedAttr& freqs_attr, } } +void NetlinkUtils::ParsePhyCapabilities(const NL80211NestedAttr& band, + BandInfo* out_band_info) { + ParseHtMcsSetAttribute(band, out_band_info); + ParseVhtMcsSetAttribute(band, out_band_info); + ParseHeMcsSetAttribute(band, out_band_info); + ParseVhtCapAttribute(band, out_band_info); + ParseHeCapAttribute(band, out_band_info); +} + +void NetlinkUtils::ParseHtMcsSetAttribute(const NL80211NestedAttr& band, + BandInfo* out_band_info) { + vector<uint8_t> ht_mcs_set; + if (!band.GetAttributeValue(NL80211_BAND_ATTR_HT_MCS_SET, &ht_mcs_set)) { + return; + } + if (ht_mcs_set.size() < kHtMcsSetNumByte) { + LOG(ERROR) << "HT MCS set size is incorrect"; + return; + } + pair<uint32_t, uint32_t> max_streams_ht = ParseHtMcsSet(ht_mcs_set); + out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams, + max_streams_ht.first); + out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams, + max_streams_ht.second); +} + +pair<uint32_t, uint32_t> NetlinkUtils::ParseHtMcsSet( + const vector<uint8_t>& ht_mcs_set) { + uint32_t max_rx_streams = 1; + for (int i = 4; i >= 1; i--) { + if (ht_mcs_set[i - 1] > 0) { + max_rx_streams = i; + break; + } + } + + uint32_t max_tx_streams = max_rx_streams; + uint8_t supported_tx_mcs_set = ht_mcs_set[12]; + uint8_t tx_mcs_set_defined = supported_tx_mcs_set & 0x1; + uint8_t tx_rx_mcs_set_not_equal = (supported_tx_mcs_set >> 1) & 0x1; + if (tx_mcs_set_defined && tx_rx_mcs_set_not_equal) { + uint8_t max_nss_tx_field_value = (supported_tx_mcs_set >> 2) & 0x3; + // The maximum number of Tx streams is 1 more than the field value. + max_tx_streams = max_nss_tx_field_value + 1; + } + + return std::make_pair(max_tx_streams, max_rx_streams); +} + +void NetlinkUtils::ParseVhtMcsSetAttribute(const NL80211NestedAttr& band, + BandInfo* out_band_info) { + vector<uint8_t> vht_mcs_set; + if (!band.GetAttributeValue(NL80211_BAND_ATTR_VHT_MCS_SET, &vht_mcs_set)) { + return; + } + if (vht_mcs_set.size() < kVhtMcsSetNumByte) { + LOG(ERROR) << "VHT MCS set size is incorrect"; + return; + } + uint16_t vht_mcs_set_rx = (vht_mcs_set[1] << 8) | vht_mcs_set[0]; + uint32_t max_rx_streams_vht = ParseMcsMap(vht_mcs_set_rx); + uint16_t vht_mcs_set_tx = (vht_mcs_set[5] << 8) | vht_mcs_set[4]; + uint32_t max_tx_streams_vht = ParseMcsMap(vht_mcs_set_tx); + out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams, + max_tx_streams_vht); + out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams, + max_rx_streams_vht); +} + +void NetlinkUtils::ParseHeMcsSetAttribute(const NL80211NestedAttr& band, + BandInfo* out_band_info) { + NL80211NestedAttr iftype_data_attr(0); + if (!band.GetAttribute(NL80211_BAND_ATTR_IFTYPE_DATA, &iftype_data_attr)) { + return; + } + vector<uint8_t> he_mcs_set; + if (!iftype_data_attr.GetAttributeValue( + NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, + &he_mcs_set)) { + return; + } + if (he_mcs_set.size() < kHeMcsSetNumByteMin) { + LOG(ERROR) << "HE MCS set size is incorrect"; + return; + } + uint16_t he_mcs_map_rx = (he_mcs_set[1] << 8) | he_mcs_set[0]; + uint32_t max_rx_streams_he = ParseMcsMap(he_mcs_map_rx); + uint16_t he_mcs_map_tx = (he_mcs_set[3] << 8) | he_mcs_set[2]; + uint32_t max_tx_streams_he = ParseMcsMap(he_mcs_map_tx); + out_band_info->max_tx_streams = std::max(out_band_info->max_tx_streams, + max_tx_streams_he); + out_band_info->max_rx_streams = std::max(out_band_info->max_rx_streams, + max_rx_streams_he); +} + +uint32_t NetlinkUtils::ParseMcsMap(uint16_t mcs_map) +{ + uint32_t max_nss = 1; + for (int i = kMaxStreams; i >= 1; i--) { + uint16_t stream_map = (mcs_map >> ((i - 1) * 2)) & 0x3; + // 0x3 means unsupported + if (stream_map != 0x3) { + max_nss = i; + break; + } + } + return max_nss; +} + +void NetlinkUtils::ParseVhtCapAttribute(const NL80211NestedAttr& band, + BandInfo* out_band_info) { + uint32_t vht_cap; + if (!band.GetAttributeValue(NL80211_BAND_ATTR_VHT_CAPA, &vht_cap)) { + return; + } + + if (vht_cap & kVht160MhzBitMask) { + out_band_info->is_160_mhz_supported = true; + } + if (vht_cap & kVht80p80MhzBitMask) { + out_band_info->is_80p80_mhz_supported = true; + } +} + +void NetlinkUtils::ParseHeCapAttribute(const NL80211NestedAttr& band, + BandInfo* out_band_info) { + NL80211NestedAttr iftype_data_attr(0); + if (!band.GetAttribute(NL80211_BAND_ATTR_IFTYPE_DATA, &iftype_data_attr)) { + return; + } + vector<uint8_t> he_cap_phy; + if (!iftype_data_attr.GetAttributeValue( + NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, + &he_cap_phy)) { + return; + } + + if (he_cap_phy.size() < kHeCapPhyNumByte) { + LOG(ERROR) << "HE Cap PHY size is incorrect"; + return; + } + if (he_cap_phy[0] & kHe160MhzBitMask) { + out_band_info->is_160_mhz_supported = true; + } + if (he_cap_phy[0] & kHe80p80MhzBitMask) { + out_band_info->is_80p80_mhz_supported = true; + } +} + bool NetlinkUtils::GetStationInfo(uint32_t interface_index, const array<uint8_t, ETH_ALEN>& mac_address, StationInfo* out_station_info) { diff --git a/net/netlink_utils.h b/net/netlink_utils.h index 938ed28..d214f94 100644 --- a/net/netlink_utils.h +++ b/net/netlink_utils.h @@ -50,7 +50,14 @@ struct InterfaceInfo { }; struct BandInfo { - BandInfo() = default; + BandInfo(): + is_80211n_supported(false), + is_80211ac_supported(false), + is_80211ax_supported(false), + is_160_mhz_supported(false), + is_80p80_mhz_supported(false), + max_tx_streams(1), + max_rx_streams(1) {}; // Frequencies for 2.4 GHz band. std::vector<uint32_t> band_2g; // Frequencies for 5 GHz band without DFS. @@ -290,6 +297,22 @@ class NetlinkUtils { WiphyFeatures* out_wiphy_features); bool ParseBandInfo(const NL80211Packet* const packet, BandInfo* out_band_info); + void ParsePhyCapabilities(const NL80211NestedAttr& band, + BandInfo* out_band_info); + void ParseHtMcsSetAttribute(const NL80211NestedAttr& band, + BandInfo* out_band_info); + void ParseVhtMcsSetAttribute(const NL80211NestedAttr& band, + BandInfo* out_band_info); + void ParseHeMcsSetAttribute(const NL80211NestedAttr& band, + BandInfo* out_band_info); + std::pair<uint32_t, uint32_t> ParseHtMcsSet( + const std::vector<uint8_t>& ht_mcs_set); + uint32_t ParseMcsMap(uint16_t mcs_map); + void ParseVhtCapAttribute(const NL80211NestedAttr& band, + BandInfo* out_band_info); + void ParseHeCapAttribute(const NL80211NestedAttr& band, + BandInfo* out_band_info); + bool ParseScanCapabilities(const NL80211Packet* const packet, ScanCapabilities* out_scan_capabilities); diff --git a/tests/netlink_utils_unittest.cpp b/tests/netlink_utils_unittest.cpp index 34f5c21..316eea4 100644 --- a/tests/netlink_utils_unittest.cpp +++ b/tests/netlink_utils_unittest.cpp @@ -75,7 +75,19 @@ const uint8_t kFakeExtFeaturesForLowPowerScan[] = {0x0, 0x0, 0x80}; const uint8_t kFakeExtFeaturesForHighAccuracy[] = {0x0, 0x0, 0x0, 0x1}; const uint8_t kFakeExtFeaturesForAllScanType[] = {0x0, 0x0, 0xC0, 0x1}; const uint8_t kFakeFrame[] = {0x00, 0x01, 0x02, 0x03}; - +constexpr bool k11nSupported = true; +constexpr bool k11acSupported = true; +constexpr bool k11axSupported = true; +constexpr uint8_t kMaxTxStreams = 4; +constexpr uint8_t kMaxRxStreams = 5; +constexpr bool k160MHzSupported = true; +constexpr bool k80p80MHzSupported = false; +const uint8_t kHtMcsSet[] = {0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0}; +const uint8_t kVhtMcsSet[] = {0xaa, 0xfe, 0xff, 0xff, 0xaa, 0xff, 0xff, 0xff}; +const uint8_t kHeMcsSet[] = {0xaa, 0xfe, 0xaa, 0xff}; +const uint8_t kVhtCap[] = {0x4, 0x0, 0x0, 0x0}; +const uint8_t kHeCapPhy[] = {0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; // Currently, control messages are only created by the kernel and sent to us. // Therefore NL80211Packet doesn't have corresponding constructor. @@ -121,6 +133,53 @@ void AppendScanCapabilitiesAttributes(NL80211Packet* packet, } } + +NL80211Attr<std::vector<uint8_t>> GenerateBandsAttributeForHtCapa() { + std::vector<uint8_t> ht_cap(2, 0); + return NL80211Attr<std::vector<uint8_t>>(NL80211_BAND_ATTR_HT_CAPA, + ht_cap); +} + + +NL80211Attr<std::vector<uint8_t>> GenerateBandsAttributeForVhtCapa() { + std::vector<uint8_t> vht_cap(kVhtCap, kVhtCap + sizeof(kVhtCap)); + return NL80211Attr<std::vector<uint8_t>>(NL80211_BAND_ATTR_VHT_CAPA, + vht_cap); +} + +NL80211Attr<std::vector<uint8_t>> GenerateBandsAttributeForHtMcsSet() { + std::vector<uint8_t> ht_mcs_set(kHtMcsSet, kHtMcsSet + sizeof(kHtMcsSet)); + return NL80211Attr<std::vector<uint8_t>>(NL80211_BAND_ATTR_HT_MCS_SET, + ht_mcs_set); +} + +NL80211Attr<std::vector<uint8_t>> GenerateBandsAttributeForVhtMcsSet() { + std::vector<uint8_t> vht_mcs_set(kVhtMcsSet, kVhtMcsSet + sizeof(kVhtMcsSet)); + return NL80211Attr<std::vector<uint8_t>>(NL80211_BAND_ATTR_VHT_MCS_SET, + vht_mcs_set); +} + +NL80211NestedAttr GenerateBandsAttributeForIfTypeData() { + NL80211NestedAttr if_type_data(NL80211_BAND_ATTR_IFTYPE_DATA); + std::vector<uint8_t> he_cap_phy(kHeCapPhy, kHeCapPhy + sizeof(kHeCapPhy)); + std::vector<uint8_t> he_mcs_set(kHeMcsSet, kHeMcsSet + sizeof(kHeMcsSet)); + + if_type_data.AddAttribute(NL80211Attr<std::vector<uint8_t>>( + NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, he_cap_phy)); + if_type_data.AddAttribute(NL80211Attr<std::vector<uint8_t>>( + NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, he_mcs_set)); + return if_type_data; +} + +void AppendBandPhyAttributes(NL80211NestedAttr* band_attr) { + band_attr->AddAttribute(GenerateBandsAttributeForHtCapa()); + band_attr->AddAttribute(GenerateBandsAttributeForHtMcsSet()); + band_attr->AddAttribute(GenerateBandsAttributeForVhtCapa()); + band_attr->AddAttribute(GenerateBandsAttributeForVhtMcsSet()); + + band_attr->AddAttribute(GenerateBandsAttributeForIfTypeData()); +} + NL80211NestedAttr GenerateBandsAttributeFor2g() { NL80211NestedAttr freq_2g_1(1); NL80211NestedAttr freq_2g_2(2); @@ -139,6 +198,7 @@ NL80211NestedAttr GenerateBandsAttributeFor2g() { NL80211NestedAttr band_2g_attr(1); band_2g_attr.AddAttribute(band_2g_freqs); + AppendBandPhyAttributes(&band_2g_attr); NL80211NestedAttr band_attr(NL80211_ATTR_WIPHY_BANDS); band_attr.AddAttribute(band_2g_attr); @@ -177,6 +237,7 @@ NL80211NestedAttr GenerateBandsAttributeFor5gAndDfs() { NL80211NestedAttr band_5g_attr(1); band_5g_attr.AddAttribute(band_5g_freqs); + AppendBandPhyAttributes(&band_5g_attr); NL80211NestedAttr band_attr(NL80211_ATTR_WIPHY_BANDS); band_attr.AddAttribute(band_5g_attr); @@ -187,6 +248,7 @@ void AppendBandInfoAttributes(NL80211Packet* packet) { NL80211NestedAttr attr_2g = GenerateBandsAttributeFor2g(); NL80211NestedAttr attr_5g_and_dfs = GenerateBandsAttributeFor5gAndDfs(); attr_2g.Merge(attr_5g_and_dfs); + packet->AddAttribute(attr_2g); } @@ -267,6 +329,13 @@ void VerifyBandInfo(const BandInfo& band_info) { EXPECT_EQ(band_info.band_2g, band_2g_expected); EXPECT_EQ(band_info.band_5g, band_5g_expected); EXPECT_EQ(band_info.band_dfs, band_dfs_expected); + EXPECT_EQ(band_info.is_80211n_supported, k11nSupported); + EXPECT_EQ(band_info.is_80211ac_supported, k11acSupported); + EXPECT_EQ(band_info.is_80211ax_supported, k11axSupported); + EXPECT_EQ(band_info.is_160_mhz_supported, k160MHzSupported); + EXPECT_EQ(band_info.is_80p80_mhz_supported, k80p80MHzSupported); + EXPECT_EQ(band_info.max_tx_streams, kMaxTxStreams); + EXPECT_EQ(band_info.max_rx_streams, kMaxRxStreams); } void VerifyWiphyFeatures(const WiphyFeatures& wiphy_features) { |