1193242Ssam/*- 2193242Ssam * Copyright (c) 2007 Sam Leffler, Errno Consulting 3193242Ssam * All rights reserved. 4193242Ssam * 5193242Ssam * Redistribution and use in source and binary forms, with or without 6193242Ssam * modification, are permitted provided that the following conditions 7193242Ssam * are met: 8193242Ssam * 1. Redistributions of source code must retain the above copyright 9193242Ssam * notice, this list of conditions and the following disclaimer, 10193242Ssam * without modification. 11193242Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12193242Ssam * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13193242Ssam * redistribution must be conditioned upon including a substantially 14193242Ssam * similar Disclaimer requirement for further binary redistribution. 15193242Ssam * 16193242Ssam * NO WARRANTY 17193242Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18193242Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19193242Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20193242Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21193242Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22193242Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23193242Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24193242Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25193242Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26193242Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27193242Ssam * THE POSSIBILITY OF SUCH DAMAGES. 28193242Ssam * 29193242Ssam * $FreeBSD$ 30193242Ssam */ 31193242Ssam 32193242Ssam/* 33193242Ssam * mwl statistics class. 34193242Ssam */ 35193242Ssam#include <sys/types.h> 36193242Ssam#include <sys/file.h> 37193242Ssam#include <sys/sockio.h> 38193242Ssam#include <sys/socket.h> 39193242Ssam#include <sys/ioctl.h> 40193242Ssam#include <net/if.h> 41193242Ssam#include <net/if_media.h> 42193242Ssam 43193242Ssam#include <stdlib.h> 44193242Ssam#include <stdio.h> 45193242Ssam#include <signal.h> 46193242Ssam#include <string.h> 47193242Ssam#include <unistd.h> 48193242Ssam#include <err.h> 49193242Ssam 50197454Srpaulo#include "../../../../sys/net80211/ieee80211_ioctl.h" 51197454Srpaulo#include "../../../../sys/net80211/ieee80211_radiotap.h" 52193242Ssam 53193242Ssam/* 54193242Ssam * Get Hardware Statistics. 55193242Ssam */ 56193242Ssamstruct mwl_hal_hwstats { 57193242Ssam uint32_t TxRetrySuccesses; 58193242Ssam uint32_t TxMultipleRetrySuccesses; 59193242Ssam uint32_t TxFailures; 60193242Ssam uint32_t RTSSuccesses; 61193242Ssam uint32_t RTSFailures; 62193242Ssam uint32_t AckFailures; 63193242Ssam uint32_t RxDuplicateFrames; 64193242Ssam uint32_t FCSErrorCount; 65193242Ssam uint32_t TxWatchDogTimeouts; 66193242Ssam uint32_t RxOverflows; 67193242Ssam uint32_t RxFragErrors; 68193242Ssam uint32_t RxMemErrors; 69193242Ssam uint32_t PointerErrors; 70193242Ssam uint32_t TxUnderflows; 71193242Ssam uint32_t TxDone; 72193242Ssam uint32_t TxDoneBufTryPut; 73193242Ssam uint32_t TxDoneBufPut; 74193242Ssam uint32_t Wait4TxBuf; 75193242Ssam uint32_t TxAttempts; 76193242Ssam uint32_t TxSuccesses; 77193242Ssam uint32_t TxFragments; 78193242Ssam uint32_t TxMulticasts; 79193242Ssam uint32_t RxNonCtlPkts; 80193242Ssam uint32_t RxMulticasts; 81193242Ssam uint32_t RxUndecryptableFrames; 82193242Ssam uint32_t RxICVErrors; 83193242Ssam uint32_t RxExcludedFrames; 84193242Ssam}; 85193242Ssam#include "../../../../sys/dev/mwl/if_mwlioctl.h" 86193242Ssam 87193242Ssam#include "mwlstats.h" 88193242Ssam 89193242Ssam#define AFTER(prev) ((prev)+1) 90193242Ssam 91193242Ssamstatic const struct fmt mwlstats[] = { 92193242Ssam#define S_INPUT 0 93193242Ssam { 8, "input", "input", "total frames received" }, 94193242Ssam#define S_RX_MCAST AFTER(S_INPUT) 95193242Ssam { 7, "rxmcast", "rxmcast", "rx multicast frames" }, 96193242Ssam#define S_RX_NONCTL AFTER(S_RX_MCAST) 97193242Ssam { 8, "rxnonctl", "rxnonctl" "rx non control frames" }, 98193242Ssam#define S_RX_MGT AFTER(S_RX_NONCTL) 99193242Ssam { 5, "rxmgt", "rxmgt", "rx management frames" }, 100193242Ssam#define S_RX_CTL AFTER(S_RX_MGT) 101193242Ssam { 5, "rxctl", "rxctl", "rx control frames" }, 102193242Ssam#define S_OUTPUT AFTER(S_RX_CTL) 103193242Ssam { 8, "output", "output", "total frames transmit" }, 104193242Ssam#define S_TX_MCAST AFTER(S_OUTPUT) 105193242Ssam { 7, "txmcast", "txmcast", "tx multicast frames" }, 106193242Ssam#define S_TX_MGMT AFTER(S_TX_MCAST) 107193242Ssam { 5, "txmgt", "txmgt", "tx management frames" }, 108193242Ssam#define S_TX_RETRY AFTER(S_TX_MGMT) 109193242Ssam { 7, "txretry", "txretry", "tx success with 1 retry" }, 110193242Ssam#define S_TX_MRETRY AFTER(S_TX_RETRY) 111193242Ssam { 8, "txmretry", "txmretry", "tx success with >1 retry" }, 112193242Ssam#define S_TX_RTSGOOD AFTER(S_TX_MRETRY) 113193242Ssam { 7, "rtsgood", "rtsgood", "RTS tx success" }, 114193242Ssam#define S_TX_RTSBAD AFTER(S_TX_RTSGOOD) 115193242Ssam { 6, "rtsbad", "rtsbad", "RTS tx failed" }, 116193242Ssam#define S_TX_NOACK AFTER(S_TX_RTSBAD) 117193242Ssam { 5, "noack", "noack", "tx failed because no ACK was received" }, 118193242Ssam#define S_RX_DUPLICATE AFTER(S_TX_NOACK) 119193242Ssam { 5, "rxdup", "rxdup", "rx discarded by f/w as dup" }, 120193242Ssam#define S_RX_FCS AFTER(S_RX_DUPLICATE) 121193242Ssam { 5, "rxfcs", "rxfcs", "rx discarded by f/w for bad FCS" }, 122193242Ssam#define S_TX_WATCHDOG AFTER(S_RX_FCS) 123193242Ssam { 7, "txwatch", "txwatch", "MAC tx hang (f/w recovery)" }, 124193242Ssam#define S_RX_OVERFLOW AFTER(S_TX_WATCHDOG) 125193242Ssam { 6, "rxover", "rxover", "no f/w buffer for rx" }, 126193242Ssam#define S_RX_FRAGERROR AFTER(S_RX_OVERFLOW) 127193242Ssam { 6, "rxfrag", "rxfrag", "rx failed in f/w due to defrag" }, 128193242Ssam#define S_RX_MEMERROR AFTER(S_RX_FRAGERROR) 129193242Ssam { 5, "rxmem", "rxmem", "rx failed in f/w 'cuz out of of memory" }, 130193242Ssam#define S_PTRERROR AFTER(S_RX_MEMERROR) 131193242Ssam { 6, "badptr", "badptr", "MAC internal pointer problem" }, 132193242Ssam#define S_TX_UNDERFLOW AFTER(S_PTRERROR) 133193242Ssam { 7, "txunder", "txunder", "tx failed in f/w 'cuz of underflow" }, 134193242Ssam#define S_TX_DONE AFTER(S_TX_UNDERFLOW) 135193242Ssam { 6, "txdone", "txdone", "MAC tx ops completed" }, 136193242Ssam#define S_TX_DONEBUFPUT AFTER(S_TX_DONE) 137193242Ssam { 9, "txdoneput", "txdoneput", "tx buffers returned by f/w to host" }, 138193242Ssam#define S_TX_WAIT4BUF AFTER(S_TX_DONEBUFPUT) 139193242Ssam { 6, "txwait", "txwait", "no f/w buffers available when supplied a tx descriptor" }, 140193242Ssam#define S_TX_ATTEMPTS AFTER(S_TX_WAIT4BUF) 141193242Ssam { 5, "txtry", "txtry", "tx descriptors processed by f/w" }, 142193242Ssam#define S_TX_SUCCESS AFTER(S_TX_ATTEMPTS) 143193242Ssam { 4, "txok", "txok", "tx attempts successful" }, 144193242Ssam#define S_TX_FRAGS AFTER(S_TX_SUCCESS) 145193242Ssam { 6, "txfrag", "txfrag", "tx attempts with fragmentation" }, 146193242Ssam#define S_RX_UNDECRYPT AFTER(S_TX_FRAGS) 147193242Ssam { 7, "rxcrypt", "rxcrypt", "rx failed in f/w 'cuz decrypt failed" }, 148193242Ssam#define S_RX_ICVERROR AFTER(S_RX_UNDECRYPT) 149193242Ssam { 5, "rxicv", "rxicv", "rx failed in f/w 'cuz ICV check" }, 150193242Ssam#define S_RX_EXCLUDE AFTER(S_RX_ICVERROR) 151193242Ssam { 8, "rxfilter", "rxfilter", "rx frames filtered in f/w" }, 152193242Ssam#define S_TX_LINEAR AFTER(S_RX_EXCLUDE) 153193242Ssam { 5, "txlinear", "txlinear", "tx linearized to cluster" }, 154193242Ssam#define S_TX_DISCARD AFTER(S_TX_LINEAR) 155193242Ssam { 5, "txdisc", "txdisc", "tx frames discarded prior to association" }, 156193242Ssam#define S_TX_QSTOP AFTER(S_TX_DISCARD) 157193242Ssam { 5, "qstop", "qstop", "tx stopped 'cuz no xmit buffer" }, 158193242Ssam#define S_TX_ENCAP AFTER(S_TX_QSTOP) 159193242Ssam { 5, "txencode", "txencode", "tx encapsulation failed" }, 160193242Ssam#define S_TX_NOMBUF AFTER(S_TX_ENCAP) 161193242Ssam { 5, "txnombuf", "txnombuf", "tx failed 'cuz mbuf allocation failed" }, 162193242Ssam#define S_TX_SHORTPRE AFTER(S_TX_NOMBUF) 163193242Ssam { 5, "shpre", "shpre", "tx frames with short preamble" }, 164193242Ssam#define S_TX_NOHEADROOM AFTER(S_TX_SHORTPRE) 165193242Ssam { 5, "nohead", "nohead", "tx frames discarded for lack of headroom" }, 166193242Ssam#define S_TX_BADFRAMETYPE AFTER(S_TX_NOHEADROOM) 167193242Ssam { 5, "badtxtype", "badtxtype", "tx frames discarded for invalid/unknown 802.11 frame type" }, 168193242Ssam#define S_RX_CRYPTO_ERR AFTER(S_TX_BADFRAMETYPE) 169193242Ssam { 5, "crypt", "crypt", "rx failed 'cuz decryption" }, 170193242Ssam#define S_RX_NOMBUF AFTER(S_RX_CRYPTO_ERR) 171193242Ssam { 5, "rxnombuf", "rxnombuf", "rx setup failed 'cuz no mbuf" }, 172193242Ssam#define S_RX_TKIPMIC AFTER(S_RX_NOMBUF) 173193242Ssam { 5, "rxtkipmic", "rxtkipmic", "rx failed 'cuz TKIP MIC error" }, 174193242Ssam#define S_RX_NODMABUF AFTER(S_RX_TKIPMIC) 175193242Ssam { 5, "rxnodmabuf", "rxnodmabuf", "rx failed 'cuz no DMA buffer available" }, 176193242Ssam#define S_RX_DMABUFMISSING AFTER(S_RX_NODMABUF) 177193242Ssam { 5, "rxdmabufmissing", "rxdmabufmissing", "rx descriptor with no DMA buffer attached" }, 178193242Ssam#define S_TX_NODATA AFTER(S_RX_DMABUFMISSING) 179193242Ssam { 5, "txnodata", "txnodata", "tx discarded empty frame" }, 180193242Ssam#define S_TX_BUSDMA AFTER(S_TX_NODATA) 181193242Ssam { 5, "txbusdma", "txbusdma", "tx failed for dma resources" }, 182193242Ssam#define S_RX_BUSDMA AFTER(S_TX_BUSDMA) 183193242Ssam { 5, "rxbusdma", "rxbusdma", "rx setup failed for dma resources" }, 184193242Ssam#define S_AMPDU_NOSTREAM AFTER(S_RX_BUSDMA) 185193242Ssam { 5, "ampdu_nostream","ampdu_nostream","ADDBA request failed 'cuz all BA streams in use" }, 186193242Ssam#define S_AMPDU_REJECT AFTER(S_AMPDU_NOSTREAM) 187193242Ssam { 5, "ampdu_reject","ampdu_reject","ADDBA request failed 'cuz station already has one BA stream" }, 188193242Ssam#define S_ADDBA_NOSTREAM AFTER(S_AMPDU_REJECT) 189193242Ssam { 5, "addba_nostream","addba_nostream","ADDBA response processed but no BA stream present" }, 190193242Ssam#define S_TX_TSO AFTER(S_ADDBA_NOSTREAM) 191193242Ssam { 8, "txtso", "tso", "tx frames using TSO" }, 192193242Ssam#define S_TSO_BADETH AFTER(S_TX_TSO) 193193242Ssam { 5, "tsoeth", "tsoeth", "TSO failed 'cuz ether header type not IPv4" }, 194193242Ssam#define S_TSO_NOHDR AFTER(S_TSO_BADETH) 195193242Ssam { 5, "tsonohdr", "tsonohdr", "TSO failed 'cuz header not in first mbuf" }, 196193242Ssam#define S_TSO_BADSPLIT AFTER(S_TSO_NOHDR) 197193242Ssam { 5, "tsobadsplit", "tsobadsplit", "TSO failed 'cuz payload split failed" }, 198193242Ssam#define S_BAWATCHDOG AFTER(S_TSO_BADSPLIT) 199193242Ssam { 5, "bawatchdog", "bawatchdog", "BA watchdog interrupts" }, 200193242Ssam#define S_BAWATCHDOG_NOTFOUND AFTER(S_BAWATCHDOG) 201193242Ssam { 5, "bawatchdog_notfound", "bawatchdog_notfound", 202193242Ssam "BA watchdog for unknown stream" }, 203193242Ssam#define S_BAWATCHDOG_EMPTY AFTER(S_BAWATCHDOG_NOTFOUND) 204193242Ssam { 5, "bawatchdog_empty", "bawatchdog_empty", 205193242Ssam "BA watchdog on all streams but none found" }, 206193242Ssam#define S_BAWATCHDOG_FAILED AFTER(S_BAWATCHDOG_EMPTY) 207193242Ssam { 5, "bawatchdog_failed", "bawatchdog_failed", 208193242Ssam "BA watchdog processing failed to get bitmap from f/w" }, 209193242Ssam#define S_RADARDETECT AFTER(S_BAWATCHDOG_FAILED) 210193242Ssam { 5, "radardetect", "radardetect", "radar detect interrupts" }, 211193242Ssam#define S_RATE AFTER(S_RADARDETECT) 212193242Ssam { 4, "rate", "rate", "rate of last transmit" }, 213193242Ssam#define S_TX_RSSI AFTER(S_RATE) 214193242Ssam { 4, "arssi", "arssi", "rssi of last ack" }, 215193242Ssam#define S_RX_RSSI AFTER(S_TX_RSSI) 216193242Ssam { 4, "rssi", "rssi", "avg recv rssi" }, 217193242Ssam#define S_RX_NOISE AFTER(S_RX_RSSI) 218193242Ssam { 5, "noise", "noise", "rx noise floor" }, 219193242Ssam#define S_TX_SIGNAL AFTER(S_RX_NOISE) 220193242Ssam { 4, "asignal", "asig", "signal of last ack (dBm)" }, 221193242Ssam#define S_RX_SIGNAL AFTER(S_TX_SIGNAL) 222193242Ssam { 4, "signal", "sig", "avg recv signal (dBm)" }, 223193242Ssam#define S_ANT_TX0 AFTER(S_RX_SIGNAL) 224193242Ssam { 8, "tx0", "ant0(tx)", "frames tx on antenna 0" }, 225193242Ssam#define S_ANT_TX1 (S_RX_SIGNAL+2) 226193242Ssam { 8, "tx1", "ant1(tx)", "frames tx on antenna 1" }, 227193242Ssam#define S_ANT_TX2 (S_RX_SIGNAL+3) 228193242Ssam { 8, "tx2", "ant2(tx)", "frames tx on antenna 2" }, 229193242Ssam#define S_ANT_TX3 (S_RX_SIGNAL+4) 230193242Ssam { 8, "tx3", "ant3(tx)", "frames tx on antenna 3" }, 231193242Ssam#define S_ANT_RX0 AFTER(S_ANT_TX3) 232193242Ssam { 8, "rx0", "ant0(rx)", "frames rx on antenna 0" }, 233193242Ssam#define S_ANT_RX1 (S_ANT_TX3+2) 234193242Ssam { 8, "rx1", "ant1(rx)", "frames rx on antenna 1" }, 235193242Ssam#define S_ANT_RX2 (S_ANT_TX3+3) 236193242Ssam { 8, "rx2", "ant2(rx)", "frames rx on antenna 2" }, 237193242Ssam#define S_ANT_RX3 (S_ANT_TX3+4) 238193242Ssam { 8, "rx3", "ant3(rx)", "frames rx on antenna 3" }, 239193242Ssam}; 240193242Ssam/* NB: this intentionally avoids per-antenna stats */ 241193242Ssam#define S_LAST (S_RX_SIGNAL+1) 242193242Ssam 243193242Ssamstruct mwlstatfoo_p { 244193242Ssam struct mwlstatfoo base; 245193242Ssam int s; 246193242Ssam struct ifreq ifr; 247193242Ssam struct mwl_stats cur; 248193242Ssam struct mwl_stats total; 249193242Ssam}; 250193242Ssam 251193242Ssamstatic void 252193242Ssammwl_setifname(struct mwlstatfoo *wf0, const char *ifname) 253193242Ssam{ 254193242Ssam struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) wf0; 255193242Ssam 256193242Ssam strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name)); 257193242Ssam} 258193242Ssam 259193242Ssamstatic void 260193242Ssammwl_collect(struct mwlstatfoo_p *wf, struct mwl_stats *stats) 261193242Ssam{ 262193242Ssam wf->ifr.ifr_data = (caddr_t) stats; 263193242Ssam if (ioctl(wf->s, SIOCGMVSTATS, &wf->ifr) < 0) 264193242Ssam err(1, wf->ifr.ifr_name); 265193242Ssam} 266193242Ssam 267193242Ssamstatic void 268193242Ssammwl_collect_cur(struct statfoo *sf) 269193242Ssam{ 270193242Ssam struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 271193242Ssam 272193242Ssam mwl_collect(wf, &wf->cur); 273193242Ssam} 274193242Ssam 275193242Ssamstatic void 276193242Ssammwl_collect_tot(struct statfoo *sf) 277193242Ssam{ 278193242Ssam struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 279193242Ssam 280193242Ssam mwl_collect(wf, &wf->total); 281193242Ssam} 282193242Ssam 283193242Ssamstatic void 284193242Ssammwl_update_tot(struct statfoo *sf) 285193242Ssam{ 286193242Ssam struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 287193242Ssam 288193242Ssam wf->total = wf->cur; 289193242Ssam} 290193242Ssam 291193242Ssamstatic void 292193242Ssamsetrate(char b[], size_t bs, uint8_t rate) 293193242Ssam{ 294193242Ssam if (rate & IEEE80211_RATE_MCS) 295193242Ssam snprintf(b, bs, "MCS%u", rate & IEEE80211_RATE_VAL); 296193242Ssam else if (rate & 1) 297193242Ssam snprintf(b, bs, "%u.5M", rate / 2); 298193242Ssam else 299193242Ssam snprintf(b, bs, "%uM", rate / 2); 300193242Ssam} 301193242Ssam 302193242Ssamstatic int 303193242Ssammwl_get_curstat(struct statfoo *sf, int s, char b[], size_t bs) 304193242Ssam{ 305193242Ssam struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 306193242Ssam#define STAT(x) \ 307193242Ssam snprintf(b, bs, "%u", wf->cur.mst_##x - wf->total.mst_##x); return 1 308193242Ssam#define HWSTAT(x) \ 309193242Ssam snprintf(b, bs, "%u", wf->cur.hw_stats.x - wf->total.hw_stats.x); return 1 310193242Ssam#define RXANT(x) \ 311193242Ssam snprintf(b, bs, "%u", wf->cur.mst_ant_rx[x] - wf->total.mst_ant_rx[x]); return 1 312193242Ssam#define TXANT(x) \ 313193242Ssam snprintf(b, bs, "%u", wf->cur.mst_ant_tx[x] - wf->total.mst_ant_tx[x]); return 1 314193242Ssam 315193242Ssam switch (s) { 316193242Ssam case S_INPUT: 317193242Ssam snprintf(b, bs, "%lu", (u_long)( 318193242Ssam (wf->cur.mst_rx_packets - wf->total.mst_rx_packets))); 319193242Ssam return 1; 320193242Ssam case S_OUTPUT: 321193242Ssam snprintf(b, bs, "%lu", (u_long)( 322193242Ssam wf->cur.mst_tx_packets - wf->total.mst_tx_packets)); 323193242Ssam return 1; 324193242Ssam case S_RATE: 325193242Ssam setrate(b, bs, wf->cur.mst_tx_rate); 326193242Ssam return 1; 327193242Ssam case S_TX_RETRY: HWSTAT(TxRetrySuccesses); 328193242Ssam case S_TX_MRETRY: HWSTAT(TxMultipleRetrySuccesses); 329193242Ssam case S_TX_RTSGOOD: HWSTAT(RTSSuccesses); 330193242Ssam case S_TX_RTSBAD: HWSTAT(RTSFailures); 331193242Ssam case S_TX_NOACK: HWSTAT(AckFailures); 332193242Ssam case S_RX_DUPLICATE: HWSTAT(RxDuplicateFrames); 333193242Ssam case S_RX_FCS: HWSTAT(FCSErrorCount); 334193242Ssam case S_TX_WATCHDOG: HWSTAT(TxWatchDogTimeouts); 335193242Ssam case S_RX_OVERFLOW: HWSTAT(RxOverflows); 336193242Ssam case S_RX_FRAGERROR: HWSTAT(RxFragErrors); 337193242Ssam case S_RX_MEMERROR: HWSTAT(RxMemErrors); 338193242Ssam case S_PTRERROR: HWSTAT(PointerErrors); 339193242Ssam case S_TX_UNDERFLOW: HWSTAT(TxUnderflows); 340193242Ssam case S_TX_DONE: HWSTAT(TxDone); 341193242Ssam case S_TX_DONEBUFPUT: HWSTAT(TxDoneBufPut); 342193242Ssam case S_TX_WAIT4BUF: HWSTAT(Wait4TxBuf); 343193242Ssam case S_TX_ATTEMPTS: HWSTAT(TxAttempts); 344193242Ssam case S_TX_SUCCESS: HWSTAT(TxSuccesses); 345193242Ssam case S_TX_FRAGS: HWSTAT(TxFragments); 346193242Ssam case S_TX_MCAST: HWSTAT(TxMulticasts); 347193242Ssam case S_RX_NONCTL: HWSTAT(RxNonCtlPkts); 348193242Ssam case S_RX_MCAST: HWSTAT(RxMulticasts); 349193242Ssam case S_RX_UNDECRYPT: HWSTAT(RxUndecryptableFrames); 350193242Ssam case S_RX_ICVERROR: HWSTAT(RxICVErrors); 351193242Ssam case S_RX_EXCLUDE: HWSTAT(RxExcludedFrames); 352193242Ssam case S_TX_MGMT: STAT(tx_mgmt); 353193242Ssam case S_TX_DISCARD: STAT(tx_discard); 354193242Ssam case S_TX_QSTOP: STAT(tx_qstop); 355193242Ssam case S_TX_ENCAP: STAT(tx_encap); 356193242Ssam case S_TX_NOMBUF: STAT(tx_nombuf); 357193242Ssam case S_TX_LINEAR: STAT(tx_linear); 358193242Ssam case S_TX_NODATA: STAT(tx_nodata); 359193242Ssam case S_TX_BUSDMA: STAT(tx_busdma); 360193242Ssam case S_TX_SHORTPRE: STAT(tx_shortpre); 361193242Ssam case S_TX_NOHEADROOM: STAT(tx_noheadroom); 362193242Ssam case S_TX_BADFRAMETYPE: STAT(tx_badframetype); 363193242Ssam case S_RX_CRYPTO_ERR: STAT(rx_crypto); 364193242Ssam case S_RX_TKIPMIC: STAT(rx_tkipmic); 365193242Ssam case S_RX_NODMABUF: STAT(rx_nodmabuf); 366193242Ssam case S_RX_DMABUFMISSING:STAT(rx_dmabufmissing); 367193242Ssam case S_RX_NOMBUF: STAT(rx_nombuf); 368193242Ssam case S_RX_BUSDMA: STAT(rx_busdma); 369193242Ssam case S_AMPDU_NOSTREAM: STAT(ampdu_nostream); 370193242Ssam case S_AMPDU_REJECT: STAT(ampdu_reject); 371193242Ssam case S_ADDBA_NOSTREAM: STAT(addba_nostream); 372193242Ssam case S_TX_TSO: STAT(tx_tso); 373193242Ssam case S_TSO_BADETH: STAT(tso_badeth); 374193242Ssam case S_TSO_NOHDR: STAT(tso_nohdr); 375193242Ssam case S_TSO_BADSPLIT: STAT(tso_badsplit); 376193242Ssam case S_BAWATCHDOG: STAT(bawatchdog); 377193242Ssam case S_BAWATCHDOG_NOTFOUND:STAT(bawatchdog_notfound); 378193242Ssam case S_BAWATCHDOG_EMPTY: STAT(bawatchdog_empty); 379193242Ssam case S_BAWATCHDOG_FAILED:STAT(bawatchdog_failed); 380193242Ssam case S_RADARDETECT: STAT(radardetect); 381193242Ssam case S_RX_RSSI: 382193242Ssam snprintf(b, bs, "%d", wf->cur.mst_rx_rssi); 383193242Ssam return 1; 384193242Ssam case S_ANT_TX0: TXANT(0); 385193242Ssam case S_ANT_TX1: TXANT(1); 386193242Ssam case S_ANT_TX2: TXANT(2); 387193242Ssam case S_ANT_TX3: TXANT(3); 388193242Ssam case S_ANT_RX0: RXANT(0); 389193242Ssam case S_ANT_RX1: RXANT(1); 390193242Ssam case S_ANT_RX2: RXANT(2); 391193242Ssam case S_ANT_RX3: RXANT(3); 392193242Ssam case S_RX_NOISE: 393193242Ssam snprintf(b, bs, "%d", wf->cur.mst_rx_noise); 394193242Ssam return 1; 395193242Ssam case S_RX_SIGNAL: 396193242Ssam snprintf(b, bs, "%d", 397193242Ssam wf->cur.mst_rx_rssi + wf->cur.mst_rx_noise); 398193242Ssam return 1; 399193242Ssam } 400193242Ssam b[0] = '\0'; 401193242Ssam return 0; 402193242Ssam#undef RXANT 403193242Ssam#undef TXANT 404193242Ssam#undef HWSTAT 405193242Ssam#undef STAT 406193242Ssam} 407193242Ssam 408193242Ssamstatic int 409193242Ssammwl_get_totstat(struct statfoo *sf, int s, char b[], size_t bs) 410193242Ssam{ 411193242Ssam struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 412193242Ssam#define STAT(x) \ 413193242Ssam snprintf(b, bs, "%u", wf->total.mst_##x); return 1 414193242Ssam#define HWSTAT(x) \ 415193242Ssam snprintf(b, bs, "%u", wf->total.hw_stats.x); return 1 416193242Ssam#define TXANT(x) \ 417193242Ssam snprintf(b, bs, "%u", wf->total.mst_ant_tx[x]); return 1 418193242Ssam#define RXANT(x) \ 419193242Ssam snprintf(b, bs, "%u", wf->total.mst_ant_rx[x]); return 1 420193242Ssam 421193242Ssam switch (s) { 422193242Ssam case S_INPUT: 423193242Ssam snprintf(b, bs, "%lu", (u_long)wf->total.mst_rx_packets); 424193242Ssam return 1; 425193242Ssam case S_OUTPUT: 426193242Ssam snprintf(b, bs, "%lu", (u_long) wf->total.mst_tx_packets); 427193242Ssam return 1; 428193242Ssam case S_RATE: 429193242Ssam setrate(b, bs, wf->total.mst_tx_rate); 430193242Ssam return 1; 431193242Ssam case S_TX_RETRY: HWSTAT(TxRetrySuccesses); 432193242Ssam case S_TX_MRETRY: HWSTAT(TxMultipleRetrySuccesses); 433193242Ssam case S_TX_RTSGOOD: HWSTAT(RTSSuccesses); 434193242Ssam case S_TX_RTSBAD: HWSTAT(RTSFailures); 435193242Ssam case S_TX_NOACK: HWSTAT(AckFailures); 436193242Ssam case S_RX_DUPLICATE: HWSTAT(RxDuplicateFrames); 437193242Ssam case S_RX_FCS: HWSTAT(FCSErrorCount); 438193242Ssam case S_TX_WATCHDOG: HWSTAT(TxWatchDogTimeouts); 439193242Ssam case S_RX_OVERFLOW: HWSTAT(RxOverflows); 440193242Ssam case S_RX_FRAGERROR: HWSTAT(RxFragErrors); 441193242Ssam case S_RX_MEMERROR: HWSTAT(RxMemErrors); 442193242Ssam case S_PTRERROR: HWSTAT(PointerErrors); 443193242Ssam case S_TX_UNDERFLOW: HWSTAT(TxUnderflows); 444193242Ssam case S_TX_DONE: HWSTAT(TxDone); 445193242Ssam case S_TX_DONEBUFPUT: HWSTAT(TxDoneBufPut); 446193242Ssam case S_TX_WAIT4BUF: HWSTAT(Wait4TxBuf); 447193242Ssam case S_TX_ATTEMPTS: HWSTAT(TxAttempts); 448193242Ssam case S_TX_SUCCESS: HWSTAT(TxSuccesses); 449193242Ssam case S_TX_FRAGS: HWSTAT(TxFragments); 450193242Ssam case S_TX_MCAST: HWSTAT(TxMulticasts); 451193242Ssam case S_RX_NONCTL: HWSTAT(RxNonCtlPkts); 452193242Ssam case S_RX_MCAST: HWSTAT(RxMulticasts); 453193242Ssam case S_RX_UNDECRYPT: HWSTAT(RxUndecryptableFrames); 454193242Ssam case S_RX_ICVERROR: HWSTAT(RxICVErrors); 455193242Ssam case S_RX_EXCLUDE: HWSTAT(RxExcludedFrames); 456193242Ssam case S_TX_MGMT: STAT(tx_mgmt); 457193242Ssam case S_TX_DISCARD: STAT(tx_discard); 458193242Ssam case S_TX_QSTOP: STAT(tx_qstop); 459193242Ssam case S_TX_ENCAP: STAT(tx_encap); 460193242Ssam case S_TX_NOMBUF: STAT(tx_nombuf); 461193242Ssam case S_TX_LINEAR: STAT(tx_linear); 462193242Ssam case S_TX_NODATA: STAT(tx_nodata); 463193242Ssam case S_TX_BUSDMA: STAT(tx_busdma); 464193242Ssam case S_TX_SHORTPRE: STAT(tx_shortpre); 465193242Ssam case S_TX_NOHEADROOM: STAT(tx_noheadroom); 466193242Ssam case S_TX_BADFRAMETYPE: STAT(tx_badframetype); 467193242Ssam case S_RX_CRYPTO_ERR: STAT(rx_crypto); 468193242Ssam case S_RX_TKIPMIC: STAT(rx_tkipmic); 469193242Ssam case S_RX_NODMABUF: STAT(rx_nodmabuf); 470193242Ssam case S_RX_DMABUFMISSING:STAT(rx_dmabufmissing); 471193242Ssam case S_RX_NOMBUF: STAT(rx_nombuf); 472193242Ssam case S_RX_BUSDMA: STAT(rx_busdma); 473193242Ssam case S_AMPDU_NOSTREAM: STAT(ampdu_nostream); 474193242Ssam case S_AMPDU_REJECT: STAT(ampdu_reject); 475193242Ssam case S_ADDBA_NOSTREAM: STAT(addba_nostream); 476193242Ssam case S_TX_TSO: STAT(tx_tso); 477193242Ssam case S_TSO_BADETH: STAT(tso_badeth); 478193242Ssam case S_TSO_NOHDR: STAT(tso_nohdr); 479193242Ssam case S_TSO_BADSPLIT: STAT(tso_badsplit); 480193242Ssam case S_BAWATCHDOG: STAT(bawatchdog); 481193242Ssam case S_BAWATCHDOG_NOTFOUND:STAT(bawatchdog_notfound); 482193242Ssam case S_BAWATCHDOG_EMPTY: STAT(bawatchdog_empty); 483193242Ssam case S_BAWATCHDOG_FAILED:STAT(bawatchdog_failed); 484193242Ssam case S_RADARDETECT: STAT(radardetect); 485193242Ssam case S_RX_RSSI: 486193242Ssam snprintf(b, bs, "%d", wf->total.mst_rx_rssi); 487193242Ssam return 1; 488193242Ssam case S_ANT_TX0: TXANT(0); 489193242Ssam case S_ANT_TX1: TXANT(1); 490193242Ssam case S_ANT_TX2: TXANT(2); 491193242Ssam case S_ANT_TX3: TXANT(3); 492193242Ssam case S_ANT_RX0: RXANT(0); 493193242Ssam case S_ANT_RX1: RXANT(1); 494193242Ssam case S_ANT_RX2: RXANT(2); 495193242Ssam case S_ANT_RX3: RXANT(3); 496193242Ssam case S_RX_NOISE: 497193242Ssam snprintf(b, bs, "%d", wf->total.mst_rx_noise); 498193242Ssam return 1; 499193242Ssam case S_RX_SIGNAL: 500193242Ssam snprintf(b, bs, "%d", 501193242Ssam wf->total.mst_rx_rssi + wf->total.mst_rx_noise); 502193242Ssam return 1; 503193242Ssam } 504193242Ssam b[0] = '\0'; 505193242Ssam return 0; 506193242Ssam#undef RXANT 507193242Ssam#undef TXANT 508193242Ssam#undef HWSTAT 509193242Ssam#undef STAT 510193242Ssam} 511193242Ssam 512193242Ssamstatic void 513193242Ssammwl_print_verbose(struct statfoo *sf, FILE *fd) 514193242Ssam{ 515193242Ssam struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 516193242Ssam const struct fmt *f; 517193242Ssam char s[32]; 518193242Ssam const char *indent; 519193242Ssam int i, width; 520193242Ssam 521193242Ssam width = 0; 522193242Ssam for (i = 0; i < S_LAST; i++) { 523193242Ssam f = &sf->stats[i]; 524193242Ssam if (f->width > width) 525193242Ssam width = f->width; 526193242Ssam } 527193242Ssam for (i = 0; i < S_LAST; i++) { 528193242Ssam f = &sf->stats[i]; 529193242Ssam if (mwl_get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) { 530193242Ssam indent = ""; 531193242Ssam fprintf(fd, "%s%-*s %s\n", indent, width, s, f->desc); 532193242Ssam } 533193242Ssam } 534193242Ssam fprintf(fd, "Antenna profile:\n"); 535193242Ssam for (i = 0; i < 4; i++) 536193242Ssam if (wf->total.mst_ant_rx[i] || wf->total.mst_ant_tx[i]) 537193242Ssam fprintf(fd, "[%u] tx %8u rx %8u\n", i, 538193242Ssam wf->total.mst_ant_tx[i], 539193242Ssam wf->total.mst_ant_rx[i]); 540193242Ssam} 541193242Ssam 542193242SsamSTATFOO_DEFINE_BOUNCE(mwlstatfoo) 543193242Ssam 544193242Ssamstruct mwlstatfoo * 545193242Ssammwlstats_new(const char *ifname, const char *fmtstring) 546193242Ssam{ 547193242Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 548193242Ssam struct mwlstatfoo_p *wf; 549193242Ssam 550193242Ssam wf = calloc(1, sizeof(struct mwlstatfoo_p)); 551193242Ssam if (wf != NULL) { 552193242Ssam statfoo_init(&wf->base.base, "mwlstats", mwlstats, N(mwlstats)); 553193242Ssam /* override base methods */ 554193242Ssam wf->base.base.collect_cur = mwl_collect_cur; 555193242Ssam wf->base.base.collect_tot = mwl_collect_tot; 556193242Ssam wf->base.base.get_curstat = mwl_get_curstat; 557193242Ssam wf->base.base.get_totstat = mwl_get_totstat; 558193242Ssam wf->base.base.update_tot = mwl_update_tot; 559193242Ssam wf->base.base.print_verbose = mwl_print_verbose; 560193242Ssam 561193242Ssam /* setup bounce functions for public methods */ 562193242Ssam STATFOO_BOUNCE(wf, mwlstatfoo); 563193242Ssam 564193242Ssam /* setup our public methods */ 565193242Ssam wf->base.setifname = mwl_setifname; 566193242Ssam#if 0 567193242Ssam wf->base.setstamac = wlan_setstamac; 568193242Ssam#endif 569193242Ssam wf->s = socket(AF_INET, SOCK_DGRAM, 0); 570193242Ssam if (wf->s < 0) 571193242Ssam err(1, "socket"); 572193242Ssam 573193242Ssam mwl_setifname(&wf->base, ifname); 574193242Ssam wf->base.setfmt(&wf->base, fmtstring); 575193242Ssam } 576193242Ssam return &wf->base; 577193242Ssam#undef N 578193242Ssam} 579