Print PMSR and FTM capabilities if any. Signed-off-by: Jaewan Kim <jaewan@xxxxxxxxxx> --- 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