xref: /freebsd/tools/tools/iwn/iwnstats/main.c (revision 8876613dc50029e88a84fd595d4a1f3c52c92350)
1 /*-
2  * Copyright (c) 2014 Adrian Chadd <adrian@FreeBSD.org>
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 <stdio.h>
33 #include <stdlib.h>
34 #include <signal.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <err.h>
38 #include <net/if.h>
39 #include <sys/endian.h>
40 
41 #include "net80211/ieee80211_ioctl.h"
42 #include "net80211/ieee80211_radiotap.h"
43 
44 #include "if_iwn_ioctl.h"
45 #include "if_iwnreg.h"
46 #include "iwnstats.h"
47 #include "iwn_ioctl.h"
48 
49 #define	IWN_DEFAULT_IF		"iwn0"
50 
51 struct iwnstats *
52 iwnstats_new(const char *ifname)
53 {
54 	struct iwnstats *is;
55 
56 	is = calloc(1, sizeof(struct iwnstats));
57 	if (is == NULL)
58 		return (NULL);
59 
60 	is->s = socket(AF_INET, SOCK_DGRAM, 0);
61 	if (is->s < 0)
62 		err(1, "socket");
63 
64 	iwn_setifname(is, ifname);
65 	return (is);
66 }
67 
68 static void
69 iwn_stats_phy_print(struct iwnstats *is, struct iwn_rx_phy_stats *rxphy,
70     const char *prefix)
71 {
72 
73 	printf("%s: %s: ina=%d, fina=%d, bad_plcp=%d, bad_crc32=%d, overrun=%d, eoverrun=%d\n",
74 	        __func__,
75 		prefix,
76 		le32toh(rxphy->ina),
77 		le32toh(rxphy->fina),
78 		le32toh(rxphy->bad_plcp),
79 		le32toh(rxphy->bad_crc32),
80 		le32toh(rxphy->overrun),
81 		le32toh(rxphy->eoverrun));
82 
83 	printf("%s: %s: fa=%d, bad_fina_sync=%d, sfd_timeout=%d, fina_timeout=%d, no_rts_ack=%d\n",
84 	        __func__,
85 		prefix,
86 		le32toh(rxphy->fa),
87 		le32toh(rxphy->bad_fina_sync),
88 		le32toh(rxphy->sfd_timeout),
89 		le32toh(rxphy->fina_timeout),
90 		le32toh(rxphy->no_rts_ack));
91 
92 	printf("%s: %s: rxe_limit=%d, ack=%d, cts=%d, ba_resp=%d, dsp_kill=%d, bad_mh=%d, rssi_sum=%d\n",
93 	        __func__,
94 		prefix,
95 		le32toh(rxphy->rxe_limit),
96 		le32toh(rxphy->ack),
97 		le32toh(rxphy->cts),
98 		le32toh(rxphy->ba_resp),
99 		le32toh(rxphy->dsp_kill),
100 		le32toh(rxphy->bad_mh),
101 		le32toh(rxphy->rssi_sum));
102 }
103 
104 static void
105 iwn_stats_rx_general_print(struct iwnstats *is, struct iwn_rx_general_stats *g)
106 {
107 
108 	printf("%s: bad_cts=%d, bad_ack=%d, not_bss=%d, filtered=%d, bad_chan=%d, beacons=%d\n",
109 	    __func__,
110 	    le32toh(g->bad_cts),
111 	    le32toh(g->bad_ack),
112 	    le32toh(g->not_bss),
113 	    le32toh(g->filtered),
114 	    le32toh(g->bad_chan),
115 	    le32toh(g->beacons));
116 
117 	/* XXX it'd be nice to have adc/ina saturated as a % of time */
118 	printf("%s: missed_beacons=%d, adc_saturated=%d, ina_searched=%d\n",
119 	    __func__,
120 	    le32toh(g->missed_beacons),
121 	    le32toh(g->adc_saturated),
122 	    le32toh(g->ina_searched));
123 
124 	printf("%s: noise=[%d, %d, %d] flags=0x%08x, load=%d, fa=%d\n",
125 	    __func__,
126 	    le32toh(g->noise[0]),
127 	    le32toh(g->noise[1]),
128 	    le32toh(g->noise[2]),
129 	    le32toh(g->flags),
130 	    le32toh(g->load),
131 	    le32toh(g->fa));
132 
133 	printf("%s: rssi=[%d, %d, %d] energy=[%d %d %d]\n",
134 	    __func__,
135 	    le32toh(g->rssi[0]),
136 	    le32toh(g->rssi[1]),
137 	    le32toh(g->rssi[2]),
138 	    le32toh(g->energy[0]),
139 	    le32toh(g->energy[1]),
140 	    le32toh(g->energy[2]));
141 }
142 
143 static void
144 iwn_stats_tx_print(struct iwnstats *is, struct iwn_tx_stats *tx)
145 {
146 
147 	printf("%s: preamble=%d, rx_detected=%d, bt_defer=%d, bt_kill=%d, short_len=%d\n",
148 	    __func__,
149 	    le32toh(tx->preamble),
150 	    le32toh(tx->rx_detected),
151 	    le32toh(tx->bt_defer),
152 	    le32toh(tx->bt_kill),
153 	    le32toh(tx->short_len));
154 
155 	printf("%s: cts_timeout=%d, ack_timeout=%d, exp_ack=%d, ack=%d, msdu=%d\n",
156 	    __func__,
157 	    le32toh(tx->cts_timeout),
158 	    le32toh(tx->ack_timeout),
159 	    le32toh(tx->exp_ack),
160 	    le32toh(tx->ack),
161 	    le32toh(tx->msdu));
162 
163 	printf("%s: burst_err1=%d, burst_err2=%d, cts_collision=%d, ack_collision=%d\n",
164 	    __func__,
165 	    le32toh(tx->burst_err1),
166 	    le32toh(tx->burst_err2),
167 	    le32toh(tx->cts_collision),
168 	    le32toh(tx->ack_collision));
169 
170 	printf("%s: ba_timeout=%d, ba_resched=%d, query_ampdu=%d, query=%d, query_ampdu_frag=%d\n",
171 	    __func__,
172 	    le32toh(tx->ba_timeout),
173 	    le32toh(tx->ba_resched),
174 	    le32toh(tx->query_ampdu),
175 	    le32toh(tx->query),
176 	    le32toh(tx->query_ampdu_frag));
177 
178 	printf("%s: query_mismatch=%d, not_ready=%d, underrun=%d, bt_ht_kill=%d, rx_ba_resp=%d\n",
179 	    __func__,
180 	    le32toh(tx->query_mismatch),
181 	    le32toh(tx->not_ready),
182 	    le32toh(tx->underrun),
183 	    le32toh(tx->bt_ht_kill),
184 	    le32toh(tx->rx_ba_resp));
185 }
186 
187 static void
188 iwn_stats_ht_phy_print(struct iwnstats *is, struct iwn_rx_ht_phy_stats *ht)
189 {
190 
191 	printf("%s: bad_plcp=%d, overrun=%d, eoverrun=%d, good_crc32=%d, bad_crc32=%d\n",
192 	    __func__,
193 	    le32toh(ht->bad_plcp),
194 	    le32toh(ht->overrun),
195 	    le32toh(ht->eoverrun),
196 	    le32toh(ht->good_crc32),
197 	    le32toh(ht->bad_crc32));
198 
199 	printf("%s: bad_mh=%d, good_ampdu_crc32=%d, ampdu=%d, fragment=%d\n",
200 	    __func__,
201 	    le32toh(ht->bad_plcp),
202 	    le32toh(ht->good_ampdu_crc32),
203 	    le32toh(ht->ampdu),
204 	    le32toh(ht->fragment));
205 }
206 
207 
208 static void
209 iwn_stats_general_print(struct iwnstats *is, struct iwn_stats *stats)
210 {
211 
212 	/* General */
213 	printf("%s: temp=%d, temp_m=%d, burst_check=%d, burst=%d, sleep=%d, slot_out=%d, slot_idle=%d\n",
214 	        __func__,
215 		le32toh(stats->general.temp),
216 		le32toh(stats->general.temp_m),
217 		le32toh(stats->general.burst_check),
218 		le32toh(stats->general.burst),
219 		le32toh(stats->general.sleep),
220 		le32toh(stats->general.slot_out),
221 		le32toh(stats->general.slot_idle));
222 	printf("%s: slot_out=%d, ttl_tstamp=0x%08x, tx_ant_a=%d, tx_ant_b=%d, exec=%d, probe=%d\n",
223 	        __func__,
224 		le32toh(stats->general.slot_out),
225 		le32toh(stats->general.ttl_tstamp),
226 		le32toh(stats->general.tx_ant_a),
227 		le32toh(stats->general.tx_ant_b),
228 		le32toh(stats->general.exec),
229 		le32toh(stats->general.probe));
230 	printf("%s: rx_enabled=%d\n",
231 	        __func__,
232 		le32toh(stats->general.rx_enabled));
233 }
234 
235 static void
236 iwn_print(struct iwnstats *is)
237 {
238 	struct iwn_stats *s;
239 
240 	s = &is->st;
241 
242 	iwn_stats_general_print(is, s);
243 
244 	/* RX */
245 	iwn_stats_phy_print(is, &s->rx.ofdm, "ofdm");
246 	iwn_stats_phy_print(is, &s->rx.cck, "cck");
247 	iwn_stats_ht_phy_print(is, &s->rx.ht);
248 	iwn_stats_rx_general_print(is, &s->rx.general);
249 
250 	/* TX */
251 	iwn_stats_tx_print(is, &s->tx);
252 	printf("--\n");
253 }
254 
255 int
256 main(int argc, const char *argv[])
257 {
258 	struct iwnstats *is;
259 
260 	is = iwnstats_new(IWN_DEFAULT_IF);
261 
262 	if (is == NULL) {
263 		fprintf(stderr, "%s: couldn't allocate new stats structure\n",
264 		    argv[0]);
265 		exit(127);
266 	}
267 
268 	/* begin fetching data */
269 	while (1) {
270 		if (iwn_collect(is) != 0) {
271 			fprintf(stderr, "%s: fetch failed\n", argv[0]);
272 			goto next;
273 		}
274 
275 		iwn_print(is);
276 
277 	next:
278 		usleep(100 * 1000);
279 	}
280 
281 	exit(0);
282 }
283