bring in ath-specific test tool; more to follow
This commit is contained in:
parent
11484af448
commit
64125f9866
@ -8,11 +8,12 @@ the other categories.
|
||||
Please make a subdir per program, and add a brief description to this
|
||||
file.
|
||||
|
||||
ath Tools specific to the Atheros 802.11 support
|
||||
backout_commit A tool for reading in a commit message and generating
|
||||
a script that will backout the commit.
|
||||
commitsdb A tool for reconstructing commit history using md5
|
||||
checksums of the commit logs.
|
||||
crypto Exercise the crypto framework through /dev/crypto
|
||||
crypto Test and exercise tools related to the crypto framework
|
||||
diffburst OBSOLETE: equivalent functionality is available via split -p.
|
||||
For example: "split -p ^diff < patchfile". See split(1).
|
||||
editing Editor modes and the like to help editing FreeBSD code.
|
||||
|
35
tools/tools/ath/Makefile
Normal file
35
tools/tools/ath/Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
# Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
|
||||
ALL= athstats
|
||||
|
||||
all: ${ALL}
|
||||
|
||||
athstats: athstats.c
|
||||
${CC} -o athstats athstats.c -lkvm
|
||||
clean:
|
||||
rm -f ${ALL} core a.out
|
409
tools/tools/ath/athstats.c
Normal file
409
tools/tools/ath/athstats.c
Normal file
@ -0,0 +1,409 @@
|
||||
/*-
|
||||
* Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer,
|
||||
* without modification.
|
||||
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
|
||||
* redistribution must be conditioned upon including a substantially
|
||||
* similar Disclaimer requirement for further binary redistribution.
|
||||
* 3. Neither the names of the above-listed copyright holders nor the names
|
||||
* of any contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") version 2 as published by the Free
|
||||
* Software Foundation.
|
||||
*
|
||||
* NO WARRANTY
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Simple Atheros-specific tool to inspect and monitor network traffic
|
||||
* statistics.
|
||||
* athstats [-i interface] [interval]
|
||||
* (default interface is ath0). If interval is specified a rolling output
|
||||
* a la netstat -i is displayed every interval seconds.
|
||||
*
|
||||
* To build: cc -o athstats athstats.c -lkvm
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_var.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <kvm.h>
|
||||
#include <nlist.h>
|
||||
|
||||
#include "../../../sys/contrib/dev/ath/ah_desc.h"
|
||||
#include "../../../sys/dev/ath/if_athioctl.h"
|
||||
|
||||
static const struct {
|
||||
u_int phyerr;
|
||||
const char* desc;
|
||||
} phyerrdescriptions[] = {
|
||||
{ HAL_PHYERR_UNDERRUN, "transmit underrun" },
|
||||
{ HAL_PHYERR_TIMING, "timing error" },
|
||||
{ HAL_PHYERR_PARITY, "illegal parity" },
|
||||
{ HAL_PHYERR_RATE, "illegal rate" },
|
||||
{ HAL_PHYERR_LENGTH, "illegal length" },
|
||||
{ HAL_PHYERR_RADAR, "radar detect" },
|
||||
{ HAL_PHYERR_SERVICE, "illegal service" },
|
||||
{ HAL_PHYERR_TOR, "transmit override receive" },
|
||||
{ HAL_PHYERR_OFDM_TIMING, "OFDM timing" },
|
||||
{ HAL_PHYERR_OFDM_SIGNAL_PARITY,"OFDM illegal parity" },
|
||||
{ HAL_PHYERR_OFDM_RATE_ILLEGAL, "OFDM illegal rate" },
|
||||
{ HAL_PHYERR_OFDM_POWER_DROP, "OFDM power drop" },
|
||||
{ HAL_PHYERR_OFDM_SERVICE, "OFDM illegal service" },
|
||||
{ HAL_PHYERR_OFDM_RESTART, "OFDM restart" },
|
||||
{ HAL_PHYERR_CCK_TIMING, "CCK timing" },
|
||||
{ HAL_PHYERR_CCK_HEADER_CRC, "CCK header crc" },
|
||||
{ HAL_PHYERR_CCK_RATE_ILLEGAL, "CCK illegal rate" },
|
||||
{ HAL_PHYERR_CCK_SERVICE, "CCK illegal service" },
|
||||
{ HAL_PHYERR_CCK_RESTART, "CCK restart" },
|
||||
};
|
||||
|
||||
static void
|
||||
printstats(FILE *fd, const struct ath_stats *stats)
|
||||
{
|
||||
#define N(a) (sizeof(a) / sizeof(a[0]))
|
||||
#define STAT(x,fmt) \
|
||||
if (stats->ast_##x) fprintf(fd, "%u " fmt "\n", stats->ast_##x)
|
||||
STAT(watchdog, "watchdog timeouts");
|
||||
STAT(hardware, "hardware error interrupts");
|
||||
STAT(bmiss, "beacon miss interrupts");
|
||||
STAT(rxorn, "recv overrun interrupts");
|
||||
STAT(rxeol, "recv eol interrupts");
|
||||
STAT(txurn, "txmit underrun interrupts");
|
||||
STAT(intrcoal, "interrupts coalesced");
|
||||
STAT(rx_orn, "rx overrun interrupts");
|
||||
STAT(tx_mgmt, "tx management frames");
|
||||
STAT(tx_discard, "tx frames discarded prior to association");
|
||||
STAT(tx_encap, "tx encapsulation failed");
|
||||
STAT(tx_nonode, "tx failed 'cuz no node");
|
||||
STAT(tx_qstop, "tx stopped 'cuz no xmit buffer");
|
||||
STAT(tx_nombuf, "tx failed 'cuz no mbuf");
|
||||
STAT(tx_nomcl, "tx failed 'cuz no cluster");
|
||||
STAT(tx_linear, "tx linearized to cluster");
|
||||
STAT(tx_nodata, "tx discarded empty frame");
|
||||
STAT(tx_busdma, "tx failed for dma resrcs");
|
||||
STAT(tx_xretries, "tx failed 'cuz too many retries");
|
||||
STAT(tx_fifoerr, "tx failed 'cuz FIFO underrun");
|
||||
STAT(tx_filtered, "tx failed 'cuz xmit filtered");
|
||||
STAT(tx_shortretry, "short on-chip tx retries");
|
||||
STAT(tx_longretry, "long on-chip tx retries");
|
||||
STAT(tx_badrate, "tx failed 'cuz bogus xmit rate");
|
||||
STAT(tx_noack, "tx frames with no ack marked");
|
||||
STAT(tx_rts, "tx frames with rts enabled");
|
||||
STAT(tx_cts, "tx frames with cts enabled");
|
||||
STAT(tx_shortpre, "tx frames with short preamble");
|
||||
STAT(rx_nombuf, "rx setup failed 'cuz no mbuf");
|
||||
STAT(rx_busdma, "rx setup failed for dma resrcs");
|
||||
STAT(rx_orn, "rx failed 'cuz of desc overrun");
|
||||
STAT(rx_tooshort, "rx failed 'cuz frame too short");
|
||||
STAT(rx_crcerr, "rx failed 'cuz of bad CRC");
|
||||
STAT(rx_fifoerr, "rx failed 'cuz of FIFO overrun");
|
||||
STAT(rx_badcrypt, "rx failed 'cuz decryption");
|
||||
STAT(rx_phyerr, "rx failed 'cuz of PHY err");
|
||||
if (stats->ast_rx_phyerr != 0) {
|
||||
int i, j;
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (stats->ast_rx_phy[i] == 0)
|
||||
continue;
|
||||
for (j = 0; j < N(phyerrdescriptions); j++)
|
||||
if (phyerrdescriptions[j].phyerr == i)
|
||||
break;
|
||||
if (j == N(phyerrdescriptions))
|
||||
fprintf(fd,
|
||||
" %u (unknown phy error code %u)\n",
|
||||
stats->ast_rx_phy[i], i);
|
||||
else
|
||||
fprintf(fd, " %u %s\n",
|
||||
stats->ast_rx_phy[i],
|
||||
phyerrdescriptions[j].desc);
|
||||
}
|
||||
}
|
||||
STAT(be_nombuf, "beacon setup failed 'cuz no mbuf");
|
||||
STAT(per_cal, "periodic calibrations");
|
||||
STAT(per_calfail, "periodic calibration failures");
|
||||
STAT(per_rfgain, "rfgain value change");
|
||||
STAT(rate_calls, "rate control checks");
|
||||
STAT(rate_raise, "rate control raised xmit rate");
|
||||
STAT(rate_drop, "rate control dropped xmit rate");
|
||||
#undef STAT
|
||||
#undef N
|
||||
}
|
||||
|
||||
static u_int
|
||||
getifrate(int s, const char* ifname)
|
||||
{
|
||||
#define N(a) (sizeof(a) / sizeof(a[0]))
|
||||
static const int rates[] = {
|
||||
-1, /* IFM_AUTO */
|
||||
0, /* IFM_MANUAL */
|
||||
0, /* IFM_NONE */
|
||||
1, /* IFM_IEEE80211_FH1 */
|
||||
2, /* IFM_IEEE80211_FH2 */
|
||||
1, /* IFM_IEEE80211_DS1 */
|
||||
2, /* IFM_IEEE80211_DS2 */
|
||||
5, /* IFM_IEEE80211_DS5 */
|
||||
11, /* IFM_IEEE80211_DS11 */
|
||||
22, /* IFM_IEEE80211_DS22 */
|
||||
6, /* IFM_IEEE80211_OFDM6 */
|
||||
9, /* IFM_IEEE80211_OFDM9 */
|
||||
12, /* IFM_IEEE80211_OFDM12 */
|
||||
18, /* IFM_IEEE80211_OFDM18 */
|
||||
24, /* IFM_IEEE80211_OFDM24 */
|
||||
36, /* IFM_IEEE80211_OFDM36 */
|
||||
48, /* IFM_IEEE80211_OFDM48 */
|
||||
54, /* IFM_IEEE80211_OFDM54 */
|
||||
72, /* IFM_IEEE80211_OFDM72 */
|
||||
};
|
||||
struct ifmediareq ifmr;
|
||||
int *media_list, i;
|
||||
|
||||
(void) memset(&ifmr, 0, sizeof(ifmr));
|
||||
(void) strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
|
||||
|
||||
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
|
||||
return 0;
|
||||
return IFM_SUBTYPE(ifmr.ifm_active) < N(rates) ?
|
||||
rates[IFM_SUBTYPE(ifmr.ifm_active)] : 0;
|
||||
#undef N
|
||||
}
|
||||
|
||||
static kvm_t *kvmd;
|
||||
static char *nlistf = NULL;
|
||||
static char *memf = NULL;
|
||||
|
||||
static struct nlist nl[] = {
|
||||
#define N_IFNET 0
|
||||
{ "_ifnet" },
|
||||
};
|
||||
|
||||
/*
|
||||
* Read kernel memory, return 0 on success.
|
||||
*/
|
||||
static int
|
||||
kread(u_long addr, void *buf, int size)
|
||||
{
|
||||
if (kvmd == 0) {
|
||||
/*
|
||||
* XXX.
|
||||
*/
|
||||
kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
|
||||
setgid(getgid());
|
||||
if (kvmd != NULL) {
|
||||
if (kvm_nlist(kvmd, nl) < 0) {
|
||||
if(nlistf)
|
||||
errx(1, "%s: kvm_nlist: %s", nlistf,
|
||||
kvm_geterr(kvmd));
|
||||
else
|
||||
errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
|
||||
}
|
||||
|
||||
if (nl[0].n_type == 0) {
|
||||
if(nlistf)
|
||||
errx(1, "%s: no namelist", nlistf);
|
||||
else
|
||||
errx(1, "no namelist");
|
||||
}
|
||||
} else {
|
||||
warnx("kvm not available");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
if (!buf)
|
||||
return (0);
|
||||
if (kvm_read(kvmd, addr, buf, size) != size) {
|
||||
warnx("%s", kvm_geterr(kvmd));
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static u_long
|
||||
ifnetsetup(const char *interface, u_long off)
|
||||
{
|
||||
struct ifnet ifnet;
|
||||
u_long firstifnet;
|
||||
struct ifnethead ifnethead;
|
||||
|
||||
if (kread(off, (char *)&ifnethead, sizeof ifnethead))
|
||||
return;
|
||||
firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
|
||||
for (off = firstifnet; off;) {
|
||||
char name[16], tname[16];
|
||||
|
||||
if (kread(off, (char *)&ifnet, sizeof ifnet))
|
||||
break;
|
||||
if (kread((u_long)ifnet.if_name, tname, sizeof(tname)))
|
||||
break;
|
||||
tname[sizeof(tname) - 1] = '\0';
|
||||
snprintf(name, sizeof(name), "%s%d", tname, ifnet.if_unit);
|
||||
if (interface && strcmp(name, interface) == 0)
|
||||
return off;
|
||||
off = (u_long)TAILQ_NEXT(&ifnet, if_link);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int signalled;
|
||||
|
||||
static void
|
||||
catchalarm(int signo __unused)
|
||||
{
|
||||
signalled = 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int s;
|
||||
struct ifreq ifr;
|
||||
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0)
|
||||
err(1, "socket");
|
||||
if (argc > 1 && strcmp(argv[1], "-i") == 0) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "%s: missing interface name for -i\n",
|
||||
argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
strncpy(ifr.ifr_name, argv[2], sizeof (ifr.ifr_name));
|
||||
argc -= 2, argv += 2;
|
||||
} else
|
||||
strncpy(ifr.ifr_name, "ath0", sizeof (ifr.ifr_name));
|
||||
if (argc > 1) {
|
||||
u_long interval = strtoul(argv[1], NULL, 0);
|
||||
u_long off;
|
||||
int line, omask;
|
||||
u_int rate = getifrate(s, ifr.ifr_name);
|
||||
u_int32_t rate_raise, rate_drop, mgmt;
|
||||
struct ath_stats cur, total;
|
||||
struct ifnet ifcur, iftot;
|
||||
|
||||
kread(0, 0, 0);
|
||||
off = ifnetsetup(ifr.ifr_name, nl[N_IFNET].n_value);
|
||||
|
||||
if (interval < 1)
|
||||
interval = 1;
|
||||
signal(SIGALRM, catchalarm);
|
||||
signalled = 0;
|
||||
alarm(interval);
|
||||
banner:
|
||||
printf("%8s %8s %7s %7s %6s %6s %6s %6s %6s"
|
||||
, "input"
|
||||
, "output"
|
||||
, "short"
|
||||
, "long"
|
||||
, "xretry"
|
||||
, "crcerr"
|
||||
, "crypt"
|
||||
, "phyerr"
|
||||
, "rate"
|
||||
);
|
||||
putchar('\n');
|
||||
fflush(stdout);
|
||||
line = 0;
|
||||
loop:
|
||||
if (line != 0) {
|
||||
ifr.ifr_data = (caddr_t) &cur;
|
||||
if (ioctl(s, SIOCGATHSTATS, &ifr) < 0)
|
||||
err(1, ifr.ifr_name);
|
||||
if (total.ast_rate_raise != rate_raise ||
|
||||
total.ast_rate_drop != rate_drop ||
|
||||
total.ast_tx_mgmt != mgmt) {
|
||||
rate = getifrate(s, ifr.ifr_name);
|
||||
rate_raise = total.ast_rate_raise;
|
||||
rate_drop = total.ast_rate_drop;
|
||||
mgmt = total.ast_tx_mgmt;
|
||||
}
|
||||
if (kread(off, &ifcur, sizeof(ifcur)))
|
||||
err(1, ifr.ifr_name);
|
||||
printf("%8u %8u %7u %7u %6u %6u %6u %6u %5uM\n"
|
||||
, ifcur.if_ipackets - iftot.if_ipackets
|
||||
, ifcur.if_opackets - iftot.if_opackets
|
||||
, cur.ast_tx_shortretry - total.ast_tx_shortretry
|
||||
, cur.ast_tx_longretry - total.ast_tx_longretry
|
||||
, cur.ast_tx_xretries - total.ast_tx_xretries
|
||||
, cur.ast_rx_crcerr - total.ast_rx_crcerr
|
||||
, cur.ast_rx_badcrypt - total.ast_rx_badcrypt
|
||||
, cur.ast_rx_phyerr - total.ast_rx_phyerr
|
||||
, rate
|
||||
);
|
||||
total = cur;
|
||||
iftot = ifcur;
|
||||
} else {
|
||||
ifr.ifr_data = (caddr_t) &total;
|
||||
if (ioctl(s, SIOCGATHSTATS, &ifr) < 0)
|
||||
err(1, ifr.ifr_name);
|
||||
if (total.ast_rate_raise != rate_raise ||
|
||||
total.ast_rate_drop != rate_drop ||
|
||||
total.ast_tx_mgmt != mgmt) {
|
||||
rate = getifrate(s, ifr.ifr_name);
|
||||
rate_raise = total.ast_rate_raise;
|
||||
rate_drop = total.ast_rate_drop;
|
||||
mgmt = total.ast_tx_mgmt;
|
||||
}
|
||||
if (kread(off, &iftot, sizeof(iftot)))
|
||||
err(1, ifr.ifr_name);
|
||||
printf("%8u %8u %7u %7u %6u %6u %6u %6u %5uM\n"
|
||||
, iftot.if_ipackets
|
||||
, iftot.if_opackets
|
||||
, total.ast_tx_shortretry
|
||||
, total.ast_tx_longretry
|
||||
, total.ast_tx_xretries
|
||||
, total.ast_rx_crcerr
|
||||
, total.ast_rx_badcrypt
|
||||
, total.ast_rx_phyerr
|
||||
, rate
|
||||
);
|
||||
}
|
||||
fflush(stdout);
|
||||
omask = sigblock(sigmask(SIGALRM));
|
||||
if (!signalled)
|
||||
sigpause(0);
|
||||
sigsetmask(omask);
|
||||
signalled = 0;
|
||||
alarm(interval);
|
||||
line++;
|
||||
if (line == 21) /* XXX tty line count */
|
||||
goto banner;
|
||||
else
|
||||
goto loop;
|
||||
/*NOTREACHED*/
|
||||
} else {
|
||||
struct ath_stats stats;
|
||||
|
||||
ifr.ifr_data = (caddr_t) &stats;
|
||||
if (ioctl(s, SIOCGATHSTATS, &ifr) < 0)
|
||||
err(1, ifr.ifr_name);
|
||||
printstats(stdout, &stats);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user