1 /*- 2 * Copyright (c) 2002-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 * ath statistics class. 34 */ 35 #include <sys/types.h> 36 #include <sys/file.h> 37 #include <sys/sockio.h> 38 #include <sys/socket.h> 39 #include <net/if.h> 40 #include <net/if_media.h> 41 #include <net/if_var.h> 42 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <signal.h> 46 #include <string.h> 47 #include <unistd.h> 48 #include <err.h> 49 50 #include "ah.h" 51 #include "ah_desc.h" 52 #include "ieee80211_ioctl.h" 53 #include "ieee80211_radiotap.h" 54 #include "if_athioctl.h" 55 56 #include "athstats.h" 57 58 #define NOTPRESENT { 0, "", "" } 59 60 #define AFTER(prev) ((prev)+1) 61 62 static const struct fmt athstats[] = { 63 #define S_INPUT 0 64 { 8, "input", "input", "data frames received" }, 65 #define S_OUTPUT AFTER(S_INPUT) 66 { 8, "output", "output", "data frames transmit" }, 67 #define S_TX_ALTRATE AFTER(S_OUTPUT) 68 { 7, "altrate", "altrate", "tx frames with an alternate rate" }, 69 #define S_TX_SHORTRETRY AFTER(S_TX_ALTRATE) 70 { 7, "short", "short", "short on-chip tx retries" }, 71 #define S_TX_LONGRETRY AFTER(S_TX_SHORTRETRY) 72 { 7, "long", "long", "long on-chip tx retries" }, 73 #define S_TX_XRETRIES AFTER(S_TX_LONGRETRY) 74 { 6, "xretry", "xretry", "tx failed 'cuz too many retries" }, 75 #define S_MIB AFTER(S_TX_XRETRIES) 76 { 5, "mib", "mib", "mib overflow interrupts" }, 77 #ifndef __linux__ 78 #define S_TX_LINEAR AFTER(S_MIB) 79 { 5, "txlinear", "txlinear", "tx linearized to cluster" }, 80 #define S_BSTUCK AFTER(S_TX_LINEAR) 81 { 5, "bstuck", "bstuck", "stuck beacon conditions" }, 82 #define S_INTRCOAL AFTER(S_BSTUCK) 83 { 5, "intrcoal", "intrcoal", "interrupts coalesced" }, 84 #define S_RATE AFTER(S_INTRCOAL) 85 #else 86 #define S_RATE AFTER(S_MIB) 87 #endif 88 { 4, "rate", "rate", "current transmit rate" }, 89 #define S_WATCHDOG AFTER(S_RATE) 90 { 5, "wdog", "wdog", "watchdog timeouts" }, 91 #define S_FATAL AFTER(S_WATCHDOG) 92 { 5, "fatal", "fatal", "hardware error interrupts" }, 93 #define S_BMISS AFTER(S_FATAL) 94 { 5, "bmiss", "bmiss", "beacon miss interrupts" }, 95 #define S_RXORN AFTER(S_BMISS) 96 { 5, "rxorn", "rxorn", "recv overrun interrupts" }, 97 #define S_RXEOL AFTER(S_RXORN) 98 { 5, "rxeol", "rxeol", "recv eol interrupts" }, 99 #define S_TXURN AFTER(S_RXEOL) 100 { 5, "txurn", "txurn", "txmit underrun interrupts" }, 101 #define S_TX_MGMT AFTER(S_TXURN) 102 { 5, "txmgt", "txmgt", "tx management frames" }, 103 #define S_TX_DISCARD AFTER(S_TX_MGMT) 104 { 5, "txdisc", "txdisc", "tx frames discarded prior to association" }, 105 #define S_TX_INVALID AFTER(S_TX_DISCARD) 106 { 5, "txinv", "txinv", "tx invalid (19)" }, 107 #define S_TX_QSTOP AFTER(S_TX_INVALID) 108 { 5, "qstop", "qstop", "tx stopped 'cuz no xmit buffer" }, 109 #define S_TX_ENCAP AFTER(S_TX_QSTOP) 110 { 5, "txencode", "txencode", "tx encapsulation failed" }, 111 #define S_TX_NONODE AFTER(S_TX_ENCAP) 112 { 5, "txnonode", "txnonode", "tx failed 'cuz no node" }, 113 #define S_TX_NOMBUF AFTER(S_TX_NONODE) 114 { 5, "txnombuf", "txnombuf", "tx failed 'cuz mbuf allocation failed" }, 115 #ifndef __linux__ 116 #define S_TX_NOMCL AFTER(S_TX_NOMBUF) 117 { 5, "txnomcl", "txnomcl", "tx failed 'cuz cluster allocation failed" }, 118 #define S_TX_FIFOERR AFTER(S_TX_NOMCL) 119 #else 120 #define S_TX_FIFOERR AFTER(S_TX_NOMBUF) 121 #endif 122 { 5, "efifo", "efifo", "tx failed 'cuz FIFO underrun" }, 123 #define S_TX_FILTERED AFTER(S_TX_FIFOERR) 124 { 5, "efilt", "efilt", "tx failed 'cuz destination filtered" }, 125 #define S_TX_BADRATE AFTER(S_TX_FILTERED) 126 { 5, "txbadrate", "txbadrate", "tx failed 'cuz bogus xmit rate" }, 127 #define S_TX_NOACK AFTER(S_TX_BADRATE) 128 { 5, "noack", "noack", "tx frames with no ack marked" }, 129 #define S_TX_RTS AFTER(S_TX_NOACK) 130 { 5, "rts", "rts", "tx frames with rts enabled" }, 131 #define S_TX_CTS AFTER(S_TX_RTS) 132 { 5, "cts", "cts", "tx frames with cts enabled" }, 133 #define S_TX_SHORTPRE AFTER(S_TX_CTS) 134 { 5, "shpre", "shpre", "tx frames with short preamble" }, 135 #define S_TX_PROTECT AFTER(S_TX_SHORTPRE) 136 { 5, "protect", "protect", "tx frames with 11g protection" }, 137 #define S_RX_ORN AFTER(S_TX_PROTECT) 138 { 5, "rxorn", "rxorn", "rx failed 'cuz of desc overrun" }, 139 #define S_RX_CRC_ERR AFTER(S_RX_ORN) 140 { 6, "crcerr", "crcerr", "rx failed 'cuz of bad CRC" }, 141 #define S_RX_FIFO_ERR AFTER(S_RX_CRC_ERR) 142 { 5, "rxfifo", "rxfifo", "rx failed 'cuz of FIFO overrun" }, 143 #define S_RX_CRYPTO_ERR AFTER(S_RX_FIFO_ERR) 144 { 5, "crypt", "crypt", "rx failed 'cuz decryption" }, 145 #define S_RX_MIC_ERR AFTER(S_RX_CRYPTO_ERR) 146 { 4, "mic", "mic", "rx failed 'cuz MIC failure" }, 147 #define S_RX_TOOSHORT AFTER(S_RX_MIC_ERR) 148 { 5, "rxshort", "rxshort", "rx failed 'cuz frame too short" }, 149 #define S_RX_NOMBUF AFTER(S_RX_TOOSHORT) 150 { 5, "rxnombuf", "rxnombuf", "rx setup failed 'cuz no mbuf" }, 151 #define S_RX_MGT AFTER(S_RX_NOMBUF) 152 { 5, "rxmgt", "rxmgt", "rx management frames" }, 153 #define S_RX_CTL AFTER(S_RX_MGT) 154 { 5, "rxctl", "rxctl", "rx control frames" }, 155 #define S_RX_PHY_ERR AFTER(S_RX_CTL) 156 { 7, "phyerr", "phyerr", "rx failed 'cuz of PHY err" }, 157 #define S_RX_PHY_UNDERRUN AFTER(S_RX_PHY_ERR) 158 { 6, "phyund", "phyund", "transmit underrun" }, 159 #define S_RX_PHY_TIMING AFTER(S_RX_PHY_UNDERRUN) 160 { 6, "phytim", "phytim", "timing error" }, 161 #define S_RX_PHY_PARITY AFTER(S_RX_PHY_TIMING) 162 { 6, "phypar", "phypar", "illegal parity" }, 163 #define S_RX_PHY_RATE AFTER(S_RX_PHY_PARITY) 164 { 6, "phyrate", "phyrate", "illegal rate" }, 165 #define S_RX_PHY_LENGTH AFTER(S_RX_PHY_RATE) 166 { 6, "phylen", "phylen", "illegal length" }, 167 #define S_RX_PHY_RADAR AFTER(S_RX_PHY_LENGTH) 168 { 6, "phyradar", "phyradar", "radar detect" }, 169 #define S_RX_PHY_SERVICE AFTER(S_RX_PHY_RADAR) 170 { 6, "physervice", "physervice", "illegal service" }, 171 #define S_RX_PHY_TOR AFTER(S_RX_PHY_SERVICE) 172 { 6, "phytor", "phytor", "transmit override receive" }, 173 #define S_RX_PHY_OFDM_TIMING AFTER(S_RX_PHY_TOR) 174 { 6, "ofdmtim", "ofdmtim", "OFDM timing" }, 175 #define S_RX_PHY_OFDM_SIGNAL_PARITY AFTER(S_RX_PHY_OFDM_TIMING) 176 { 6, "ofdmsig", "ofdmsig", "OFDM illegal parity" }, 177 #define S_RX_PHY_OFDM_RATE_ILLEGAL AFTER(S_RX_PHY_OFDM_SIGNAL_PARITY) 178 { 6, "ofdmrate", "ofdmrate", "OFDM illegal rate" }, 179 #define S_RX_PHY_OFDM_POWER_DROP AFTER(S_RX_PHY_OFDM_RATE_ILLEGAL) 180 { 6, "ofdmpow", "ofdmpow", "OFDM power drop" }, 181 #define S_RX_PHY_OFDM_SERVICE AFTER(S_RX_PHY_OFDM_POWER_DROP) 182 { 6, "ofdmservice", "ofdmservice", "OFDM illegal service" }, 183 #define S_RX_PHY_OFDM_RESTART AFTER(S_RX_PHY_OFDM_SERVICE) 184 { 6, "ofdmrestart", "ofdmrestart", "OFDM restart" }, 185 #define S_RX_PHY_CCK_TIMING AFTER(S_RX_PHY_OFDM_RESTART) 186 { 6, "ccktim", "ccktim", "CCK timing" }, 187 #define S_RX_PHY_CCK_HEADER_CRC AFTER(S_RX_PHY_CCK_TIMING) 188 { 6, "cckhead", "cckhead", "CCK header crc" }, 189 #define S_RX_PHY_CCK_RATE_ILLEGAL AFTER(S_RX_PHY_CCK_HEADER_CRC) 190 { 6, "cckrate", "cckrate", "CCK illegal rate" }, 191 #define S_RX_PHY_CCK_SERVICE AFTER(S_RX_PHY_CCK_RATE_ILLEGAL) 192 { 6, "cckservice", "cckservice", "CCK illegal service" }, 193 #define S_RX_PHY_CCK_RESTART AFTER(S_RX_PHY_CCK_SERVICE) 194 { 6, "cckrestar", "cckrestar", "CCK restart" }, 195 #define S_BE_NOMBUF AFTER(S_RX_PHY_CCK_RESTART) 196 { 4, "benombuf", "benombuf", "beacon setup failed 'cuz no mbuf" }, 197 #define S_BE_XMIT AFTER(S_BE_NOMBUF) 198 { 7, "bexmit", "bexmit", "beacons transmitted" }, 199 #define S_PER_CAL AFTER(S_BE_XMIT) 200 { 4, "pcal", "pcal", "periodic calibrations" }, 201 #define S_PER_CALFAIL AFTER(S_PER_CAL) 202 { 4, "pcalf", "pcalf", "periodic calibration failures" }, 203 #define S_PER_RFGAIN AFTER(S_PER_CALFAIL) 204 { 4, "prfga", "prfga", "rfgain value change" }, 205 #if ATH_SUPPORT_TDMA 206 #define S_TDMA_UPDATE AFTER(S_PER_RFGAIN) 207 { 5, "tdmau", "tdmau", "TDMA slot timing updates" }, 208 #define S_TDMA_TIMERS AFTER(S_TDMA_UPDATE) 209 { 5, "tdmab", "tdmab", "TDMA slot update set beacon timers" }, 210 #define S_TDMA_TSF AFTER(S_TDMA_TIMERS) 211 { 5, "tdmat", "tdmat", "TDMA slot update set TSF" }, 212 #define S_RATE_CALLS AFTER(S_TDMA_TSF) 213 #else 214 #define S_RATE_CALLS AFTER(S_PER_RFGAIN) 215 #endif 216 { 5, "ratec", "ratec", "rate control checks" }, 217 #define S_RATE_RAISE AFTER(S_RATE_CALLS) 218 { 5, "rate+", "rate+", "rate control raised xmit rate" }, 219 #define S_RATE_DROP AFTER(S_RATE_RAISE) 220 { 5, "rate-", "rate-", "rate control dropped xmit rate" }, 221 #define S_TX_RSSI AFTER(S_RATE_DROP) 222 { 4, "arssi", "arssi", "rssi of last ack" }, 223 #define S_RX_RSSI AFTER(S_TX_RSSI) 224 { 4, "rssi", "rssi", "avg recv rssi" }, 225 #define S_RX_NOISE AFTER(S_RX_RSSI) 226 { 5, "noise", "noise", "rx noise floor" }, 227 #define S_BMISS_PHANTOM AFTER(S_RX_NOISE) 228 { 5, "bmissphantom", "bmissphantom", "phantom beacon misses" }, 229 #define S_TX_RAW AFTER(S_BMISS_PHANTOM) 230 { 5, "txraw", "txraw", "tx frames through raw api" }, 231 #define S_RX_TOOBIG AFTER(S_TX_RAW) 232 { 5, "rx2big", "rx2big", "rx failed 'cuz frame too large" }, 233 #ifndef __linux__ 234 #define S_CABQ_XMIT AFTER(S_RX_TOOBIG) 235 { 5, "cabxmit", "cabxmit", "cabq frames transmitted" }, 236 #define S_CABQ_BUSY AFTER(S_CABQ_XMIT) 237 { 5, "cabqbusy", "cabqbusy", "cabq xmit overflowed beacon interval" }, 238 #define S_TX_NODATA AFTER(S_CABQ_BUSY) 239 { 5, "txnodata", "txnodata", "tx discarded empty frame" }, 240 #define S_TX_BUSDMA AFTER(S_TX_NODATA) 241 { 5, "txbusdma", "txbusdma", "tx failed for dma resrcs" }, 242 #define S_RX_BUSDMA AFTER(S_TX_BUSDMA) 243 { 5, "rxbusdma", "rxbusdma", "rx setup failed for dma resrcs" }, 244 #define S_FF_TXOK AFTER(S_RX_BUSDMA) 245 #else 246 #define S_FF_TXOK AFTER(S_RX_PHY_UNDERRUN) 247 #endif 248 { 5, "fftxok", "fftxok", "fast frames xmit successfully" }, 249 #define S_FF_TXERR AFTER(S_FF_TXOK) 250 { 5, "fftxerr", "fftxerr", "fast frames not xmit due to error" }, 251 #define S_FF_RX AFTER(S_FF_TXERR) 252 { 5, "ffrx", "ffrx", "fast frames received" }, 253 #define S_FF_FLUSH AFTER(S_FF_RX) 254 { 5, "ffflush", "ffflush", "fast frames flushed from staging q" }, 255 #define S_TX_QFULL AFTER(S_FF_FLUSH) 256 { 5, "txqfull", "txqfull", "tx discarded 'cuz queue is full" }, 257 #define S_ANT_DEFSWITCH AFTER(S_TX_QFULL) 258 { 5, "defsw", "defsw", "switched default/rx antenna" }, 259 #define S_ANT_TXSWITCH AFTER(S_ANT_DEFSWITCH) 260 { 5, "txsw", "txsw", "tx used alternate antenna" }, 261 #define S_ANT_TX0 AFTER(S_ANT_TXSWITCH) 262 { 8, "tx0", "ant0(tx)", "frames tx on antenna 0" }, 263 #define S_ANT_TX1 AFTER(S_ANT_TX0) 264 { 8, "tx1", "ant1(tx)", "frames tx on antenna 1" }, 265 #define S_ANT_TX2 AFTER(S_ANT_TX1) 266 { 8, "tx2", "ant2(tx)", "frames tx on antenna 2" }, 267 #define S_ANT_TX3 AFTER(S_ANT_TX2) 268 { 8, "tx3", "ant3(tx)", "frames tx on antenna 3" }, 269 #define S_ANT_TX4 AFTER(S_ANT_TX3) 270 { 8, "tx4", "ant4(tx)", "frames tx on antenna 4" }, 271 #define S_ANT_TX5 AFTER(S_ANT_TX4) 272 { 8, "tx5", "ant5(tx)", "frames tx on antenna 5" }, 273 #define S_ANT_TX6 AFTER(S_ANT_TX5) 274 { 8, "tx6", "ant6(tx)", "frames tx on antenna 6" }, 275 #define S_ANT_TX7 AFTER(S_ANT_TX6) 276 { 8, "tx7", "ant7(tx)", "frames tx on antenna 7" }, 277 #define S_ANT_RX0 AFTER(S_ANT_TX7) 278 { 8, "rx0", "ant0(rx)", "frames rx on antenna 0" }, 279 #define S_ANT_RX1 AFTER(S_ANT_RX0) 280 { 8, "rx1", "ant1(rx)", "frames rx on antenna 1" }, 281 #define S_ANT_RX2 AFTER(S_ANT_RX1) 282 { 8, "rx2", "ant2(rx)", "frames rx on antenna 2" }, 283 #define S_ANT_RX3 AFTER(S_ANT_RX2) 284 { 8, "rx3", "ant3(rx)", "frames rx on antenna 3" }, 285 #define S_ANT_RX4 AFTER(S_ANT_RX3) 286 { 8, "rx4", "ant4(rx)", "frames rx on antenna 4" }, 287 #define S_ANT_RX5 AFTER(S_ANT_RX4) 288 { 8, "rx5", "ant5(rx)", "frames rx on antenna 5" }, 289 #define S_ANT_RX6 AFTER(S_ANT_RX5) 290 { 8, "rx6", "ant6(rx)", "frames rx on antenna 6" }, 291 #define S_ANT_RX7 AFTER(S_ANT_RX6) 292 { 8, "rx7", "ant7(rx)", "frames rx on antenna 7" }, 293 #define S_TX_SIGNAL AFTER(S_ANT_RX7) 294 { 4, "asignal", "asig", "signal of last ack (dBm)" }, 295 #define S_RX_SIGNAL AFTER(S_TX_SIGNAL) 296 { 4, "signal", "sig", "avg recv signal (dBm)" }, 297 }; 298 #define S_PHY_MIN S_RX_PHY_UNDERRUN 299 #define S_PHY_MAX S_RX_PHY_CCK_RESTART 300 #define S_LAST S_ANT_TX0 301 #define S_MAX S_ANT_RX7+1 302 303 struct _athstats { 304 struct ath_stats ath; 305 }; 306 307 struct athstatfoo_p { 308 struct athstatfoo base; 309 int s; 310 int optstats; 311 struct ifreq ifr; 312 struct ath_diag atd; 313 struct _athstats cur; 314 struct _athstats total; 315 }; 316 317 static void 318 ath_setifname(struct athstatfoo *wf0, const char *ifname) 319 { 320 struct athstatfoo_p *wf = (struct athstatfoo_p *) wf0; 321 322 strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name)); 323 } 324 325 static void 326 ath_collect(struct athstatfoo_p *wf, struct _athstats *stats) 327 { 328 wf->ifr.ifr_data = (caddr_t) &stats->ath; 329 if (ioctl(wf->s, SIOCGATHSTATS, &wf->ifr) < 0) 330 err(1, wf->ifr.ifr_name); 331 } 332 333 static void 334 ath_collect_cur(struct statfoo *sf) 335 { 336 struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; 337 338 ath_collect(wf, &wf->cur); 339 } 340 341 static void 342 ath_collect_tot(struct statfoo *sf) 343 { 344 struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; 345 346 ath_collect(wf, &wf->total); 347 } 348 349 static void 350 ath_update_tot(struct statfoo *sf) 351 { 352 struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; 353 354 wf->total = wf->cur; 355 } 356 357 static int 358 ath_get_curstat(struct statfoo *sf, int s, char b[], size_t bs) 359 { 360 struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; 361 #define STAT(x) \ 362 snprintf(b, bs, "%u", wf->cur.ath.ast_##x - wf->total.ath.ast_##x); return 1 363 #define PHY(x) \ 364 snprintf(b, bs, "%u", wf->cur.ath.ast_rx_phy[x] - wf->total.ath.ast_rx_phy[x]); return 1 365 #define TXANT(x) \ 366 snprintf(b, bs, "%u", wf->cur.ath.ast_ant_tx[x] - wf->total.ath.ast_ant_tx[x]); return 1 367 #define RXANT(x) \ 368 snprintf(b, bs, "%u", wf->cur.ath.ast_ant_rx[x] - wf->total.ath.ast_ant_rx[x]); return 1 369 370 switch (s) { 371 case S_INPUT: 372 snprintf(b, bs, "%lu", 373 (wf->cur.ath.ast_rx_packets - wf->total.ath.ast_rx_packets) - 374 (wf->cur.ath.ast_rx_mgt - wf->total.ath.ast_rx_mgt)); 375 return 1; 376 case S_OUTPUT: 377 snprintf(b, bs, "%lu", 378 wf->cur.ath.ast_tx_packets - wf->total.ath.ast_tx_packets); 379 return 1; 380 case S_RATE: 381 snprintf(b, bs, "%uM", wf->cur.ath.ast_tx_rate / 2); 382 return 1; 383 case S_WATCHDOG: STAT(watchdog); 384 case S_FATAL: STAT(hardware); 385 case S_BMISS: STAT(bmiss); 386 case S_BMISS_PHANTOM: STAT(bmiss_phantom); 387 #ifdef S_BSTUCK 388 case S_BSTUCK: STAT(bstuck); 389 #endif 390 case S_RXORN: STAT(rxorn); 391 case S_RXEOL: STAT(rxeol); 392 case S_TXURN: STAT(txurn); 393 case S_MIB: STAT(mib); 394 #ifdef S_INTRCOAL 395 case S_INTRCOAL: STAT(intrcoal); 396 #endif 397 case S_TX_MGMT: STAT(tx_mgmt); 398 case S_TX_DISCARD: STAT(tx_discard); 399 case S_TX_QSTOP: STAT(tx_qstop); 400 case S_TX_ENCAP: STAT(tx_encap); 401 case S_TX_NONODE: STAT(tx_nonode); 402 case S_TX_NOMBUF: STAT(tx_nombuf); 403 #ifdef S_TX_NOMCL 404 case S_TX_NOMCL: STAT(tx_nomcl); 405 case S_TX_LINEAR: STAT(tx_linear); 406 case S_TX_NODATA: STAT(tx_nodata); 407 case S_TX_BUSDMA: STAT(tx_busdma); 408 #endif 409 case S_TX_XRETRIES: STAT(tx_xretries); 410 case S_TX_FIFOERR: STAT(tx_fifoerr); 411 case S_TX_FILTERED: STAT(tx_filtered); 412 case S_TX_SHORTRETRY: STAT(tx_shortretry); 413 case S_TX_LONGRETRY: STAT(tx_longretry); 414 case S_TX_BADRATE: STAT(tx_badrate); 415 case S_TX_NOACK: STAT(tx_noack); 416 case S_TX_RTS: STAT(tx_rts); 417 case S_TX_CTS: STAT(tx_cts); 418 case S_TX_SHORTPRE: STAT(tx_shortpre); 419 case S_TX_ALTRATE: STAT(tx_altrate); 420 case S_TX_PROTECT: STAT(tx_protect); 421 case S_RX_NOMBUF: STAT(rx_nombuf); 422 #ifdef S_RX_BUSDMA 423 case S_RX_BUSDMA: STAT(rx_busdma); 424 #endif 425 case S_RX_ORN: STAT(rx_orn); 426 case S_RX_CRC_ERR: STAT(rx_crcerr); 427 case S_RX_FIFO_ERR: STAT(rx_fifoerr); 428 case S_RX_CRYPTO_ERR: STAT(rx_badcrypt); 429 case S_RX_MIC_ERR: STAT(rx_badmic); 430 case S_RX_PHY_ERR: STAT(rx_phyerr); 431 case S_RX_PHY_UNDERRUN: PHY(HAL_PHYERR_UNDERRUN); 432 case S_RX_PHY_TIMING: PHY(HAL_PHYERR_TIMING); 433 case S_RX_PHY_PARITY: PHY(HAL_PHYERR_PARITY); 434 case S_RX_PHY_RATE: PHY(HAL_PHYERR_RATE); 435 case S_RX_PHY_LENGTH: PHY(HAL_PHYERR_LENGTH); 436 case S_RX_PHY_RADAR: PHY(HAL_PHYERR_RADAR); 437 case S_RX_PHY_SERVICE: PHY(HAL_PHYERR_SERVICE); 438 case S_RX_PHY_TOR: PHY(HAL_PHYERR_TOR); 439 case S_RX_PHY_OFDM_TIMING: PHY(HAL_PHYERR_OFDM_TIMING); 440 case S_RX_PHY_OFDM_SIGNAL_PARITY: PHY(HAL_PHYERR_OFDM_SIGNAL_PARITY); 441 case S_RX_PHY_OFDM_RATE_ILLEGAL: PHY(HAL_PHYERR_OFDM_RATE_ILLEGAL); 442 case S_RX_PHY_OFDM_POWER_DROP: PHY(HAL_PHYERR_OFDM_POWER_DROP); 443 case S_RX_PHY_OFDM_SERVICE: PHY(HAL_PHYERR_OFDM_SERVICE); 444 case S_RX_PHY_OFDM_RESTART: PHY(HAL_PHYERR_OFDM_RESTART); 445 case S_RX_PHY_CCK_TIMING: PHY(HAL_PHYERR_CCK_TIMING); 446 case S_RX_PHY_CCK_HEADER_CRC: PHY(HAL_PHYERR_CCK_HEADER_CRC); 447 case S_RX_PHY_CCK_RATE_ILLEGAL: PHY(HAL_PHYERR_CCK_RATE_ILLEGAL); 448 case S_RX_PHY_CCK_SERVICE: PHY(HAL_PHYERR_CCK_SERVICE); 449 case S_RX_PHY_CCK_RESTART: PHY(HAL_PHYERR_CCK_RESTART); 450 case S_RX_TOOSHORT: STAT(rx_tooshort); 451 case S_RX_TOOBIG: STAT(rx_toobig); 452 case S_RX_MGT: STAT(rx_mgt); 453 case S_RX_CTL: STAT(rx_ctl); 454 case S_TX_RSSI: 455 snprintf(b, bs, "%d", wf->cur.ath.ast_tx_rssi); 456 return 1; 457 case S_RX_RSSI: 458 snprintf(b, bs, "%d", wf->cur.ath.ast_rx_rssi); 459 return 1; 460 case S_BE_XMIT: STAT(be_xmit); 461 case S_BE_NOMBUF: STAT(be_nombuf); 462 case S_PER_CAL: STAT(per_cal); 463 case S_PER_CALFAIL: STAT(per_calfail); 464 case S_PER_RFGAIN: STAT(per_rfgain); 465 #ifdef S_TDMA_UPDATE 466 case S_TDMA_UPDATE: STAT(tdma_update); 467 case S_TDMA_TIMERS: STAT(tdma_timers); 468 case S_TDMA_TSF: STAT(tdma_tsf); 469 #endif 470 case S_RATE_CALLS: STAT(rate_calls); 471 case S_RATE_RAISE: STAT(rate_raise); 472 case S_RATE_DROP: STAT(rate_drop); 473 case S_ANT_DEFSWITCH: STAT(ant_defswitch); 474 case S_ANT_TXSWITCH: STAT(ant_txswitch); 475 case S_ANT_TX0: TXANT(0); 476 case S_ANT_TX1: TXANT(1); 477 case S_ANT_TX2: TXANT(2); 478 case S_ANT_TX3: TXANT(3); 479 case S_ANT_TX4: TXANT(4); 480 case S_ANT_TX5: TXANT(5); 481 case S_ANT_TX6: TXANT(6); 482 case S_ANT_TX7: TXANT(7); 483 case S_ANT_RX0: RXANT(0); 484 case S_ANT_RX1: RXANT(1); 485 case S_ANT_RX2: RXANT(2); 486 case S_ANT_RX3: RXANT(3); 487 case S_ANT_RX4: RXANT(4); 488 case S_ANT_RX5: RXANT(5); 489 case S_ANT_RX6: RXANT(6); 490 case S_ANT_RX7: RXANT(7); 491 #ifdef S_CABQ_XMIT 492 case S_CABQ_XMIT: STAT(cabq_xmit); 493 case S_CABQ_BUSY: STAT(cabq_busy); 494 #endif 495 case S_FF_TXOK: STAT(ff_txok); 496 case S_FF_TXERR: STAT(ff_txerr); 497 case S_FF_RX: STAT(ff_rx); 498 case S_FF_FLUSH: STAT(ff_flush); 499 case S_TX_QFULL: STAT(tx_qfull); 500 case S_RX_NOISE: 501 snprintf(b, bs, "%d", wf->cur.ath.ast_rx_noise); 502 return 1; 503 case S_TX_SIGNAL: 504 snprintf(b, bs, "%d", 505 wf->cur.ath.ast_tx_rssi + wf->cur.ath.ast_rx_noise); 506 return 1; 507 case S_RX_SIGNAL: 508 snprintf(b, bs, "%d", 509 wf->cur.ath.ast_rx_rssi + wf->cur.ath.ast_rx_noise); 510 return 1; 511 } 512 b[0] = '\0'; 513 return 0; 514 #undef RXANT 515 #undef TXANT 516 #undef PHY 517 #undef STAT 518 } 519 520 static int 521 ath_get_totstat(struct statfoo *sf, int s, char b[], size_t bs) 522 { 523 struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; 524 #define STAT(x) \ 525 snprintf(b, bs, "%u", wf->total.ath.ast_##x); return 1 526 #define PHY(x) \ 527 snprintf(b, bs, "%u", wf->total.ath.ast_rx_phy[x]); return 1 528 #define TXANT(x) \ 529 snprintf(b, bs, "%u", wf->total.ath.ast_ant_tx[x]); return 1 530 #define RXANT(x) \ 531 snprintf(b, bs, "%u", wf->total.ath.ast_ant_rx[x]); return 1 532 533 switch (s) { 534 case S_INPUT: 535 snprintf(b, bs, "%lu", 536 wf->total.ath.ast_rx_packets - wf->total.ath.ast_rx_mgt); 537 return 1; 538 case S_OUTPUT: 539 snprintf(b, bs, "%lu", wf->total.ath.ast_tx_packets); 540 return 1; 541 case S_RATE: 542 snprintf(b, bs, "%uM", wf->total.ath.ast_tx_rate / 2); 543 return 1; 544 case S_WATCHDOG: STAT(watchdog); 545 case S_FATAL: STAT(hardware); 546 case S_BMISS: STAT(bmiss); 547 case S_BMISS_PHANTOM: STAT(bmiss_phantom); 548 #ifdef S_BSTUCK 549 case S_BSTUCK: STAT(bstuck); 550 #endif 551 case S_RXORN: STAT(rxorn); 552 case S_RXEOL: STAT(rxeol); 553 case S_TXURN: STAT(txurn); 554 case S_MIB: STAT(mib); 555 #ifdef S_INTRCOAL 556 case S_INTRCOAL: STAT(intrcoal); 557 #endif 558 case S_TX_MGMT: STAT(tx_mgmt); 559 case S_TX_DISCARD: STAT(tx_discard); 560 case S_TX_QSTOP: STAT(tx_qstop); 561 case S_TX_ENCAP: STAT(tx_encap); 562 case S_TX_NONODE: STAT(tx_nonode); 563 case S_TX_NOMBUF: STAT(tx_nombuf); 564 #ifdef S_TX_NOMCL 565 case S_TX_NOMCL: STAT(tx_nomcl); 566 case S_TX_LINEAR: STAT(tx_linear); 567 case S_TX_NODATA: STAT(tx_nodata); 568 case S_TX_BUSDMA: STAT(tx_busdma); 569 #endif 570 case S_TX_XRETRIES: STAT(tx_xretries); 571 case S_TX_FIFOERR: STAT(tx_fifoerr); 572 case S_TX_FILTERED: STAT(tx_filtered); 573 case S_TX_SHORTRETRY: STAT(tx_shortretry); 574 case S_TX_LONGRETRY: STAT(tx_longretry); 575 case S_TX_BADRATE: STAT(tx_badrate); 576 case S_TX_NOACK: STAT(tx_noack); 577 case S_TX_RTS: STAT(tx_rts); 578 case S_TX_CTS: STAT(tx_cts); 579 case S_TX_SHORTPRE: STAT(tx_shortpre); 580 case S_TX_ALTRATE: STAT(tx_altrate); 581 case S_TX_PROTECT: STAT(tx_protect); 582 case S_RX_NOMBUF: STAT(rx_nombuf); 583 #ifdef S_RX_BUSDMA 584 case S_RX_BUSDMA: STAT(rx_busdma); 585 #endif 586 case S_RX_ORN: STAT(rx_orn); 587 case S_RX_CRC_ERR: STAT(rx_crcerr); 588 case S_RX_FIFO_ERR: STAT(rx_fifoerr); 589 case S_RX_CRYPTO_ERR: STAT(rx_badcrypt); 590 case S_RX_MIC_ERR: STAT(rx_badmic); 591 case S_RX_PHY_ERR: STAT(rx_phyerr); 592 case S_RX_PHY_UNDERRUN: PHY(HAL_PHYERR_UNDERRUN); 593 case S_RX_PHY_TIMING: PHY(HAL_PHYERR_TIMING); 594 case S_RX_PHY_PARITY: PHY(HAL_PHYERR_PARITY); 595 case S_RX_PHY_RATE: PHY(HAL_PHYERR_RATE); 596 case S_RX_PHY_LENGTH: PHY(HAL_PHYERR_LENGTH); 597 case S_RX_PHY_RADAR: PHY(HAL_PHYERR_RADAR); 598 case S_RX_PHY_SERVICE: PHY(HAL_PHYERR_SERVICE); 599 case S_RX_PHY_TOR: PHY(HAL_PHYERR_TOR); 600 case S_RX_PHY_OFDM_TIMING: PHY(HAL_PHYERR_OFDM_TIMING); 601 case S_RX_PHY_OFDM_SIGNAL_PARITY: PHY(HAL_PHYERR_OFDM_SIGNAL_PARITY); 602 case S_RX_PHY_OFDM_RATE_ILLEGAL: PHY(HAL_PHYERR_OFDM_RATE_ILLEGAL); 603 case S_RX_PHY_OFDM_POWER_DROP: PHY(HAL_PHYERR_OFDM_POWER_DROP); 604 case S_RX_PHY_OFDM_SERVICE: PHY(HAL_PHYERR_OFDM_SERVICE); 605 case S_RX_PHY_OFDM_RESTART: PHY(HAL_PHYERR_OFDM_RESTART); 606 case S_RX_PHY_CCK_TIMING: PHY(HAL_PHYERR_CCK_TIMING); 607 case S_RX_PHY_CCK_HEADER_CRC: PHY(HAL_PHYERR_CCK_HEADER_CRC); 608 case S_RX_PHY_CCK_RATE_ILLEGAL: PHY(HAL_PHYERR_CCK_RATE_ILLEGAL); 609 case S_RX_PHY_CCK_SERVICE: PHY(HAL_PHYERR_CCK_SERVICE); 610 case S_RX_PHY_CCK_RESTART: PHY(HAL_PHYERR_CCK_RESTART); 611 case S_RX_TOOSHORT: STAT(rx_tooshort); 612 case S_RX_TOOBIG: STAT(rx_toobig); 613 case S_RX_MGT: STAT(rx_mgt); 614 case S_RX_CTL: STAT(rx_ctl); 615 case S_TX_RSSI: 616 snprintf(b, bs, "%d", wf->total.ath.ast_tx_rssi); 617 return 1; 618 case S_RX_RSSI: 619 snprintf(b, bs, "%d", wf->total.ath.ast_rx_rssi); 620 return 1; 621 case S_BE_XMIT: STAT(be_xmit); 622 case S_BE_NOMBUF: STAT(be_nombuf); 623 case S_PER_CAL: STAT(per_cal); 624 case S_PER_CALFAIL: STAT(per_calfail); 625 case S_PER_RFGAIN: STAT(per_rfgain); 626 #ifdef S_TDMA_UPDATE 627 case S_TDMA_UPDATE: STAT(tdma_update); 628 case S_TDMA_TIMERS: STAT(tdma_timers); 629 case S_TDMA_TSF: STAT(tdma_tsf); 630 #endif 631 case S_RATE_CALLS: STAT(rate_calls); 632 case S_RATE_RAISE: STAT(rate_raise); 633 case S_RATE_DROP: STAT(rate_drop); 634 case S_ANT_DEFSWITCH: STAT(ant_defswitch); 635 case S_ANT_TXSWITCH: STAT(ant_txswitch); 636 case S_ANT_TX0: TXANT(0); 637 case S_ANT_TX1: TXANT(1); 638 case S_ANT_TX2: TXANT(2); 639 case S_ANT_TX3: TXANT(3); 640 case S_ANT_TX4: TXANT(4); 641 case S_ANT_TX5: TXANT(5); 642 case S_ANT_TX6: TXANT(6); 643 case S_ANT_TX7: TXANT(7); 644 case S_ANT_RX0: RXANT(0); 645 case S_ANT_RX1: RXANT(1); 646 case S_ANT_RX2: RXANT(2); 647 case S_ANT_RX3: RXANT(3); 648 case S_ANT_RX4: RXANT(4); 649 case S_ANT_RX5: RXANT(5); 650 case S_ANT_RX6: RXANT(6); 651 case S_ANT_RX7: RXANT(7); 652 #ifdef S_CABQ_XMIT 653 case S_CABQ_XMIT: STAT(cabq_xmit); 654 case S_CABQ_BUSY: STAT(cabq_busy); 655 #endif 656 case S_FF_TXOK: STAT(ff_txok); 657 case S_FF_TXERR: STAT(ff_txerr); 658 case S_FF_RX: STAT(ff_rx); 659 case S_FF_FLUSH: STAT(ff_flush); 660 case S_TX_QFULL: STAT(tx_qfull); 661 case S_RX_NOISE: 662 snprintf(b, bs, "%d", wf->total.ath.ast_rx_noise); 663 return 1; 664 case S_TX_SIGNAL: 665 snprintf(b, bs, "%d", 666 wf->total.ath.ast_tx_rssi + wf->total.ath.ast_rx_noise); 667 return 1; 668 case S_RX_SIGNAL: 669 snprintf(b, bs, "%d", 670 wf->total.ath.ast_rx_rssi + wf->total.ath.ast_rx_noise); 671 return 1; 672 } 673 b[0] = '\0'; 674 return 0; 675 #undef RXANT 676 #undef TXANT 677 #undef PHY 678 #undef STAT 679 } 680 681 static void 682 ath_print_verbose(struct statfoo *sf, FILE *fd) 683 { 684 struct athstatfoo_p *wf = (struct athstatfoo_p *) sf; 685 #define isphyerr(i) (S_PHY_MIN <= i && i <= S_PHY_MAX) 686 const struct fmt *f; 687 char s[32]; 688 const char *indent; 689 int i, width; 690 691 width = 0; 692 for (i = 0; i < S_LAST; i++) { 693 f = &sf->stats[i]; 694 if (!isphyerr(i) && f->width > width) 695 width = f->width; 696 } 697 for (i = 0; i < S_LAST; i++) { 698 if (ath_get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) { 699 if (isphyerr(i)) 700 indent = " "; 701 else 702 indent = ""; 703 fprintf(fd, "%s%-*s %s\n", indent, width, s, athstats[i].desc); 704 } 705 } 706 fprintf(fd, "Antenna profile:\n"); 707 for (i = 0; i < 8; i++) 708 if (wf->total.ath.ast_ant_rx[i] || wf->total.ath.ast_ant_tx[i]) 709 fprintf(fd, "[%u] tx %8u rx %8u\n", i, 710 wf->total.ath.ast_ant_tx[i], 711 wf->total.ath.ast_ant_rx[i]); 712 #undef isphyerr 713 } 714 715 STATFOO_DEFINE_BOUNCE(athstatfoo) 716 717 struct athstatfoo * 718 athstats_new(const char *ifname, const char *fmtstring) 719 { 720 #define N(a) (sizeof(a) / sizeof(a[0])) 721 struct athstatfoo_p *wf; 722 723 wf = calloc(1, sizeof(struct athstatfoo_p)); 724 if (wf != NULL) { 725 statfoo_init(&wf->base.base, "athstats", athstats, N(athstats)); 726 /* override base methods */ 727 wf->base.base.collect_cur = ath_collect_cur; 728 wf->base.base.collect_tot = ath_collect_tot; 729 wf->base.base.get_curstat = ath_get_curstat; 730 wf->base.base.get_totstat = ath_get_totstat; 731 wf->base.base.update_tot = ath_update_tot; 732 wf->base.base.print_verbose = ath_print_verbose; 733 734 /* setup bounce functions for public methods */ 735 STATFOO_BOUNCE(wf, athstatfoo); 736 737 /* setup our public methods */ 738 wf->base.setifname = ath_setifname; 739 #if 0 740 wf->base.setstamac = wlan_setstamac; 741 #endif 742 wf->s = socket(AF_INET, SOCK_DGRAM, 0); 743 if (wf->s < 0) 744 err(1, "socket"); 745 746 ath_setifname(&wf->base, ifname); 747 wf->base.setfmt(&wf->base, fmtstring); 748 } 749 return &wf->base; 750 #undef N 751 } 752