Copy out some 11n information to net80211 ioctl node records. Use a subset of this info to display the highest AP Rx rate during scan.
Since 11n implies support for 11a/b/g rates up to 54Mbit/s, we only show a legacy rate if the AP doesn't support 11n. In theory, 11n rate suport is not symmetric, ie. the max Tx rate can differ from the max Rx rate. I'd like to keep things simple for now and just show Rx. Rx is more straightforward to parse and, in practice, assymmetric rate support is rare. Note that converting an MCS index to Mbit/s is non-trivial since the actual rate depends on several feature toggles (short guard, wide channels, etc.). Some of these toggles can change at run time so it's impossible to make a good guess in advance. If you really want to know the max Mbit/s value for a given MCS index, go to mcsindex.com. But that won't tell you the actual run-time throughput. Kernel and ifconfig diffs follow. ok? Index: ieee80211_ioctl.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_ioctl.c,v retrieving revision 1.40 diff -u -p -r1.40 ieee80211_ioctl.c --- ieee80211_ioctl.c 4 Jan 2016 12:28:46 -0000 1.40 +++ ieee80211_ioctl.c 27 Apr 2016 11:52:23 -0000 @@ -106,6 +106,12 @@ ieee80211_node2req(struct ieee80211com * nr->nr_flags |= IEEE80211_NODEREQ_AP; if (ni == ic->ic_bss) nr->nr_flags |= IEEE80211_NODEREQ_AP_BSS; + + /* HT */ + nr->nr_htcaps = ni->ni_htcaps; + memcpy(nr->nr_rxmcs, ni->ni_rxmcs, sizeof(nr->nr_rxmcs)); + nr->nr_max_rxrate = ni->ni_max_rxrate; + nr->nr_tx_mcs_set = ni->ni_tx_mcs_set; } void Index: ieee80211_ioctl.h =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_ioctl.h,v retrieving revision 1.24 diff -u -p -r1.24 ieee80211_ioctl.h --- ieee80211_ioctl.h 27 Apr 2016 11:58:10 -0000 1.24 +++ ieee80211_ioctl.h 27 Apr 2016 12:39:01 -0000 @@ -332,6 +332,12 @@ struct ieee80211_nodereq { /* Node flags */ u_int8_t nr_flags; + + /* HT */ + uint16_t nr_htcaps; + uint8_t nr_rxmcs[howmany(80,NBBY)]; + uint16_t nr_max_rxrate; /* in Mb/s, 0 <= rate <= 1023 */ + uint8_t nr_tx_mcs_set; }; #define IEEE80211_NODEREQ_STATE(_s) (1 << _s) Index: ifconfig.c =================================================================== RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v retrieving revision 1.320 diff -u -p -r1.320 ifconfig.c --- ifconfig.c 18 Apr 2016 06:20:23 -0000 1.320 +++ ifconfig.c 27 Apr 2016 12:14:02 -0000 @@ -63,6 +63,7 @@ #include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> +#include <sys/param.h> #include <net/if.h> #include <net/if_dl.h> @@ -2283,7 +2284,7 @@ ieee80211_listnodes(void) void ieee80211_printnode(struct ieee80211_nodereq *nr) { - int len; + int len, i; if (nr->nr_flags & IEEE80211_NODEREQ_AP || nr->nr_capinfo & IEEE80211_CAPINFO_IBSS) { @@ -2311,8 +2312,15 @@ ieee80211_printnode(struct ieee80211_nod if (nr->nr_pwrsave) printf("powersave "); - if (nr->nr_nrates) { - /* Only print the fastest rate */ + /* Only print the fastest rate */ + if (nr->nr_max_rxrate) { + printf("%uM HT ", nr->nr_max_rxrate); + } else if (nr->nr_rxmcs[0] != 0) { + for (i = IEEE80211_HT_NUM_MCS - 1; i >= 0; i--) + if (isset(nr->nr_rxmcs, i)) + break; + printf("HT-MCS%d ", i); + } else if (nr->nr_nrates) { printf("%uM", (nr->nr_rates[nr->nr_nrates - 1] & IEEE80211_RATE_VAL) / 2); putchar(' ');