diff mbox series

[v4] iw: scan: add EHT beacon info support

Message ID 20240731162022.2943045-3-dylan.eskew@candelatech.com
State New
Headers show
Series [v4] iw: scan: add EHT beacon info support | expand

Commit Message

Dylan Eskew July 31, 2024, 4:20 p.m. UTC
Update and add to the old EHT beacon info implementation to print
EHT PHY and MAC capabilities as well as MCS/NSS information for WiFi-7
beacons.

Signed-off-by: Dylan Eskew <dylan.eskew@candelatech.com>
---
v4:
- Change s-o-b to use full name
v3:
- Clean up changes and drop he logic Johannes commented on
v2:
- Fix subject
 info.c |   2 +-
 iw.h   |   3 +-
 scan.c |  18 +++++++---
 util.c | 105 +++++++++++++++++++++++++++++++--------------------------
 4 files changed, 74 insertions(+), 54 deletions(-)

Comments

Johannes Berg Aug. 28, 2024, 11:39 a.m. UTC | #1
On Wed, 2024-07-31 at 09:20 -0700, Dylan Eskew wrote:
> 
> -	if (!(he_phy_cap[0] & ((BIT(2) | BIT(3) | BIT(4)) << 8))){
> -		for (i = 0; i < 4; i++)
> -			printf("%s\t\tEHT bw=20 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
> -			       pre, mcs[i],
> -			       mcs_set[i] & 0xf, mcs_set[i] >> 4);
> -	} else {
> -		if (he_phy_cap[0] & (BIT(2) << 8)) {
> -			for (i = 0; i < 3; i++)
> -				printf("%s\t\tEHT bw <= 80 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
> -				       pre, mcs[i + 1],
> -				       mcs_set[i] & 0xf, mcs_set[i] >> 4);
> -		}
> -		mcs_set += 3;
> +	for (i = 0; i < 3; i++) {
> +		char *bw[] = { "<= 80", "160", "320" };
> +		char *mcs[] = { "0-9", "10-11", "12-13" };
> +		int j;
>  
> -		if (he_phy_cap[0] & (BIT(3) << 8)) {
> -			for (i = 0; i < 3; i++)
> -				printf("%s\t\tEHT bw=160 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
> -				       pre, mcs[i + 1],
> -				       mcs_set[i] & 0xf, mcs_set[i] >> 4);
> -		}
> +		if ((i * 3 + 2) * sizeof(mcs_set[0]) >= mcs_len)
> +		   break;

nit: a bunch of places here have weird indentation suddenly,


> -		mcs_set += 3;
> -		if (band == NL80211_BAND_6GHZ && (phy_cap[0] & BIT(1))) {
> -			for (i = 0; i < 3; i++)
> -				printf("%s\t\tEHT bw=320 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
> -				       pre, mcs[i + 1],
> -				       mcs_set[i] & 0xf, mcs_set[i] >> 4);
> +		printf("%s\t\tEHT MCS and NSS set %s MHz\n", pre, bw[i]);
> +		for (j = 0; j < 6; j++) {
> +			__u8 nss = mcs_set[(i * 3) + j / 2];
> +			nss >>= (j % 2) * 4;
> +			nss &= 0xF;
> +
> +			printf("%s\t\t\t%s Max NSS that supports MCS %s: ",
> +			      pre, j % 2 ? "TX" : "RX", mcs[j / 2]);
> +			if (nss == 0)
> +				printf("not supported\n");
> +			else
> +			   printf("%d streams\n", nss);

e.g. this especially - are you using 3 spaces for tabs and didn't see it
or something?

I'm a bit more concerned though with the changes about the EHT MCS/NSS
set. You don't have the HE stuff now, and you're not handling "20 MHz-
only non-AP STA" here any more, which seems relevant for local
capability printing?

johannes
Dylan Eskew Aug. 28, 2024, 10:06 p.m. UTC | #2
On 8/28/24 4:39 AM, Johannes Berg wrote:
> nit: a bunch of places here have weird indentation suddenly,
Apologies. I'll be more diligent moving forward about spacing.
> I'm a bit more concerned though with the changes about the EHT MCS/NSS 
> set. You don't have the HE stuff now, and you're not handling "20 MHz- 
> only non-AP STA" here any more, which seems relevant for local 
> capability printing? 

Your concerns are well placed. My initial iterations have been naive; I 
now have a better idea of what's required after looking back at 
documentation and having a better grasp of the standard generally. Your 
patience here has been and will continue to be appreciated.

Dylan
diff mbox series

Patch

diff --git a/info.c b/info.c
index c5e863f..79a2a71 100644
--- a/info.c
+++ b/info.c
@@ -391,7 +391,7 @@  static int print_phy_handler(struct nl_msg *msg, void *arg)
 						    tb_band[NL80211_BAND_ATTR_IFTYPE_DATA],
 						    rem_band) {
 					print_he_info(nl_iftype);
-					print_eht_info(nl_iftype, last_band);
+					print_eht_info(nl_iftype);
 				}
 			}
 			if (tb_band[NL80211_BAND_ATTR_FREQS]) {
diff --git a/iw.h b/iw.h
index f416d6d..eda9a3a 100644
--- a/iw.h
+++ b/iw.h
@@ -237,7 +237,8 @@  void print_ht_capability(__u16 cap);
 void print_vht_info(__u32 capa, const __u8 *mcs);
 void print_he_capability(const uint8_t *ie, int len);
 void print_he_info(struct nlattr *nl_iftype);
-void print_eht_info(struct nlattr *nl_iftype, int band);
+void print_eht_capability(const uint8_t *ie, int len);
+void print_eht_info(struct nlattr *nl_iftype);
 void print_s1g_capability(const uint8_t *caps);
 
 char *channel_width_name(enum nl80211_chan_width width);
diff --git a/scan.c b/scan.c
index faf406d..3c8d6ee 100644
--- a/scan.c
+++ b/scan.c
@@ -2384,12 +2384,21 @@  static void print_he_capa(const uint8_t type, uint8_t len, const uint8_t *data,
 	print_he_capability(data, len);
 }
 
+static void print_eht_capa(const uint8_t type, uint8_t len, const uint8_t *data,
+			   const struct print_ies_data *ie_buffer)
+{
+	printf("\n");
+	print_eht_capability(data, len);
+}
+
 static const struct ie_print ext_printers[] = {
 	[35] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), },
+	[108] = { "EHT capabilties", print_eht_capa, 13, 30, BIT(PRINT_SCAN), },
 };
 
 static void print_extension(unsigned char len, unsigned char *ie,
-			    bool unknown, enum print_ie_type ptype)
+			    bool unknown, enum print_ie_type ptype,
+			    const struct print_ies_data *ie_buffer)
 {
 	unsigned char tag;
 
@@ -2401,7 +2410,7 @@  static void print_extension(unsigned char len, unsigned char *ie,
 	tag = ie[0];
 	if (tag < ARRAY_SIZE(ext_printers) && ext_printers[tag].name &&
 	    ext_printers[tag].flags & BIT(ptype)) {
-		print_ie(&ext_printers[tag], tag, len - 1, ie + 1, NULL);
+		print_ie(&ext_printers[tag], tag, len - 1, ie + 1, ie_buffer);
 		return;
 	}
 
@@ -2435,7 +2444,7 @@  void print_ies(unsigned char *ie, int ielen, bool unknown,
 		} else if (ie[0] == 221 /* vendor */) {
 			print_vendor(ie[1], ie + 2, unknown, ptype);
 		} else if (ie[0] == 255 /* extension */) {
-			print_extension(ie[1], ie + 2, unknown, ptype);
+			print_extension(ie[1], ie + 2, unknown, ptype, &ie_buffer);
 		} else if (unknown) {
 			int i;
 
@@ -2639,8 +2648,7 @@  static int print_bss_handler(struct nl_msg *msg, void *arg)
 				       nla_len(ies)))))
 			printf("\tInformation elements from Probe Response "
 			       "frame:\n");
