1 /*-
2 * Copyright (c) 2002-2009 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
30 /*
31 * Simple Atheros-specific tool to inspect and monitor network traffic
32 * statistics.
33 *
34 * athstats [-i interface] [-bz] [-l] [-o fmtstring] [interval]
35 *
36 * (default interface is ath0). If interval is specified a rolling output
37 * a la netstat -i is displayed every interval seconds. The format of
38 * the rolling display can be controlled a la ps. The -l option will
39 * print a list of all possible statistics for use with the -o option.
40 */
41
42 #include <sys/param.h>
43
44 #include <err.h>
45 #include <signal.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <unistd.h>
50
51 #include "athstats.h"
52
53 static struct {
54 const char *tag;
55 const char *fmt;
56 } tags[] = {
57 { "default",
58 "input,output,altrate,short,long,xretry,crcerr,crypt,phyerr,rssi,rate"
59 },
60 { "ani",
61 "avgbrssi,avgrssi,avgtxrssi,NI,SI,step,owsd,cwst,NI+,NI-,SI+,SI-,OFDM,CCK,LISTEN"
62 },
63 { "tdma",
64 "input,output,bexmit,tdmau,tdmadj,crcerr,phyerr,phytor,rssi,noise,rate"
65 },
66 { "beacon",
67 "bstuck,bmiss,bexmit,beacons,bmisscount,reset,ofdm,cck,input,output"
68 },
69 };
70
71 static const char *
getfmt(const char * tag)72 getfmt(const char *tag)
73 {
74 int i;
75 for (i = 0; i < nitems(tags); i++)
76 if (strcasecmp(tags[i].tag, tag) == 0)
77 return tags[i].fmt;
78 return tag;
79 }
80
81 static int signalled;
82
83 static void
catchalarm(int signo __unused)84 catchalarm(int signo __unused)
85 {
86 signalled = 1;
87 }
88
89 int
main(int argc,char * argv[])90 main(int argc, char *argv[])
91 {
92 struct athstatfoo *wf;
93 const char *ifname;
94 int c, banner = 1;
95
96 ifname = getenv("ATH");
97 if (ifname == NULL)
98 ifname = ATH_DEFAULT;
99 wf = athstats_new(ifname, getfmt("default"));
100 while ((c = getopt(argc, argv, "bi:lo:z")) != -1) {
101 switch (c) {
102 case 'b':
103 banner = 0;
104 break;
105 case 'i':
106 wf->setifname(wf, optarg);
107 break;
108 case 'l':
109 wf->print_fields(wf, stdout);
110 return 0;
111 case 'o':
112 wf->setfmt(wf, getfmt(optarg));
113 break;
114 case 'z':
115 wf->zerostats(wf);
116 break;
117 default:
118 errx(-1, "usage: %s [-a] [-i ifname] [-l] [-o fmt] [-z] [interval]\n", argv[0]);
119 /*NOTREACHED*/
120 }
121 }
122 argc -= optind;
123 argv += optind;
124
125 if (argc > 0) {
126 u_long interval = strtoul(argv[0], NULL, 0);
127 int line, omask;
128
129 if (interval < 1)
130 interval = 1;
131 signal(SIGALRM, catchalarm);
132 signalled = 0;
133 alarm(interval);
134 banner:
135 if (banner)
136 wf->print_header(wf, stdout);
137 line = 0;
138 loop:
139 if (line != 0) {
140 wf->collect_cur(wf);
141 wf->print_current(wf, stdout);
142 wf->update_tot(wf);
143 } else {
144 wf->collect_tot(wf);
145 wf->print_total(wf, stdout);
146 }
147 fflush(stdout);
148 omask = sigblock(sigmask(SIGALRM));
149 if (!signalled)
150 sigpause(0);
151 sigsetmask(omask);
152 signalled = 0;
153 alarm(interval);
154 line++;
155 if (line == 21) /* XXX tty line count */
156 goto banner;
157 else
158 goto loop;
159 /*NOTREACHED*/
160 } else {
161 wf->collect_tot(wf);
162 wf->print_verbose(wf, stdout);
163 }
164 return 0;
165 }
166