2022-09-23 02:21:43

by Jaewan Kim

[permalink] [raw]
Subject: [PATCH] iw: info: print PMSR capabilities

Print PMSR and FTM capabilities if any.

Signed-off-by: Jaewan Kim <[email protected]>
---
info.c | 3 ++
iw.h | 1 +
util.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 122 insertions(+)

diff --git a/info.c b/info.c
index 21ed07b..d13fc16 100644
--- a/info.c
+++ b/info.c
@@ -741,6 +741,9 @@ broken_combination:
pat->max_pattern_len, pat->max_pkt_offset, rule->max_delay);
}

+ if (tb_msg[NL80211_ATTR_PEER_MEASUREMENTS])
+ print_pmsr_capabilities(tb_msg[NL80211_ATTR_PEER_MEASUREMENTS]);
+
if (tb_msg[NL80211_ATTR_MAX_AP_ASSOC_STA])
printf("\tMaximum associated stations in AP mode: %u\n",
nla_get_u16(tb_msg[NL80211_ATTR_MAX_AP_ASSOC_STA]));
diff --git a/iw.h b/iw.h
index e712c59..0707cb4 100644
--- a/iw.h
+++ b/iw.h
@@ -221,6 +221,7 @@ 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_pmsr_capabilities(const struct nlattr *pmsr_capa);

char *channel_width_name(enum nl80211_chan_width width);
const char *iftype_name(enum nl80211_iftype iftype);
diff --git a/util.c b/util.c
index 8a2ba10..18f6e71 100644
--- a/util.c
+++ b/util.c
@@ -1673,6 +1673,124 @@ 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);
}

