diff options
author | sam <sam@FreeBSD.org> | 2004-12-08 17:42:53 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2004-12-08 17:42:53 +0000 |
commit | 21e06e4bb02890259326936aad2e26187681147e (patch) | |
tree | 090b2b0998afd0bf584b0e11b745944f00c37b6c /tools | |
parent | 26fa487b00ab36b0ce7690667e89d200f8881937 (diff) | |
download | FreeBSD-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.c | 218 | ||||
-rw-r--r-- | tools/tools/ath/80211stats.c | 195 | ||||
-rw-r--r-- | tools/tools/ath/Makefile | 12 | ||||
-rw-r--r-- | tools/tools/ath/athdebug.c | 217 | ||||
-rw-r--r-- | tools/tools/ath/athstats.c | 183 |
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 ); } |