When I added support for the HT Capabilities element to tcpdump(1) I left out a couple of fields we did not yet have #defines for.
Since these fields contain valuable information (such as the MCS rates supported by an AP), let's print them, too. ok? Index: sys/net80211/ieee80211.h =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211.h,v retrieving revision 1.52 diff -u -p -r1.52 ieee80211.h --- sys/net80211/ieee80211.h 14 Jul 2015 21:13:12 -0000 1.52 +++ sys/net80211/ieee80211.h 9 Oct 2015 12:11:03 -0000 @@ -572,6 +572,29 @@ enum { #define IEEE80211_HTCAP_LSIGTXOPPROT 0x00008000 /* + * HT A-MPDU parameters (see 802.11-2012 8.4.2.58.3). + */ +#define IEEE80211_AMPDU_PARAM_LE 0x03 +#define IEEE80211_AMPDU_PARAM_SS 0x1c + +/* + * HT Supported MCS Set (see 802.11-2012 8.4.2.58.4). + * This field is 16 bytes in size. Bitmasks given below + * operate on 8 or 16 bit integer subsets of this field. + */ +/* Bits 0-77: Supported Rx MCS bitmask */ +/* Bits 77-79: Reserved */ +/* Bits 80-89: Highest Rx rate in units of 1MB/s */ +#define IEEE80211_MCS_RX_RATE_HIGH 0x03ff +/* Bits 90-95: Reserved */ +/* Bits 96-100: Tx MCS set */ +#define IEEE80211_TX_MCS_SET_DEFINED 0x01 +#define IEEE80211_TX_RX_MCS_NOT_EQUAL 0x02 +#define IEEE80211_TX_SPATIAL_STREAMS 0x18 +#define IEEE80211_TX_UNEQUAL_MODULATION 0x20 +/* Bits 101-127: Reserved */ + +/* * HT Extended Capabilities (see 802.11-2012 8.4.2.58.5). */ #define IEEE80211_HTXCAP_PCO 0x0001 Index: usr.sbin/tcpdump/Makefile =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/Makefile,v retrieving revision 1.56 diff -u -p -r1.56 Makefile --- usr.sbin/tcpdump/Makefile 30 Jun 2014 04:25:11 -0000 1.56 +++ usr.sbin/tcpdump/Makefile 9 Oct 2015 11:01:27 -0000 @@ -30,7 +30,7 @@ CFLAGS+=-I${.CURDIR}/../../lib/libpcap CFLAGS+=-DCSLIP -DPPP -DHAVE_FDDI -DETHER_SERVICE -DRETSIGTYPE=void -DHAVE_NET_SLIP_H -DHAVE_ETHER_NTOHOST -DINET6 -LDADD+= -lpcap -ll -lcrypto +LDADD+= -lpcap -ll -lcrypto -lm DPADD+= ${LIBL} ${LIBPCAP} ${LIBCRYPTO} SRCS= tcpdump.c addrtoname.c privsep.c privsep_fdpass.c privsep_pcap.c \ Index: usr.sbin/tcpdump/print-802_11.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-802_11.c,v retrieving revision 1.24 diff -u -p -r1.24 print-802_11.c --- usr.sbin/tcpdump/print-802_11.c 19 Jul 2015 02:49:54 -0000 1.24 +++ usr.sbin/tcpdump/print-802_11.c 9 Oct 2015 12:16:33 -0000 @@ -33,6 +33,7 @@ #include <pcap.h> #include <stdio.h> #include <string.h> +#include <math.h> #include "addrtoname.h" #include "interface.h" @@ -279,8 +280,11 @@ ieee80211_print_country(u_int8_t *data, void ieee80211_print_htcaps(u_int8_t *data, u_int len) { - u_int16_t htcaps; + uint16_t htcaps, rxrate; int smps, rxstbc; + uint8_t ampdu, txmcs; + int i; + uint8_t *rxmcs; if (len < 2) { ieee80211_print_element(data, len); @@ -347,6 +351,83 @@ ieee80211_print_htcaps(u_int8_t *data, u /* L-SIG TXOP protection */ if (htcaps & IEEE80211_HTCAP_LSIGTXOPPROT) printf(",L-SIG TXOP prot"); + + if (len < 3) { + printf(">"); + return; + } + + /* A-MPDU parameters. */ + ampdu = data[2]; + + /* A-MPDU length exponent */ + if ((ampdu & IEEE80211_AMPDU_PARAM_LE) >= 0 && + (ampdu & IEEE80211_AMPDU_PARAM_LE) <= 3) + printf(",A-MPDU max %d", + (int)(exp2f(13 + (ampdu & IEEE80211_AMPDU_PARAM_LE)) - 1)); + + /* A-MPDU start spacing */ + if (ampdu & IEEE80211_AMPDU_PARAM_SS) { + float ss; + + switch ((ampdu & IEEE80211_AMPDU_PARAM_SS) >> 2) { + case 1: + ss = 0.25; + break; + case 2: + ss = 0.5; + break; + case 3: + ss = 1; + break; + case 4: + ss = 2; + break; + case 5: + ss = 4; + break; + case 6: + ss = 8; + break; + case 7: + ss = 16; + break; + default: + ss = 0; + break; + } + if (ss != 0) + printf(",A-MPDU spacing %.2fus", ss); + } + + if (len < 21) { + printf(">"); + return; + } + + /* Supported MCS set. */ + printf(",RxMCS 0x"); + rxmcs = &data[3]; + for (i = 0; i < 10; i++) + printf("%x", rxmcs[i]); + + /* Max MCS Rx rate (a value of 0 means "not specified"). */ + rxrate = ((data[13] | (data[14]) << 8) & IEEE80211_MCS_RX_RATE_HIGH); + if (rxrate) + printf(",RxMaxrate %huMb/s", rxrate); + + /* Tx MCS Set */ + txmcs = data[15]; + if (txmcs & IEEE80211_TX_MCS_SET_DEFINED) { + if (txmcs & IEEE80211_TX_RX_MCS_NOT_EQUAL) { + /* Number of spatial Tx streams. */ + printf(",%d Tx streams", + 1 + ((txmcs & IEEE80211_TX_SPATIAL_STREAMS) >> 2)); + /* Transmit unequal modulation supported. */ + if (txmcs & IEEE80211_TX_UNEQUAL_MODULATION) + printf(",UEQM"); + } + } printf(">"); }