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