xref: /freebsd/tools/tools/ath/athstats/athstats.c (revision 44301bc9d59dc69198f8a65bc5d8011c84fa0fee)
112f961f4SSam Leffler /*-
212f961f4SSam Leffler  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
312f961f4SSam Leffler  * All rights reserved.
412f961f4SSam Leffler  *
512f961f4SSam Leffler  * Redistribution and use in source and binary forms, with or without
612f961f4SSam Leffler  * modification, are permitted provided that the following conditions
712f961f4SSam Leffler  * are met:
812f961f4SSam Leffler  * 1. Redistributions of source code must retain the above copyright
912f961f4SSam Leffler  *    notice, this list of conditions and the following disclaimer,
1012f961f4SSam Leffler  *    without modification.
1112f961f4SSam Leffler  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1212f961f4SSam Leffler  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
1312f961f4SSam Leffler  *    redistribution must be conditioned upon including a substantially
1412f961f4SSam Leffler  *    similar Disclaimer requirement for further binary redistribution.
1512f961f4SSam Leffler  * 3. Neither the names of the above-listed copyright holders nor the names
1612f961f4SSam Leffler  *    of any contributors may be used to endorse or promote products derived
1712f961f4SSam Leffler  *    from this software without specific prior written permission.
1812f961f4SSam Leffler  *
1912f961f4SSam Leffler  * Alternatively, this software may be distributed under the terms of the
2012f961f4SSam Leffler  * GNU General Public License ("GPL") version 2 as published by the Free
2112f961f4SSam Leffler  * Software Foundation.
2212f961f4SSam Leffler  *
2312f961f4SSam Leffler  * NO WARRANTY
2412f961f4SSam Leffler  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2512f961f4SSam Leffler  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2612f961f4SSam Leffler  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
2712f961f4SSam Leffler  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
2812f961f4SSam Leffler  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
2912f961f4SSam Leffler  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3012f961f4SSam Leffler  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3112f961f4SSam Leffler  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
3212f961f4SSam Leffler  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3312f961f4SSam Leffler  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3412f961f4SSam Leffler  * THE POSSIBILITY OF SUCH DAMAGES.
3512f961f4SSam Leffler  *
3612f961f4SSam Leffler  * $FreeBSD$
3712f961f4SSam Leffler  */
3812f961f4SSam Leffler 
3912f961f4SSam Leffler /*
4012f961f4SSam Leffler  * Simple Atheros-specific tool to inspect and monitor network traffic
4112f961f4SSam Leffler  * statistics.
4212f961f4SSam Leffler  *	athstats [-i interface] [interval]
4312f961f4SSam Leffler  * (default interface is ath0).  If interval is specified a rolling output
4412f961f4SSam Leffler  * a la netstat -i is displayed every interval seconds.
4512f961f4SSam Leffler  *
4612f961f4SSam Leffler  * To build: cc -o athstats athstats.c -lkvm
4712f961f4SSam Leffler  */
4812f961f4SSam Leffler #include <sys/types.h>
4912f961f4SSam Leffler #include <sys/file.h>
5012f961f4SSam Leffler #include <sys/sockio.h>
5112f961f4SSam Leffler #include <sys/socket.h>
5212f961f4SSam Leffler #include <net/if.h>
5312f961f4SSam Leffler #include <net/if_media.h>
5412f961f4SSam Leffler #include <net/if_var.h>
5512f961f4SSam Leffler 
5612f961f4SSam Leffler #include <stdio.h>
5712f961f4SSam Leffler #include <signal.h>
5812f961f4SSam Leffler 
5944301bc9SSam Leffler #include "../../../../sys/contrib/dev/ath/ah_desc.h"
6044301bc9SSam Leffler #include "../../../../sys/net80211/ieee80211_ioctl.h"
6144301bc9SSam Leffler #include "../../../../sys/net80211/ieee80211_radiotap.h"
6244301bc9SSam Leffler #include "../../../../sys/dev/ath/if_athioctl.h"
6312f961f4SSam Leffler 
6412f961f4SSam Leffler static const struct {
6512f961f4SSam Leffler 	u_int		phyerr;
6612f961f4SSam Leffler 	const char*	desc;
6712f961f4SSam Leffler } phyerrdescriptions[] = {
6812f961f4SSam Leffler 	{ HAL_PHYERR_UNDERRUN,		"transmit underrun" },
6912f961f4SSam Leffler 	{ HAL_PHYERR_TIMING,		"timing error" },
7012f961f4SSam Leffler 	{ HAL_PHYERR_PARITY,		"illegal parity" },
7112f961f4SSam Leffler 	{ HAL_PHYERR_RATE,		"illegal rate" },
7212f961f4SSam Leffler 	{ HAL_PHYERR_LENGTH,		"illegal length" },
7312f961f4SSam Leffler 	{ HAL_PHYERR_RADAR,		"radar detect" },
7412f961f4SSam Leffler 	{ HAL_PHYERR_SERVICE,		"illegal service" },
7512f961f4SSam Leffler 	{ HAL_PHYERR_TOR,		"transmit override receive" },
7612f961f4SSam Leffler 	{ HAL_PHYERR_OFDM_TIMING,	"OFDM timing" },
7712f961f4SSam Leffler 	{ HAL_PHYERR_OFDM_SIGNAL_PARITY,"OFDM illegal parity" },
7812f961f4SSam Leffler 	{ HAL_PHYERR_OFDM_RATE_ILLEGAL,	"OFDM illegal rate" },
7912f961f4SSam Leffler 	{ HAL_PHYERR_OFDM_POWER_DROP,	"OFDM power drop" },
8012f961f4SSam Leffler 	{ HAL_PHYERR_OFDM_SERVICE,	"OFDM illegal service" },
8112f961f4SSam Leffler 	{ HAL_PHYERR_OFDM_RESTART,	"OFDM restart" },
8212f961f4SSam Leffler 	{ HAL_PHYERR_CCK_TIMING,	"CCK timing" },
8312f961f4SSam Leffler 	{ HAL_PHYERR_CCK_HEADER_CRC,	"CCK header crc" },
8412f961f4SSam Leffler 	{ HAL_PHYERR_CCK_RATE_ILLEGAL,	"CCK illegal rate" },
8512f961f4SSam Leffler 	{ HAL_PHYERR_CCK_SERVICE,	"CCK illegal service" },
8612f961f4SSam Leffler 	{ HAL_PHYERR_CCK_RESTART,	"CCK restart" },
8712f961f4SSam Leffler };
8812f961f4SSam Leffler 
8912f961f4SSam Leffler static void
9012f961f4SSam Leffler printstats(FILE *fd, const struct ath_stats *stats)
9112f961f4SSam Leffler {
9212f961f4SSam Leffler #define	N(a)	(sizeof(a) / sizeof(a[0]))
9312f961f4SSam Leffler #define	STAT(x,fmt) \
9412f961f4SSam Leffler 	if (stats->ast_##x) fprintf(fd, "%u " fmt "\n", stats->ast_##x)
9512f961f4SSam Leffler 	int i, j;
9612f961f4SSam Leffler 
9712f961f4SSam Leffler 	STAT(watchdog, "watchdog timeouts");
9812f961f4SSam Leffler 	STAT(hardware, "hardware error interrupts");
9912f961f4SSam Leffler 	STAT(bmiss, "beacon miss interrupts");
10012f961f4SSam Leffler 	STAT(bstuck, "stuck beacon conditions");
10112f961f4SSam Leffler 	STAT(rxorn, "recv overrun interrupts");
10212f961f4SSam Leffler 	STAT(rxeol, "recv eol interrupts");
10312f961f4SSam Leffler 	STAT(txurn, "txmit underrun interrupts");
10412f961f4SSam Leffler 	STAT(mib, "mib overflow interrupts");
10512f961f4SSam Leffler 	STAT(intrcoal, "interrupts coalesced");
10612f961f4SSam Leffler 	STAT(tx_mgmt, "tx management frames");
10712f961f4SSam Leffler 	STAT(tx_discard, "tx frames discarded prior to association");
10812f961f4SSam Leffler 	STAT(tx_qstop, "tx stopped 'cuz no xmit buffer");
10912f961f4SSam Leffler 	STAT(tx_encap, "tx encapsulation failed");
11012f961f4SSam Leffler 	STAT(tx_nonode, "tx failed 'cuz no node");
11112f961f4SSam Leffler 	STAT(tx_nombuf, "tx failed 'cuz no mbuf");
11212f961f4SSam Leffler 	STAT(tx_nomcl, "tx failed 'cuz no cluster");
11312f961f4SSam Leffler 	STAT(tx_linear, "tx linearized to cluster");
11412f961f4SSam Leffler 	STAT(tx_nodata, "tx discarded empty frame");
11512f961f4SSam Leffler 	STAT(tx_busdma, "tx failed for dma resrcs");
11612f961f4SSam Leffler 	STAT(tx_xretries, "tx failed 'cuz too many retries");
11712f961f4SSam Leffler 	STAT(tx_fifoerr, "tx failed 'cuz FIFO underrun");
11812f961f4SSam Leffler 	STAT(tx_filtered, "tx failed 'cuz xmit filtered");
11912f961f4SSam Leffler 	STAT(tx_shortretry, "short on-chip tx retries");
12012f961f4SSam Leffler 	STAT(tx_longretry, "long on-chip tx retries");
12112f961f4SSam Leffler 	STAT(tx_badrate, "tx failed 'cuz bogus xmit rate");
12212f961f4SSam Leffler 	STAT(tx_noack, "tx frames with no ack marked");
12312f961f4SSam Leffler 	STAT(tx_rts, "tx frames with rts enabled");
12412f961f4SSam Leffler 	STAT(tx_cts, "tx frames with cts enabled");
12512f961f4SSam Leffler 	STAT(tx_shortpre, "tx frames with short preamble");
12612f961f4SSam Leffler 	STAT(tx_altrate, "tx frames with an alternate rate");
12712f961f4SSam Leffler 	STAT(tx_protect, "tx frames with 11g protection");
12812f961f4SSam Leffler 	STAT(rx_nombuf,	"rx setup failed 'cuz no mbuf");
12912f961f4SSam Leffler 	STAT(rx_busdma,	"rx setup failed for dma resrcs");
13012f961f4SSam Leffler 	STAT(rx_orn, "rx failed 'cuz of desc overrun");
13112f961f4SSam Leffler 	STAT(rx_crcerr, "rx failed 'cuz of bad CRC");
13212f961f4SSam Leffler 	STAT(rx_fifoerr, "rx failed 'cuz of FIFO overrun");
13312f961f4SSam Leffler 	STAT(rx_badcrypt, "rx failed 'cuz decryption");
13412f961f4SSam Leffler 	STAT(rx_badmic, "rx failed 'cuz MIC failure");
13512f961f4SSam Leffler 	STAT(rx_tooshort, "rx failed 'cuz frame too short");
13612f961f4SSam Leffler 	STAT(rx_toobig, "rx failed 'cuz frame too large");
13712f961f4SSam Leffler 	STAT(rx_mgt, "rx management frames");
13812f961f4SSam Leffler 	STAT(rx_ctl, "rx control frames");
13912f961f4SSam Leffler 	STAT(rx_phyerr, "rx failed 'cuz of PHY err");
14012f961f4SSam Leffler 	if (stats->ast_rx_phyerr != 0) {
14112f961f4SSam Leffler 		for (i = 0; i < 32; i++) {
14212f961f4SSam Leffler 			if (stats->ast_rx_phy[i] == 0)
14312f961f4SSam Leffler 				continue;
14412f961f4SSam Leffler 			for (j = 0; j < N(phyerrdescriptions); j++)
14512f961f4SSam Leffler 				if (phyerrdescriptions[j].phyerr == i)
14612f961f4SSam Leffler 					break;
14712f961f4SSam Leffler 			if (j == N(phyerrdescriptions))
14812f961f4SSam Leffler 				fprintf(fd,
14912f961f4SSam Leffler 					"    %u (unknown phy error code %u)\n",
15012f961f4SSam Leffler 					stats->ast_rx_phy[i], i);
15112f961f4SSam Leffler 			else
15212f961f4SSam Leffler 				fprintf(fd, "    %u %s\n",
15312f961f4SSam Leffler 					stats->ast_rx_phy[i],
15412f961f4SSam Leffler 					phyerrdescriptions[j].desc);
15512f961f4SSam Leffler 		}
15612f961f4SSam Leffler 	}
15712f961f4SSam Leffler 	STAT(be_nombuf,	"beacon setup failed 'cuz no mbuf");
15812f961f4SSam Leffler 	STAT(be_xmit,	"beacons transmitted");
15912f961f4SSam Leffler 	STAT(per_cal, "periodic calibrations");
16012f961f4SSam Leffler 	STAT(per_calfail, "periodic calibration failures");
16112f961f4SSam Leffler 	STAT(per_rfgain, "rfgain value change");
16212f961f4SSam Leffler 	STAT(rate_calls, "rate control checks");
16312f961f4SSam Leffler 	STAT(rate_raise, "rate control raised xmit rate");
16412f961f4SSam Leffler 	STAT(rate_drop, "rate control dropped xmit rate");
16512f961f4SSam Leffler 	if (stats->ast_tx_rssi)
16612f961f4SSam Leffler 		fprintf(fd, "rssi of last ack: %u\n", stats->ast_tx_rssi);
16712f961f4SSam Leffler 	if (stats->ast_rx_rssi)
16812f961f4SSam Leffler 		fprintf(fd, "avg recv rssi: %u\n", stats->ast_rx_rssi);
16912f961f4SSam Leffler 	STAT(ant_defswitch, "switched default/rx antenna");
17012f961f4SSam Leffler 	STAT(ant_txswitch, "tx used alternate antenna");
17112f961f4SSam Leffler 	fprintf(fd, "Antenna profile:\n");
17212f961f4SSam Leffler 	for (i = 0; i < 8; i++)
17312f961f4SSam Leffler 		if (stats->ast_ant_rx[i] || stats->ast_ant_tx[i])
17412f961f4SSam Leffler 			fprintf(fd, "[%u] tx %8u rx %8u\n", i,
17512f961f4SSam Leffler 				stats->ast_ant_tx[i], stats->ast_ant_rx[i]);
17612f961f4SSam Leffler #undef STAT
17712f961f4SSam Leffler #undef N
17812f961f4SSam Leffler }
17912f961f4SSam Leffler 
18012f961f4SSam Leffler static u_int
18112f961f4SSam Leffler getifrate(int s, const char* ifname)
18212f961f4SSam Leffler {
18312f961f4SSam Leffler #define	N(a)	(sizeof(a) / sizeof(a[0]))
18412f961f4SSam Leffler 	static const int rates[] = {
18512f961f4SSam Leffler 		0,		/* IFM_AUTO */
18612f961f4SSam Leffler 		0,		/* IFM_MANUAL */
18712f961f4SSam Leffler 		0,		/* IFM_NONE */
18812f961f4SSam Leffler 		1,		/* IFM_IEEE80211_FH1 */
18912f961f4SSam Leffler 		2,		/* IFM_IEEE80211_FH2 */
19012f961f4SSam Leffler 		1,		/* IFM_IEEE80211_DS1 */
19112f961f4SSam Leffler 		2,		/* IFM_IEEE80211_DS2 */
19212f961f4SSam Leffler 		5,		/* IFM_IEEE80211_DS5 */
19312f961f4SSam Leffler 		11,		/* IFM_IEEE80211_DS11 */
19412f961f4SSam Leffler 		22,		/* IFM_IEEE80211_DS22 */
19512f961f4SSam Leffler 		6,		/* IFM_IEEE80211_OFDM6 */
19612f961f4SSam Leffler 		9,		/* IFM_IEEE80211_OFDM9 */
19712f961f4SSam Leffler 		12,		/* IFM_IEEE80211_OFDM12 */
19812f961f4SSam Leffler 		18,		/* IFM_IEEE80211_OFDM18 */
19912f961f4SSam Leffler 		24,		/* IFM_IEEE80211_OFDM24 */
20012f961f4SSam Leffler 		36,		/* IFM_IEEE80211_OFDM36 */
20112f961f4SSam Leffler 		48,		/* IFM_IEEE80211_OFDM48 */
20212f961f4SSam Leffler 		54,		/* IFM_IEEE80211_OFDM54 */
20312f961f4SSam Leffler 		72,		/* IFM_IEEE80211_OFDM72 */
20412f961f4SSam Leffler 	};
20512f961f4SSam Leffler 	struct ifmediareq ifmr;
20612f961f4SSam Leffler 	int *media_list, i;
20712f961f4SSam Leffler 
20812f961f4SSam Leffler 	(void) memset(&ifmr, 0, sizeof(ifmr));
20912f961f4SSam Leffler 	(void) strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
21012f961f4SSam Leffler 
21112f961f4SSam Leffler 	if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
21212f961f4SSam Leffler 		return 0;
21312f961f4SSam Leffler 	return IFM_SUBTYPE(ifmr.ifm_active) < N(rates) ?
21412f961f4SSam Leffler 		rates[IFM_SUBTYPE(ifmr.ifm_active)] : 0;
21512f961f4SSam Leffler #undef N
21612f961f4SSam Leffler }
21712f961f4SSam Leffler 
21812f961f4SSam Leffler static int signalled;
21912f961f4SSam Leffler 
22012f961f4SSam Leffler static void
22112f961f4SSam Leffler catchalarm(int signo __unused)
22212f961f4SSam Leffler {
22312f961f4SSam Leffler 	signalled = 1;
22412f961f4SSam Leffler }
22512f961f4SSam Leffler 
22612f961f4SSam Leffler int
22712f961f4SSam Leffler main(int argc, char *argv[])
22812f961f4SSam Leffler {
22912f961f4SSam Leffler 	int s;
23012f961f4SSam Leffler 	struct ifreq ifr;
23112f961f4SSam Leffler 
23212f961f4SSam Leffler 	s = socket(AF_INET, SOCK_DGRAM, 0);
23312f961f4SSam Leffler 	if (s < 0)
23412f961f4SSam Leffler 		err(1, "socket");
23512f961f4SSam Leffler 	if (argc > 1 && strcmp(argv[1], "-i") == 0) {
23612f961f4SSam Leffler 		if (argc < 2) {
23712f961f4SSam Leffler 			fprintf(stderr, "%s: missing interface name for -i\n",
23812f961f4SSam Leffler 				argv[0]);
23912f961f4SSam Leffler 			exit(-1);
24012f961f4SSam Leffler 		}
24112f961f4SSam Leffler 		strncpy(ifr.ifr_name, argv[2], sizeof (ifr.ifr_name));
24212f961f4SSam Leffler 		argc -= 2, argv += 2;
24312f961f4SSam Leffler 	} else
24412f961f4SSam Leffler 		strncpy(ifr.ifr_name, "ath0", sizeof (ifr.ifr_name));
24512f961f4SSam Leffler 	if (argc > 1) {
24612f961f4SSam Leffler 		u_long interval = strtoul(argv[1], NULL, 0);
24712f961f4SSam Leffler 		int line, omask;
24812f961f4SSam Leffler 		u_int rate = getifrate(s, ifr.ifr_name);
24912f961f4SSam Leffler 		struct ath_stats cur, total;
25012f961f4SSam Leffler 
25112f961f4SSam Leffler 		if (interval < 1)
25212f961f4SSam Leffler 			interval = 1;
25312f961f4SSam Leffler 		signal(SIGALRM, catchalarm);
25412f961f4SSam Leffler 		signalled = 0;
25512f961f4SSam Leffler 		alarm(interval);
25612f961f4SSam Leffler 	banner:
25712f961f4SSam Leffler 		printf("%8s %8s %7s %7s %7s %6s %6s %5s %7s %4s %4s"
25812f961f4SSam Leffler 			, "input"
25912f961f4SSam Leffler 			, "output"
26012f961f4SSam Leffler 			, "altrate"
26112f961f4SSam Leffler 			, "short"
26212f961f4SSam Leffler 			, "long"
26312f961f4SSam Leffler 			, "xretry"
26412f961f4SSam Leffler 			, "crcerr"
26512f961f4SSam Leffler 			, "crypt"
26612f961f4SSam Leffler 			, "phyerr"
26712f961f4SSam Leffler 			, "rssi"
26812f961f4SSam Leffler 			, "rate"
26912f961f4SSam Leffler 		);
27012f961f4SSam Leffler 		putchar('\n');
27112f961f4SSam Leffler 		fflush(stdout);
27212f961f4SSam Leffler 		line = 0;
27312f961f4SSam Leffler 	loop:
27412f961f4SSam Leffler 		if (line != 0) {
27512f961f4SSam Leffler 			ifr.ifr_data = (caddr_t) &cur;
27612f961f4SSam Leffler 			if (ioctl(s, SIOCGATHSTATS, &ifr) < 0)
27712f961f4SSam Leffler 				err(1, ifr.ifr_name);
27812f961f4SSam Leffler 			rate = getifrate(s, ifr.ifr_name);
27912f961f4SSam Leffler 			printf("%8u %8u %7u %7u %7u %6u %6u %5u %7u %4u %3uM\n"
28012f961f4SSam Leffler 				, cur.ast_rx_packets - total.ast_rx_packets
28112f961f4SSam Leffler 				, cur.ast_tx_packets - total.ast_tx_packets
28212f961f4SSam Leffler 				, cur.ast_tx_altrate - total.ast_tx_altrate
28312f961f4SSam Leffler 				, cur.ast_tx_shortretry - total.ast_tx_shortretry
28412f961f4SSam Leffler 				, cur.ast_tx_longretry - total.ast_tx_longretry
28512f961f4SSam Leffler 				, cur.ast_tx_xretries - total.ast_tx_xretries
28612f961f4SSam Leffler 				, cur.ast_rx_crcerr - total.ast_rx_crcerr
28712f961f4SSam Leffler 				, cur.ast_rx_badcrypt - total.ast_rx_badcrypt
28812f961f4SSam Leffler 				, cur.ast_rx_phyerr - total.ast_rx_phyerr
28912f961f4SSam Leffler 				, cur.ast_rx_rssi
29012f961f4SSam Leffler 				, rate
29112f961f4SSam Leffler 			);
29212f961f4SSam Leffler 			total = cur;
29312f961f4SSam Leffler 		} else {
29412f961f4SSam Leffler 			ifr.ifr_data = (caddr_t) &total;
29512f961f4SSam Leffler 			if (ioctl(s, SIOCGATHSTATS, &ifr) < 0)
29612f961f4SSam Leffler 				err(1, ifr.ifr_name);
29712f961f4SSam Leffler 			rate = getifrate(s, ifr.ifr_name);
29812f961f4SSam Leffler 			printf("%8u %8u %7u %7u %7u %6u %6u %5u %7u %4u %3uM\n"
29912f961f4SSam Leffler 				, total.ast_rx_packets
30012f961f4SSam Leffler 				, total.ast_tx_packets
30112f961f4SSam Leffler 				, total.ast_tx_altrate
30212f961f4SSam Leffler 				, total.ast_tx_shortretry
30312f961f4SSam Leffler 				, total.ast_tx_longretry
30412f961f4SSam Leffler 				, total.ast_tx_xretries
30512f961f4SSam Leffler 				, total.ast_rx_crcerr
30612f961f4SSam Leffler 				, total.ast_rx_badcrypt
30712f961f4SSam Leffler 				, total.ast_rx_phyerr
30812f961f4SSam Leffler 				, total.ast_rx_rssi
30912f961f4SSam Leffler 				, rate
31012f961f4SSam Leffler 			);
31112f961f4SSam Leffler 		}
31212f961f4SSam Leffler 		fflush(stdout);
31312f961f4SSam Leffler 		omask = sigblock(sigmask(SIGALRM));
31412f961f4SSam Leffler 		if (!signalled)
31512f961f4SSam Leffler 			sigpause(0);
31612f961f4SSam Leffler 		sigsetmask(omask);
31712f961f4SSam Leffler 		signalled = 0;
31812f961f4SSam Leffler 		alarm(interval);
31912f961f4SSam Leffler 		line++;
32012f961f4SSam Leffler 		if (line == 21)		/* XXX tty line count */
32112f961f4SSam Leffler 			goto banner;
32212f961f4SSam Leffler 		else
32312f961f4SSam Leffler 			goto loop;
32412f961f4SSam Leffler 		/*NOTREACHED*/
32512f961f4SSam Leffler 	} else {
32612f961f4SSam Leffler 		struct ath_stats stats;
32712f961f4SSam Leffler 
32812f961f4SSam Leffler 		ifr.ifr_data = (caddr_t) &stats;
32912f961f4SSam Leffler 		if (ioctl(s, SIOCGATHSTATS, &ifr) < 0)
33012f961f4SSam Leffler 			err(1, ifr.ifr_name);
33112f961f4SSam Leffler 		printstats(stdout, &stats);
33212f961f4SSam Leffler 	}
33312f961f4SSam Leffler 	return 0;
33412f961f4SSam Leffler }
335