Currently tcpdump shows "0 Mbit/s" for any frame sent with 11n HT MCS.
To make progress easier, I'd like to see which MCS are used on the air,
by any device.
The change below matches what FreeBSD did to pass an MCS index via radiotap.
This simply writes the MCS index into a previously unused range of rate values.
This format is already recognized by third party tools such as wireshark
so let's just do it the same way.
The diff below updates the radiotap docs, makes iwn pass the MCS index,
shows it in tcpdump. I can now see MCS with iwn in monitor mode.
ok?
Index: sys/net80211/ieee80211_radiotap.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_radiotap.h,v
retrieving revision 1.13
diff -u -p -r1.13 ieee80211_radiotap.h
--- sys/net80211/ieee80211_radiotap.h 12 Jan 2016 09:28:09 -0000 1.13
+++ sys/net80211/ieee80211_radiotap.h 7 Oct 2016 13:15:59 -0000
@@ -90,9 +90,10 @@ struct ieee80211_radiotap_header {
* For frequency-hopping radios, the hop set (first byte)
* and pattern (second byte).
*
- * IEEE80211_RADIOTAP_RATE u_int8_t 500kb/s
+ * IEEE80211_RADIOTAP_RATE u_int8_t 500kb/s or MCS index
*
- * Tx/Rx data rate
+ * Tx/Rx data rate in units of 500kb/s. If the high bit (0x80) is set
+ * the remaining bits contain an MCS index instead of a date rate.
*
* IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from
* one milliwatt (dBm)
Index: sys/dev/pci/if_iwn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.172
diff -u -p -r1.172 if_iwn.c
--- sys/dev/pci/if_iwn.c 5 Sep 2016 08:18:18 -0000 1.172
+++ sys/dev/pci/if_iwn.c 7 Oct 2016 13:10:42 -0000
@@ -2131,23 +2131,27 @@ iwn_rx_done(struct iwn_softc *sc, struct
tap->wr_dbm_antsignal = (int8_t)rssi;
tap->wr_dbm_antnoise = (int8_t)sc->noise;
tap->wr_tsft = stat->tstamp;
- switch (stat->rate) {
- /* CCK rates. */
- case 10: tap->wr_rate = 2; break;
- case 20: tap->wr_rate = 4; break;
- case 55: tap->wr_rate = 11; break;
- case 110: tap->wr_rate = 22; break;
- /* OFDM rates. */
- case 0xd: tap->wr_rate = 12; break;
- case 0xf: tap->wr_rate = 18; break;
- case 0x5: tap->wr_rate = 24; break;
- case 0x7: tap->wr_rate = 36; break;
- case 0x9: tap->wr_rate = 48; break;
- case 0xb: tap->wr_rate = 72; break;
- case 0x1: tap->wr_rate = 96; break;
- case 0x3: tap->wr_rate = 108; break;
- /* Unknown rate: should not happen. */
- default: tap->wr_rate = 0;
+ if (stat->rflags & IWN_RFLAG_MCS) {
+ tap->wr_rate = (0x80 | stat->rate); /* HT MCS index */
+ } else {
+ switch (stat->rate) {
+ /* CCK rates. */
+ case 10: tap->wr_rate = 2; break;
+ case 20: tap->wr_rate = 4; break;
+ case 55: tap->wr_rate = 11; break;
+ case 110: tap->wr_rate = 22; break;
+ /* OFDM rates. */
+ case 0xd: tap->wr_rate = 12; break;
+ case 0xf: tap->wr_rate = 18; break;
+ case 0x5: tap->wr_rate = 24; break;
+ case 0x7: tap->wr_rate = 36; break;
+ case 0x9: tap->wr_rate = 48; break;
+ case 0xb: tap->wr_rate = 72; break;
+ case 0x1: tap->wr_rate = 96; break;
+ case 0x3: tap->wr_rate = 108; break;
+ /* Unknown rate: should not happen. */
+ default: tap->wr_rate = 0;
+ }
}
mb.m_data = (caddr_t)tap;
@@ -2876,8 +2880,7 @@ iwn_tx(struct iwn_softc *sc, struct mbuf
if ((ni->ni_flags & IEEE80211_NODE_HT) &&
!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
type == IEEE80211_FC0_TYPE_DATA) {
- /* XXX need a way to pass current MCS in 11n mode */
- tap->wt_rate = 0;
+ tap->wt_rate = (0x80 | ni->ni_txmcs);
} else
tap->wt_rate = rinfo->rate;
tap->wt_hwqueue = ac;
Index: usr.sbin/tcpdump/print-802_11.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/print-802_11.c,v
retrieving revision 1.33
diff -u -p -r1.33 print-802_11.c
--- usr.sbin/tcpdump/print-802_11.c 2 Sep 2016 17:11:46 -0000 1.33
+++ usr.sbin/tcpdump/print-802_11.c 7 Oct 2016 12:44:25 -0000
@@ -1075,8 +1075,13 @@ ieee802_11_radio_if_print(u_char *user,
if (RADIOTAP(RATE)) {
TCHECK2(*t, 1);
- if (vflag)
- printf(", %uMbit/s", (*(u_int8_t*)t) / 2);
+ if (vflag) {
+ uint8_t rate = *(u_int8_t*)t;
+ if (rate & 0x80)
+ printf(", MCS %u", rate & 0x7f);
+ else
+ printf(", %uMbit/s", rate / 2);
+ }
t += 1;
}