+static void __print_ftm_capability(struct nlattr *ftm_capa)
+{
+#define PRINT_FTM_FLAG(T, NAME) \
+ do { \
+ if (T[NL80211_PMSR_FTM_CAPA_ATTR_##NAME]) \
+ printf("\t\t\t" #NAME "\n"); \
+ } while (0)
+
+#define PRINT_FTM_U8(T, NAME) \
+ do { \
+ if (T[NL80211_PMSR_FTM_CAPA_ATTR_##NAME]) \
+ printf("\t\t\t" #NAME "=\n", \
+ nla_get_u8(T[NL80211_PMSR_FTM_CAPA_ATTR_##NAME])); \
+ } while (0)
+
+ struct nlattr *tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1];
+ int ret;
+
+ printf("\t\tFTM (Fine time measurement or Flight time measurement)\n");
+
+ ret = nla_parse_nested(tb, NL80211_PMSR_FTM_CAPA_ATTR_MAX, ftm_capa,
+ NULL);
+ if (ret)
+ return;
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES]) {
+#define PRINT_PREAMBLE(P, V) \
+ do { \
+ if (P | NL80211_PREAMBLE_##V) \
+ printf(#V " "); \
+ } while (0)
+
+ uint32_t preambles =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES]);
+ printf("\t\t\tPreambles=");
+
+ PRINT_PREAMBLE(preambles, LEGACY);
+ PRINT_PREAMBLE(preambles, HT);
+ PRINT_PREAMBLE(preambles, VHT);
+ PRINT_PREAMBLE(preambles, DMG);
+ printf("\n");
+#undef PRINT_PREAMBLE
+ }
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS]) {
+#define PRINT_BANDWIDTH(B, V) \
+ do { \
+ if (B | NL80211_CHAN_WIDTH_##V) \
+ printf(#V " "); \
+ } while (0)
+
+ uint32_t bandwidth =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS]);
+ printf("\t\t\tBandwidth=");
+ PRINT_BANDWIDTH(bandwidth, 20_NOHT);
+ PRINT_BANDWIDTH(bandwidth, 20);
+ PRINT_BANDWIDTH(bandwidth, 40);
+ PRINT_BANDWIDTH(bandwidth, 80);
+ PRINT_BANDWIDTH(bandwidth, 80P80);
+ PRINT_BANDWIDTH(bandwidth, 160);
+ PRINT_BANDWIDTH(bandwidth, 5);
+ PRINT_BANDWIDTH(bandwidth, 10);
+ PRINT_BANDWIDTH(bandwidth, 1);
+ PRINT_BANDWIDTH(bandwidth, 2);
+ PRINT_BANDWIDTH(bandwidth, 4);
+ PRINT_BANDWIDTH(bandwidth, 8);
+ PRINT_BANDWIDTH(bandwidth, 16);
+ PRINT_BANDWIDTH(bandwidth, 320);
+ printf("\n");
+#undef PRINT_BANDWIDTH
+ }
+ PRINT_FTM_U8(tb, MAX_BURSTS_EXPONENT);
+ PRINT_FTM_U8(tb, MAX_FTMS_PER_BURST);
+ PRINT_FTM_FLAG(tb, ASAP);
+ PRINT_FTM_FLAG(tb, NON_ASAP);
+ PRINT_FTM_FLAG(tb, REQ_LCI);
+ PRINT_FTM_FLAG(tb, REQ_CIVICLOC);
+ PRINT_FTM_FLAG(tb, TRIGGER_BASED);
+ PRINT_FTM_FLAG(tb, NON_TRIGGER_BASED);
+
+#undef PRINT_FTM_U8
+#undef PRINT_FTM_FLAG
+}
+
+void print_pmsr_capabilities(struct nlattr *pmsr_capa)
+{
+ struct nlattr *tb[NL80211_PMSR_ATTR_MAX + 1];
+ struct nlattr *nla;
+ int size;
+ int ret;
+
+ printf("\tPeer measurement (PMSR)\n");
+ ret = nla_parse_nested(tb, NL80211_PMSR_ATTR_MAX, pmsr_capa, NULL);
+ if (ret) {
+ printf("\t\tMalformed PMSR\n");
+ return;
+ }
+
+ if (tb[NL80211_PMSR_ATTR_MAX_PEERS])
+ printf("\t\tMax peers=%d\n",
+ nla_get_u32(tb[NL80211_PMSR_ATTR_MAX_PEERS]));
+ if (tb[NL80211_PMSR_ATTR_REPORT_AP_TSF])
+ printf("\t\tREPORT_AP_TSF\n");
+ if (tb[NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR])
+ printf("\t\tRANDOMIZE_MAC_ADDR\n");
+
+ if (tb[NL80211_PMSR_ATTR_TYPE_CAPA]) {
+ nla_for_each_nested(nla, tb[NL80211_PMSR_ATTR_TYPE_CAPA], size) {
+ switch (nla_type(nla)) {
+ case NL80211_PMSR_TYPE_FTM:
+ __print_ftm_capability(nla);
+ break;
+ }
+ }
+ } else {
+ printf("\t\tPMSR type is missing\n");
+ }
+}
+
void iw_hexdump(const char *prefix, const __u8 *buf, size_t size)
{
size_t i;
--
2.37.3.998.g577e59143f-goog


2022-10-05 09:50:39

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] iw: info: print PMSR capabilities

On Fri, 2022-09-23 at 10:55 +0900, Jaewan Kim wrote:
>
> +#define PRINT_FTM_U8(T, NAME) \
> + do { \
> + if (T[NL80211_PMSR_FTM_CAPA_ATTR_##NAME]) \
> + printf("\t\t\t" #NAME "=\n", \
> + nla_get_u8(T[NL80211_PMSR_FTM_CAPA_ATTR_##NAME])); \

This doesn't compile, and there are also a few compiler warnings.

That's all easy to fix, but it does make me wonder if you tested this at
all, or accidentally sent out an unfixed version from before testing, or
so?

johannes

2022-10-05 09:51:57

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] iw: info: print PMSR capabilities

On Fri, 2022-09-23 at 10:55 +0900, Jaewan Kim wrote:
>
> +++ b/info.c
> @@ -741,6 +741,9 @@ broken_combination:
> pat->max_pattern_len, pat->max_pkt_offset, rule->max_delay);
> }
>
> + if (tb_msg[NL80211_ATTR_PEER_MEASUREMENTS])
> + print_pmsr_capabilities(tb_msg[NL80211_ATTR_PEER_MEASUREMENTS]);
> +
> if (tb_msg[NL80211_ATTR_MAX_AP_ASSOC_STA])
> printf("\tMaximum associated stations in AP mode: %u\n",
> nla_get_u16(tb_msg[NL80211_ATTR_MAX_AP_ASSOC_STA]));
> diff --git a/iw.h b/iw.h
> index e712c59..0707cb4 100644
> --- a/iw.h
> +++ b/iw.h
> @@ -221,6 +221,7 @@ 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_pmsr_capabilities(const struct nlattr *pmsr_capa);

Also, FWIW, it would probably make sense to make this static and put it
into info.c at least while it's not used elsewhere?

johannes

2022-10-11 05:41:15

by Jaewan Kim

[permalink] [raw]
Subject: Re: [PATCH] iw: info: print PMSR capabilities

On Wed, Oct 5, 2022 at 6:48 PM Johannes Berg <[email protected]> wrote:
>
> On Fri, 2022-09-23 at 10:55 +0900, Jaewan Kim wrote:
> >
> > +++ b/info.c
> > @@ -741,6 +741,9 @@ broken_combination:
> > pat->max_pattern_len, pat->max_pkt_offset, rule->max_delay);
> > }
> >
> > + if (tb_msg[NL80211_ATTR_PEER_MEASUREMENTS])
> > + print_pmsr_capabilities(tb_msg[NL80211_ATTR_PEER_MEASUREMENTS]);
> > +
> > if (tb_msg[NL80211_ATTR_MAX_AP_ASSOC_STA])
> > printf("\tMaximum associated stations in AP mode: %u\n",
> > nla_get_u16(tb_msg[NL80211_ATTR_MAX_AP_ASSOC_STA]));
> > diff --git a/iw.h b/iw.h
> > index e712c59..0707cb4 100644
> > --- a/iw.h
> > +++ b/iw.h
> > @@ -221,6 +221,7 @@ 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_pmsr_capabilities(const struct nlattr *pmsr_capa);
>
> Also, FWIW, it would probably make sense to make this static and put it
> into info.c at least while it's not used elsewhere?
>
> johannes

My apologies. I made a mistake when moving changes from the Android repo.
Could you take another look at the patch? It would be a great help.

--
Jaewan Kim (김재완) | Software Engineer in Google Korea |
[email protected] | +82-10-2781-5078

2022-10-11 05:44:06

by Jaewan Kim

[permalink] [raw]
Subject: [PATCH v2] iw: info: print PMSR capabilities

Print PMSR and FTM capabilities if any.

Signed-off-by: Jaewan Kim <[email protected]>
---
info.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 121 insertions(+)

diff --git a/info.c b/info.c
index 21ed07b..eb257f8 100644
--- a/info.c
+++ b/info.c
@@ -169,6 +169,124 @@ static void ext_feat_print(enum nl80211_ext_feature_index idx)
}
}

+static void __print_ftm_capability(struct nlattr *ftm_capa)
+{
+#define PRINT_FTM_FLAG(T, NAME) \
+ do { \
+ if (T[NL80211_PMSR_FTM_CAPA_ATTR_##NAME]) \
+ printf("\t\t\t" #NAME "\n"); \
+ } while (0)
+
+#define PRINT_FTM_U8(T, NAME) \
+ do { \
+ if (T[NL80211_PMSR_FTM_CAPA_ATTR_##NAME]) \
+ printf("\t\t\t" #NAME ": %d\n", \
+ nla_get_u8(T[NL80211_PMSR_FTM_CAPA_ATTR_##NAME])); \
+ } while (0)
+
+ struct nlattr *tb[NL80211_PMSR_FTM_CAPA_ATTR_MAX + 1];
+ int ret;
+
+ printf("\t\tFTM (Fine time measurement or Flight time measurement)\n");
+
+ ret = nla_parse_nested(tb, NL80211_PMSR_FTM_CAPA_ATTR_MAX, ftm_capa,
+ NULL);
+ if (ret)
+ return;
+
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES]) {
+#define PRINT_PREAMBLE(P, V) \
+ do { \
+ if (P | NL80211_PREAMBLE_##V) \
+ printf(" " #V); \
+ } while (0)
+
+ uint32_t preambles =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_PREAMBLES]);
+ printf("\t\t\tPreambles:");
+
+ PRINT_PREAMBLE(preambles, LEGACY);
+ PRINT_PREAMBLE(preambles, HT);
+ PRINT_PREAMBLE(preambles, VHT);
+ PRINT_PREAMBLE(preambles, DMG);
+ printf("\n");
+#undef PRINT_PREAMBLE
+ }
+ if (tb[NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS]) {
+#define PRINT_BANDWIDTH(B, V) \
+ do { \
+ if (B | NL80211_CHAN_WIDTH_##V) \
+ printf(" " #V); \
+ } while (0)
+
+ uint32_t bandwidth =
+ nla_get_u32(tb[NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS]);
+ printf("\t\t\tBandwidth:");
+ PRINT_BANDWIDTH(bandwidth, 20_NOHT);
+ PRINT_BANDWIDTH(bandwidth, 20);
+ PRINT_BANDWIDTH(bandwidth, 40);
+ PRINT_BANDWIDTH(bandwidth, 80);
+ PRINT_BANDWIDTH(bandwidth, 80P80);
+ PRINT_BANDWIDTH(bandwidth, 160);
+ PRINT_BANDWIDTH(bandwidth, 5);
+ PRINT_BANDWIDTH(bandwidth, 10);
+ PRINT_BANDWIDTH(bandwidth, 1);
+ PRINT_BANDWIDTH(bandwidth, 2);
+ PRINT_BANDWIDTH(bandwidth, 4);
+ PRINT_BANDWIDTH(bandwidth, 8);
+ PRINT_BANDWIDTH(bandwidth, 16);
+ PRINT_BANDWIDTH(bandwidth, 320);
+ printf("\n");
+#undef PRINT_BANDWIDTH
+ }
+ PRINT_FTM_U8(tb, MAX_BURSTS_EXPONENT);
+ PRINT_FTM_U8(tb, MAX_FTMS_PER_BURST);
+ PRINT_FTM_FLAG(tb, ASAP);
+ PRINT_FTM_FLAG(tb, NON_ASAP);
+ PRINT_FTM_FLAG(tb, REQ_LCI);
+ PRINT_FTM_FLAG(tb, REQ_CIVICLOC);
+ PRINT_FTM_FLAG(tb, TRIGGER_BASED);
+ PRINT_FTM_FLAG(tb, NON_TRIGGER_BASED);
+
+#undef PRINT_FTM_U8
+#undef PRINT_FTM_FLAG
+}
+
+static void print_pmsr_capabilities(struct nlattr *pmsr_capa)
+{
+ struct nlattr *tb[NL80211_PMSR_ATTR_MAX + 1];
+ struct nlattr *nla;
+ int size;
+ int ret;
+
+ printf("\tPeer measurement (PMSR)\n");
+ ret = nla_parse_nested(tb, NL80211_PMSR_ATTR_MAX, pmsr_capa, NULL);
+ if (ret) {
+ printf("\t\tMalformed PMSR\n");
+ return;
+ }
+
+ if (tb[NL80211_PMSR_ATTR_MAX_PEERS])
+ printf("\t\tMax peers: %d\n",
+ nla_get_u32(tb[NL80211_PMSR_ATTR_MAX_PEERS]));
+ if (tb[NL80211_PMSR_ATTR_REPORT_AP_TSF])
+ printf("\t\tREPORT_AP_TSF\n");
+ if (tb[NL80211_PMSR_ATTR_RANDOMIZE_MAC_ADDR])
+ printf("\t\tRANDOMIZE_MAC_ADDR\n");
+
+ if (tb[NL80211_PMSR_ATTR_TYPE_CAPA]) {
+ nla_for_each_nested(nla, tb[NL80211_PMSR_ATTR_TYPE_CAPA], size) {
+ switch (nla_type(nla)) {
+ case NL80211_PMSR_TYPE_FTM:
+ __print_ftm_capability(nla);
+ break;
+ }
+ }
+ } else {
+ printf("\t\tPMSR type is missing\n");
+ }
+}
+
static int print_phy_handler(struct nl_msg *msg, void *arg)
{
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
@@ -741,6 +859,9 @@ broken_combination:
pat->max_pattern_len, pat->max_pkt_offset, rule->max_delay);
}

+ if (tb_msg[NL80211_ATTR_PEER_MEASUREMENTS])
+ print_pmsr_capabilities(tb_msg[NL80211_ATTR_PEER_MEASUREMENTS]);
+
if (tb_msg[NL80211_ATTR_MAX_AP_ASSOC_STA])
printf("\tMaximum associated stations in AP mode: %u\n",
nla_get_u16(tb_msg[NL80211_ATTR_MAX_AP_ASSOC_STA]));
--
2.38.0.rc1.362.ged0d419d3c-goog