]> git.ipfire.org Git - people/ms/network.git/commitdiff
ibnetwork: Add command to show available VHT capabilities of phys
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 19 Sep 2018 14:39:48 +0000 (15:39 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 19 Sep 2018 14:40:33 +0000 (15:40 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/libnetwork/libnetwork.sym
src/libnetwork/network/phy.h
src/libnetwork/phy.c
src/utils/.gitignore
src/utils/network-phy-list-vht-caps.c [new file with mode: 0644]

index e40e33225bb679445761819cd9d5dfa1ac249929..a295e379e6146d3ec96855b58b09ab753e2fead8 100644 (file)
@@ -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 = \
index 0b6c90b81f96630a5166f70b6b9a1e6becfaebf4..3ae81e90b99def7311a8d12927f25bfa205722c8 100644 (file)
@@ -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;
index afa42d572263bc01a948f85c4e094c9ab65a805a..b33aee5e24084752605f253f771199d1a5186160 100644 (file)
@@ -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)
 
index 6662eae489c50f0115a4d9e3f37309a3de155ed2..b58ccc7c0b8b8bb6849a4860522355c2174d7bad 100644 (file)
@@ -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';
index 9310e4a2f2ed48a3342972f9131f85ef63351f7c..8ae0032857ea327bfebdb2b0ba35e7265d9d2d10 100644 (file)
@@ -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 (file)
index 0000000..e8f645c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <network/libnetwork.h>
+#include <network/logging.h>
+#include <network/phy.h>
+
+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;
+}