Skip to content

Commit

Permalink
Add MCS rates parsing for 802.11n
Browse files Browse the repository at this point in the history
Some display code is still broken
  • Loading branch information
Bruno Randolf committed Jun 3, 2013
1 parent aae9d4c commit 68b99df
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 23 deletions.
16 changes: 8 additions & 8 deletions display-main.c
Expand Up @@ -249,7 +249,7 @@ update_status_win(struct packet_info* p)
#define COL_CHAN COL_PKT + 7
#define COL_SNR COL_CHAN + 3
#define COL_RATE COL_SNR + 3
#define COL_SOURCE COL_RATE + 3
#define COL_SOURCE COL_RATE + 4
#define COL_STA COL_SOURCE + 18
#define COL_BSSID COL_STA + 2
#define COL_ENC COL_BSSID + 20
Expand Down Expand Up @@ -291,7 +291,7 @@ print_list_line(int line, struct node_info* n)

mvwprintw(list_win, line, COL_ENC, n->wlan_wep ? "W" : "");

mvwprintw(list_win, line, COL_RATE, "%2d", p->phy_rate/2);
mvwprintw(list_win, line, COL_RATE, "%3d q", p->phy_rate/10);
mvwprintw(list_win, line, COL_SOURCE, "%s", ether_sprintf(p->wlan_src));
mvwprintw(list_win, line, COL_BSSID, "(%s)", ether_sprintf(n->wlan_bssid));

Expand Down Expand Up @@ -331,7 +331,7 @@ update_list_win(void)
mvwprintw(list_win, 0, COL_PKT, "Pk/Re%%");
mvwprintw(list_win, 0, COL_CHAN, "CH");
mvwprintw(list_win, 0, COL_SNR, "SN");
mvwprintw(list_win, 0, COL_RATE, "RT");
mvwprintw(list_win, 0, COL_RATE, "RAT");
mvwprintw(list_win, 0, COL_SOURCE, "SOURCE");
mvwprintw(list_win, 0, COL_STA, "M");
mvwprintw(list_win, 0, COL_BSSID, "(BSSID)");
Expand All @@ -344,10 +344,10 @@ update_list_win(void)
wprintw(list_win, "/No");
nadd = 3;
}
wprintw(list_win, "-RT-SOURCE");
mvwprintw(list_win, win_split - 1, 28 + nadd, "(BSSID)");
mvwprintw(list_win, win_split - 1, 48 + nadd, "TYPE");
mvwprintw(list_win, win_split - 1, 55 + nadd, "INFO");
wprintw(list_win, "-RAT-SOURCE");
mvwprintw(list_win, win_split - 1, 29 + nadd, "(BSSID)");
mvwprintw(list_win, win_split - 1, 49 + nadd, "TYPE");
mvwprintw(list_win, win_split - 1, 56 + nadd, "INFO");
mvwprintw(list_win, win_split - 1, COLS-10, "LiveStatus");

if (sortfunc)
Expand Down Expand Up @@ -393,7 +393,7 @@ update_dump_win(struct packet_info* p)
wprintw(dump_win, "/%02d ", -p->phy_noise);
else
wprintw(dump_win, " ");
wprintw(dump_win, "%2d ", p->phy_rate/2);
wprintw(dump_win, "%3d ", p->phy_rate/10);
wprintw(dump_win, "%s ", ether_sprintf(p->wlan_src));
wprintw(dump_win, "(%s) ", ether_sprintf(p->wlan_bssid));

Expand Down
28 changes: 28 additions & 0 deletions ieee80211_radiotap.h
Expand Up @@ -181,6 +181,12 @@ struct ieee80211_radiotap_header {
* IEEE80211_RADIOTAP_DATA_RETRIES u_int8_t data
*
* Number of unicast retries a transmitted frame used.
*
* IEEE80211_RADIOTAP_MCS u_int8_t, u_int8_t, u_int8_t unitless
*
* Contains a bitmap of known fields/flags, the flags, and
* the MCS index.
*
*/
enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TSFT = 0,
Expand All @@ -201,6 +207,12 @@ enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TX_FLAGS = 15,
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
IEEE80211_RADIOTAP_DATA_RETRIES = 17,

IEEE80211_RADIOTAP_MCS = 19,

/* valid in every it_present bitmap, even vendor namespaces */
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
IEEE80211_RADIOTAP_EXT = 31,
};

