Search Linux Wireless

[PATCH 2/4] iw: util: factor out HE capability parser

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We're going to use this for scan parsing.

Signed-off-by: Brian Norris <briannorris@xxxxxxxxxxxx>
---
 util.c | 144 ++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 80 insertions(+), 64 deletions(-)

diff --git a/util.c b/util.c
index 0a9083c613a4..4591cbf77ec1 100644
--- a/util.c
+++ b/util.c
@@ -989,19 +989,11 @@ void print_vht_info(__u32 capa, const __u8 *mcs)
 	printf("\t\tVHT TX highest supported: %d Mbps\n", tmp & 0x1fff);
 }
 
-void print_he_info(struct nlattr *nl_iftype)
+static void __print_he_capa(const __u16 *mac_cap,
+			    const __u16 *phy_cap,
+			    const __u16 *mcs_set, size_t mcs_len,
+			    const __u8 *ppet, int ppet_len)
 {
-	struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1];
-	struct nlattr *tb_flags[NL80211_IFTYPE_MAX + 1];
-	char *iftypes[NUM_NL80211_IFTYPES] = {
-		"Unspec", "Adhoc", "Station", "AP", "AP/VLAN", "WDS", "Monitor",
-		"Mesh", "P2P/Client", "P2P/Go", "P2P/Device", "OCB", "NAN",
-	};
-	__u16 mac_cap[3] = { 0 };
-	__u16 phy_cap[6] = { 0 };
-	__u16 mcs_set[6] = { 0 };
-	__u8 ppet[25] = { 0 };
-	size_t len;
 	int i;
 
 	#define PRINT_HE_CAP(_var, _idx, _bit, _str) \
@@ -1022,30 +1014,6 @@ void print_he_info(struct nlattr *nl_iftype)
 	#define PRINT_HE_PHY_CAP0(_idx, _bit, ...) PRINT_HE_CAP(phy_cap, _idx, _bit + 8, __VA_ARGS__)
 	#define PRINT_HE_PHY_CAP_MASK(...) PRINT_HE_CAP_MASK(phy_cap, __VA_ARGS__)
 
-	nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX,
-		  nla_data(nl_iftype), nla_len(nl_iftype), NULL);
-
-	if (!tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES])
-		return;
-
-	if (nla_parse_nested(tb_flags, NL80211_IFTYPE_MAX,
-			     tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES], NULL))
-		return;
-
-	printf("\t\tHE Iftypes:");
-	for (i = 0; i < NUM_NL80211_IFTYPES; i++)
-		if (nla_get_flag(tb_flags[i]) && iftypes[i])
-			printf(" %s", iftypes[i]);
-	printf("\n");
-
-	if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]) {
-		len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]);
-		if (len > sizeof(mac_cap))
-			len = sizeof(mac_cap);
-		memcpy(mac_cap,
-		       nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]),
-		       len);
-	}
 	printf("\t\t\tHE MAC Capabilities (0x");
 	for (i = 0; i < 3; i++)
 		printf("%04x", mac_cap[i]);
@@ -1086,15 +1054,6 @@ void print_he_info(struct nlattr *nl_iftype)
 	PRINT_HE_MAC_CAP(2, 11, "UL 2x996-Tone RU");
 	PRINT_HE_MAC_CAP(2, 12, "OM Control UL MU Data Disable RX");
 
-	if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) {
-		len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]);
-
-		if (len > sizeof(phy_cap) - 1)
-			len = sizeof(phy_cap) - 1;
-		memcpy(&((__u8 *)phy_cap)[1],
-		       nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]),
-		       len);
-	}
 	printf("\t\t\tHE PHY Capabilities: (0x");
 	for (i = 0; i < 11; i++)
 		printf("%02x", ((__u8 *)phy_cap)[i + 1]);
@@ -1165,15 +1124,6 @@ void print_he_info(struct nlattr *nl_iftype)
 	PRINT_HE_PHY_CAP(5, 4, "RX Full BW SU Using HE MU PPDU with Compression SIGB");
 	PRINT_HE_PHY_CAP(5, 5, "RX Full BW SU Using HE MU PPDU with Non-Compression SIGB");
 
