From b2323e584529d34769f7baa57dcc45ec6c6af7f4 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Wed, 19 Sep 2018 15:39:48 +0100 Subject: [PATCH] ibnetwork: Add command to show available VHT capabilities of phys Signed-off-by: Michael Tremer --- Makefile.am | 9 +- src/libnetwork/libnetwork.sym | 2 + src/libnetwork/network/phy.h | 23 ++++ src/libnetwork/phy.c | 177 +++++++++++++++++++++++++- src/utils/.gitignore | 1 + src/utils/network-phy-list-vht-caps.c | 61 +++++++++ 6 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 src/utils/network-phy-list-vht-caps.c diff --git a/Makefile.am b/Makefile.am index e40e3322..a295e379 100644 --- a/Makefile.am +++ b/Makefile.am @@ -296,7 +296,8 @@ EXTRA_DIST += \ # ------------------------------------------------------------------------------ util_PROGRAMS = \ - src/utils/network-phy-list-ht-caps + src/utils/network-phy-list-ht-caps \ + src/utils/network-phy-list-vht-caps src_utils_network_phy_list_ht_caps_SOURCES = \ src/utils/network-phy-list-ht-caps.c @@ -304,6 +305,12 @@ src_utils_network_phy_list_ht_caps_SOURCES = \ src_utils_network_phy_list_ht_caps_LDADD = \ src/libnetwork.la +src_utils_network_phy_list_vht_caps_SOURCES = \ + src/utils/network-phy-list-vht-caps.c + +src_utils_network_phy_list_vht_caps_LDADD = \ + src/libnetwork.la + # ------------------------------------------------------------------------------ ppp_SCRIPTS = \ diff --git a/src/libnetwork/libnetwork.sym b/src/libnetwork/libnetwork.sym index 0b6c90b8..3ae81e90 100644 --- a/src/libnetwork/libnetwork.sym +++ b/src/libnetwork/libnetwork.sym @@ -6,7 +6,9 @@ global: network_interface_unref; network_new; network_phy_has_ht_capability; + network_phy_has_vht_capability; network_phy_list_ht_capabilities; + network_phy_list_vht_capabilities; network_phy_new; network_phy_ref; network_phy_unref; diff --git a/src/libnetwork/network/phy.h b/src/libnetwork/network/phy.h index afa42d57..b33aee5e 100644 --- a/src/libnetwork/network/phy.h +++ b/src/libnetwork/network/phy.h @@ -49,6 +49,26 @@ enum network_phy_ht_caps { NETWORK_PHY_HT_CAP_LSIG_TXOP_PROT = (1 << 15), }; +enum network_phy_vht_caps { + NETWORK_PHY_VHT_CAP_VHT160 = (1 << 0), + NETWORK_PHY_VHT_CAP_VHT80PLUS80 = (1 << 1), + NETWORK_PHY_VHT_CAP_RX_LDPC = (1 << 2), + NETWORK_PHY_VHT_CAP_RX_SHORT_GI_80 = (1 << 3), + NETWORK_PHY_VHT_CAP_RX_SHORT_GI_160 = (1 << 4), + NETWORK_PHY_VHT_CAP_TX_STBC = (1 << 5), + NETWORK_PHY_VHT_CAP_SU_BEAMFORMER = (1 << 6), + NETWORK_PHY_VHT_CAP_SU_BEAMFORMEE = (1 << 7), + NETWORK_PHY_VHT_CAP_MU_BEAMFORMER = (1 << 8), + NETWORK_PHY_VHT_CAP_MU_BEAMFORMEE = (1 << 9), + NETWORK_PHY_VHT_CAP_TXOP_PS = (1 << 10), + NETWORK_PHY_VHT_CAP_HTC_VHT = (1 << 11), + NETWORK_PHY_VHT_CAP_RX_ANTENNA_PATTERN = (1 << 12), + NETWORK_PHY_VHT_CAP_TX_ANTENNA_PATTERN = (1 << 13), +}; + + +int network_phy_has_vht_capability(struct network_phy* phy, const enum network_phy_vht_caps cap); +char* network_phy_list_vht_capabilities(struct network_phy* phy); int network_phy_has_ht_capability(struct network_phy* phy, const enum network_phy_ht_caps cap); char* network_phy_list_ht_capabilities(struct network_phy* phy); @@ -60,6 +80,9 @@ char* network_phy_list_ht_capabilities(struct network_phy* phy); struct nl_msg* network_phy_make_netlink_message(struct network_phy* phy, enum nl80211_commands cmd, int flags); +#define foreach_vht_cap(cap) \ + for(int cap = NETWORK_PHY_VHT_CAP_VHT160; cap <= NETWORK_PHY_VHT_CAP_TX_ANTENNA_PATTERN; cap <<= 1) + #define foreach_ht_cap(cap) \ for(int cap = NETWORK_PHY_HT_CAP_RX_LDCP; cap != NETWORK_PHY_HT_CAP_LSIG_TXOP_PROT; cap <<= 1) diff --git a/src/libnetwork/phy.c b/src/libnetwork/phy.c index 6662eae4..b58ccc7c 100644 --- a/src/libnetwork/phy.c +++ b/src/libnetwork/phy.c @@ -39,6 +39,8 @@ struct network_phy { int index; char* name; + ssize_t max_mpdu_length; + unsigned int vht_caps; unsigned int ht_caps; }; @@ -65,6 +67,91 @@ static int phy_get_index(const char* name) { return atoi(index); } +static void phy_parse_vht_capabilities(struct network_phy* phy, __u32 caps) { + // Max MPDU length + switch (caps & 0x3) { + case 0: + phy->max_mpdu_length = 3895; + break; + + case 1: + phy->max_mpdu_length = 7991; + break; + + case 2: + phy->max_mpdu_length = 11454; + break; + + case 3: + phy->max_mpdu_length = -1; + } + + // Supported channel widths + switch ((caps >> 2) & 0x3) { + case 0: + break; + + // Supports 160 MHz + case 1: + phy->vht_caps |= NETWORK_PHY_VHT_CAP_VHT160; + break; + + // Supports 160 MHz and 80+80 MHz + case 2: + phy->vht_caps |= NETWORK_PHY_VHT_CAP_VHT160; + phy->vht_caps |= NETWORK_PHY_VHT_CAP_VHT80PLUS80; + break; + } + + // RX LDPC + if (caps & BIT(4)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_RX_LDPC; + + // RX Short GI 80 MHz + if (caps & BIT(5)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_RX_SHORT_GI_80; + + // RX Short GI 160 MHz and 80+80 MHz + if (caps & BIT(6)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_RX_SHORT_GI_160; + + // TX STBC + if (caps & BIT(7)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_TX_STBC; + + // Single User Beamformer + if (caps & BIT(11)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_SU_BEAMFORMER; + + // Single User Beamformee + if (caps & BIT(12)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_SU_BEAMFORMEE; + + // Multi User Beamformer + if (caps & BIT(19)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_MU_BEAMFORMER; + + // Multi User Beamformee + if (caps & BIT(20)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_MU_BEAMFORMEE; + + // TX-OP-PS + if (caps & BIT(21)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_TXOP_PS; + + // HTC-VHT + if (caps & BIT(22)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_HTC_VHT; + + // RX Antenna Pattern Consistency + if (caps & BIT(28)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_RX_ANTENNA_PATTERN; + + // TX Antenna Pattern Consistency + if (caps & BIT(29)) + phy->vht_caps |= NETWORK_PHY_VHT_CAP_TX_ANTENNA_PATTERN; +} + static void phy_parse_ht_capabilities(struct network_phy* phy, __u16 caps) { // RX LDCP if (caps & BIT(0)) @@ -165,8 +252,15 @@ static int phy_parse_info(struct nl_msg* msg, void* data) { // HT Capabilities if (band_attrs[NL80211_BAND_ATTR_HT_CAPA]) { - __u16 caps = nla_get_u16(band_attrs[NL80211_BAND_ATTR_HT_CAPA]); - phy_parse_ht_capabilities(phy, caps); + __u16 ht_caps = nla_get_u16(band_attrs[NL80211_BAND_ATTR_HT_CAPA]); + phy_parse_ht_capabilities(phy, ht_caps); + } + + // VHT Capabilities + if (band_attrs[NL80211_BAND_ATTR_VHT_CAPA]) { + __u32 vht_caps = nla_get_u32(band_attrs[NL80211_BAND_ATTR_VHT_CAPA]); + + phy_parse_vht_capabilities(phy, vht_caps); } } } @@ -271,10 +365,62 @@ nla_put_failure: return NULL; } +NETWORK_EXPORT int network_phy_has_vht_capability(struct network_phy* phy, const enum network_phy_vht_caps cap) { + return phy->vht_caps & cap; +} + NETWORK_EXPORT int network_phy_has_ht_capability(struct network_phy* phy, const enum network_phy_ht_caps cap) { return phy->ht_caps & cap; } +static const char* network_phy_get_vht_capability_string(const enum network_phy_vht_caps cap) { + switch (cap) { + case NETWORK_PHY_VHT_CAP_VHT160: + return "[VHT-160]"; + + case NETWORK_PHY_VHT_CAP_VHT80PLUS80: + return "[VHT-160-80PLUS80]"; + + case NETWORK_PHY_VHT_CAP_RX_LDPC: + return "[RXLDPC]"; + + case NETWORK_PHY_VHT_CAP_RX_SHORT_GI_80: + return "[SHORT-GI-80]"; + + case NETWORK_PHY_VHT_CAP_RX_SHORT_GI_160: + return "[SHORT-GI-160]"; + + case NETWORK_PHY_VHT_CAP_TX_STBC: + return "[TX-STBC-2BY1]"; + + case NETWORK_PHY_VHT_CAP_SU_BEAMFORMER: + return "[SU-BEAMFORMER]"; + + case NETWORK_PHY_VHT_CAP_SU_BEAMFORMEE: + return "[SU-BEAMFORMEE]"; + + case NETWORK_PHY_VHT_CAP_MU_BEAMFORMER: + return "[MU-BEAMFORMER]"; + + case NETWORK_PHY_VHT_CAP_MU_BEAMFORMEE: + return "[MU-BEAMFORMEE]"; + + case NETWORK_PHY_VHT_CAP_TXOP_PS: + return "[VHT-TXOP-PS]"; + + case NETWORK_PHY_VHT_CAP_HTC_VHT: + return "[HTC-VHT]"; + + case NETWORK_PHY_VHT_CAP_RX_ANTENNA_PATTERN: + return "[RX-ANTENNA-PATTERN]"; + + case NETWORK_PHY_VHT_CAP_TX_ANTENNA_PATTERN: + return "[TX-ANTENNA-PATTERN]"; + } + + return NULL; +} + static const char* network_phy_get_ht_capability_string(const enum network_phy_ht_caps cap) { switch (cap) { case NETWORK_PHY_HT_CAP_RX_LDCP: @@ -329,6 +475,33 @@ static const char* network_phy_get_ht_capability_string(const enum network_phy_h return NULL; } +NETWORK_EXPORT char* network_phy_list_vht_capabilities(struct network_phy* phy) { + char* buffer = malloc(1024); + *buffer = '\0'; + + char* p = buffer; + + switch (phy->max_mpdu_length) { + case 7991: + case 11454: + snprintf(p, 1024 - 1, "[MAX-MPDU-%zu]", phy->max_mpdu_length); + break; + + } + + foreach_vht_cap(cap) { + printf("%d\n", cap); + if (network_phy_has_vht_capability(phy, cap)) { + const char* cap_str = network_phy_get_vht_capability_string(cap); + + if (cap_str) + p = strncat(p, cap_str, 1024 - 1); + } + } + + return buffer; +} + NETWORK_EXPORT char* network_phy_list_ht_capabilities(struct network_phy* phy) { char* buffer = malloc(1024); *buffer = '\0'; diff --git a/src/utils/.gitignore b/src/utils/.gitignore index 9310e4a2..8ae00328 100644 --- a/src/utils/.gitignore +++ b/src/utils/.gitignore @@ -1 +1,2 @@ /network-phy-list-ht-caps +/network-phy-list-vht-caps diff --git a/src/utils/network-phy-list-vht-caps.c b/src/utils/network-phy-list-vht-caps.c new file mode 100644 index 00000000..e8f645c6 --- /dev/null +++ b/src/utils/network-phy-list-vht-caps.c @@ -0,0 +1,61 @@ +/*############################################################################# +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2018 IPFire Network Development Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +#############################################################################*/ + +#include +#include + +#include +#include +#include + +int main(int argc, char** argv) { + struct network_ctx* ctx = NULL; + struct network_phy* phy = NULL; + int r; + + if (argc < 2) { + fprintf(stderr, "No enough arguments\n"); + r = 2; + goto END; + } + + // Initialise context + r = network_new(&ctx); + if (r) + return r; + + r = network_phy_new(ctx, &phy, argv[1]); + if (r) { + fprintf(stderr, "Could not find %s\n", argv[1]); + goto END; + } + + // Print all supported VHT capabilities + char* vht_caps = network_phy_list_vht_capabilities(phy); + if (vht_caps && *vht_caps) { + printf("%s\n", vht_caps); + free(vht_caps); + } + +END: + network_phy_unref(phy); + network_unref(ctx); + return r; +} -- 2.39.2