1 /*- 2 * Copyright (c) 2007 Sam Leffler, Errno Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 * 29 * $FreeBSD$ 30 */ 31 32 /* 33 * mwl statistics class. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/file.h> 38 #include <sys/ioctl.h> 39 #include <sys/sockio.h> 40 #include <sys/socket.h> 41 42 #include <net/if.h> 43 #include <net/if_media.h> 44 45 #include <err.h> 46 #include <signal.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 52 #include "../../../../sys/net80211/ieee80211_ioctl.h" 53 #include "../../../../sys/net80211/ieee80211_radiotap.h" 54 55 /* 56 * Get Hardware Statistics. 57 */ 58 struct mwl_hal_hwstats { 59 uint32_t TxRetrySuccesses; 60 uint32_t TxMultipleRetrySuccesses; 61 uint32_t TxFailures; 62 uint32_t RTSSuccesses; 63 uint32_t RTSFailures; 64 uint32_t AckFailures; 65 uint32_t RxDuplicateFrames; 66 uint32_t FCSErrorCount; 67 uint32_t TxWatchDogTimeouts; 68 uint32_t RxOverflows; 69 uint32_t RxFragErrors; 70 uint32_t RxMemErrors; 71 uint32_t PointerErrors; 72 uint32_t TxUnderflows; 73 uint32_t TxDone; 74 uint32_t TxDoneBufTryPut; 75 uint32_t TxDoneBufPut; 76 uint32_t Wait4TxBuf; 77 uint32_t TxAttempts; 78 uint32_t TxSuccesses; 79 uint32_t TxFragments; 80 uint32_t TxMulticasts; 81 uint32_t RxNonCtlPkts; 82 uint32_t RxMulticasts; 83 uint32_t RxUndecryptableFrames; 84 uint32_t RxICVErrors; 85 uint32_t RxExcludedFrames; 86 }; 87 #include "../../../../sys/dev/mwl/if_mwlioctl.h" 88 89 #include "mwlstats.h" 90 91 #define AFTER(prev) ((prev)+1) 92 93 static const struct fmt mwlstats[] = { 94 #define S_INPUT 0 95 { 8, "input", "input", "total frames received" }, 96 #define S_RX_MCAST AFTER(S_INPUT) 97 { 7, "rxmcast", "rxmcast", "rx multicast frames" }, 98 #define S_RX_NONCTL AFTER(S_RX_MCAST) 99 { 8, "rxnonctl", "rxnonctl" "rx non control frames" }, 100 #define S_RX_MGT AFTER(S_RX_NONCTL) 101 { 5, "rxmgt", "rxmgt", "rx management frames" }, 102 #define S_RX_CTL AFTER(S_RX_MGT) 103 { 5, "rxctl", "rxctl", "rx control frames" }, 104 #define S_OUTPUT AFTER(S_RX_CTL) 105 { 8, "output", "output", "total frames transmit" }, 106 #define S_TX_MCAST AFTER(S_OUTPUT) 107 { 7, "txmcast", "txmcast", "tx multicast frames" }, 108 #define S_TX_MGMT AFTER(S_TX_MCAST) 109 { 5, "txmgt", "txmgt", "tx management frames" }, 110 #define S_TX_RETRY AFTER(S_TX_MGMT) 111 { 7, "txretry", "txretry", "tx success with 1 retry" }, 112 #define S_TX_MRETRY AFTER(S_TX_RETRY) 113 { 8, "txmretry", "txmretry", "tx success with >1 retry" }, 114 #define S_TX_RTSGOOD AFTER(S_TX_MRETRY) 115 { 7, "rtsgood", "rtsgood", "RTS tx success" }, 116 #define S_TX_RTSBAD AFTER(S_TX_RTSGOOD) 117 { 6, "rtsbad", "rtsbad", "RTS tx failed" }, 118 #define S_TX_NOACK AFTER(S_TX_RTSBAD) 119 { 5, "noack", "noack", "tx failed because no ACK was received" }, 120 #define S_RX_DUPLICATE AFTER(S_TX_NOACK) 121 { 5, "rxdup", "rxdup", "rx discarded by f/w as dup" }, 122 #define S_RX_FCS AFTER(S_RX_DUPLICATE) 123 { 5, "rxfcs", "rxfcs", "rx discarded by f/w for bad FCS" }, 124 #define S_TX_WATCHDOG AFTER(S_RX_FCS) 125 { 7, "txwatch", "txwatch", "MAC tx hang (f/w recovery)" }, 126 #define S_RX_OVERFLOW AFTER(S_TX_WATCHDOG) 127 { 6, "rxover", "rxover", "no f/w buffer for rx" }, 128 #define S_RX_FRAGERROR AFTER(S_RX_OVERFLOW) 129 { 6, "rxfrag", "rxfrag", "rx failed in f/w due to defrag" }, 130 #define S_RX_MEMERROR AFTER(S_RX_FRAGERROR) 131 { 5, "rxmem", "rxmem", "rx failed in f/w 'cuz out of of memory" }, 132 #define S_PTRERROR AFTER(S_RX_MEMERROR) 133 { 6, "badptr", "badptr", "MAC internal pointer problem" }, 134 #define S_TX_UNDERFLOW AFTER(S_PTRERROR) 135 { 7, "txunder", "txunder", "tx failed in f/w 'cuz of underflow" }, 136 #define S_TX_DONE AFTER(S_TX_UNDERFLOW) 137 { 6, "txdone", "txdone", "MAC tx ops completed" }, 138 #define S_TX_DONEBUFPUT AFTER(S_TX_DONE) 139 { 9, "txdoneput", "txdoneput", "tx buffers returned by f/w to host" }, 140 #define S_TX_WAIT4BUF AFTER(S_TX_DONEBUFPUT) 141 { 6, "txwait", "txwait", "no f/w buffers available when supplied a tx descriptor" }, 142 #define S_TX_ATTEMPTS AFTER(S_TX_WAIT4BUF) 143 { 5, "txtry", "txtry", "tx descriptors processed by f/w" }, 144 #define S_TX_SUCCESS AFTER(S_TX_ATTEMPTS) 145 { 4, "txok", "txok", "tx attempts successful" }, 146 #define S_TX_FRAGS AFTER(S_TX_SUCCESS) 147 { 6, "txfrag", "txfrag", "tx attempts with fragmentation" }, 148 #define S_RX_UNDECRYPT AFTER(S_TX_FRAGS) 149 { 7, "rxcrypt", "rxcrypt", "rx failed in f/w 'cuz decrypt failed" }, 150 #define S_RX_ICVERROR AFTER(S_RX_UNDECRYPT) 151 { 5, "rxicv", "rxicv", "rx failed in f/w 'cuz ICV check" }, 152 #define S_RX_EXCLUDE AFTER(S_RX_ICVERROR) 153 { 8, "rxfilter", "rxfilter", "rx frames filtered in f/w" }, 154 #define S_TX_LINEAR AFTER(S_RX_EXCLUDE) 155 { 5, "txlinear", "txlinear", "tx linearized to cluster" }, 156 #define S_TX_DISCARD AFTER(S_TX_LINEAR) 157 { 5, "txdisc", "txdisc", "tx frames discarded prior to association" }, 158 #define S_TX_QSTOP AFTER(S_TX_DISCARD) 159 { 5, "qstop", "qstop", "tx stopped 'cuz no xmit buffer" }, 160 #define S_TX_ENCAP AFTER(S_TX_QSTOP) 161 { 5, "txencode", "txencode", "tx encapsulation failed" }, 162 #define S_TX_NOMBUF AFTER(S_TX_ENCAP) 163 { 5, "txnombuf", "txnombuf", "tx failed 'cuz mbuf allocation failed" }, 164 #define S_TX_SHORTPRE AFTER(S_TX_NOMBUF) 165 { 5, "shpre", "shpre", "tx frames with short preamble" }, 166 #define S_TX_NOHEADROOM AFTER(S_TX_SHORTPRE) 167 { 5, "nohead", "nohead", "tx frames discarded for lack of headroom" }, 168 #define S_TX_BADFRAMETYPE AFTER(S_TX_NOHEADROOM) 169 { 5, "badtxtype", "badtxtype", "tx frames discarded for invalid/unknown 802.11 frame type" }, 170 #define S_RX_CRYPTO_ERR AFTER(S_TX_BADFRAMETYPE) 171 { 5, "crypt", "crypt", "rx failed 'cuz decryption" }, 172 #define S_RX_NOMBUF AFTER(S_RX_CRYPTO_ERR) 173 { 5, "rxnombuf", "rxnombuf", "rx setup failed 'cuz no mbuf" }, 174 #define S_RX_TKIPMIC AFTER(S_RX_NOMBUF) 175 { 5, "rxtkipmic", "rxtkipmic", "rx failed 'cuz TKIP MIC error" }, 176 #define S_RX_NODMABUF AFTER(S_RX_TKIPMIC) 177 { 5, "rxnodmabuf", "rxnodmabuf", "rx failed 'cuz no DMA buffer available" }, 178 #define S_RX_DMABUFMISSING AFTER(S_RX_NODMABUF) 179 { 5, "rxdmabufmissing", "rxdmabufmissing", "rx descriptor with no DMA buffer attached" }, 180 #define S_TX_NODATA AFTER(S_RX_DMABUFMISSING) 181 { 5, "txnodata", "txnodata", "tx discarded empty frame" }, 182 #define S_TX_BUSDMA AFTER(S_TX_NODATA) 183 { 5, "txbusdma", "txbusdma", "tx failed for dma resources" }, 184 #define S_RX_BUSDMA AFTER(S_TX_BUSDMA) 185 { 5, "rxbusdma", "rxbusdma", "rx setup failed for dma resources" }, 186 #define S_AMPDU_NOSTREAM AFTER(S_RX_BUSDMA) 187 { 5, "ampdu_nostream","ampdu_nostream","ADDBA request failed 'cuz all BA streams in use" }, 188 #define S_AMPDU_REJECT AFTER(S_AMPDU_NOSTREAM) 189 { 5, "ampdu_reject","ampdu_reject","ADDBA request failed 'cuz station already has one BA stream" }, 190 #define S_ADDBA_NOSTREAM AFTER(S_AMPDU_REJECT) 191 { 5, "addba_nostream","addba_nostream","ADDBA response processed but no BA stream present" }, 192 #define S_TX_TSO AFTER(S_ADDBA_NOSTREAM) 193 { 8, "txtso", "tso", "tx frames using TSO" }, 194 #define S_TSO_BADETH AFTER(S_TX_TSO) 195 { 5, "tsoeth", "tsoeth", "TSO failed 'cuz ether header type not IPv4" }, 196 #define S_TSO_NOHDR AFTER(S_TSO_BADETH) 197 { 5, "tsonohdr", "tsonohdr", "TSO failed 'cuz header not in first mbuf" }, 198 #define S_TSO_BADSPLIT AFTER(S_TSO_NOHDR) 199 { 5, "tsobadsplit", "tsobadsplit", "TSO failed 'cuz payload split failed" }, 200 #define S_BAWATCHDOG AFTER(S_TSO_BADSPLIT) 201 { 5, "bawatchdog", "bawatchdog", "BA watchdog interrupts" }, 202 #define S_BAWATCHDOG_NOTFOUND AFTER(S_BAWATCHDOG) 203 { 5, "bawatchdog_notfound", "bawatchdog_notfound", 204 "BA watchdog for unknown stream" }, 205 #define S_BAWATCHDOG_EMPTY AFTER(S_BAWATCHDOG_NOTFOUND) 206 { 5, "bawatchdog_empty", "bawatchdog_empty", 207 "BA watchdog on all streams but none found" }, 208 #define S_BAWATCHDOG_FAILED AFTER(S_BAWATCHDOG_EMPTY) 209 { 5, "bawatchdog_failed", "bawatchdog_failed", 210 "BA watchdog processing failed to get bitmap from f/w" }, 211 #define S_RADARDETECT AFTER(S_BAWATCHDOG_FAILED) 212 { 5, "radardetect", "radardetect", "radar detect interrupts" }, 213 #define S_RATE AFTER(S_RADARDETECT) 214 { 4, "rate", "rate", "rate of last transmit" }, 215 #define S_TX_RSSI AFTER(S_RATE) 216 { 4, "arssi", "arssi", "rssi of last ack" }, 217 #define S_RX_RSSI AFTER(S_TX_RSSI) 218 { 4, "rssi", "rssi", "avg recv rssi" }, 219 #define S_RX_NOISE AFTER(S_RX_RSSI) 220 { 5, "noise", "noise", "rx noise floor" }, 221 #define S_TX_SIGNAL AFTER(S_RX_NOISE) 222 { 4, "asignal", "asig", "signal of last ack (dBm)" }, 223 #define S_RX_SIGNAL AFTER(S_TX_SIGNAL) 224 { 4, "signal", "sig", "avg recv signal (dBm)" }, 225 #define S_ANT_TX0 AFTER(S_RX_SIGNAL) 226 { 8, "tx0", "ant0(tx)", "frames tx on antenna 0" }, 227 #define S_ANT_TX1 (S_RX_SIGNAL+2) 228 { 8, "tx1", "ant1(tx)", "frames tx on antenna 1" }, 229 #define S_ANT_TX2 (S_RX_SIGNAL+3) 230 { 8, "tx2", "ant2(tx)", "frames tx on antenna 2" }, 231 #define S_ANT_TX3 (S_RX_SIGNAL+4) 232 { 8, "tx3", "ant3(tx)", "frames tx on antenna 3" }, 233 #define S_ANT_RX0 AFTER(S_ANT_TX3) 234 { 8, "rx0", "ant0(rx)", "frames rx on antenna 0" }, 235 #define S_ANT_RX1 (S_ANT_TX3+2) 236 { 8, "rx1", "ant1(rx)", "frames rx on antenna 1" }, 237 #define S_ANT_RX2 (S_ANT_TX3+3) 238 { 8, "rx2", "ant2(rx)", "frames rx on antenna 2" }, 239 #define S_ANT_RX3 (S_ANT_TX3+4) 240 { 8, "rx3", "ant3(rx)", "frames rx on antenna 3" }, 241 }; 242 /* NB: this intentionally avoids per-antenna stats */ 243 #define S_LAST (S_RX_SIGNAL+1) 244 245 struct mwlstatfoo_p { 246 struct mwlstatfoo base; 247 int s; 248 struct ifreq ifr; 249 struct mwl_stats cur; 250 struct mwl_stats total; 251 }; 252 253 static void 254 mwl_setifname(struct mwlstatfoo *wf0, const char *ifname) 255 { 256 struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) wf0; 257 258 strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name)); 259 } 260 261 static void 262 mwl_collect(struct mwlstatfoo_p *wf, struct mwl_stats *stats) 263 { 264 wf->ifr.ifr_data = (caddr_t) stats; 265 if (ioctl(wf->s, SIOCGMVSTATS, &wf->ifr) < 0) 266 err(1, "%s: ioctl: %s", __func__, wf->ifr.ifr_name); 267 } 268 269 static void 270 mwl_collect_cur(struct bsdstat *sf) 271 { 272 struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 273 274 mwl_collect(wf, &wf->cur); 275 } 276 277 static void 278 mwl_collect_tot(struct bsdstat *sf) 279 { 280 struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 281 282 mwl_collect(wf, &wf->total); 283 } 284 285 static void 286 mwl_update_tot(struct bsdstat *sf) 287 { 288 struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 289 290 wf->total = wf->cur; 291 } 292 293 static void 294 setrate(char b[], size_t bs, uint8_t rate) 295 { 296 if (rate & IEEE80211_RATE_MCS) 297 snprintf(b, bs, "MCS%u", rate & IEEE80211_RATE_VAL); 298 else if (rate & 1) 299 snprintf(b, bs, "%u.5M", rate / 2); 300 else 301 snprintf(b, bs, "%uM", rate / 2); 302 } 303 304 static int 305 mwl_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs) 306 { 307 struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 308 #define STAT(x) \ 309 snprintf(b, bs, "%u", wf->cur.mst_##x - wf->total.mst_##x); return 1 310 #define HWSTAT(x) \ 311 snprintf(b, bs, "%u", wf->cur.hw_stats.x - wf->total.hw_stats.x); return 1 312 #define RXANT(x) \ 313 snprintf(b, bs, "%u", wf->cur.mst_ant_rx[x] - wf->total.mst_ant_rx[x]); return 1 314 #define TXANT(x) \ 315 snprintf(b, bs, "%u", wf->cur.mst_ant_tx[x] - wf->total.mst_ant_tx[x]); return 1 316 317 switch (s) { 318 case S_INPUT: 319 snprintf(b, bs, "%lu", (u_long)( 320 (wf->cur.mst_rx_packets - wf->total.mst_rx_packets))); 321 return 1; 322 case S_OUTPUT: 323 snprintf(b, bs, "%lu", (u_long)( 324 wf->cur.mst_tx_packets - wf->total.mst_tx_packets)); 325 return 1; 326 case S_RATE: 327 setrate(b, bs, wf->cur.mst_tx_rate); 328 return 1; 329 case S_TX_RETRY: HWSTAT(TxRetrySuccesses); 330 case S_TX_MRETRY: HWSTAT(TxMultipleRetrySuccesses); 331 case S_TX_RTSGOOD: HWSTAT(RTSSuccesses); 332 case S_TX_RTSBAD: HWSTAT(RTSFailures); 333 case S_TX_NOACK: HWSTAT(AckFailures); 334 case S_RX_DUPLICATE: HWSTAT(RxDuplicateFrames); 335 case S_RX_FCS: HWSTAT(FCSErrorCount); 336 case S_TX_WATCHDOG: HWSTAT(TxWatchDogTimeouts); 337 case S_RX_OVERFLOW: HWSTAT(RxOverflows); 338 case S_RX_FRAGERROR: HWSTAT(RxFragErrors); 339 case S_RX_MEMERROR: HWSTAT(RxMemErrors); 340 case S_PTRERROR: HWSTAT(PointerErrors); 341 case S_TX_UNDERFLOW: HWSTAT(TxUnderflows); 342 case S_TX_DONE: HWSTAT(TxDone); 343 case S_TX_DONEBUFPUT: HWSTAT(TxDoneBufPut); 344 case S_TX_WAIT4BUF: HWSTAT(Wait4TxBuf); 345 case S_TX_ATTEMPTS: HWSTAT(TxAttempts); 346 case S_TX_SUCCESS: HWSTAT(TxSuccesses); 347 case S_TX_FRAGS: HWSTAT(TxFragments); 348 case S_TX_MCAST: HWSTAT(TxMulticasts); 349 case S_RX_NONCTL: HWSTAT(RxNonCtlPkts); 350 case S_RX_MCAST: HWSTAT(RxMulticasts); 351 case S_RX_UNDECRYPT: HWSTAT(RxUndecryptableFrames); 352 case S_RX_ICVERROR: HWSTAT(RxICVErrors); 353 case S_RX_EXCLUDE: HWSTAT(RxExcludedFrames); 354 case S_TX_MGMT: STAT(tx_mgmt); 355 case S_TX_DISCARD: STAT(tx_discard); 356 case S_TX_QSTOP: STAT(tx_qstop); 357 case S_TX_ENCAP: STAT(tx_encap); 358 case S_TX_NOMBUF: STAT(tx_nombuf); 359 case S_TX_LINEAR: STAT(tx_linear); 360 case S_TX_NODATA: STAT(tx_nodata); 361 case S_TX_BUSDMA: STAT(tx_busdma); 362 case S_TX_SHORTPRE: STAT(tx_shortpre); 363 case S_TX_NOHEADROOM: STAT(tx_noheadroom); 364 case S_TX_BADFRAMETYPE: STAT(tx_badframetype); 365 case S_RX_CRYPTO_ERR: STAT(rx_crypto); 366 case S_RX_TKIPMIC: STAT(rx_tkipmic); 367 case S_RX_NODMABUF: STAT(rx_nodmabuf); 368 case S_RX_DMABUFMISSING:STAT(rx_dmabufmissing); 369 case S_RX_NOMBUF: STAT(rx_nombuf); 370 case S_RX_BUSDMA: STAT(rx_busdma); 371 case S_AMPDU_NOSTREAM: STAT(ampdu_nostream); 372 case S_AMPDU_REJECT: STAT(ampdu_reject); 373 case S_ADDBA_NOSTREAM: STAT(addba_nostream); 374 case S_TX_TSO: STAT(tx_tso); 375 case S_TSO_BADETH: STAT(tso_badeth); 376 case S_TSO_NOHDR: STAT(tso_nohdr); 377 case S_TSO_BADSPLIT: STAT(tso_badsplit); 378 case S_BAWATCHDOG: STAT(bawatchdog); 379 case S_BAWATCHDOG_NOTFOUND:STAT(bawatchdog_notfound); 380 case S_BAWATCHDOG_EMPTY: STAT(bawatchdog_empty); 381 case S_BAWATCHDOG_FAILED:STAT(bawatchdog_failed); 382 case S_RADARDETECT: STAT(radardetect); 383 case S_RX_RSSI: 384 snprintf(b, bs, "%d", wf->cur.mst_rx_rssi); 385 return 1; 386 case S_ANT_TX0: TXANT(0); 387 case S_ANT_TX1: TXANT(1); 388 case S_ANT_TX2: TXANT(2); 389 case S_ANT_TX3: TXANT(3); 390 case S_ANT_RX0: RXANT(0); 391 case S_ANT_RX1: RXANT(1); 392 case S_ANT_RX2: RXANT(2); 393 case S_ANT_RX3: RXANT(3); 394 case S_RX_NOISE: 395 snprintf(b, bs, "%d", wf->cur.mst_rx_noise); 396 return 1; 397 case S_RX_SIGNAL: 398 snprintf(b, bs, "%d", 399 wf->cur.mst_rx_rssi + wf->cur.mst_rx_noise); 400 return 1; 401 } 402 b[0] = '\0'; 403 return 0; 404 #undef RXANT 405 #undef TXANT 406 #undef HWSTAT 407 #undef STAT 408 } 409 410 static int 411 mwl_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs) 412 { 413 struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 414 #define STAT(x) \ 415 snprintf(b, bs, "%u", wf->total.mst_##x); return 1 416 #define HWSTAT(x) \ 417 snprintf(b, bs, "%u", wf->total.hw_stats.x); return 1 418 #define TXANT(x) \ 419 snprintf(b, bs, "%u", wf->total.mst_ant_tx[x]); return 1 420 #define RXANT(x) \ 421 snprintf(b, bs, "%u", wf->total.mst_ant_rx[x]); return 1 422 423 switch (s) { 424 case S_INPUT: 425 snprintf(b, bs, "%lu", (u_long)wf->total.mst_rx_packets); 426 return 1; 427 case S_OUTPUT: 428 snprintf(b, bs, "%lu", (u_long) wf->total.mst_tx_packets); 429 return 1; 430 case S_RATE: 431 setrate(b, bs, wf->total.mst_tx_rate); 432 return 1; 433 case S_TX_RETRY: HWSTAT(TxRetrySuccesses); 434 case S_TX_MRETRY: HWSTAT(TxMultipleRetrySuccesses); 435 case S_TX_RTSGOOD: HWSTAT(RTSSuccesses); 436 case S_TX_RTSBAD: HWSTAT(RTSFailures); 437 case S_TX_NOACK: HWSTAT(AckFailures); 438 case S_RX_DUPLICATE: HWSTAT(RxDuplicateFrames); 439 case S_RX_FCS: HWSTAT(FCSErrorCount); 440 case S_TX_WATCHDOG: HWSTAT(TxWatchDogTimeouts); 441 case S_RX_OVERFLOW: HWSTAT(RxOverflows); 442 case S_RX_FRAGERROR: HWSTAT(RxFragErrors); 443 case S_RX_MEMERROR: HWSTAT(RxMemErrors); 444 case S_PTRERROR: HWSTAT(PointerErrors); 445 case S_TX_UNDERFLOW: HWSTAT(TxUnderflows); 446 case S_TX_DONE: HWSTAT(TxDone); 447 case S_TX_DONEBUFPUT: HWSTAT(TxDoneBufPut); 448 case S_TX_WAIT4BUF: HWSTAT(Wait4TxBuf); 449 case S_TX_ATTEMPTS: HWSTAT(TxAttempts); 450 case S_TX_SUCCESS: HWSTAT(TxSuccesses); 451 case S_TX_FRAGS: HWSTAT(TxFragments); 452 case S_TX_MCAST: HWSTAT(TxMulticasts); 453 case S_RX_NONCTL: HWSTAT(RxNonCtlPkts); 454 case S_RX_MCAST: HWSTAT(RxMulticasts); 455 case S_RX_UNDECRYPT: HWSTAT(RxUndecryptableFrames); 456 case S_RX_ICVERROR: HWSTAT(RxICVErrors); 457 case S_RX_EXCLUDE: HWSTAT(RxExcludedFrames); 458 case S_TX_MGMT: STAT(tx_mgmt); 459 case S_TX_DISCARD: STAT(tx_discard); 460 case S_TX_QSTOP: STAT(tx_qstop); 461 case S_TX_ENCAP: STAT(tx_encap); 462 case S_TX_NOMBUF: STAT(tx_nombuf); 463 case S_TX_LINEAR: STAT(tx_linear); 464 case S_TX_NODATA: STAT(tx_nodata); 465 case S_TX_BUSDMA: STAT(tx_busdma); 466 case S_TX_SHORTPRE: STAT(tx_shortpre); 467 case S_TX_NOHEADROOM: STAT(tx_noheadroom); 468 case S_TX_BADFRAMETYPE: STAT(tx_badframetype); 469 case S_RX_CRYPTO_ERR: STAT(rx_crypto); 470 case S_RX_TKIPMIC: STAT(rx_tkipmic); 471 case S_RX_NODMABUF: STAT(rx_nodmabuf); 472 case S_RX_DMABUFMISSING:STAT(rx_dmabufmissing); 473 case S_RX_NOMBUF: STAT(rx_nombuf); 474 case S_RX_BUSDMA: STAT(rx_busdma); 475 case S_AMPDU_NOSTREAM: STAT(ampdu_nostream); 476 case S_AMPDU_REJECT: STAT(ampdu_reject); 477 case S_ADDBA_NOSTREAM: STAT(addba_nostream); 478 case S_TX_TSO: STAT(tx_tso); 479 case S_TSO_BADETH: STAT(tso_badeth); 480 case S_TSO_NOHDR: STAT(tso_nohdr); 481 case S_TSO_BADSPLIT: STAT(tso_badsplit); 482 case S_BAWATCHDOG: STAT(bawatchdog); 483 case S_BAWATCHDOG_NOTFOUND:STAT(bawatchdog_notfound); 484 case S_BAWATCHDOG_EMPTY: STAT(bawatchdog_empty); 485 case S_BAWATCHDOG_FAILED:STAT(bawatchdog_failed); 486 case S_RADARDETECT: STAT(radardetect); 487 case S_RX_RSSI: 488 snprintf(b, bs, "%d", wf->total.mst_rx_rssi); 489 return 1; 490 case S_ANT_TX0: TXANT(0); 491 case S_ANT_TX1: TXANT(1); 492 case S_ANT_TX2: TXANT(2); 493 case S_ANT_TX3: TXANT(3); 494 case S_ANT_RX0: RXANT(0); 495 case S_ANT_RX1: RXANT(1); 496 case S_ANT_RX2: RXANT(2); 497 case S_ANT_RX3: RXANT(3); 498 case S_RX_NOISE: 499 snprintf(b, bs, "%d", wf->total.mst_rx_noise); 500 return 1; 501 case S_RX_SIGNAL: 502 snprintf(b, bs, "%d", 503 wf->total.mst_rx_rssi + wf->total.mst_rx_noise); 504 return 1; 505 } 506 b[0] = '\0'; 507 return 0; 508 #undef RXANT 509 #undef TXANT 510 #undef HWSTAT 511 #undef STAT 512 } 513 514 static void 515 mwl_print_verbose(struct bsdstat *sf, FILE *fd) 516 { 517 struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 518 const struct fmt *f; 519 char s[32]; 520 const char *indent; 521 int i, width; 522 523 width = 0; 524 for (i = 0; i < S_LAST; i++) { 525 f = &sf->stats[i]; 526 if (f->width > width) 527 width = f->width; 528 } 529 for (i = 0; i < S_LAST; i++) { 530 f = &sf->stats[i]; 531 if (mwl_get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) { 532 indent = ""; 533 fprintf(fd, "%s%-*s %s\n", indent, width, s, f->desc); 534 } 535 } 536 fprintf(fd, "Antenna profile:\n"); 537 for (i = 0; i < 4; i++) 538 if (wf->total.mst_ant_rx[i] || wf->total.mst_ant_tx[i]) 539 fprintf(fd, "[%u] tx %8u rx %8u\n", i, 540 wf->total.mst_ant_tx[i], 541 wf->total.mst_ant_rx[i]); 542 } 543 544 BSDSTAT_DEFINE_BOUNCE(mwlstatfoo) 545 546 struct mwlstatfoo * 547 mwlstats_new(const char *ifname, const char *fmtstring) 548 { 549 struct mwlstatfoo_p *wf; 550 551 wf = calloc(1, sizeof(struct mwlstatfoo_p)); 552 if (wf != NULL) { 553 bsdstat_init(&wf->base.base, "mwlstats", mwlstats, 554 nitems(mwlstats)); 555 /* override base methods */ 556 wf->base.base.collect_cur = mwl_collect_cur; 557 wf->base.base.collect_tot = mwl_collect_tot; 558 wf->base.base.get_curstat = mwl_get_curstat; 559 wf->base.base.get_totstat = mwl_get_totstat; 560 wf->base.base.update_tot = mwl_update_tot; 561 wf->base.base.print_verbose = mwl_print_verbose; 562 563 /* setup bounce functions for public methods */ 564 BSDSTAT_BOUNCE(wf, mwlstatfoo); 565 566 /* setup our public methods */ 567 wf->base.setifname = mwl_setifname; 568 #if 0 569 wf->base.setstamac = wlan_setstamac; 570 #endif 571 wf->s = socket(AF_INET, SOCK_DGRAM, 0); 572 if (wf->s < 0) 573 err(1, "socket"); 574 575 mwl_setifname(&wf->base, ifname); 576 wf->base.setfmt(&wf->base, fmtstring); 577 } 578 return &wf->base; 579 } 580