I'd like to add some 802.11n-related counters to netstat -W output.
The first diff below is for the kernel, the second for netstat.
ok?
Index: ieee80211_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.171
diff -u -p -r1.171 ieee80211_input.c
--- ieee80211_input.c 15 Apr 2016 03:04:27 -0000 1.171
+++ ieee80211_input.c 27 Apr 2016 11:30:08 -0000
@@ -707,7 +707,7 @@ ieee80211_input_ba(struct ieee80211com *
timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);
if (SEQ_LT(sn, ba->ba_winstart)) { /* SN < WinStartB */
- ic->ic_stats.is_rx_dup++;
+ ic->ic_stats.is_ht_rx_frame_below_ba_winstart++;
m_freem(m); /* discard the MPDU */
return;
}
@@ -730,6 +730,7 @@ ieee80211_input_ba(struct ieee80211com *
"%d, expecting %d:%d\n", __func__,
sn, ba->ba_winstart, ba->ba_winend);
#endif
+ ic->ic_stats.is_ht_rx_frame_above_ba_winend++;
if (count > ba->ba_winsize) {
if (ba->ba_winmiss < IEEE80211_BA_MAX_WINMISS) {
if (ba->ba_missedsn == sn - 1)
@@ -743,6 +744,7 @@ ieee80211_input_ba(struct ieee80211com *
}
/* It appears the window has moved for real. */
+ ic->ic_stats.is_ht_rx_ba_window_jump++;
ba->ba_winmiss = 0;
ba->ba_missedsn = 0;
@@ -754,7 +756,8 @@ ieee80211_input_ba(struct ieee80211com *
ieee80211_input(ifp, ba->ba_buf[ba->ba_head].m,
ni, &ba->ba_buf[ba->ba_head].rxi);
ba->ba_buf[ba->ba_head].m = NULL;
- }
+ } else
+ ic->ic_stats.is_ht_rx_ba_frame_lost++;
ba->ba_head = (ba->ba_head + 1) %
IEEE80211_BA_MAX_WINSZ;
}
@@ -769,6 +772,7 @@ ieee80211_input_ba(struct ieee80211com *
/* store the received MPDU in the buffer */
if (ba->ba_buf[idx].m != NULL) {
ifp->if_ierrors++;
+ ic->ic_stats.is_ht_rx_ba_no_buf++;
m_freem(m);
return;
}
@@ -820,6 +824,8 @@ ieee80211_input_ba_gap_timeout(void *arg
struct ieee80211com *ic = ni->ni_ic;
int s, skipped;
+ ic->ic_stats.is_ht_rx_ba_window_gap_timeout++;
+
s = splnet();
skipped = 0;
@@ -828,6 +834,7 @@ ieee80211_input_ba_gap_timeout(void *arg
ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;
ba->ba_winstart = (ba->ba_winstart + 1) & 0xfff;
skipped++;
+ ic->ic_stats.is_ht_rx_ba_frame_lost++;
}
if (skipped > 0)
ba->ba_winend = (ba->ba_winstart + ba->ba_winsize - 1) & 0xfff;
@@ -861,7 +868,8 @@ ieee80211_ba_move_window(struct ieee8021
ieee80211_input(ifp, ba->ba_buf[ba->ba_head].m, ni,
&ba->ba_buf[ba->ba_head].rxi);
ba->ba_buf[ba->ba_head].m = NULL;
- }
+ } else
+ ic->ic_stats.is_ht_rx_ba_frame_lost++;
ba->ba_head = (ba->ba_head + 1) % IEEE80211_BA_MAX_WINSZ;
}
/* move window forward */
@@ -1580,6 +1588,7 @@ ieee80211_recv_probe_resp(struct ieee802
DPRINTF(("[%s] htprot change: was %d, now %d\n",
ether_sprintf((u_int8_t *)wh->i_addr2),
htprot_last, htprot));
+ ic->ic_stats.is_ht_prot_change++;
ic->ic_bss->ni_htop1 = ni->ni_htop1;
ic->ic_update_htprot(ic, ic->ic_bss);
}
@@ -2491,6 +2500,7 @@ ieee80211_recv_addba_req(struct ieee8021
goto resp;
}
ba->ba_state = IEEE80211_BA_AGREED;
+ ic->ic_stats.is_ht_rx_ba_agreements++;
/* start Block Ack inactivity timer */
if (ba->ba_timeout_val != 0)
timeout_add_usec(&ba->ba_to, ba->ba_timeout_val);
@@ -2561,6 +2571,7 @@ ieee80211_recv_addba_resp(struct ieee802
}
/* MLME-ADDBA.confirm(Success) */
ba->ba_state = IEEE80211_BA_AGREED;
+ ic->ic_stats.is_ht_tx_ba_agreements++;
/* notify drivers of this new Block Ack agreement */
if (ic->ic_ampdu_tx_start != NULL)
Index: ieee80211_ioctl.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_ioctl.h,v
retrieving revision 1.23
diff -u -p -r1.23 ieee80211_ioctl.h
--- ieee80211_ioctl.h 12 Jan 2016 09:28:09 -0000 1.23
+++ ieee80211_ioctl.h 27 Apr 2016 11:19:38 -0000
@@ -95,6 +95,20 @@ struct ieee80211_stats {
u_int32_t is_cmac_replays;
u_int32_t is_cmac_icv_errs;
u_int32_t is_pbac_errs;
+ u_int32_t is_ht_nego_no_mandatory_mcs;
+ u_int32_t is_ht_nego_no_basic_mcs;
+ u_int32_t is_ht_nego_bad_crypto;
+ u_int32_t is_ht_prot_change;
+ u_int32_t is_ht_rx_ba_agreements;
+ u_int32_t is_ht_tx_ba_agreements;
+ u_int32_t is_ht_rx_frame_below_ba_winstart;
+ u_int32_t is_ht_rx_frame_above_ba_winend;
+ u_int32_t is_ht_rx_ba_window_jump;
+ u_int32_t is_ht_rx_ba_no_buf;
+ u_int32_t is_ht_rx_ba_frame_lost;
+ u_int32_t is_ht_rx_ba_window_gap_timeout;
+ u_int32_t is_ht_rx_ba_timeout;
+ u_int32_t is_ht_tx_ba_timeout;
};
#define SIOCG80211STATS _IOWR('i', 242, struct ifreq)
Index: ieee80211_proto.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_proto.c,v
retrieving revision 1.65
diff -u -p -r1.65 ieee80211_proto.c
--- ieee80211_proto.c 12 Apr 2016 14:33:27 -0000 1.65
+++ ieee80211_proto.c 27 Apr 2016 10:42:05 -0000
@@ -560,15 +560,19 @@ ieee80211_ht_negotiate(struct ieee80211c
return;
/* Check if the peer supports HT. MCS 0-7 are mandatory. */
- if (ni->ni_rxmcs[0] != 0xff)
+ if (ni->ni_rxmcs[0] != 0xff) {
+ ic->ic_stats.is_ht_nego_no_mandatory_mcs++;
return;
+ }
if (ic->ic_opmode == IEEE80211_M_STA) {
/* We must support the AP's basic MCS set. */
for (i = 0; i < IEEE80211_HT_NUM_MCS; i++) {
if (isset(ni->ni_basic_mcs, i) &&
- !isset(ic->ic_sup_mcs, i))
+ !isset(ic->ic_sup_mcs, i)) {
+ ic->ic_stats.is_ht_nego_no_basic_mcs++;
return;
+ }
}
}
@@ -576,12 +580,16 @@ ieee80211_ht_negotiate(struct ieee80211c
* Don't allow group cipher (includes WEP) or TKIP
* for pairwise encryption (see 802.11-2012 11.1.6).
*/
- if (ic->ic_flags & IEEE80211_F_WEPON)
+ if (ic->ic_flags & IEEE80211_F_WEPON) {
+ ic->ic_stats.is_ht_nego_bad_crypto++;
return;
+ }
if ((ic->ic_flags & IEEE80211_F_RSNON) &&
(ni->ni_rsnciphers & IEEE80211_CIPHER_USEGROUP ||
- ni->ni_rsnciphers & IEEE80211_CIPHER_TKIP))
+ ni->ni_rsnciphers & IEEE80211_CIPHER_TKIP)) {
+ ic->ic_stats.is_ht_nego_bad_crypto++;
return;
+ }
ni->ni_flags |= IEEE80211_NODE_HT;
}
@@ -595,6 +603,8 @@ ieee80211_tx_ba_timeout(void *arg)
u_int8_t tid;
int s;
+ ic->ic_stats.is_ht_tx_ba_timeout++;
+
s = splnet();
if (ba->ba_state == IEEE80211_BA_REQUESTED) {
/* MLME-ADDBA.confirm(TIMEOUT) */
@@ -618,6 +628,8 @@ ieee80211_rx_ba_timeout(void *arg)
u_int8_t tid;
int s;
+ ic->ic_stats.is_ht_rx_ba_timeout++;
+
s = splnet();
/* Block Ack inactivity timeout */
Index: net80211.c
===================================================================
RCS file: /cvs/src/usr.bin/netstat/net80211.c,v
retrieving revision 1.13
diff -u -p -r1.13 net80211.c
--- net80211.c 16 Jan 2015 06:40:10 -0000 1.13
+++ net80211.c 27 Apr 2016 11:29:11 -0000
@@ -114,6 +114,30 @@ net80211_ifstats(char *ifname)
p(is_cmac_replays, "\t%lu cmac replayed frame%s\n");
p(is_tkip_icv_errs, "\t%lu tkip icv error%s\n");
p(is_tkip_replays, "\t%lu tkip replay%s\n");
+ p(is_pbac_errs, "\t%lu pbac error%s\n");
+ p(is_ht_nego_no_mandatory_mcs, "\t%lu HT negotiation failure%s because "
+ "peer does not support MCS 0-7\n");
+ p(is_ht_nego_no_mandatory_mcs, "\t%lu HT negotiation failure%s because "
+ "we do not support basic MCS set\n");
+ p(is_ht_nego_bad_crypto,
+ "\t%lu HT negotiation failure%s because peer uses bad crypto\n");
+ p(is_ht_prot_change, "\t%lu HT protection change%s\n");
+ p(is_ht_rx_ba_agreements, "\t%lu new input block ack agreement%s\n");
+ p(is_ht_tx_ba_agreements, "\t%lu new output block ack agreement%s\n");
+ p(is_ht_rx_frame_below_ba_winstart,
+ "\t%lu input frame%s below block ack window start\n");
+ p(is_ht_rx_frame_above_ba_winend,
+ "\t%lu input frame%s above block ack window end\n");
+ p(is_ht_rx_ba_window_jump, "\t%lu input block ack window jump%s\n");
+ p(is_ht_rx_ba_no_buf, "\t%lu duplicate input block ack frame%s\n");
+ p(is_ht_rx_ba_frame_lost,
+ "\t%lu expected input block ack frame%s never arrived\n");
+ p(is_ht_rx_ba_window_gap_timeout,
+ "\t%lu input block ack window gap%s timed out\n");
+ p(is_ht_rx_ba_timeout,
+ "\t%lu input block ack agreement%s timed out\n");
+ p(is_ht_tx_ba_timeout,
+ "\t%lu output block ack agreement%s timed out\n");
close(s);