]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
iw: handle VHT extended NSS
authorMaxime Bizon <mbizon@freebox.fr>
Mon, 16 May 2022 09:07:56 +0000 (11:07 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 27 May 2022 09:29:35 +0000 (11:29 +0200)
No change in "Supported Channel Width" output format when extended NSS
is not supported.

Sample output for a PHY with 1/2 NSS ratio:

VHT Capabilities (0xb39b79f2):
Max MPDU length: 11454
Supported Channel Width: 160Mhz (1/2 NSS) 80+80Mhz (1/2 NSS)
[...]
VHT extended NSS: supported

Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
Link: https://lore.kernel.org/r/405f5ed2c434846f8ab2730b34288c5f649b8915.camel@freebox.fr
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
util.c

diff --git a/util.c b/util.c
index f8ab6cae778be8e4fcf6c9cbb453f20a2aa0a34c..8a2ba10c687a5e38e2df02c4d9c20e3efdb50727 100644 (file)
--- a/util.c
+++ b/util.c
@@ -922,9 +922,159 @@ void print_ht_mcs(const __u8 *mcs)
        }
 }
 
+struct vht_nss_ratio {
+       bool valid;
+       int bw_20;
+       int bw_40;
+       int bw_80;
+       int bw_160;
+       int bw_80_80;
+};
+
+/*
+ * indexed by [chan_width][ext_nss_bw], ratio in 1/4 unit
+ */
+static const struct vht_nss_ratio nss_ratio_tbl[3][4] = {
+       {
+               /* chan_width == 0, ext_nss_bw == 0 */
+               {
+                       .valid = true,
+                       .bw_20 = 4,
+                       .bw_40 = 4,
+                       .bw_80 = 4,
+               },
+               /* chan_width == 0, ext_nss_bw == 1 */
+               {
+                       .valid = true,
+                       .bw_20 = 4,
+                       .bw_40 = 4,
+                       .bw_80 = 4,
+                       .bw_160 = 2,
+               },
+               /* chan_width == 0, ext_nss_bw == 2 */
+               {
+                       .valid = true,
+                       .bw_20 = 4,
+                       .bw_40 = 4,
+                       .bw_80 = 4,
+                       .bw_160 = 2,
+                       .bw_80_80 = 2,
+               },
+               /* chan_width == 0, ext_nss_bw == 3 */
+               {
+                       .valid = true,
+                       .bw_20 = 4,
+                       .bw_40 = 4,
+                       .bw_80 = 4,
+                       .bw_160 = 3,
+                       .bw_80_80 = 3,
+               },
+       },
+       {
+               /* chan_width == 1, ext_nss_bw == 0 */
+               {
+                       .valid = true,
+                       .bw_20 = 4,
+                       .bw_40 = 4,
+                       .bw_80 = 4,
+                       .bw_160 = 4,
+               },
+               /* chan_width == 1, ext_nss_bw == 1 */
+               {
+                       .valid = true,
+                       .bw_20 = 4,
+                       .bw_40 = 4,
+                       .bw_80 = 4,
+                       .bw_160 = 4,
+                       .bw_80_80 = 2,
+               },
+               /* chan_width == 1, ext_nss_bw == 2 */
+               {
+                       .valid = true,
+                       .bw_20 = 4,
+                       .bw_40 = 4,
+                       .bw_80 = 4,
+                       .bw_160 = 4,
+                       .bw_80_80 = 3,
+               },
+               /* chan_width == 1, ext_nss_bw == 3 */
+               {
+                       .valid = true,
+                       .bw_20 = 8,
+                       .bw_40 = 8,
+                       .bw_80 = 8,
+                       .bw_160 = 8,
+                       .bw_80_80 = 1,
+               },
+       },
+       {
+               /* chan_width == 2, ext_nss_bw == 0 */
+               {
+                       .valid = true,
+                       .bw_20 = 4,
+                       .bw_40 = 4,
+                       .bw_80 = 4,
+                       .bw_160 = 4,
+                       .bw_80_80 = 4,
+               },
+               /* chan_width == 2, ext_nss_bw == 1 */
+               {},
+               /* chan_width == 2, ext_nss_bw == 2 */
+               {},
+               /* chan_width == 2, ext_nss_bw == 3 */
+               {
+                       .valid = true,
+                       .bw_20 = 8,
+                       .bw_40 = 8,
+                       .bw_80 = 8,
+                       .bw_160 = 4,
+                       .bw_80_80 = 4,
+               },
+       },
+};
+
+static void print_nss_ratio_value(int ratio)
+{
+       const char *rstr;
+
+       switch (ratio) {
+       case 4:
+               return;
+       case 3:
+               rstr = "3/4";
+               break;
+       case 2:
+               rstr = "1/2";
+               break;
+       case 8:
+               rstr = "x2";
+               break;
+       default:
+               rstr = "undef";
+               break;
+       }
+
+       printf("(%s NSS) ", rstr);
+}
+
+static void print_nss_ratio(const char *str, bool force_show, int ratio)
+{
+       if (!ratio)
+               return;
+       if (ratio == 4) {
+               if (force_show)
+                       printf("%s ", str);
+       } else {
+               printf("%s ", str);
+               print_nss_ratio_value(ratio);
+       }
+}
+
 void print_vht_info(__u32 capa, const __u8 *mcs)
 {
        __u16 tmp;
+       __u32 supp_chan_width, ext_nss_bw;
+       const struct vht_nss_ratio *nss_tbl;
        int i;
 
        printf("\t\tVHT Capabilities (0x%.8x):\n", capa);
@@ -942,13 +1092,34 @@ void print_vht_info(__u32 capa, const __u8 *mcs)
        case 2: printf("11454\n"); break;
        case 3: printf("(reserved)\n");
        }