-	if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]) {
-		len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]);
-		if (len > sizeof(mcs_set))
-			len = sizeof(mcs_set);
-		memcpy(mcs_set,
-		       nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]),
-		       len);
-	}
-
 	for (i = 0; i < 3; i++) {
 		__u8 phy_cap_support[] = { BIT(1) | BIT(2), BIT(3), BIT(4) };
 		char *bw[] = { "<= 80", "160", "80+80" };
@@ -1182,6 +1132,10 @@ void print_he_info(struct nlattr *nl_iftype)
 		if ((phy_cap[0] & (phy_cap_support[i] << 8)) == 0)
 			continue;
 
+		/* Supports more, but overflow? Abort. */
+		if ((i * 2 + 2) * sizeof(mcs_set[0]) >= mcs_len)
+			return;
+
 		for (j = 0; j < 2; j++) {
 			int k;
 			printf("\t\t\tHE %s MCS and NSS set %s MHz\n", j ? "TX" : "RX", bw[i]);
@@ -1199,7 +1153,76 @@ void print_he_info(struct nlattr *nl_iftype)
 		}
 	}
 
-	len = 0;
+	if (ppet_len && (phy_cap[3] & BIT(15))) {
+		printf("\t\t\tPPE Threshold ");
+		for (i = 0; i < ppet_len; i++)
+			if (ppet[i])
+				printf("0x%02x ", ppet[i]);
+		printf("\n");
+	}
+}
+
+void print_he_info(struct nlattr *nl_iftype)
+{
+	struct nlattr *tb[NL80211_BAND_IFTYPE_ATTR_MAX + 1];
+	struct nlattr *tb_flags[NL80211_IFTYPE_MAX + 1];
+	char *iftypes[NUM_NL80211_IFTYPES] = {
+		"Unspec", "Adhoc", "Station", "AP", "AP/VLAN", "WDS", "Monitor",
+		"Mesh", "P2P/Client", "P2P/Go", "P2P/Device", "OCB", "NAN",
+	};
+	__u16 mac_cap[3] = { 0 };
+	__u16 phy_cap[6] = { 0 };
+	__u16 mcs_set[6] = { 0 };
+	__u8 ppet[25] = { 0 };
+	size_t len;
+	int i;
+	int mcs_len = 0, ppet_len = 0;
+
+	nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX,
+		  nla_data(nl_iftype), nla_len(nl_iftype), NULL);
+
+	if (!tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES])
+		return;
+
+	if (nla_parse_nested(tb_flags, NL80211_IFTYPE_MAX,
+			     tb[NL80211_BAND_IFTYPE_ATTR_IFTYPES], NULL))
+		return;
+
+	printf("\t\tHE Iftypes:");
+	for (i = 0; i < NUM_NL80211_IFTYPES; i++)
+		if (nla_get_flag(tb_flags[i]) && iftypes[i])
+			printf(" %s", iftypes[i]);
+	printf("\n");
+
+	if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]) {
+		len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]);
+		if (len > sizeof(mac_cap))
+			len = sizeof(mac_cap);
+		memcpy(mac_cap,
+		       nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MAC]),
+		       len);
+	}
+
+	if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) {
+		len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]);
+
+		if (len > sizeof(phy_cap) - 1)
+			len = sizeof(phy_cap) - 1;
+		memcpy(&((__u8 *)phy_cap)[1],
+		       nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]),
+		       len);
+	}
+
+	if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]) {
+		len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]);
+		if (len > sizeof(mcs_set))
+			len = sizeof(mcs_set);
+		memcpy(mcs_set,
+		       nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET]),
+		       len);
+		mcs_len = len;
+	}
+
 	if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]) {
 		len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]);
 		if (len > sizeof(ppet))
@@ -1207,17 +1230,10 @@ void print_he_info(struct nlattr *nl_iftype)
 		memcpy(ppet,
 		       nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]),
 		       len);
+		ppet_len = len;
 	}
 
-	if (len && (phy_cap[3] & BIT(15))) {
-		size_t i;
-
-		printf("\t\t\tPPE Threshold ");
-		for (i = 0; i < len; i++)
-			if (ppet[i])
-				printf("0x%02x ", ppet[i]);
-		printf("\n");
-	}
+	__print_he_capa(mac_cap, phy_cap, mcs_set, mcs_len, ppet, ppet_len);
 }
 
 void iw_hexdump(const char *prefix, const __u8 *buf, size_t size)
-- 
2.29.2.299.gdc1121823c-goog




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux