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