]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/tools/ath/athaggrstats/athaggrstats.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / tools / ath / athaggrstats / athaggrstats.c
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  * $FreeBSD$
30  */
31
32 #include "opt_ah.h"
33
34 /*
35  * ath statistics class.
36  */
37 #include <sys/types.h>
38 #include <sys/file.h>
39 #include <sys/sockio.h>
40 #include <sys/socket.h>
41 #include <net/if.h>
42 #include <net/if_media.h>
43 #include <net/if_var.h>
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <signal.h>
48 #include <string.h>
49 #include <unistd.h>
50 #include <err.h>
51
52 #include "ah.h"
53 #include "ah_desc.h"
54 #include "net80211/ieee80211_ioctl.h"
55 #include "net80211/ieee80211_radiotap.h"
56 #include "if_athioctl.h"
57
58 #include "athaggrstats.h"
59
60 #define NOTPRESENT      { 0, "", "" }
61
62 #define AFTER(prev)     ((prev)+1)
63
64 static const struct fmt athaggrstats[] = {
65
66 #define S_SINGLE_PKT    0
67         { 4,    "singlepkt",    "spkt", "single frames scheduled" },
68 #define S_NONBAW_PKT                    AFTER(S_SINGLE_PKT)
69         { 5,    "nonbawpkt",    "nbpkt",        "frames outside of the BAW" },
70 #define S_AGGR_PKT                      AFTER(S_NONBAW_PKT)
71         { 6,    "aggrpkt",      "aggpkt",       "aggregate frames scheduled" },
72 #define S_BAW_CLOSED_SINGLE_PKT         AFTER(S_AGGR_PKT)
73         { 8,    "bawclosedpkt", "bawclpkt",     "single frames due to closed BAW" },
74 #define S_LOW_HWQ_SINGLE_PKT            AFTER(S_BAW_CLOSED_SINGLE_PKT)
75         { 6,    "lhsinglepkt",  "lhspkt",       "single frames scheduled due to low HWQ depth" },
76 #define S_SCHED_NOPKT                   AFTER(S_LOW_HWQ_SINGLE_PKT)
77         { 6,    "schednopkt",   "snopkt",       "sched called with no frames" },
78 #define S_RTS_AGGR_LIMITED              AFTER(S_SCHED_NOPKT)
79         { 8,    "rtsaggrlimit", "rtslimit",     "RTS limited aggregates" },
80 #define S_PKT0                          AFTER(S_RTS_AGGR_LIMITED)
81         { 2,    "p0",   "p0",   "" },
82 #define S_PKT1                          AFTER(S_PKT0)
83         { 2,    "p1",   "p1",   "" },
84 #define S_PKT2                          AFTER(S_PKT1)
85         { 2,    "p2",   "p2",   "" },
86 #define S_PKT3                          AFTER(S_PKT2)
87         { 2,    "p3",   "p3",   "" },
88 #define S_PKT4                          AFTER(S_PKT3)
89         { 2,    "p4",   "p4",   "" },
90 #define S_PKT5                          AFTER(S_PKT4)
91         { 2,    "p5",   "p5",   "" },
92 #define S_PKT6                          AFTER(S_PKT5)
93         { 2,    "p6",   "p6",   "" },
94 #define S_PKT7                          AFTER(S_PKT6)
95         { 2,    "p7",   "p7",   "" },
96 #define S_PKT8                          AFTER(S_PKT7)
97         { 2,    "p8",   "p8",   "" },
98 #define S_PKT9                          AFTER(S_PKT8)
99         { 2,    "p9",   "p9",   "" },
100 #define S_PKT10                         AFTER(S_PKT9)
101         { 3,    "p10",  "p10",  "" },
102 #define S_PKT11                         AFTER(S_PKT10)
103         { 3,    "p11",  "p11",  "" },
104 #define S_PKT12                         AFTER(S_PKT11)
105         { 3,    "p12",  "p12",  "" },
106 #define S_PKT13                         AFTER(S_PKT12)
107         { 3,    "p13",  "p13",  "" },
108 #define S_PKT14                         AFTER(S_PKT13)
109         { 3,    "p14",  "p14",  "" },
110 #define S_PKT15                         AFTER(S_PKT14)
111         { 3,    "p15",  "p15",  "" },
112 #define S_PKT16                         AFTER(S_PKT15)
113         { 3,    "p16",  "p16",  "" },
114 #define S_PKT17                         AFTER(S_PKT16)
115         { 3,    "p17",  "p17",  "" },
116 #define S_PKT18                         AFTER(S_PKT17)
117         { 3,    "p18",  "p18",  "" },
118 #define S_PKT19                         AFTER(S_PKT18)
119         { 3,    "p19",  "p19",  "" },
120 #define S_PKT20                         AFTER(S_PKT19)
121         { 3,    "p20",  "p20",  "" },
122 #define S_PKT21                         AFTER(S_PKT20)
123         { 3,    "p21",  "p21",  "" },
124 #define S_PKT22                         AFTER(S_PKT21)
125         { 3,    "p22",  "p22",  "" },
126 #define S_PKT23                         AFTER(S_PKT22)
127         { 3,    "p23",  "p23",  "" },
128 #define S_PKT24                         AFTER(S_PKT23)
129         { 3,    "p24",  "p24",  "" },
130 #define S_PKT25                         AFTER(S_PKT24)
131         { 3,    "p25",  "p25",  "" },
132 #define S_PKT26                         AFTER(S_PKT25)
133         { 3,    "p26",  "p26",  "" },
134 #define S_PKT27                         AFTER(S_PKT26)
135         { 3,    "p27",  "p27",  "" },
136 #define S_PKT28                         AFTER(S_PKT27)
137         { 3,    "p28",  "p28",  "" },
138 #define S_PKT29                         AFTER(S_PKT28)
139         { 3,    "p29",  "p29",  "" },
140 #define S_PKT30                         AFTER(S_PKT29)
141         { 3,    "p30",  "p30",  "" },
142 #define S_PKT31                         AFTER(S_PKT30)
143         { 3,    "p31",  "p31",  "" },
144 };
145
146 #define S_LAST          S_RTS_AGGR_LIMITED
147 #define S_MAX           (S_PKT31 + 1)
148
149 struct athaggrstatfoo_p {
150         struct athaggrstatfoo base;
151         int s;
152         int optstats;
153         struct ifreq ifr;
154         struct ath_diag atd;
155         struct ath_tx_aggr_stats cur;
156         struct ath_tx_aggr_stats total;
157 };
158
159 static void
160 ath_setifname(struct athaggrstatfoo *wf0, const char *ifname)
161 {
162         struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) wf0;
163
164         strncpy(wf->ifr.ifr_name, ifname, sizeof (wf->ifr.ifr_name));
165 }
166
167 static void 
168 ath_zerostats(struct athaggrstatfoo *wf0)
169 {
170 #if 0
171         struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) wf0;
172
173         if (ioctl(wf->s, SIOCZATHSTATS, &wf->ifr) < 0)
174                 err(-1, wf->ifr.ifr_name);
175 #endif
176 }
177
178 static void
179 ath_collect(struct athaggrstatfoo_p *wf, struct ath_tx_aggr_stats *stats)
180 {
181         wf->ifr.ifr_data = (caddr_t) stats;
182         if (ioctl(wf->s, SIOCGATHAGSTATS, &wf->ifr) < 0)
183                 err(1, wf->ifr.ifr_name);
184 }
185
186 static void
187 ath_collect_cur(struct statfoo *sf)
188 {
189         struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf;
190
191         ath_collect(wf, &wf->cur);
192 }
193
194 static void
195 ath_collect_tot(struct statfoo *sf)
196 {
197         struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf;
198
199         ath_collect(wf, &wf->total);
200 }
201
202 static void
203 ath_update_tot(struct statfoo *sf)
204 {
205         struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf;
206
207         wf->total = wf->cur;
208 }
209
210 static void
211 snprintrate(char b[], size_t bs, int rate)
212 {
213         if (rate & IEEE80211_RATE_MCS)
214                 snprintf(b, bs, "MCS%u", rate &~ IEEE80211_RATE_MCS);
215         else if (rate & 1)
216                 snprintf(b, bs, "%u.5M", rate / 2);
217         else
218                 snprintf(b, bs, "%uM", rate / 2);
219 }
220
221 static int
222 ath_get_curstat(struct statfoo *sf, int s, char b[], size_t bs)
223 {
224         struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf;
225 #define STAT(x) \
226         snprintf(b, bs, "%u", wf->cur.aggr_##x - wf->total.aggr_##x); return 1
227 #define PKT(x) \
228         snprintf(b, bs, "%u", wf->cur.aggr_pkts[x] - wf->total.aggr_pkts[x]); return 1
229
230         switch (s) {
231         case S_SINGLE_PKT:              STAT(single_pkt);
232         case S_NONBAW_PKT:              STAT(nonbaw_pkt);
233         case S_AGGR_PKT:                STAT(aggr_pkt);
234         case S_BAW_CLOSED_SINGLE_PKT:   STAT(baw_closed_single_pkt);
235         case S_LOW_HWQ_SINGLE_PKT:      STAT(low_hwq_single_pkt);
236         case S_SCHED_NOPKT:             STAT(sched_nopkt);
237         case S_RTS_AGGR_LIMITED:        STAT(rts_aggr_limited);
238         case S_PKT0:                    PKT(0);
239         case S_PKT1:                    PKT(1);
240         case S_PKT2:                    PKT(2);
241         case S_PKT3:                    PKT(3);
242         case S_PKT4:                    PKT(4);
243         case S_PKT5:                    PKT(5);
244         case S_PKT6:                    PKT(6);
245         case S_PKT7:                    PKT(7);
246         case S_PKT8:                    PKT(8);
247         case S_PKT9:                    PKT(9);
248         case S_PKT10:                   PKT(10);
249         case S_PKT11:                   PKT(11);
250         case S_PKT12:                   PKT(12);
251         case S_PKT13:                   PKT(13);
252         case S_PKT14:                   PKT(14);
253         case S_PKT15:                   PKT(15);
254         case S_PKT16:                   PKT(16);
255         case S_PKT17:                   PKT(17);
256         case S_PKT18:                   PKT(18);
257         case S_PKT19:                   PKT(19);
258         case S_PKT20:                   PKT(20);
259         case S_PKT21:                   PKT(21);
260         case S_PKT22:                   PKT(22);
261         case S_PKT23:                   PKT(23);
262         case S_PKT24:                   PKT(24);
263         case S_PKT25:                   PKT(25);
264         case S_PKT26:                   PKT(26);
265         case S_PKT27:                   PKT(27);
266         case S_PKT28:                   PKT(28);
267         case S_PKT29:                   PKT(29);
268         case S_PKT30:                   PKT(30);
269         case S_PKT31:                   PKT(31);
270         }
271         b[0] = '\0';
272         return 0;
273 #undef PKT
274 #undef STAT
275 }
276
277 static int
278 ath_get_totstat(struct statfoo *sf, int s, char b[], size_t bs)
279 {
280         struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf;
281 #define STAT(x) \
282         snprintf(b, bs, "%u", wf->total.aggr_##x); return 1
283 #define PKT(x) \
284         snprintf(b, bs, "%u", wf->total.aggr_pkts[x]); return 1
285
286         switch (s) {
287         case S_SINGLE_PKT:              STAT(single_pkt);
288         case S_NONBAW_PKT:              STAT(nonbaw_pkt);
289         case S_AGGR_PKT:                STAT(aggr_pkt);
290         case S_BAW_CLOSED_SINGLE_PKT:   STAT(baw_closed_single_pkt);
291         case S_LOW_HWQ_SINGLE_PKT:      STAT(low_hwq_single_pkt);
292         case S_SCHED_NOPKT:             STAT(sched_nopkt);
293         case S_RTS_AGGR_LIMITED:        STAT(rts_aggr_limited);
294         case S_PKT0:                    PKT(0);
295         case S_PKT1:                    PKT(1);
296         case S_PKT2:                    PKT(2);
297         case S_PKT3:                    PKT(3);
298         case S_PKT4:                    PKT(4);
299         case S_PKT5:                    PKT(5);
300         case S_PKT6:                    PKT(6);
301         case S_PKT7:                    PKT(7);
302         case S_PKT8:                    PKT(8);
303         case S_PKT9:                    PKT(9);
304         case S_PKT10:                   PKT(10);
305         case S_PKT11:                   PKT(11);
306         case S_PKT12:                   PKT(12);
307         case S_PKT13:                   PKT(13);
308         case S_PKT14:                   PKT(14);
309         case S_PKT15:                   PKT(15);
310         case S_PKT16:                   PKT(16);
311         case S_PKT17:                   PKT(17);
312         case S_PKT18:                   PKT(18);
313         case S_PKT19:                   PKT(19);
314         case S_PKT20:                   PKT(20);
315         case S_PKT21:                   PKT(21);
316         case S_PKT22:                   PKT(22);
317         case S_PKT23:                   PKT(23);
318         case S_PKT24:                   PKT(24);
319         case S_PKT25:                   PKT(25);
320         case S_PKT26:                   PKT(26);
321         case S_PKT27:                   PKT(27);
322         case S_PKT28:                   PKT(28);
323         case S_PKT29:                   PKT(29);
324         case S_PKT30:                   PKT(30);
325         case S_PKT31:                   PKT(31);
326         }
327         b[0] = '\0';
328         return 0;
329 #undef PKT
330 #undef STAT
331 }
332
333 static void
334 ath_print_verbose(struct statfoo *sf, FILE *fd)
335 {
336         struct athaggrstatfoo_p *wf = (struct athaggrstatfoo_p *) sf;
337         const struct fmt *f;
338         char s[32];
339         const char *indent;
340         int i, width;
341
342         width = 0;
343         for (i = 0; i < S_LAST; i++) {
344                 f = &sf->stats[i];
345                 if (f->width > width)
346                         width = f->width;
347         }
348         for (i = 0; i < S_LAST; i++) {
349                 if (ath_get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) {
350                         indent = "";
351                         fprintf(fd, "%s%-*s %s\n", indent, width, s,
352                             athaggrstats[i].desc);
353                 }
354         }
355
356         fprintf(fd, "\nAggregate size profile:\n\n");
357         for (i = 0; i < 64; i++) {
358                 fprintf(fd, "%2d: %12u%s",
359                     i,
360                     wf->total.aggr_pkts[i],
361                     (i % 4 == 3) ? "\n" : " ");
362         }
363         fprintf(fd, "\n");
364 }
365
366 STATFOO_DEFINE_BOUNCE(athaggrstatfoo)
367
368 struct athaggrstatfoo *
369 athaggrstats_new(const char *ifname, const char *fmtstring)
370 {
371 #define N(a)    (sizeof(a) / sizeof(a[0]))
372         struct athaggrstatfoo_p *wf;
373
374         wf = calloc(1, sizeof(struct athaggrstatfoo_p));
375         if (wf != NULL) {
376                 statfoo_init(&wf->base.base, "athaggrstats",
377                     athaggrstats, N(athaggrstats));
378                 /* override base methods */
379                 wf->base.base.collect_cur = ath_collect_cur;
380                 wf->base.base.collect_tot = ath_collect_tot;
381                 wf->base.base.get_curstat = ath_get_curstat;
382                 wf->base.base.get_totstat = ath_get_totstat;
383                 wf->base.base.update_tot = ath_update_tot;
384                 wf->base.base.print_verbose = ath_print_verbose;
385
386                 /* setup bounce functions for public methods */
387                 STATFOO_BOUNCE(wf, athaggrstatfoo);
388
389                 /* setup our public methods */
390                 wf->base.setifname = ath_setifname;
391 #if 0
392                 wf->base.setstamac = wlan_setstamac;
393 #endif
394                 wf->base.zerostats = ath_zerostats;
395                 wf->s = socket(AF_INET, SOCK_DGRAM, 0);
396                 if (wf->s < 0)
397                         err(1, "socket");
398
399                 ath_setifname(&wf->base, ifname);
400                 wf->base.setfmt(&wf->base, fmtstring);
401         }
402         return &wf->base;
403 #undef N
404 }