+
        printf("\t\t\tSupported Channel Width: ");
-       switch ((capa >> 2) & 3) {
-       case 0: printf("neither 160 nor 80+80\n"); break;
-       case 1: printf("160 MHz\n"); break;
-       case 2: printf("160 MHz, 80+80 MHz\n"); break;
-       case 3: printf("(reserved)\n");
+       supp_chan_width = (capa >> 2) & 3;
+       ext_nss_bw = (capa >> 30) & 3;
+       nss_tbl = &nss_ratio_tbl[supp_chan_width][ext_nss_bw];
+
+       if (!nss_tbl->valid)
+               printf("(reserved)\n");
+       else if (nss_tbl->bw_20 == 4 &&
+                nss_tbl->bw_40 == 4 &&
+                nss_tbl->bw_80 == 4 &&
+                (!nss_tbl->bw_160 || nss_tbl->bw_160 == 4) &&
+                (!nss_tbl->bw_80_80 || nss_tbl->bw_80_80 == 4)) {
+               /* old style print format */
+               switch (supp_chan_width) {
+               case 0: printf("neither 160 nor 80+80\n"); break;
+               case 1: printf("160 MHz\n"); break;
+               case 2: printf("160 MHz, 80+80 MHz\n"); break;
+               }
+       } else {
+               print_nss_ratio("20Mhz", false, nss_tbl->bw_20);
+               print_nss_ratio("40Mhz", false, nss_tbl->bw_40);
+               print_nss_ratio("80Mhz", false, nss_tbl->bw_80);
+               print_nss_ratio("160Mhz", false, nss_tbl->bw_160);
+               print_nss_ratio("80+80Mhz", false, nss_tbl->bw_80_80);
+               printf("\n");
        }
+
        PRINT_VHT_CAPA(4, "RX LDPC");
        PRINT_VHT_CAPA(5, "short GI (80 MHz)");
        PRINT_VHT_CAPA(6, "short GI (160/80+80 MHz)");
@@ -994,6 +1165,9 @@ void print_vht_info(__u32 capa, const __u8 *mcs)
        }
        tmp = mcs[6] | (mcs[7] << 8);
        printf("\t\tVHT TX highest supported: %d Mbps\n", tmp & 0x1fff);
+
+       printf("\t\tVHT extended NSS: %ssupported\n",
+              (tmp & (1 << 13)) ? "" : "not ");
 }
 
 static void __print_he_capa(const __u16 *mac_cap,