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