105c3c371SSam Leffler /*- 205c3c371SSam Leffler * Copyright (c) 2007 Sam Leffler, Errno Consulting 305c3c371SSam Leffler * All rights reserved. 405c3c371SSam Leffler * 505c3c371SSam Leffler * Redistribution and use in source and binary forms, with or without 605c3c371SSam Leffler * modification, are permitted provided that the following conditions 705c3c371SSam Leffler * are met: 805c3c371SSam Leffler * 1. Redistributions of source code must retain the above copyright 905c3c371SSam Leffler * notice, this list of conditions and the following disclaimer, 1005c3c371SSam Leffler * without modification. 1105c3c371SSam Leffler * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1205c3c371SSam Leffler * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 1305c3c371SSam Leffler * redistribution must be conditioned upon including a substantially 1405c3c371SSam Leffler * similar Disclaimer requirement for further binary redistribution. 1505c3c371SSam Leffler * 1605c3c371SSam Leffler * NO WARRANTY 1705c3c371SSam Leffler * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1805c3c371SSam Leffler * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1905c3c371SSam Leffler * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 2005c3c371SSam Leffler * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 2105c3c371SSam Leffler * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 2205c3c371SSam Leffler * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2305c3c371SSam Leffler * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2405c3c371SSam Leffler * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 2505c3c371SSam Leffler * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2605c3c371SSam Leffler * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 2705c3c371SSam Leffler * THE POSSIBILITY OF SUCH DAMAGES. 2805c3c371SSam Leffler */ 2905c3c371SSam Leffler 3005c3c371SSam Leffler /* 3105c3c371SSam Leffler * mwl statistics class. 3205c3c371SSam Leffler */ 3360caf0c9SCraig Rodrigues 3460caf0c9SCraig Rodrigues #include <sys/param.h> 3505c3c371SSam Leffler #include <sys/file.h> 3660caf0c9SCraig Rodrigues #include <sys/ioctl.h> 3705c3c371SSam Leffler #include <sys/sockio.h> 3805c3c371SSam Leffler #include <sys/socket.h> 3960caf0c9SCraig Rodrigues 4005c3c371SSam Leffler #include <net/if.h> 4105c3c371SSam Leffler #include <net/if_media.h> 4205c3c371SSam Leffler 4360caf0c9SCraig Rodrigues #include <err.h> 4405c3c371SSam Leffler #include <signal.h> 4560caf0c9SCraig Rodrigues #include <stdio.h> 4660caf0c9SCraig Rodrigues #include <stdlib.h> 4705c3c371SSam Leffler #include <string.h> 4805c3c371SSam Leffler #include <unistd.h> 4905c3c371SSam Leffler 50249e7759SRui Paulo #include "../../../../sys/net80211/ieee80211_ioctl.h" 51249e7759SRui Paulo #include "../../../../sys/net80211/ieee80211_radiotap.h" 5205c3c371SSam Leffler 5305c3c371SSam Leffler /* 5405c3c371SSam Leffler * Get Hardware Statistics. 5505c3c371SSam Leffler */ 5605c3c371SSam Leffler struct mwl_hal_hwstats { 5705c3c371SSam Leffler uint32_t TxRetrySuccesses; 5805c3c371SSam Leffler uint32_t TxMultipleRetrySuccesses; 5905c3c371SSam Leffler uint32_t TxFailures; 6005c3c371SSam Leffler uint32_t RTSSuccesses; 6105c3c371SSam Leffler uint32_t RTSFailures; 6205c3c371SSam Leffler uint32_t AckFailures; 6305c3c371SSam Leffler uint32_t RxDuplicateFrames; 6405c3c371SSam Leffler uint32_t FCSErrorCount; 6505c3c371SSam Leffler uint32_t TxWatchDogTimeouts; 6605c3c371SSam Leffler uint32_t RxOverflows; 6705c3c371SSam Leffler uint32_t RxFragErrors; 6805c3c371SSam Leffler uint32_t RxMemErrors; 6905c3c371SSam Leffler uint32_t PointerErrors; 7005c3c371SSam Leffler uint32_t TxUnderflows; 7105c3c371SSam Leffler uint32_t TxDone; 7205c3c371SSam Leffler uint32_t TxDoneBufTryPut; 7305c3c371SSam Leffler uint32_t TxDoneBufPut; 7405c3c371SSam Leffler uint32_t Wait4TxBuf; 7505c3c371SSam Leffler uint32_t TxAttempts; 7605c3c371SSam Leffler uint32_t TxSuccesses; 7705c3c371SSam Leffler uint32_t TxFragments; 7805c3c371SSam Leffler uint32_t TxMulticasts; 7905c3c371SSam Leffler uint32_t RxNonCtlPkts; 8005c3c371SSam Leffler uint32_t RxMulticasts; 8105c3c371SSam Leffler uint32_t RxUndecryptableFrames; 8205c3c371SSam Leffler uint32_t RxICVErrors; 8305c3c371SSam Leffler uint32_t RxExcludedFrames; 8405c3c371SSam Leffler }; 8505c3c371SSam Leffler #include "../../../../sys/dev/mwl/if_mwlioctl.h" 8605c3c371SSam Leffler 8705c3c371SSam Leffler #include "mwlstats.h" 8805c3c371SSam Leffler 8905c3c371SSam Leffler #define AFTER(prev) ((prev)+1) 9005c3c371SSam Leffler 9105c3c371SSam Leffler static const struct fmt mwlstats[] = { 9205c3c371SSam Leffler #define S_INPUT 0 9305c3c371SSam Leffler { 8, "input", "input", "total frames received" }, 9405c3c371SSam Leffler #define S_RX_MCAST AFTER(S_INPUT) 9505c3c371SSam Leffler { 7, "rxmcast", "rxmcast", "rx multicast frames" }, 9605c3c371SSam Leffler #define S_RX_NONCTL AFTER(S_RX_MCAST) 9705c3c371SSam Leffler { 8, "rxnonctl", "rxnonctl" "rx non control frames" }, 9805c3c371SSam Leffler #define S_RX_MGT AFTER(S_RX_NONCTL) 9905c3c371SSam Leffler { 5, "rxmgt", "rxmgt", "rx management frames" }, 10005c3c371SSam Leffler #define S_RX_CTL AFTER(S_RX_MGT) 10105c3c371SSam Leffler { 5, "rxctl", "rxctl", "rx control frames" }, 10205c3c371SSam Leffler #define S_OUTPUT AFTER(S_RX_CTL) 10305c3c371SSam Leffler { 8, "output", "output", "total frames transmit" }, 10405c3c371SSam Leffler #define S_TX_MCAST AFTER(S_OUTPUT) 10505c3c371SSam Leffler { 7, "txmcast", "txmcast", "tx multicast frames" }, 10605c3c371SSam Leffler #define S_TX_MGMT AFTER(S_TX_MCAST) 10705c3c371SSam Leffler { 5, "txmgt", "txmgt", "tx management frames" }, 10805c3c371SSam Leffler #define S_TX_RETRY AFTER(S_TX_MGMT) 10905c3c371SSam Leffler { 7, "txretry", "txretry", "tx success with 1 retry" }, 11005c3c371SSam Leffler #define S_TX_MRETRY AFTER(S_TX_RETRY) 11105c3c371SSam Leffler { 8, "txmretry", "txmretry", "tx success with >1 retry" }, 11205c3c371SSam Leffler #define S_TX_RTSGOOD AFTER(S_TX_MRETRY) 11305c3c371SSam Leffler { 7, "rtsgood", "rtsgood", "RTS tx success" }, 11405c3c371SSam Leffler #define S_TX_RTSBAD AFTER(S_TX_RTSGOOD) 11505c3c371SSam Leffler { 6, "rtsbad", "rtsbad", "RTS tx failed" }, 11605c3c371SSam Leffler #define S_TX_NOACK AFTER(S_TX_RTSBAD) 11705c3c371SSam Leffler { 5, "noack", "noack", "tx failed because no ACK was received" }, 11805c3c371SSam Leffler #define S_RX_DUPLICATE AFTER(S_TX_NOACK) 11905c3c371SSam Leffler { 5, "rxdup", "rxdup", "rx discarded by f/w as dup" }, 12005c3c371SSam Leffler #define S_RX_FCS AFTER(S_RX_DUPLICATE) 12105c3c371SSam Leffler { 5, "rxfcs", "rxfcs", "rx discarded by f/w for bad FCS" }, 12205c3c371SSam Leffler #define S_TX_WATCHDOG AFTER(S_RX_FCS) 12305c3c371SSam Leffler { 7, "txwatch", "txwatch", "MAC tx hang (f/w recovery)" }, 12405c3c371SSam Leffler #define S_RX_OVERFLOW AFTER(S_TX_WATCHDOG) 12505c3c371SSam Leffler { 6, "rxover", "rxover", "no f/w buffer for rx" }, 12605c3c371SSam Leffler #define S_RX_FRAGERROR AFTER(S_RX_OVERFLOW) 12705c3c371SSam Leffler { 6, "rxfrag", "rxfrag", "rx failed in f/w due to defrag" }, 12805c3c371SSam Leffler #define S_RX_MEMERROR AFTER(S_RX_FRAGERROR) 129*e1e149adSGordon Bergling { 5, "rxmem", "rxmem", "rx failed in f/w 'cuz out of memory" }, 13005c3c371SSam Leffler #define S_PTRERROR AFTER(S_RX_MEMERROR) 13105c3c371SSam Leffler { 6, "badptr", "badptr", "MAC internal pointer problem" }, 13205c3c371SSam Leffler #define S_TX_UNDERFLOW AFTER(S_PTRERROR) 13305c3c371SSam Leffler { 7, "txunder", "txunder", "tx failed in f/w 'cuz of underflow" }, 13405c3c371SSam Leffler #define S_TX_DONE AFTER(S_TX_UNDERFLOW) 13505c3c371SSam Leffler { 6, "txdone", "txdone", "MAC tx ops completed" }, 13605c3c371SSam Leffler #define S_TX_DONEBUFPUT AFTER(S_TX_DONE) 13705c3c371SSam Leffler { 9, "txdoneput", "txdoneput", "tx buffers returned by f/w to host" }, 13805c3c371SSam Leffler #define S_TX_WAIT4BUF AFTER(S_TX_DONEBUFPUT) 13905c3c371SSam Leffler { 6, "txwait", "txwait", "no f/w buffers available when supplied a tx descriptor" }, 14005c3c371SSam Leffler #define S_TX_ATTEMPTS AFTER(S_TX_WAIT4BUF) 14105c3c371SSam Leffler { 5, "txtry", "txtry", "tx descriptors processed by f/w" }, 14205c3c371SSam Leffler #define S_TX_SUCCESS AFTER(S_TX_ATTEMPTS) 14305c3c371SSam Leffler { 4, "txok", "txok", "tx attempts successful" }, 14405c3c371SSam Leffler #define S_TX_FRAGS AFTER(S_TX_SUCCESS) 14505c3c371SSam Leffler { 6, "txfrag", "txfrag", "tx attempts with fragmentation" }, 14605c3c371SSam Leffler #define S_RX_UNDECRYPT AFTER(S_TX_FRAGS) 14705c3c371SSam Leffler { 7, "rxcrypt", "rxcrypt", "rx failed in f/w 'cuz decrypt failed" }, 14805c3c371SSam Leffler #define S_RX_ICVERROR AFTER(S_RX_UNDECRYPT) 14905c3c371SSam Leffler { 5, "rxicv", "rxicv", "rx failed in f/w 'cuz ICV check" }, 15005c3c371SSam Leffler #define S_RX_EXCLUDE AFTER(S_RX_ICVERROR) 15105c3c371SSam Leffler { 8, "rxfilter", "rxfilter", "rx frames filtered in f/w" }, 15205c3c371SSam Leffler #define S_TX_LINEAR AFTER(S_RX_EXCLUDE) 15305c3c371SSam Leffler { 5, "txlinear", "txlinear", "tx linearized to cluster" }, 15405c3c371SSam Leffler #define S_TX_DISCARD AFTER(S_TX_LINEAR) 15505c3c371SSam Leffler { 5, "txdisc", "txdisc", "tx frames discarded prior to association" }, 15605c3c371SSam Leffler #define S_TX_QSTOP AFTER(S_TX_DISCARD) 15705c3c371SSam Leffler { 5, "qstop", "qstop", "tx stopped 'cuz no xmit buffer" }, 15805c3c371SSam Leffler #define S_TX_ENCAP AFTER(S_TX_QSTOP) 15905c3c371SSam Leffler { 5, "txencode", "txencode", "tx encapsulation failed" }, 16005c3c371SSam Leffler #define S_TX_NOMBUF AFTER(S_TX_ENCAP) 16105c3c371SSam Leffler { 5, "txnombuf", "txnombuf", "tx failed 'cuz mbuf allocation failed" }, 16205c3c371SSam Leffler #define S_TX_SHORTPRE AFTER(S_TX_NOMBUF) 16305c3c371SSam Leffler { 5, "shpre", "shpre", "tx frames with short preamble" }, 16405c3c371SSam Leffler #define S_TX_NOHEADROOM AFTER(S_TX_SHORTPRE) 16505c3c371SSam Leffler { 5, "nohead", "nohead", "tx frames discarded for lack of headroom" }, 16605c3c371SSam Leffler #define S_TX_BADFRAMETYPE AFTER(S_TX_NOHEADROOM) 16705c3c371SSam Leffler { 5, "badtxtype", "badtxtype", "tx frames discarded for invalid/unknown 802.11 frame type" }, 16805c3c371SSam Leffler #define S_RX_CRYPTO_ERR AFTER(S_TX_BADFRAMETYPE) 16905c3c371SSam Leffler { 5, "crypt", "crypt", "rx failed 'cuz decryption" }, 17005c3c371SSam Leffler #define S_RX_NOMBUF AFTER(S_RX_CRYPTO_ERR) 17105c3c371SSam Leffler { 5, "rxnombuf", "rxnombuf", "rx setup failed 'cuz no mbuf" }, 17205c3c371SSam Leffler #define S_RX_TKIPMIC AFTER(S_RX_NOMBUF) 17305c3c371SSam Leffler { 5, "rxtkipmic", "rxtkipmic", "rx failed 'cuz TKIP MIC error" }, 17405c3c371SSam Leffler #define S_RX_NODMABUF AFTER(S_RX_TKIPMIC) 17505c3c371SSam Leffler { 5, "rxnodmabuf", "rxnodmabuf", "rx failed 'cuz no DMA buffer available" }, 17605c3c371SSam Leffler #define S_RX_DMABUFMISSING AFTER(S_RX_NODMABUF) 17705c3c371SSam Leffler { 5, "rxdmabufmissing", "rxdmabufmissing", "rx descriptor with no DMA buffer attached" }, 17805c3c371SSam Leffler #define S_TX_NODATA AFTER(S_RX_DMABUFMISSING) 17905c3c371SSam Leffler { 5, "txnodata", "txnodata", "tx discarded empty frame" }, 18005c3c371SSam Leffler #define S_TX_BUSDMA AFTER(S_TX_NODATA) 18105c3c371SSam Leffler { 5, "txbusdma", "txbusdma", "tx failed for dma resources" }, 18205c3c371SSam Leffler #define S_RX_BUSDMA AFTER(S_TX_BUSDMA) 18305c3c371SSam Leffler { 5, "rxbusdma", "rxbusdma", "rx setup failed for dma resources" }, 18405c3c371SSam Leffler #define S_AMPDU_NOSTREAM AFTER(S_RX_BUSDMA) 18505c3c371SSam Leffler { 5, "ampdu_nostream","ampdu_nostream","ADDBA request failed 'cuz all BA streams in use" }, 18605c3c371SSam Leffler #define S_AMPDU_REJECT AFTER(S_AMPDU_NOSTREAM) 18705c3c371SSam Leffler { 5, "ampdu_reject","ampdu_reject","ADDBA request failed 'cuz station already has one BA stream" }, 18805c3c371SSam Leffler #define S_ADDBA_NOSTREAM AFTER(S_AMPDU_REJECT) 18905c3c371SSam Leffler { 5, "addba_nostream","addba_nostream","ADDBA response processed but no BA stream present" }, 19005c3c371SSam Leffler #define S_TX_TSO AFTER(S_ADDBA_NOSTREAM) 19105c3c371SSam Leffler { 8, "txtso", "tso", "tx frames using TSO" }, 19205c3c371SSam Leffler #define S_TSO_BADETH AFTER(S_TX_TSO) 19305c3c371SSam Leffler { 5, "tsoeth", "tsoeth", "TSO failed 'cuz ether header type not IPv4" }, 19405c3c371SSam Leffler #define S_TSO_NOHDR AFTER(S_TSO_BADETH) 19505c3c371SSam Leffler { 5, "tsonohdr", "tsonohdr", "TSO failed 'cuz header not in first mbuf" }, 19605c3c371SSam Leffler #define S_TSO_BADSPLIT AFTER(S_TSO_NOHDR) 19705c3c371SSam Leffler { 5, "tsobadsplit", "tsobadsplit", "TSO failed 'cuz payload split failed" }, 19805c3c371SSam Leffler #define S_BAWATCHDOG AFTER(S_TSO_BADSPLIT) 19905c3c371SSam Leffler { 5, "bawatchdog", "bawatchdog", "BA watchdog interrupts" }, 20005c3c371SSam Leffler #define S_BAWATCHDOG_NOTFOUND AFTER(S_BAWATCHDOG) 20105c3c371SSam Leffler { 5, "bawatchdog_notfound", "bawatchdog_notfound", 20205c3c371SSam Leffler "BA watchdog for unknown stream" }, 20305c3c371SSam Leffler #define S_BAWATCHDOG_EMPTY AFTER(S_BAWATCHDOG_NOTFOUND) 20405c3c371SSam Leffler { 5, "bawatchdog_empty", "bawatchdog_empty", 20505c3c371SSam Leffler "BA watchdog on all streams but none found" }, 20605c3c371SSam Leffler #define S_BAWATCHDOG_FAILED AFTER(S_BAWATCHDOG_EMPTY) 20705c3c371SSam Leffler { 5, "bawatchdog_failed", "bawatchdog_failed", 20805c3c371SSam Leffler "BA watchdog processing failed to get bitmap from f/w" }, 20905c3c371SSam Leffler #define S_RADARDETECT AFTER(S_BAWATCHDOG_FAILED) 21005c3c371SSam Leffler { 5, "radardetect", "radardetect", "radar detect interrupts" }, 21105c3c371SSam Leffler #define S_RATE AFTER(S_RADARDETECT) 21205c3c371SSam Leffler { 4, "rate", "rate", "rate of last transmit" }, 21305c3c371SSam Leffler #define S_TX_RSSI AFTER(S_RATE) 21405c3c371SSam Leffler { 4, "arssi", "arssi", "rssi of last ack" }, 21505c3c371SSam Leffler #define S_RX_RSSI AFTER(S_TX_RSSI) 21605c3c371SSam Leffler { 4, "rssi", "rssi", "avg recv rssi" }, 21705c3c371SSam Leffler #define S_RX_NOISE AFTER(S_RX_RSSI) 21805c3c371SSam Leffler { 5, "noise", "noise", "rx noise floor" }, 21905c3c371SSam Leffler #define S_TX_SIGNAL AFTER(S_RX_NOISE) 22005c3c371SSam Leffler { 4, "asignal", "asig", "signal of last ack (dBm)" }, 22105c3c371SSam Leffler #define S_RX_SIGNAL AFTER(S_TX_SIGNAL) 22205c3c371SSam Leffler { 4, "signal", "sig", "avg recv signal (dBm)" }, 22305c3c371SSam Leffler #define S_ANT_TX0 AFTER(S_RX_SIGNAL) 22405c3c371SSam Leffler { 8, "tx0", "ant0(tx)", "frames tx on antenna 0" }, 22505c3c371SSam Leffler #define S_ANT_TX1 (S_RX_SIGNAL+2) 22605c3c371SSam Leffler { 8, "tx1", "ant1(tx)", "frames tx on antenna 1" }, 22705c3c371SSam Leffler #define S_ANT_TX2 (S_RX_SIGNAL+3) 22805c3c371SSam Leffler { 8, "tx2", "ant2(tx)", "frames tx on antenna 2" }, 22905c3c371SSam Leffler #define S_ANT_TX3 (S_RX_SIGNAL+4) 23005c3c371SSam Leffler { 8, "tx3", "ant3(tx)", "frames tx on antenna 3" }, 23105c3c371SSam Leffler #define S_ANT_RX0 AFTER(S_ANT_TX3) 23205c3c371SSam Leffler { 8, "rx0", "ant0(rx)", "frames rx on antenna 0" }, 23305c3c371SSam Leffler #define S_ANT_RX1 (S_ANT_TX3+2) 23405c3c371SSam Leffler { 8, "rx1", "ant1(rx)", "frames rx on antenna 1" }, 23505c3c371SSam Leffler #define S_ANT_RX2 (S_ANT_TX3+3) 23605c3c371SSam Leffler { 8, "rx2", "ant2(rx)", "frames rx on antenna 2" }, 23705c3c371SSam Leffler #define S_ANT_RX3 (S_ANT_TX3+4) 23805c3c371SSam Leffler { 8, "rx3", "ant3(rx)", "frames rx on antenna 3" }, 23905c3c371SSam Leffler }; 24005c3c371SSam Leffler /* NB: this intentionally avoids per-antenna stats */ 24105c3c371SSam Leffler #define S_LAST (S_RX_SIGNAL+1) 24205c3c371SSam Leffler 24305c3c371SSam Leffler struct mwlstatfoo_p { 24405c3c371SSam Leffler struct mwlstatfoo base; 24505c3c371SSam Leffler int s; 24605c3c371SSam Leffler struct ifreq ifr; 24705c3c371SSam Leffler struct mwl_stats cur; 24805c3c371SSam Leffler struct mwl_stats total; 24905c3c371SSam Leffler }; 25005c3c371SSam Leffler 25105c3c371SSam Leffler static void 25205c3c371SSam Leffler mwl_setifname(struct mwlstatfoo *wf0, const char *ifname) 25305c3c371SSam Leffler { 25405c3c371SSam Leffler struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) wf0; 25505c3c371SSam Leffler 25605c3c371SSam Leffler strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name)); 25705c3c371SSam Leffler } 25805c3c371SSam Leffler 25905c3c371SSam Leffler static void 26005c3c371SSam Leffler mwl_collect(struct mwlstatfoo_p *wf, struct mwl_stats *stats) 26105c3c371SSam Leffler { 26205c3c371SSam Leffler wf->ifr.ifr_data = (caddr_t) stats; 26305c3c371SSam Leffler if (ioctl(wf->s, SIOCGMVSTATS, &wf->ifr) < 0) 2642178f429SAdrian Chadd err(1, "%s: ioctl: %s", __func__, wf->ifr.ifr_name); 26505c3c371SSam Leffler } 26605c3c371SSam Leffler 26705c3c371SSam Leffler static void 26802d6be62SAdrian Chadd mwl_collect_cur(struct bsdstat *sf) 26905c3c371SSam Leffler { 27005c3c371SSam Leffler struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 27105c3c371SSam Leffler 27205c3c371SSam Leffler mwl_collect(wf, &wf->cur); 27305c3c371SSam Leffler } 27405c3c371SSam Leffler 27505c3c371SSam Leffler static void 27602d6be62SAdrian Chadd mwl_collect_tot(struct bsdstat *sf) 27705c3c371SSam Leffler { 27805c3c371SSam Leffler struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 27905c3c371SSam Leffler 28005c3c371SSam Leffler mwl_collect(wf, &wf->total); 28105c3c371SSam Leffler } 28205c3c371SSam Leffler 28305c3c371SSam Leffler static void 28402d6be62SAdrian Chadd mwl_update_tot(struct bsdstat *sf) 28505c3c371SSam Leffler { 28605c3c371SSam Leffler struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 28705c3c371SSam Leffler 28805c3c371SSam Leffler wf->total = wf->cur; 28905c3c371SSam Leffler } 29005c3c371SSam Leffler 29105c3c371SSam Leffler static void 29205c3c371SSam Leffler setrate(char b[], size_t bs, uint8_t rate) 29305c3c371SSam Leffler { 29405c3c371SSam Leffler if (rate & IEEE80211_RATE_MCS) 29505c3c371SSam Leffler snprintf(b, bs, "MCS%u", rate & IEEE80211_RATE_VAL); 29605c3c371SSam Leffler else if (rate & 1) 29705c3c371SSam Leffler snprintf(b, bs, "%u.5M", rate / 2); 29805c3c371SSam Leffler else 29905c3c371SSam Leffler snprintf(b, bs, "%uM", rate / 2); 30005c3c371SSam Leffler } 30105c3c371SSam Leffler 30205c3c371SSam Leffler static int 30302d6be62SAdrian Chadd mwl_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs) 30405c3c371SSam Leffler { 30505c3c371SSam Leffler struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 30605c3c371SSam Leffler #define STAT(x) \ 30705c3c371SSam Leffler snprintf(b, bs, "%u", wf->cur.mst_##x - wf->total.mst_##x); return 1 30805c3c371SSam Leffler #define HWSTAT(x) \ 30905c3c371SSam Leffler snprintf(b, bs, "%u", wf->cur.hw_stats.x - wf->total.hw_stats.x); return 1 31005c3c371SSam Leffler #define RXANT(x) \ 31105c3c371SSam Leffler snprintf(b, bs, "%u", wf->cur.mst_ant_rx[x] - wf->total.mst_ant_rx[x]); return 1 31205c3c371SSam Leffler #define TXANT(x) \ 31305c3c371SSam Leffler snprintf(b, bs, "%u", wf->cur.mst_ant_tx[x] - wf->total.mst_ant_tx[x]); return 1 31405c3c371SSam Leffler 31505c3c371SSam Leffler switch (s) { 31605c3c371SSam Leffler case S_INPUT: 31705c3c371SSam Leffler snprintf(b, bs, "%lu", (u_long)( 31805c3c371SSam Leffler (wf->cur.mst_rx_packets - wf->total.mst_rx_packets))); 31905c3c371SSam Leffler return 1; 32005c3c371SSam Leffler case S_OUTPUT: 32105c3c371SSam Leffler snprintf(b, bs, "%lu", (u_long)( 32205c3c371SSam Leffler wf->cur.mst_tx_packets - wf->total.mst_tx_packets)); 32305c3c371SSam Leffler return 1; 32405c3c371SSam Leffler case S_RATE: 32505c3c371SSam Leffler setrate(b, bs, wf->cur.mst_tx_rate); 32605c3c371SSam Leffler return 1; 32705c3c371SSam Leffler case S_TX_RETRY: HWSTAT(TxRetrySuccesses); 32805c3c371SSam Leffler case S_TX_MRETRY: HWSTAT(TxMultipleRetrySuccesses); 32905c3c371SSam Leffler case S_TX_RTSGOOD: HWSTAT(RTSSuccesses); 33005c3c371SSam Leffler case S_TX_RTSBAD: HWSTAT(RTSFailures); 33105c3c371SSam Leffler case S_TX_NOACK: HWSTAT(AckFailures); 33205c3c371SSam Leffler case S_RX_DUPLICATE: HWSTAT(RxDuplicateFrames); 33305c3c371SSam Leffler case S_RX_FCS: HWSTAT(FCSErrorCount); 33405c3c371SSam Leffler case S_TX_WATCHDOG: HWSTAT(TxWatchDogTimeouts); 33505c3c371SSam Leffler case S_RX_OVERFLOW: HWSTAT(RxOverflows); 33605c3c371SSam Leffler case S_RX_FRAGERROR: HWSTAT(RxFragErrors); 33705c3c371SSam Leffler case S_RX_MEMERROR: HWSTAT(RxMemErrors); 33805c3c371SSam Leffler case S_PTRERROR: HWSTAT(PointerErrors); 33905c3c371SSam Leffler case S_TX_UNDERFLOW: HWSTAT(TxUnderflows); 34005c3c371SSam Leffler case S_TX_DONE: HWSTAT(TxDone); 34105c3c371SSam Leffler case S_TX_DONEBUFPUT: HWSTAT(TxDoneBufPut); 34205c3c371SSam Leffler case S_TX_WAIT4BUF: HWSTAT(Wait4TxBuf); 34305c3c371SSam Leffler case S_TX_ATTEMPTS: HWSTAT(TxAttempts); 34405c3c371SSam Leffler case S_TX_SUCCESS: HWSTAT(TxSuccesses); 34505c3c371SSam Leffler case S_TX_FRAGS: HWSTAT(TxFragments); 34605c3c371SSam Leffler case S_TX_MCAST: HWSTAT(TxMulticasts); 34705c3c371SSam Leffler case S_RX_NONCTL: HWSTAT(RxNonCtlPkts); 34805c3c371SSam Leffler case S_RX_MCAST: HWSTAT(RxMulticasts); 34905c3c371SSam Leffler case S_RX_UNDECRYPT: HWSTAT(RxUndecryptableFrames); 35005c3c371SSam Leffler case S_RX_ICVERROR: HWSTAT(RxICVErrors); 35105c3c371SSam Leffler case S_RX_EXCLUDE: HWSTAT(RxExcludedFrames); 35205c3c371SSam Leffler case S_TX_MGMT: STAT(tx_mgmt); 35305c3c371SSam Leffler case S_TX_DISCARD: STAT(tx_discard); 35405c3c371SSam Leffler case S_TX_QSTOP: STAT(tx_qstop); 35505c3c371SSam Leffler case S_TX_ENCAP: STAT(tx_encap); 35605c3c371SSam Leffler case S_TX_NOMBUF: STAT(tx_nombuf); 35705c3c371SSam Leffler case S_TX_LINEAR: STAT(tx_linear); 35805c3c371SSam Leffler case S_TX_NODATA: STAT(tx_nodata); 35905c3c371SSam Leffler case S_TX_BUSDMA: STAT(tx_busdma); 36005c3c371SSam Leffler case S_TX_SHORTPRE: STAT(tx_shortpre); 36105c3c371SSam Leffler case S_TX_NOHEADROOM: STAT(tx_noheadroom); 36205c3c371SSam Leffler case S_TX_BADFRAMETYPE: STAT(tx_badframetype); 36305c3c371SSam Leffler case S_RX_CRYPTO_ERR: STAT(rx_crypto); 36405c3c371SSam Leffler case S_RX_TKIPMIC: STAT(rx_tkipmic); 36505c3c371SSam Leffler case S_RX_NODMABUF: STAT(rx_nodmabuf); 36605c3c371SSam Leffler case S_RX_DMABUFMISSING:STAT(rx_dmabufmissing); 36705c3c371SSam Leffler case S_RX_NOMBUF: STAT(rx_nombuf); 36805c3c371SSam Leffler case S_RX_BUSDMA: STAT(rx_busdma); 36905c3c371SSam Leffler case S_AMPDU_NOSTREAM: STAT(ampdu_nostream); 37005c3c371SSam Leffler case S_AMPDU_REJECT: STAT(ampdu_reject); 37105c3c371SSam Leffler case S_ADDBA_NOSTREAM: STAT(addba_nostream); 37205c3c371SSam Leffler case S_TX_TSO: STAT(tx_tso); 37305c3c371SSam Leffler case S_TSO_BADETH: STAT(tso_badeth); 37405c3c371SSam Leffler case S_TSO_NOHDR: STAT(tso_nohdr); 37505c3c371SSam Leffler case S_TSO_BADSPLIT: STAT(tso_badsplit); 37605c3c371SSam Leffler case S_BAWATCHDOG: STAT(bawatchdog); 37705c3c371SSam Leffler case S_BAWATCHDOG_NOTFOUND:STAT(bawatchdog_notfound); 37805c3c371SSam Leffler case S_BAWATCHDOG_EMPTY: STAT(bawatchdog_empty); 37905c3c371SSam Leffler case S_BAWATCHDOG_FAILED:STAT(bawatchdog_failed); 38005c3c371SSam Leffler case S_RADARDETECT: STAT(radardetect); 38105c3c371SSam Leffler case S_RX_RSSI: 38205c3c371SSam Leffler snprintf(b, bs, "%d", wf->cur.mst_rx_rssi); 38305c3c371SSam Leffler return 1; 38405c3c371SSam Leffler case S_ANT_TX0: TXANT(0); 38505c3c371SSam Leffler case S_ANT_TX1: TXANT(1); 38605c3c371SSam Leffler case S_ANT_TX2: TXANT(2); 38705c3c371SSam Leffler case S_ANT_TX3: TXANT(3); 38805c3c371SSam Leffler case S_ANT_RX0: RXANT(0); 38905c3c371SSam Leffler case S_ANT_RX1: RXANT(1); 39005c3c371SSam Leffler case S_ANT_RX2: RXANT(2); 39105c3c371SSam Leffler case S_ANT_RX3: RXANT(3); 39205c3c371SSam Leffler case S_RX_NOISE: 39305c3c371SSam Leffler snprintf(b, bs, "%d", wf->cur.mst_rx_noise); 39405c3c371SSam Leffler return 1; 39505c3c371SSam Leffler case S_RX_SIGNAL: 39605c3c371SSam Leffler snprintf(b, bs, "%d", 39705c3c371SSam Leffler wf->cur.mst_rx_rssi + wf->cur.mst_rx_noise); 39805c3c371SSam Leffler return 1; 39905c3c371SSam Leffler } 40005c3c371SSam Leffler b[0] = '\0'; 40105c3c371SSam Leffler return 0; 40205c3c371SSam Leffler #undef RXANT 40305c3c371SSam Leffler #undef TXANT 40405c3c371SSam Leffler #undef HWSTAT 40505c3c371SSam Leffler #undef STAT 40605c3c371SSam Leffler } 40705c3c371SSam Leffler 40805c3c371SSam Leffler static int 40902d6be62SAdrian Chadd mwl_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs) 41005c3c371SSam Leffler { 41105c3c371SSam Leffler struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 41205c3c371SSam Leffler #define STAT(x) \ 41305c3c371SSam Leffler snprintf(b, bs, "%u", wf->total.mst_##x); return 1 41405c3c371SSam Leffler #define HWSTAT(x) \ 41505c3c371SSam Leffler snprintf(b, bs, "%u", wf->total.hw_stats.x); return 1 41605c3c371SSam Leffler #define TXANT(x) \ 41705c3c371SSam Leffler snprintf(b, bs, "%u", wf->total.mst_ant_tx[x]); return 1 41805c3c371SSam Leffler #define RXANT(x) \ 41905c3c371SSam Leffler snprintf(b, bs, "%u", wf->total.mst_ant_rx[x]); return 1 42005c3c371SSam Leffler 42105c3c371SSam Leffler switch (s) { 42205c3c371SSam Leffler case S_INPUT: 42305c3c371SSam Leffler snprintf(b, bs, "%lu", (u_long)wf->total.mst_rx_packets); 42405c3c371SSam Leffler return 1; 42505c3c371SSam Leffler case S_OUTPUT: 42605c3c371SSam Leffler snprintf(b, bs, "%lu", (u_long) wf->total.mst_tx_packets); 42705c3c371SSam Leffler return 1; 42805c3c371SSam Leffler case S_RATE: 42905c3c371SSam Leffler setrate(b, bs, wf->total.mst_tx_rate); 43005c3c371SSam Leffler return 1; 43105c3c371SSam Leffler case S_TX_RETRY: HWSTAT(TxRetrySuccesses); 43205c3c371SSam Leffler case S_TX_MRETRY: HWSTAT(TxMultipleRetrySuccesses); 43305c3c371SSam Leffler case S_TX_RTSGOOD: HWSTAT(RTSSuccesses); 43405c3c371SSam Leffler case S_TX_RTSBAD: HWSTAT(RTSFailures); 43505c3c371SSam Leffler case S_TX_NOACK: HWSTAT(AckFailures); 43605c3c371SSam Leffler case S_RX_DUPLICATE: HWSTAT(RxDuplicateFrames); 43705c3c371SSam Leffler case S_RX_FCS: HWSTAT(FCSErrorCount); 43805c3c371SSam Leffler case S_TX_WATCHDOG: HWSTAT(TxWatchDogTimeouts); 43905c3c371SSam Leffler case S_RX_OVERFLOW: HWSTAT(RxOverflows); 44005c3c371SSam Leffler case S_RX_FRAGERROR: HWSTAT(RxFragErrors); 44105c3c371SSam Leffler case S_RX_MEMERROR: HWSTAT(RxMemErrors); 44205c3c371SSam Leffler case S_PTRERROR: HWSTAT(PointerErrors); 44305c3c371SSam Leffler case S_TX_UNDERFLOW: HWSTAT(TxUnderflows); 44405c3c371SSam Leffler case S_TX_DONE: HWSTAT(TxDone); 44505c3c371SSam Leffler case S_TX_DONEBUFPUT: HWSTAT(TxDoneBufPut); 44605c3c371SSam Leffler case S_TX_WAIT4BUF: HWSTAT(Wait4TxBuf); 44705c3c371SSam Leffler case S_TX_ATTEMPTS: HWSTAT(TxAttempts); 44805c3c371SSam Leffler case S_TX_SUCCESS: HWSTAT(TxSuccesses); 44905c3c371SSam Leffler case S_TX_FRAGS: HWSTAT(TxFragments); 45005c3c371SSam Leffler case S_TX_MCAST: HWSTAT(TxMulticasts); 45105c3c371SSam Leffler case S_RX_NONCTL: HWSTAT(RxNonCtlPkts); 45205c3c371SSam Leffler case S_RX_MCAST: HWSTAT(RxMulticasts); 45305c3c371SSam Leffler case S_RX_UNDECRYPT: HWSTAT(RxUndecryptableFrames); 45405c3c371SSam Leffler case S_RX_ICVERROR: HWSTAT(RxICVErrors); 45505c3c371SSam Leffler case S_RX_EXCLUDE: HWSTAT(RxExcludedFrames); 45605c3c371SSam Leffler case S_TX_MGMT: STAT(tx_mgmt); 45705c3c371SSam Leffler case S_TX_DISCARD: STAT(tx_discard); 45805c3c371SSam Leffler case S_TX_QSTOP: STAT(tx_qstop); 45905c3c371SSam Leffler case S_TX_ENCAP: STAT(tx_encap); 46005c3c371SSam Leffler case S_TX_NOMBUF: STAT(tx_nombuf); 46105c3c371SSam Leffler case S_TX_LINEAR: STAT(tx_linear); 46205c3c371SSam Leffler case S_TX_NODATA: STAT(tx_nodata); 46305c3c371SSam Leffler case S_TX_BUSDMA: STAT(tx_busdma); 46405c3c371SSam Leffler case S_TX_SHORTPRE: STAT(tx_shortpre); 46505c3c371SSam Leffler case S_TX_NOHEADROOM: STAT(tx_noheadroom); 46605c3c371SSam Leffler case S_TX_BADFRAMETYPE: STAT(tx_badframetype); 46705c3c371SSam Leffler case S_RX_CRYPTO_ERR: STAT(rx_crypto); 46805c3c371SSam Leffler case S_RX_TKIPMIC: STAT(rx_tkipmic); 46905c3c371SSam Leffler case S_RX_NODMABUF: STAT(rx_nodmabuf); 47005c3c371SSam Leffler case S_RX_DMABUFMISSING:STAT(rx_dmabufmissing); 47105c3c371SSam Leffler case S_RX_NOMBUF: STAT(rx_nombuf); 47205c3c371SSam Leffler case S_RX_BUSDMA: STAT(rx_busdma); 47305c3c371SSam Leffler case S_AMPDU_NOSTREAM: STAT(ampdu_nostream); 47405c3c371SSam Leffler case S_AMPDU_REJECT: STAT(ampdu_reject); 47505c3c371SSam Leffler case S_ADDBA_NOSTREAM: STAT(addba_nostream); 47605c3c371SSam Leffler case S_TX_TSO: STAT(tx_tso); 47705c3c371SSam Leffler case S_TSO_BADETH: STAT(tso_badeth); 47805c3c371SSam Leffler case S_TSO_NOHDR: STAT(tso_nohdr); 47905c3c371SSam Leffler case S_TSO_BADSPLIT: STAT(tso_badsplit); 48005c3c371SSam Leffler case S_BAWATCHDOG: STAT(bawatchdog); 48105c3c371SSam Leffler case S_BAWATCHDOG_NOTFOUND:STAT(bawatchdog_notfound); 48205c3c371SSam Leffler case S_BAWATCHDOG_EMPTY: STAT(bawatchdog_empty); 48305c3c371SSam Leffler case S_BAWATCHDOG_FAILED:STAT(bawatchdog_failed); 48405c3c371SSam Leffler case S_RADARDETECT: STAT(radardetect); 48505c3c371SSam Leffler case S_RX_RSSI: 48605c3c371SSam Leffler snprintf(b, bs, "%d", wf->total.mst_rx_rssi); 48705c3c371SSam Leffler return 1; 48805c3c371SSam Leffler case S_ANT_TX0: TXANT(0); 48905c3c371SSam Leffler case S_ANT_TX1: TXANT(1); 49005c3c371SSam Leffler case S_ANT_TX2: TXANT(2); 49105c3c371SSam Leffler case S_ANT_TX3: TXANT(3); 49205c3c371SSam Leffler case S_ANT_RX0: RXANT(0); 49305c3c371SSam Leffler case S_ANT_RX1: RXANT(1); 49405c3c371SSam Leffler case S_ANT_RX2: RXANT(2); 49505c3c371SSam Leffler case S_ANT_RX3: RXANT(3); 49605c3c371SSam Leffler case S_RX_NOISE: 49705c3c371SSam Leffler snprintf(b, bs, "%d", wf->total.mst_rx_noise); 49805c3c371SSam Leffler return 1; 49905c3c371SSam Leffler case S_RX_SIGNAL: 50005c3c371SSam Leffler snprintf(b, bs, "%d", 50105c3c371SSam Leffler wf->total.mst_rx_rssi + wf->total.mst_rx_noise); 50205c3c371SSam Leffler return 1; 50305c3c371SSam Leffler } 50405c3c371SSam Leffler b[0] = '\0'; 50505c3c371SSam Leffler return 0; 50605c3c371SSam Leffler #undef RXANT 50705c3c371SSam Leffler #undef TXANT 50805c3c371SSam Leffler #undef HWSTAT 50905c3c371SSam Leffler #undef STAT 51005c3c371SSam Leffler } 51105c3c371SSam Leffler 51205c3c371SSam Leffler static void 51302d6be62SAdrian Chadd mwl_print_verbose(struct bsdstat *sf, FILE *fd) 51405c3c371SSam Leffler { 51505c3c371SSam Leffler struct mwlstatfoo_p *wf = (struct mwlstatfoo_p *) sf; 51605c3c371SSam Leffler const struct fmt *f; 51705c3c371SSam Leffler char s[32]; 51805c3c371SSam Leffler const char *indent; 51905c3c371SSam Leffler int i, width; 52005c3c371SSam Leffler 52105c3c371SSam Leffler width = 0; 52205c3c371SSam Leffler for (i = 0; i < S_LAST; i++) { 52305c3c371SSam Leffler f = &sf->stats[i]; 52405c3c371SSam Leffler if (f->width > width) 52505c3c371SSam Leffler width = f->width; 52605c3c371SSam Leffler } 52705c3c371SSam Leffler for (i = 0; i < S_LAST; i++) { 52805c3c371SSam Leffler f = &sf->stats[i]; 52905c3c371SSam Leffler if (mwl_get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) { 53005c3c371SSam Leffler indent = ""; 53105c3c371SSam Leffler fprintf(fd, "%s%-*s %s\n", indent, width, s, f->desc); 53205c3c371SSam Leffler } 53305c3c371SSam Leffler } 53405c3c371SSam Leffler fprintf(fd, "Antenna profile:\n"); 53505c3c371SSam Leffler for (i = 0; i < 4; i++) 53605c3c371SSam Leffler if (wf->total.mst_ant_rx[i] || wf->total.mst_ant_tx[i]) 53705c3c371SSam Leffler fprintf(fd, "[%u] tx %8u rx %8u\n", i, 53805c3c371SSam Leffler wf->total.mst_ant_tx[i], 53905c3c371SSam Leffler wf->total.mst_ant_rx[i]); 54005c3c371SSam Leffler } 54105c3c371SSam Leffler 54202d6be62SAdrian Chadd BSDSTAT_DEFINE_BOUNCE(mwlstatfoo) 54305c3c371SSam Leffler 54405c3c371SSam Leffler struct mwlstatfoo * 54505c3c371SSam Leffler mwlstats_new(const char *ifname, const char *fmtstring) 54605c3c371SSam Leffler { 54705c3c371SSam Leffler struct mwlstatfoo_p *wf; 54805c3c371SSam Leffler 54905c3c371SSam Leffler wf = calloc(1, sizeof(struct mwlstatfoo_p)); 55005c3c371SSam Leffler if (wf != NULL) { 55160caf0c9SCraig Rodrigues bsdstat_init(&wf->base.base, "mwlstats", mwlstats, 55260caf0c9SCraig Rodrigues nitems(mwlstats)); 55305c3c371SSam Leffler /* override base methods */ 55405c3c371SSam Leffler wf->base.base.collect_cur = mwl_collect_cur; 55505c3c371SSam Leffler wf->base.base.collect_tot = mwl_collect_tot; 55605c3c371SSam Leffler wf->base.base.get_curstat = mwl_get_curstat; 55705c3c371SSam Leffler wf->base.base.get_totstat = mwl_get_totstat; 55805c3c371SSam Leffler wf->base.base.update_tot = mwl_update_tot; 55905c3c371SSam Leffler wf->base.base.print_verbose = mwl_print_verbose; 56005c3c371SSam Leffler 56105c3c371SSam Leffler /* setup bounce functions for public methods */ 56202d6be62SAdrian Chadd BSDSTAT_BOUNCE(wf, mwlstatfoo); 56305c3c371SSam Leffler 56405c3c371SSam Leffler /* setup our public methods */ 56505c3c371SSam Leffler wf->base.setifname = mwl_setifname; 56605c3c371SSam Leffler #if 0 56705c3c371SSam Leffler wf->base.setstamac = wlan_setstamac; 56805c3c371SSam Leffler #endif 56905c3c371SSam Leffler wf->s = socket(AF_INET, SOCK_DGRAM, 0); 57005c3c371SSam Leffler if (wf->s < 0) 57105c3c371SSam Leffler err(1, "socket"); 57205c3c371SSam Leffler 57305c3c371SSam Leffler mwl_setifname(&wf->base, ifname); 57405c3c371SSam Leffler wf->base.setfmt(&wf->base, fmtstring); 57505c3c371SSam Leffler } 57605c3c371SSam Leffler return &wf->base; 57705c3c371SSam Leffler } 578