Expand Down Expand Up @@ -266,4 +278,20 @@ enum ieee80211_radiotap_type {
#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */

/* MCS */
#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01
#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02
#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10

#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
#define IEEE80211_RADIOTAP_MCS_BW_20 0
#define IEEE80211_RADIOTAP_MCS_BW_40 1
#define IEEE80211_RADIOTAP_MCS_BW_20L 2
#define IEEE80211_RADIOTAP_MCS_BW_20U 3
#define IEEE80211_RADIOTAP_MCS_SGI 0x04
#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10

#endif /* _NET_IF_IEEE80211RADIOTAP_H_ */
2 changes: 1 addition & 1 deletion main.h
Expand Up @@ -114,7 +114,7 @@ struct packet_info {
int phy_signal; /* signal strength (usually dBm) */
int phy_noise; /* noise level (usually dBm) */
unsigned int phy_snr; /* signal to noise ratio */
unsigned int phy_rate; /* physical rate */
unsigned int phy_rate; /* physical rate * 10 (=in 100kbps) */
unsigned int phy_freq; /* frequency from driver */
unsigned char phy_chan; /* channel from driver */
unsigned int phy_flags; /* A, B, G, shortpre */
Expand Down
2 changes: 1 addition & 1 deletion network.c
Expand Up @@ -104,7 +104,7 @@ struct net_packet_info {
int phy_signal; /* signal strength (usually dBm) */
int phy_noise; /* noise level (usually dBm) */
unsigned int phy_snr; /* signal to noise ratio */
unsigned int phy_rate; /* physical rate */
unsigned int phy_rate; /* physical rate * 10 (= in 100kbps) */
unsigned int phy_freq; /* frequency (unused) */
unsigned char phy_chan; /* channel from driver */
unsigned int phy_flags; /* A, B, G, shortpre */
Expand Down
88 changes: 75 additions & 13 deletions protocol_parser.c
Expand Up @@ -125,20 +125,20 @@ parse_prism_header(unsigned char** buf, int len, struct packet_info* p)
p->phy_snr = ph->signal.data - ph->noise.data; //XXX rssi?
}

p->phy_rate = ph->rate.data;
p->phy_rate = ph->rate.data * 10;

/* just in case...*/
if (p->phy_snr < 0)
p->phy_snr = -p->phy_snr;
if (p->phy_snr > 99)
p->phy_snr = 99;
if (p->phy_rate == 0 || p->phy_rate > 108) {
if (p->phy_rate == 0 || p->phy_rate > 1080) {
/* assume min rate, guess mode from channel */
DEBUG("*** fixing wrong rate\n");
if (ph->channel.data > 14)
p->phy_rate = 12; /* 6 * 2 */
p->phy_rate = 120; /* 6 * 2 */
else
p->phy_rate = 2; /* 1 * 2 */
p->phy_rate = 20; /* 1 * 2 */
}

/* guess phy mode */
Expand Down Expand Up @@ -169,6 +169,7 @@ parse_radiotap_header(unsigned char** buf, int len, struct packet_info* p)
unsigned char* b; /* current byte */
int i;
u16 rt_len, x;
unsigned char known, flags, ht20, lgi;

DEBUG("RADIOTAP HEADER\n");

Expand All @@ -193,8 +194,8 @@ parse_radiotap_header(unsigned char** buf, int len, struct packet_info* p)
present = le32toh(rh->it_present); // in case it moved

/* radiotap bitmap has 32 bit, but we are only interrested until
* bit 12 (IEEE80211_RADIOTAP_DB_ANTSIGNAL) => i<13 */
for (i = 0; i < 13 && b - *buf < rt_len; i++) {
* bit 19 (IEEE80211_RADIOTAP_MCS) => i<20 */
for (i = 0; i < 20 && b - *buf < rt_len; i++) {
if ((present >> i) & 1) {
DEBUG("1");
switch (i) {
Expand Down Expand Up @@ -226,7 +227,7 @@ parse_radiotap_header(unsigned char** buf, int len, struct packet_info* p)
/* we are only interrested in these: */
case IEEE80211_RADIOTAP_RATE:
DEBUG("[rate %0x]", *b);
p->phy_rate = (*b);
p->phy_rate = (*b)*10;
b++;
break;
case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
Expand Down Expand Up @@ -281,6 +282,67 @@ parse_radiotap_header(unsigned char** buf, int len, struct packet_info* p)
}
b = b + 2;
break;
case IEEE80211_RADIOTAP_MCS:
/* Ref http://www.radiotap.org/defined-fields/MCS */
b++;
known = *b;
DEBUG("[MCS known %0x", *b);
b++;
flags = *b;
DEBUG(" flags %0x ", *b);
b++;//b = b + 2;
DEBUG(" index %0x]", *b);

if (known & IEEE80211_RADIOTAP_MCS_HAVE_BW) {
ht20 = (flags & IEEE80211_RADIOTAP_MCS_BW_MASK) == IEEE80211_RADIOTAP_MCS_BW_20;
DEBUG(" HT20 %d", ht20);
} else
ht20 = 1; /* assume HT20 if not present */

if (known & IEEE80211_RADIOTAP_MCS_HAVE_GI) {
lgi = !(flags & IEEE80211_RADIOTAP_MCS_SGI);
DEBUG(" LGI %d", lgi);
} else
lgi = 1; /* assume long GI if not present */

/* MCS Index, http://en.wikipedia.org/wiki/IEEE_802.11n-2009#Data_rates */
switch (*b) {
case 0: p->phy_rate = ht20 ? (lgi ? 65 : 72) : (lgi ? 135 : 150); break;
case 1: p->phy_rate = ht20 ? (lgi ? 130 : 144) : (lgi ? 270 : 300); break;
case 2: p->phy_rate = ht20 ? (lgi ? 195 : 217) : (lgi ? 405 : 450); break;
case 3: p->phy_rate = ht20 ? (lgi ? 260 : 289) : (lgi ? 540 : 600); break;
case 4: p->phy_rate = ht20 ? (lgi ? 390 : 433) : (lgi ? 810 : 900); break;
case 5: p->phy_rate = ht20 ? (lgi ? 520 : 578) : (lgi ? 1080 : 1200); break;
case 6: p->phy_rate = ht20 ? (lgi ? 585 : 650) : (lgi ? 1215 : 1350); break;
case 7: p->phy_rate = ht20 ? (lgi ? 650 : 722) : (lgi ? 1350 : 1500); break;
case 8: p->phy_rate = ht20 ? (lgi ? 130 : 144) : (lgi ? 270 : 300); break;
case 9: p->phy_rate = ht20 ? (lgi ? 260 : 289) : (lgi ? 540 : 600); break;
case 10: p->phy_rate = ht20 ? (lgi ? 390 : 433) : (lgi ? 810 : 900); break;
case 11: p->phy_rate = ht20 ? (lgi ? 520 : 578) : (lgi ? 1080 : 1200); break;
case 12: p->phy_rate = ht20 ? (lgi ? 780 : 867) : (lgi ? 1620 : 1800); break;
case 13: p->phy_rate = ht20 ? (lgi ? 1040 : 1156) : (lgi ? 2160 : 2400); break;
case 14: p->phy_rate = ht20 ? (lgi ? 1170 : 1300) : (lgi ? 2430 : 2700); break;
case 15: p->phy_rate = ht20 ? (lgi ? 1300 : 1444) : (lgi ? 2700 : 3000); break;
case 16: p->phy_rate = ht20 ? (lgi ? 195 : 217) : (lgi ? 405 : 450); break;
case 17: p->phy_rate = ht20 ? (lgi ? 39 : 433) : (lgi ? 810 : 900); break;
case 18: p->phy_rate = ht20 ? (lgi ? 585 : 650) : (lgi ? 1215 : 1350); break;
case 19: p->phy_rate = ht20 ? (lgi ? 78 : 867) : (lgi ? 1620 : 1800); break;
case 20: p->phy_rate = ht20 ? (lgi ? 1170 : 1300) : (lgi ? 2430 : 2700); break;
case 21: p->phy_rate = ht20 ? (lgi ? 1560 : 1733) : (lgi ? 3240 : 3600); break;
case 22: p->phy_rate = ht20 ? (lgi ? 1755 : 1950) : (lgi ? 3645 : 4050); break;
case 23: p->phy_rate = ht20 ? (lgi ? 1950 : 2167) : (lgi ? 4050 : 4500); break;
case 24: p->phy_rate = ht20 ? (lgi ? 260 : 288) : (lgi ? 540 : 600); break;
case 25: p->phy_rate = ht20 ? (lgi ? 520 : 576) : (lgi ? 1080 : 1200); break;
case 26: p->phy_rate = ht20 ? (lgi ? 780 : 868) : (lgi ? 1620 : 1800); break;
case 27: p->phy_rate = ht20 ? (lgi ? 1040 : 1156) : (lgi ? 2160 : 2400); break;
case 28: p->phy_rate = ht20 ? (lgi ? 1560 : 1732) : (lgi ? 3240 : 3600); break;
case 29: p->phy_rate = ht20 ? (lgi ? 2080 : 2312) : (lgi ? 4320 : 4800); break;
case 30: p->phy_rate = ht20 ? (lgi ? 2340 : 2600) : (lgi ? 4860 : 5400); break;
case 31: p->phy_rate = ht20 ? (lgi ? 2600 : 2888) : (lgi ? 5400 : 6000); break;
}
DEBUG(" RATE %d ", p->phy_rate);
b++;
break;
}
}
else {
Expand All @@ -305,20 +367,20 @@ parse_radiotap_header(unsigned char** buf, int len, struct packet_info* p)
/* sanitize */
if (p->phy_snr > 99)
p->phy_snr = 99;
if (p->phy_rate == 0 || p->phy_rate > 108) {
if (p->phy_rate == 0 || p->phy_rate > 6000) {
/* assume min rate for mode */
DEBUG("*** fixing wrong rate\n");
if (p->phy_flags & PHY_FLAG_A)
p->phy_rate = 12; /* 6 * 2 */
p->phy_rate = 120; /* 6 * 2 */
else if (p->phy_flags & PHY_FLAG_B)
p->phy_rate = 2; /* 1 * 2 */
p->phy_rate = 20; /* 1 * 2 */
else if (p->phy_flags & PHY_FLAG_G)
p->phy_rate = 12; /* 6 * 2 */
p->phy_rate = 120; /* 6 * 2 */
else
p->phy_rate = 2;
p->phy_rate = 20;
}

DEBUG("\nrate: %d\n", p->phy_rate);
DEBUG("\nrate: %.2f\n", (float)p->phy_rate/10);
DEBUG("signal: %d\n", p->phy_signal);
DEBUG("noise: %d\n", p->phy_noise);
DEBUG("snr: %d\n", p->phy_snr);
Expand Down

0 comments on commit 68b99df

Please sign in to comment.