-		print_ies(nla_data(ies), nla_len(ies),
-			  params->unknown, params->type);
+		print_ies(nla_data(ies), nla_len(ies), params->unknown, params->type);
 	}
 	if (bss[NL80211_BSS_BEACON_IES] && show--) {
 		printf("\tInformation elements from Beacon frame:\n");
diff --git a/util.c b/util.c
index 1341a22..b5a92db 100644
--- a/util.c
+++ b/util.c
@@ -1525,17 +1525,14 @@  void print_he_info(struct nlattr *nl_iftype)
 			true);
 }
 
-static void __print_eht_capa(int band,
-			     const __u8 *mac_cap,
+static void __print_eht_capa(const __u8 *mac_cap,
 			     const __u32 *phy_cap,
 			     const __u8 *mcs_set, size_t mcs_len,
 			     const __u8 *ppet, size_t ppet_len,
-			     const __u16 *he_phy_cap,
 			     bool indent)
 {
-	unsigned int i;
+	size_t i;
 	const char *pre = indent ? "\t" : "";
-	const char *mcs[] = { "0-7", "8-9", "10-11", "12-13"};
 
 	#define PRINT_EHT_CAP(_var, _idx, _bit, _str) \
 	do { \
@@ -1550,6 +1547,7 @@  static void __print_eht_capa(int band,
 	} while (0)
 
 	#define PRINT_EHT_MAC_CAP(...) PRINT_EHT_CAP(mac_cap, __VA_ARGS__)
+	#define PRINT_EHT_MAC_CAP_MASK(...) PRINT_EHT_CAP_MASK(mac_cap, __VA_ARGS__)
 	#define PRINT_EHT_PHY_CAP(...) PRINT_EHT_CAP(phy_cap, __VA_ARGS__)
 	#define PRINT_EHT_PHY_CAP_MASK(...) PRINT_EHT_CAP_MASK(phy_cap, __VA_ARGS__)
 
@@ -1558,10 +1556,19 @@  static void __print_eht_capa(int band,
 		printf("%02x", mac_cap[i]);
 	printf("):\n");
 
-	PRINT_EHT_MAC_CAP(0, 0, "NSEP priority access Supported");
+	PRINT_EHT_MAC_CAP(0, 0, "EPCS Priority Access Supported");
 	PRINT_EHT_MAC_CAP(0, 1, "EHT OM Control Supported");
-	PRINT_EHT_MAC_CAP(0, 2, "Triggered TXOP Sharing Supported");
-	PRINT_EHT_MAC_CAP(0, 3, "ARR Supported");
+	PRINT_EHT_MAC_CAP(0, 2, "Triggered TXOP Sharing Mode 1 Supported");
+	PRINT_EHT_MAC_CAP(0, 3, "Triggered TXOP Sharing Mode 2 Supported");
+	PRINT_EHT_MAC_CAP(0, 4, "Restricted TWP Supported");
+	PRINT_EHT_MAC_CAP(0, 5, "SCS Traffic Description Supported");
+	PRINT_EHT_MAC_CAP_MASK(0, 6, 0x3, "Maximum MPDU Length");
+
+	PRINT_EHT_MAC_CAP(1, 1, "Maximum A-MPDU Length Exponent Extension");
+	PRINT_EHT_MAC_CAP(1, 2, "EHT TRS Supported");
+	PRINT_EHT_MAC_CAP(1, 3, "TXOP Return In TXOP Sharing Mode 2 Supported");
+	PRINT_EHT_MAC_CAP(1, 4, "Two BQRs Supported");
+	PRINT_EHT_MAC_CAP_MASK(1, 5, 0x3, "EHT Link Adaptation Supported");
 
 	printf("%s\t\tEHT PHY Capabilities: (0x", pre);
 	for (i = 0; i < 8; i++)
@@ -1610,39 +1617,36 @@  static void __print_eht_capa(int band,
 	PRINT_EHT_PHY_CAP(1, 28, "MU Beamformer (80MHz)");
 	PRINT_EHT_PHY_CAP(1, 29, "MU Beamformer (160MHz)");
 	PRINT_EHT_PHY_CAP(1, 30, "MU Beamformer (320MHz)");
+	PRINT_EHT_PHY_CAP(1, 31, "TB Sounding Feedback Rate Limit");
+
+	PRINT_EHT_PHY_CAP(2, 0, "Rx 1024-QAM In Wider Bandwidth DL OFDMA Supported");
+	PRINT_EHT_PHY_CAP(2, 1, "Rx 4096-QAM In Wider Bandwidth DL OFDMA Supported");
 
 	printf("%s\t\tEHT MCS/NSS: (0x", pre);
 	for (i = 0; i < mcs_len; i++)
 		printf("%02x", ((__u8 *)mcs_set)[i]);
 	printf("):\n");
 
-	if (!(he_phy_cap[0] & ((BIT(2) | BIT(3) | BIT(4)) << 8))){
-		for (i = 0; i < 4; i++)
-			printf("%s\t\tEHT bw=20 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
-			       pre, mcs[i],
-			       mcs_set[i] & 0xf, mcs_set[i] >> 4);
-	} else {
-		if (he_phy_cap[0] & (BIT(2) << 8)) {
-			for (i = 0; i < 3; i++)
-				printf("%s\t\tEHT bw <= 80 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
-				       pre, mcs[i + 1],
-				       mcs_set[i] & 0xf, mcs_set[i] >> 4);
-		}
-		mcs_set += 3;
+	for (i = 0; i < 3; i++) {
+		char *bw[] = { "<= 80", "160", "320" };
+		char *mcs[] = { "0-9", "10-11", "12-13" };
+		int j;
 
-		if (he_phy_cap[0] & (BIT(3) << 8)) {
-			for (i = 0; i < 3; i++)
-				printf("%s\t\tEHT bw=160 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
-				       pre, mcs[i + 1],
-				       mcs_set[i] & 0xf, mcs_set[i] >> 4);
-		}
+		if ((i * 3 + 2) * sizeof(mcs_set[0]) >= mcs_len)
+		   break;
 
-		mcs_set += 3;
-		if (band == NL80211_BAND_6GHZ && (phy_cap[0] & BIT(1))) {
-			for (i = 0; i < 3; i++)
-				printf("%s\t\tEHT bw=320 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n",
-				       pre, mcs[i + 1],
-				       mcs_set[i] & 0xf, mcs_set[i] >> 4);
+		printf("%s\t\tEHT MCS and NSS set %s MHz\n", pre, bw[i]);
+		for (j = 0; j < 6; j++) {
+			__u8 nss = mcs_set[(i * 3) + j / 2];
+			nss >>= (j % 2) * 4;
+			nss &= 0xF;
+
+			printf("%s\t\t\t%s Max NSS that supports MCS %s: ",
+			      pre, j % 2 ? "TX" : "RX", mcs[j / 2]);
+			if (nss == 0)
+				printf("not supported\n");
+			else
+			   printf("%d streams\n", nss);
 		}
 	}
 
@@ -1655,14 +1659,13 @@  static void __print_eht_capa(int band,
 	}
 }
 
-void print_eht_info(struct nlattr *nl_iftype, int band)
+void print_eht_info(struct nlattr *nl_iftype)
 {
 	struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1];
 	__u8 mac_cap[2] = { 0 };
 	__u32 phy_cap[2] = { 0 };
 	__u8 mcs_set[13] = { 0 };
 	__u8 ppet[31] = { 0 };
-	__u16 he_phy_cap[6] = { 0 };
 	size_t len, mcs_len = 0, ppet_len = 0;
 
 	nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX,
@@ -1718,18 +1721,8 @@  void print_eht_info(struct nlattr *nl_iftype, int band)
 		ppet_len = len;
 	}
 
-	if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) {
-		len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]);
-
-		if (len > sizeof(he_phy_cap) - 1)
-			len = sizeof(he_phy_cap) - 1;
-		memcpy(&((__u8 *)he_phy_cap)[1],
-		       nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]),
-		       len);
-	}
-
-	__print_eht_capa(band, mac_cap, phy_cap, mcs_set, mcs_len, ppet, ppet_len,
-			 he_phy_cap, true);
+	__print_eht_capa(mac_cap, phy_cap, mcs_set, mcs_len, ppet, ppet_len,
+			 true);
 }
 
 void print_he_capability(const uint8_t *ie, int len)
@@ -1750,6 +1743,24 @@  void print_he_capability(const uint8_t *ie, int len)
 	__print_he_capa(mac_cap, phy_cap - 1, mcs_set, mcs_len, NULL, 0, false);
 }
 
+void print_eht_capability(const uint8_t *ie, int len)
+{
+	const void *mac_cap, *phy_cap, *mcs_set;
+	int mcs_len;
+	int i = 0;
+
+	mac_cap = &ie[i];
+	i += 3;
+
+	phy_cap = &ie[i];
+	i += 8;
+
+	mcs_set = &ie[i];
+	mcs_len = len - i;
+
+	__print_eht_capa(mac_cap, phy_cap - 1, mcs_set, mcs_len, NULL, 0, false);
+}
+
 void iw_hexdump(const char *prefix, const __u8 *buf, size_t size)
 {
 	size_t i;