summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2004-12-08 17:42:53 +0000
committersam <sam@FreeBSD.org>2004-12-08 17:42:53 +0000
commit21e06e4bb02890259326936aad2e26187681147e (patch)
tree090b2b0998afd0bf584b0e11b745944f00c37b6c /tools
parent26fa487b00ab36b0ce7690667e89d200f8881937 (diff)
downloadFreeBSD-src-21e06e4bb02890259326936aad2e26187681147e.zip
FreeBSD-src-21e06e4bb02890259326936aad2e26187681147e.tar.gz
o new tools for futzing with 80211 and ath debug masks symbolically
o update stats programs to reflect driver and net80211 changes
Diffstat (limited to 'tools')
-rw-r--r--tools/tools/ath/80211debug.c218
-rw-r--r--tools/tools/ath/80211stats.c195
-rw-r--r--tools/tools/ath/Makefile12
-rw-r--r--tools/tools/ath/athdebug.c217
-rw-r--r--tools/tools/ath/athstats.c183
5 files changed, 659 insertions, 166 deletions
diff --git a/tools/tools/ath/80211debug.c b/tools/tools/ath/80211debug.c
new file mode 100644
index 0000000..d874943
--- /dev/null
+++ b/tools/tools/ath/80211debug.c
@@ -0,0 +1,218 @@
+/*-
+ * Copyright (c) 2002-2004 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$
+ */
+
+/*
+ * 80211debug [-i interface] flags
+ * (default interface is wlan.0).
+ */
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <string.h>
+
+#define N(a) (sizeof(a)/sizeof(a[0]))
+
+const char *progname;
+
+#define IEEE80211_MSG_DEBUG 0x40000000 /* IFF_DEBUG equivalent */
+#define IEEE80211_MSG_DUMPPKTS 0x20000000 /* IFF_LINK2 equivalant */
+#define IEEE80211_MSG_CRYPTO 0x10000000 /* crypto work */
+#define IEEE80211_MSG_INPUT 0x08000000 /* input handling */
+#define IEEE80211_MSG_XRATE 0x04000000 /* rate set handling */
+#define IEEE80211_MSG_ELEMID 0x02000000 /* element id parsing */
+#define IEEE80211_MSG_NODE 0x01000000 /* node handling */
+#define IEEE80211_MSG_ASSOC 0x00800000 /* association handling */
+#define IEEE80211_MSG_AUTH 0x00400000 /* authentication handling */
+#define IEEE80211_MSG_SCAN 0x00200000 /* scanning */
+#define IEEE80211_MSG_OUTPUT 0x00100000 /* output handling */
+#define IEEE80211_MSG_STATE 0x00080000 /* state machine */
+#define IEEE80211_MSG_POWER 0x00040000 /* power save handling */
+#define IEEE80211_MSG_DOT1X 0x00020000 /* 802.1x authenticator */
+#define IEEE80211_MSG_DOT1XSM 0x00010000 /* 802.1x state machine */
+#define IEEE80211_MSG_RADIUS 0x00008000 /* 802.1x radius client */
+#define IEEE80211_MSG_RADDUMP 0x00004000 /* dump 802.1x radius packets */
+#define IEEE80211_MSG_RADKEYS 0x00002000 /* dump 802.1x keys */
+#define IEEE80211_MSG_WPA 0x00001000 /* WPA/RSN protocol */
+#define IEEE80211_MSG_ACL 0x00000800 /* ACL handling */
+#define IEEE80211_MSG_WME 0x00000400 /* WME protocol */
+
+static struct {
+ const char *name;
+ u_int bit;
+} flags[] = {
+ { "debug", IEEE80211_MSG_DEBUG },
+ { "dumppkts", IEEE80211_MSG_DUMPPKTS },
+ { "crypto", IEEE80211_MSG_CRYPTO },
+ { "input", IEEE80211_MSG_INPUT },
+ { "xrate", IEEE80211_MSG_XRATE },
+ { "elemid", IEEE80211_MSG_ELEMID },
+ { "node", IEEE80211_MSG_NODE },
+ { "assoc", IEEE80211_MSG_ASSOC },
+ { "auth", IEEE80211_MSG_AUTH },
+ { "scan", IEEE80211_MSG_SCAN },
+ { "output", IEEE80211_MSG_OUTPUT },
+ { "state", IEEE80211_MSG_STATE },
+ { "power", IEEE80211_MSG_POWER },
+ { "dotx1", IEEE80211_MSG_DOT1X },
+ { "dot1xsm", IEEE80211_MSG_DOT1XSM },
+ { "radius", IEEE80211_MSG_RADIUS },
+ { "raddump", IEEE80211_MSG_RADDUMP },
+ { "radkeys", IEEE80211_MSG_RADKEYS },
+ { "wpa", IEEE80211_MSG_WPA },
+ { "acl", IEEE80211_MSG_ACL },
+ { "wme", IEEE80211_MSG_WME },
+};
+
+static u_int
+getflag(const char *name, int len)
+{
+ int i;
+
+ for (i = 0; i < N(flags); i++)
+ if (strncasecmp(flags[i].name, name, len) == 0)
+ return flags[i].bit;
+ return 0;
+}
+
+static const char *
+getflagname(u_int flag)
+{
+ int i;
+
+ for (i = 0; i < N(flags); i++)
+ if (flags[i].bit == flag)
+ return flags[i].name;
+ return "???";
+}
+
+static void
+usage(void)
+{
+ int i;
+
+ fprintf(stderr, "usage: %s [-i device] [flags]\n", progname);
+ fprintf(stderr, "where flags are:\n");
+ for (i = 0; i < N(flags); i++)
+ printf("%s\n", flags[i].name);
+ exit(-1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *ifname = "ath0";
+ const char *cp, *tp;
+ const char *sep;
+ int c, op, i;
+ u_int32_t debug, ndebug;
+ size_t debuglen;
+ char oid[256];
+
+ progname = argv[0];
+ if (argc > 1) {
+ if (strcmp(argv[1], "-i") == 0) {
+ if (argc < 2)
+ errx(1, "missing interface name for -i option");
+ ifname = argv[2];
+ if (strncmp(ifname, "ath", 3) != 0)
+ errx(2, "huh, this is for ath devices?");
+ argc -= 2, argv += 2;
+ } else if (strcmp(argv[1], "-?") == 0)
+ usage();
+ }
+
+#ifdef __linux__
+ snprintf(oid, sizeof(oid), "net.wlan%s.debug", ifname+3);
+#else
+ snprintf(oid, sizeof(oid), "net.wlan.%s.debug", ifname+3);
+#endif
+ debuglen = sizeof(debug);
+ if (sysctlbyname(oid, &debug, &debuglen, NULL, 0) < 0)
+ err(1, "sysctl-get(%s)", oid);
+ ndebug = debug;
+ for (; argc > 1; argc--, argv++) {
+ cp = argv[1];
+ do {
+ u_int bit;
+
+ if (*cp == '-') {
+ cp++;
+ op = -1;
+ } else if (*cp == '+') {
+ cp++;
+ op = 1;
+ } else
+ op = 0;
+ for (tp = cp; *tp != '\0' && *tp != '+' && *tp != '-';)
+ tp++;
+ bit = getflag(cp, tp-cp);
+ if (op < 0)
+ ndebug &= ~bit;
+ else if (op > 0)
+ ndebug |= bit;
+ else {
+ if (bit == 0) {
+ if (isdigit(*cp))
+ bit = strtoul(cp, NULL, 0);
+ else
+ errx(1, "unknown flag %.*s",
+ tp-cp, cp);
+ }
+ ndebug = bit;
+ }
+ } while (*(cp = tp) != '\0');
+ }
+ if (debug != ndebug) {
+ printf("%s: 0x%x => ", oid, debug);
+ if (sysctlbyname(oid, NULL, NULL, &ndebug, sizeof(ndebug)) < 0)
+ err(1, "sysctl-set(%s)", oid);
+ printf("0x%x", ndebug);
+ debug = ndebug;
+ } else
+ printf("%s: 0x%x", oid, debug);
+ sep = "<";
+ for (i = 0; i < N(flags); i++)
+ if (debug & flags[i].bit) {
+ printf("%s%s", sep, flags[i].name);
+ sep = ",";
+ }
+ printf("%s\n", *sep != '<' ? ">" : "");
+ return 0;
+}
diff --git a/tools/tools/ath/80211stats.c b/tools/tools/ath/80211stats.c
index fb515b1..c148a4f 100644
--- a/tools/tools/ath/80211stats.c
+++ b/tools/tools/ath/80211stats.c
@@ -47,9 +47,12 @@
#include <net/if.h>
#include <net/if_media.h>
#include <net/if_var.h>
+#include <net/ethernet.h>
#include <stdio.h>
#include <signal.h>
+#include <unistd.h>
+#include <err.h>
#include "../../../sys/net80211/ieee80211_ioctl.h"
@@ -66,11 +69,13 @@ printstats(FILE *fd, const struct ieee80211_stats *stats)
STAT(rx_wrongdir, "rx w/ wrong direction");
STAT(rx_mcastecho, "rx discard 'cuz mcast echo");
STAT(rx_notassoc, "rx discard 'cuz sta !assoc");
- STAT(rx_nowep, "rx w/ wep but wep !config");
+ STAT(rx_noprivacy, "rx w/ wep but privacy off");
+ STAT(rx_unencrypted, "rx w/o wep and privacy on");
STAT(rx_wepfail, "rx wep processing failed");
STAT(rx_decap, "rx decapsulation failed");
STAT(rx_mgtdiscard, "rx discard mgt frames");
STAT(rx_ctl, "rx discard ctrl frames");
+ STAT(rx_beacon, "rx beacon frames");
STAT(rx_rstoobig, "rx rate set truncated");
STAT(rx_elem_missing, "rx required element missing");
STAT(rx_elem_toobig, "rx element too big");
@@ -82,48 +87,202 @@ printstats(FILE *fd, const struct ieee80211_stats *stats)
STAT(rx_ssidmismatch, "rx frame ssid mismatch");
STAT(rx_auth_unsupported,"rx w/ unsupported auth alg");
STAT(rx_auth_fail, "rx sta auth failure");
+ STAT(rx_auth_countermeasures,
+ "rx sta auth failure 'cuz of TKIP countermeasures");
STAT(rx_assoc_bss, "rx assoc from wrong bssid");
STAT(rx_assoc_notauth, "rx assoc w/o auth");
STAT(rx_assoc_capmismatch,"rx assoc w/ cap mismatch");
STAT(rx_assoc_norate, "rx assoc w/ no rate match");
+ STAT(rx_assoc_badwpaie, "rx assoc w/ bad WPA IE");
STAT(rx_deauth, "rx deauthentication");
STAT(rx_disassoc, "rx disassociation");
STAT(rx_badsubtype, "rx frame w/ unknown subtype");
- STAT(rx_nombuf, "rx failed for lack of mbuf");
+ STAT(rx_nobuf, "rx failed for lack of sk_buffer");
STAT(rx_decryptcrc, "rx decrypt failed on crc");
STAT(rx_ahdemo_mgt,
"rx discard mgmt frame received in ahdoc demo mode");
STAT(rx_bad_auth, "rx bad authentication request");
- STAT(tx_nombuf, "tx failed for lack of mbuf");
+ STAT(rx_unauth, "rx discard 'cuz port unauthorized");
+ STAT(rx_badkeyid, "rx w/ incorrect keyid");
+ STAT(rx_ccmpreplay, "rx seq# violation (CCMP)");
+ STAT(rx_ccmpformat, "rx format bad (CCMP)");
+ STAT(rx_ccmpmic, "rx MIC check failed (CCMP)");
+ STAT(rx_tkipreplay, "rx seq# violation (TKIP)");
+ STAT(rx_tkipformat, "rx format bad (TKIP)");
+ STAT(rx_tkipmic, "rx MIC check failed (TKIP)");
+ STAT(rx_tkipicv, "rx ICV check failed (TKIP)");
+ STAT(rx_badcipher, "rx failed 'cuz bad cipher/key type");
+ STAT(rx_nocipherctx, "rx failed 'cuz key/cipher ctx not setup");
+ STAT(rx_acl, "rx discard 'cuz acl policy");
+ STAT(tx_nobuf, "tx failed for lack of sk_buffer");
STAT(tx_nonode, "tx failed for no node");
STAT(tx_unknownmgt, "tx of unknown mgt frame");
+ STAT(tx_badcipher, "tx failed 'cuz bad ciper/key type");
+ STAT(tx_nodefkey, "tx failed 'cuz no defkey");
+ STAT(tx_noheadroom, "tx failed 'cuz no space for crypto hdrs");
STAT(scan_active, "active scans started");
STAT(scan_passive, "passive scans started");
STAT(node_timeout, "nodes timed out inactivity");
- STAT(crypto_nomem, "malloc failure of rc4 context");
+ STAT(crypto_nomem, "cipher context malloc failed");
+ STAT(crypto_tkip, "tkip crypto done in s/w");
+ STAT(crypto_tkipenmic, "tkip tx MIC done in s/w");
+ STAT(crypto_tkipdemic, "tkip rx MIC done in s/w");
+ STAT(crypto_tkipcm, "tkip dropped frames 'cuz of countermeasures");
+ STAT(crypto_ccmp, "ccmp crypto done in s/w");
+ STAT(crypto_wep, "wep crypto done in s/w");
+ STAT(crypto_setkey_cipher,"setkey failed 'cuz cipher rejected data");
+ STAT(crypto_setkey_nokey,"setkey failed 'cuz no key index");
+ STAT(crypto_delkey, "driver key delete failed");
+ STAT(crypto_badcipher, "setkey failed 'cuz unknown cipher");
+ STAT(crypto_nocipher, "setkey failed 'cuz cipher module unavailable");
+ STAT(crypto_attachfail, "setkey failed 'cuz cipher attach failed");
+ STAT(crypto_swfallback, "crypto fell back to s/w implementation");
+ STAT(crypto_keyfail, "setkey faied 'cuz driver key alloc failed");
+ STAT(ibss_capmismatch, "ibss merge faied 'cuz capabilities mismatch");
+ STAT(ibss_norate, "ibss merge faied 'cuz rate set mismatch");
+ STAT(ps_unassoc, "ps-poll received for unassociated station");
+ STAT(ps_badaid, "ps-poll received with invalid association id");
+ STAT(ps_qempty, "ps-poll received with nothing to send");
#undef STAT
#undef N
}
+struct ifreq ifr;
+int s;
+
+static void
+print_sta_stats(FILE *fd, const u_int8_t macaddr[IEEE80211_ADDR_LEN])
+{
+#define STAT(x,fmt) \
+ if (ns->ns_##x) { fprintf(fd, "%s" #x " " fmt, sep, ns->ns_##x); sep = " "; }
+ struct ieee80211req ireq;
+ struct ieee80211req_sta_stats stats;
+ const struct ieee80211_nodestats *ns = &stats.is_stats;
+ const char *sep;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, ifr.ifr_name, sizeof(ireq.i_name));
+ ireq.i_type = IEEE80211_IOC_STA_STATS;
+ ireq.i_data = &stats;
+ ireq.i_len = sizeof(stats);
+ memcpy(stats.is_u.macaddr, macaddr, IEEE80211_ADDR_LEN);
+ if (ioctl(s, SIOCG80211, &ireq) < 0)
+ err(1, "unable to get station stats for %s",
+ ether_ntoa((const struct ether_addr*) macaddr));
+
+ fprintf(fd, "%s:\n", ether_ntoa((const struct ether_addr*) macaddr));
+
+ sep = "\t";
+ STAT(rx_data, "%u");
+ STAT(rx_mgmt, "%u");
+ STAT(rx_ctrl, "%u");
+ STAT(rx_beacons, "%u");
+ STAT(rx_proberesp, "%u");
+ STAT(rx_ucast, "%u");
+ STAT(rx_mcast, "%u");
+ STAT(rx_bytes, "%llu");
+ STAT(rx_dup, "%u");
+ STAT(rx_noprivacy, "%u");
+ STAT(rx_wepfail, "%u");
+ STAT(rx_demicfail, "%u");
+ STAT(rx_decap, "%u");
+ STAT(rx_defrag, "%u");
+ STAT(rx_disassoc, "%u");
+ STAT(rx_deauth, "%u");
+ STAT(rx_decryptcrc, "%u");
+ STAT(rx_unauth, "%u");
+ STAT(rx_unencrypted, "%u");
+ fprintf(fd, "\n");
+
+ sep = "\t";
+ STAT(tx_data, "%u");
+ STAT(tx_mgmt, "%u");
+ STAT(tx_probereq, "%u");
+ STAT(tx_ucast, "%u");
+ STAT(tx_mcast, "%u");
+ STAT(tx_bytes, "%llu");
+ STAT(tx_novlantag, "%u");
+ STAT(tx_vlanmismatch, "%u");
+ fprintf(fd, "\n");
+
+ sep = "\t";
+ STAT(tx_assoc, "%u");
+ STAT(tx_assoc_fail, "%u");
+ STAT(tx_auth, "%u");
+ STAT(tx_auth_fail, "%u");
+ STAT(tx_deauth, "%u");
+ STAT(tx_deauth_code, "%llu");
+ STAT(tx_disassoc, "%u");
+ STAT(tx_disassoc_code, "%u");
+ fprintf(fd, "\n");
+
+#undef STAT
+}
+
int
main(int argc, char *argv[])
{
- int s;
- struct ifreq ifr;
- struct ieee80211_stats stats;
+ int c, len;
+ struct ieee80211req_sta_info *si;
+ uint8_t buf[24*1024], *cp;
+ struct ieee80211req ireq;
+ int allnodes = 0;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0)
err(1, "socket");
- if (argc > 1) {
- strncpy(ifr.ifr_name, argv[1], sizeof (ifr.ifr_name));
- argc -= 1, argv += 1;
- } else
- strncpy(ifr.ifr_name, "ath0", sizeof (ifr.ifr_name));
-
- ifr.ifr_data = (caddr_t) &stats;
- if (ioctl(s, SIOCG80211STATS, &ifr) < 0)
- err(1, ifr.ifr_name);
- printstats(stdout, &stats);
- return 0;
+ strncpy(ifr.ifr_name, "ath0", sizeof (ifr.ifr_name));
+ while ((c = getopt(argc, argv, "ai:")) != -1)
+ switch (c) {
+ case 'a':
+ allnodes++;
+ break;
+ case 'i':
+ strncpy(ifr.ifr_name, optarg, sizeof (ifr.ifr_name));
+ break;
+ default:
+ errx(1, "usage: %s [-a] [-i device] [mac...]\n");
+ /*NOTREACHED*/
+ }
+
+ if (argc == optind && !allnodes) {
+ struct ieee80211_stats stats;
+
+ /* no args, just show global stats */
+ ifr.ifr_data = (caddr_t) &stats;
+ if (ioctl(s, SIOCG80211STATS, &ifr) < 0)
+ err(1, ifr.ifr_name);
+ printstats(stdout, &stats);
+ return 0;
+ }
+ if (allnodes) {
+ /*
+ * Retrieve station/neighbor table and print stats for each.
+ */
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, ifr.ifr_name, sizeof(ireq.i_name));
+ ireq.i_type = IEEE80211_IOC_STA_INFO;
+ ireq.i_data = buf;
+ ireq.i_len = sizeof(buf);
+ if (ioctl(s, SIOCG80211, &ireq) < 0)
+ err(1, "unable to get station information");
+ len = ireq.i_len;
+ if (len >= sizeof(struct ieee80211req_sta_info)) {
+ cp = buf;
+ do {
+ si = (struct ieee80211req_sta_info *) cp;
+ print_sta_stats(stdout, si->isi_macaddr);
+ cp += si->isi_len, len -= si->isi_len;
+ } while (len >= sizeof(struct ieee80211req_sta_info));
+ }
+ } else {
+ /*
+ * Print stats for specified stations.
+ */
+ for (c = optind; c < argc; c++) {
+ const struct ether_addr *ea = ether_aton(argv[c]);
+ if (ea != NULL)
+ print_sta_stats(stdout, ea->octet);
+ }
+ }
}
diff --git a/tools/tools/ath/Makefile b/tools/tools/ath/Makefile
index e0f8ff0..899ef47 100644
--- a/tools/tools/ath/Makefile
+++ b/tools/tools/ath/Makefile
@@ -26,20 +26,26 @@
#
BINDIR= /usr/local/bin
-ALL= athstats 80211stats 80211watch
+ALL= athstats 80211stats 80211watch athdebug 80211debug
all: ${ALL}
athstats: athstats.c
- ${CC} -o athstats athstats.c -lkvm
+ ${CC} -o athstats athstats.c
+athdebug: athdebug.c
+ ${CC} -o athdebug athdebug.c
80211stats: 80211stats.c
${CC} -o 80211stats 80211stats.c
80211watch: 80211watch.c
${CC} -o 80211watch 80211watch.c
+80211debug: 80211debug.c
+ ${CC} -o 80211debug 80211debug.c
install: ${ALL}
- install -g kmem -m 2755 athstats ${DESTDIR}${BINDIR}
+ install athstats ${DESTDIR}${BINDIR}
install 80211stats ${DESTDIR}${BINDIR}
install 80211watch ${DESTDIR}${BINDIR}
+ install 80211debug ${DESTDIR}${BINDIR}
+ install athdebug ${DESTDIR}${BINDIR}
clean:
rm -f ${ALL} core a.out
diff --git a/tools/tools/ath/athdebug.c b/tools/tools/ath/athdebug.c
new file mode 100644
index 0000000..06591cd
--- /dev/null
+++ b/tools/tools/ath/athdebug.c
@@ -0,0 +1,217 @@
+/*-
+ * Copyright (c) 2002-2004 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$
+ */
+
+/*
+ * athdebug [-i interface] flags
+ * (default interface is ath0).
+ */
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#include <getopt.h>
+
+#define N(a) (sizeof(a)/sizeof(a[0]))
+
+const char *progname;
+
+enum {
+ ATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
+ ATH_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */
+ ATH_DEBUG_RECV = 0x00000004, /* basic recv operation */
+ ATH_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */
+ ATH_DEBUG_RATE = 0x00000010, /* rate control */
+ ATH_DEBUG_RESET = 0x00000020, /* reset processing */
+ ATH_DEBUG_MODE = 0x00000040, /* mode init/setup */
+ ATH_DEBUG_BEACON = 0x00000080, /* beacon handling */
+ ATH_DEBUG_WATCHDOG = 0x00000100, /* watchdog timeout */
+ ATH_DEBUG_INTR = 0x00001000, /* ISR */
+ ATH_DEBUG_TX_PROC = 0x00002000, /* tx ISR proc */
+ ATH_DEBUG_RX_PROC = 0x00004000, /* rx ISR proc */
+ ATH_DEBUG_BEACON_PROC = 0x00008000, /* beacon ISR proc */
+ ATH_DEBUG_CALIBRATE = 0x00010000, /* periodic calibration */
+ ATH_DEBUG_KEYCACHE = 0x00020000, /* key cache management */
+ ATH_DEBUG_STATE = 0x00040000, /* 802.11 state transitions */
+ ATH_DEBUG_NODE = 0x00080000, /* node management */
+ ATH_DEBUG_FATAL = 0x80000000, /* fatal errors */
+ ATH_DEBUG_ANY = 0xffffffff
+};
+
+static struct {
+ const char *name;
+ u_int bit;
+} flags[] = {
+ { "xmit", ATH_DEBUG_XMIT },
+ { "xmit_desc", ATH_DEBUG_XMIT_DESC },
+ { "recv", ATH_DEBUG_RECV },
+ { "recv_desc", ATH_DEBUG_RECV_DESC },
+ { "rate", ATH_DEBUG_RATE },
+ { "reset", ATH_DEBUG_RESET },
+ { "mode", ATH_DEBUG_MODE },
+ { "beacon", ATH_DEBUG_BEACON },
+ { "watchdog", ATH_DEBUG_WATCHDOG },
+ { "intr", ATH_DEBUG_INTR },
+ { "xmit_proc", ATH_DEBUG_TX_PROC },
+ { "recv_proc", ATH_DEBUG_RX_PROC },
+ { "beacon_proc",ATH_DEBUG_BEACON_PROC },
+ { "calibrate", ATH_DEBUG_CALIBRATE },
+ { "keycache", ATH_DEBUG_KEYCACHE },
+ { "state", ATH_DEBUG_STATE },
+ { "node", ATH_DEBUG_NODE },
+ { "fatal", ATH_DEBUG_FATAL },
+};
+
+static u_int
+getflag(const char *name, int len)
+{
+ int i;
+
+ for (i = 0; i < N(flags); i++)
+ if (strncasecmp(flags[i].name, name, len) == 0)
+ return flags[i].bit;
+ return 0;
+}
+
+static const char *
+getflagname(u_int flag)
+{
+ int i;
+
+ for (i = 0; i < N(flags); i++)
+ if (flags[i].bit == flag)
+ return flags[i].name;
+ return "???";
+}
+
+static void
+usage(void)
+{
+ int i;
+
+ fprintf(stderr, "usage: %s [-i device] [flags]\n", progname);
+ fprintf(stderr, "where flags are:\n");
+ for (i = 0; i < N(flags); i++)
+ printf("%s\n", flags[i].name);
+ exit(-1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *ifname = "ath0";
+ const char *cp, *tp;
+ const char *sep;
+ int c, op, i;
+ u_int32_t debug, ndebug;
+ size_t debuglen;
+ char oid[256];
+
+ progname = argv[0];
+ if (argc > 1) {
+ if (strcmp(argv[1], "-i") == 0) {
+ if (argc < 2)
+ errx(1, "missing interface name for -i option");
+ ifname = argv[2];
+ if (strncmp(ifname, "ath", 3) != 0)
+ errx(2, "huh, this is for ath devices?");
+ argc -= 2, argv += 2;
+ } else if (strcmp(argv[1], "-?") == 0)
+ usage();
+ }
+
+#ifdef __linux__
+ snprintf(oid, sizeof(oid), "dev.%s.debug", ifname);
+#else
+ snprintf(oid, sizeof(oid), "dev.ath.%s.debug", ifname+3);
+#endif
+ debuglen = sizeof(debug);
+ if (sysctlbyname(oid, &debug, &debuglen, NULL, 0) < 0)
+ err(1, "sysctl-get(%s)", oid);
+ ndebug = debug;
+ for (; argc > 1; argc--, argv++) {
+ cp = argv[1];
+ do {
+ u_int bit;
+
+ if (*cp == '-') {
+ cp++;
+ op = -1;
+ } else if (*cp == '+') {
+ cp++;
+ op = 1;
+ } else
+ op = 0;
+ for (tp = cp; *tp != '\0' && *tp != '+' && *tp != '-';)
+ tp++;
+ bit = getflag(cp, tp-cp);
+ if (op < 0)
+ ndebug &= ~bit;
+ else if (op > 0)
+ ndebug |= bit;
+ else {
+ if (bit == 0) {
+ if (isdigit(*cp))
+ bit = strtoul(cp, NULL, 0);
+ else
+ errx(1, "unknown flag %.*s",
+ tp-cp, cp);
+ }
+ ndebug = bit;
+ }
+ } while (*(cp = tp) != '\0');
+ }
+ if (debug != ndebug) {
+ printf("%s: 0x%x => ", oid, debug);
+ if (sysctlbyname(oid, NULL, NULL, &ndebug, sizeof(ndebug)) < 0)
+ err(1, "sysctl-set(%s)", oid);
+ printf("0x%x", ndebug);
+ debug = ndebug;
+ } else
+ printf("%s: 0x%x", oid, debug);
+ sep = "<";
+ for (i = 0; i < N(flags); i++)
+ if (debug & flags[i].bit) {
+ printf("%s%s", sep, flags[i].name);
+ sep = ",";
+ }
+ printf("%s\n", *sep != '<' ? ">" : "");
+ return 0;
+}
diff --git a/tools/tools/ath/athstats.c b/tools/tools/ath/athstats.c
index 7e3bd74..ed3a35b 100644
--- a/tools/tools/ath/athstats.c
+++ b/tools/tools/ath/athstats.c
@@ -55,8 +55,6 @@
#include <stdio.h>
#include <signal.h>
-#include <kvm.h>
-#include <nlist.h>
#include "../../../sys/contrib/dev/ath/ah_desc.h"
#include "../../../sys/net80211/ieee80211_ioctl.h"
@@ -94,19 +92,22 @@ 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)
+ int i, j;
+
STAT(watchdog, "watchdog timeouts");
STAT(hardware, "hardware error interrupts");
STAT(bmiss, "beacon miss interrupts");
+ STAT(bstuck, "stuck beacon conditions");
STAT(rxorn, "recv overrun interrupts");
STAT(rxeol, "recv eol interrupts");
STAT(txurn, "txmit underrun interrupts");
+ STAT(mib, "mib overflow 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_qstop, "tx stopped 'cuz no xmit buffer");
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");
@@ -122,16 +123,21 @@ printstats(FILE *fd, const struct ath_stats *stats)
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(tx_altrate, "tx frames with an alternate rate");
+ STAT(tx_protect, "tx frames with 11g protection");
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_badmic, "rx failed 'cuz MIC failure");
+ STAT(rx_tooshort, "rx failed 'cuz frame too short");
+ STAT(rx_toobig, "rx failed 'cuz frame too large");
+ STAT(rx_mgt, "rx management frames");
+ STAT(rx_ctl, "rx control frames");
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;
@@ -149,12 +155,24 @@ printstats(FILE *fd, const struct ath_stats *stats)
}
}
STAT(be_nombuf, "beacon setup failed 'cuz no mbuf");
+ STAT(be_xmit, "beacons transmitted");
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");
+ if (stats->ast_tx_rssi)
+ fprintf(fd, "rssi of last ack: %u\n", stats->ast_tx_rssi);
+ if (stats->ast_rx_rssi)
+ fprintf(fd, "avg recv rssi: %u\n", stats->ast_rx_rssi);
+ STAT(ant_defswitch, "switched default/rx antenna");
+ STAT(ant_txswitch, "tx used alternate antenna");
+ fprintf(fd, "Antenna profile:\n");
+ for (i = 0; i < 8; i++)
+ if (stats->ast_ant_rx[i] || stats->ast_ant_tx[i])
+ fprintf(fd, "[%u] tx %8u rx %8u\n", i,
+ stats->ast_ant_tx[i], stats->ast_ant_rx[i]);
#undef STAT
#undef N
}
@@ -197,109 +215,6 @@ getifrate(int s, const char* ifname)
#undef N
}
-#define WI_RID_COMMS_QUALITY 0xFD43
-/*
- * Technically I don't think there's a limit to a record
- * length. The largest record is the one that contains the CIS
- * data, which is 240 words long, so 256 should be a safe
- * value.
- */
-#define WI_MAX_DATALEN 512
-
-struct wi_req {
- u_int16_t wi_len;
- u_int16_t wi_type;
- u_int16_t wi_val[WI_MAX_DATALEN];
-};
-
-static u_int
-getrssi(int s, const char *iface)
-{
- struct ifreq ifr;
- struct wi_req wreq;
-
- bzero(&wreq, sizeof(wreq));
- wreq.wi_len = WI_MAX_DATALEN;
- wreq.wi_type = WI_RID_COMMS_QUALITY;
-
- bzero(&ifr, sizeof(ifr));
- strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
- ifr.ifr_data = (caddr_t)&wreq;
- return ioctl(s, SIOCGIFGENERIC, &ifr) == -1 ? 0 : wreq.wi_val[1];
-}
-
-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[IFNAMSIZ];
-
- if (kread(off, (char *)&ifnet, sizeof ifnet))
- break;
- if (interface && strcmp(ifnet.if_xname, interface) == 0)
- return off;
- off = (u_long)TAILQ_NEXT(&ifnet, if_link);
- }
- return 0;
-}
-
static int signalled;
static void
@@ -329,15 +244,9 @@ main(int argc, char *argv[])
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;
@@ -345,9 +254,10 @@ main(int argc, char *argv[])
signalled = 0;
alarm(interval);
banner:
- printf("%8s %8s %7s %7s %6s %6s %6s %7s %4s %4s"
+ printf("%8s %8s %7s %7s %7s %6s %6s %5s %7s %4s %4s"
, "input"
, "output"
+ , "altrate"
, "short"
, "long"
, "xretry"
@@ -365,54 +275,37 @@ main(int argc, char *argv[])
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 %7u %4u %3uM\n"
- , ifcur.if_ipackets - iftot.if_ipackets
- , ifcur.if_opackets - iftot.if_opackets
+ rate = getifrate(s, ifr.ifr_name);
+ printf("%8u %8u %7u %7u %7u %6u %6u %5u %7u %4u %3uM\n"
+ , cur.ast_rx_packets - total.ast_rx_packets
+ , cur.ast_tx_packets - total.ast_tx_packets
+ , cur.ast_tx_altrate - total.ast_tx_altrate
, 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
- , getrssi(s, ifr.ifr_name)
+ , cur.ast_rx_rssi
, 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 %7u %4u %3uM\n"
- , iftot.if_ipackets
- , iftot.if_opackets
+ rate = getifrate(s, ifr.ifr_name);
+ printf("%8u %8u %7u %7u %7u %6u %6u %5u %7u %4u %3uM\n"
+ , total.ast_rx_packets
+ , total.ast_tx_packets
+ , total.ast_tx_altrate
, total.ast_tx_shortretry
, total.ast_tx_longretry
, total.ast_tx_xretries
, total.ast_rx_crcerr
, total.ast_rx_badcrypt
, total.ast_rx_phyerr
- , getrssi(s, ifr.ifr_name)
+ , total.ast_rx_rssi
, rate
);
}
OpenPOWER on IntegriCloud