From 7e506a9a093f2d88aceaa93771d06dad59da1e45 Mon Sep 17 00:00:00 2001 From: cvs2svn Date: Thu, 17 Aug 2006 10:55:50 +0000 Subject: This commit was manufactured by cvs2svn to create branch 'RELENG_6'. --- tools/tools/ath/athstats/athstats.h | 52 ++++++ tools/tools/ath/athstats/main.c | 134 +++++++++++++++ tools/tools/ath/athstats/statfoo.c | 191 +++++++++++++++++++++ tools/tools/ath/athstats/statfoo.h | 127 ++++++++++++++ tools/tools/net80211/wlanstats/main.c | 255 +++++++++++++++++++++++++++++ tools/tools/net80211/wlanstats/statfoo.c | 191 +++++++++++++++++++++ tools/tools/net80211/wlanstats/statfoo.h | 127 ++++++++++++++ tools/tools/net80211/wlanstats/wlanstats.h | 56 +++++++ 8 files changed, 1133 insertions(+) create mode 100644 tools/tools/ath/athstats/athstats.h create mode 100644 tools/tools/ath/athstats/main.c create mode 100644 tools/tools/ath/athstats/statfoo.c create mode 100644 tools/tools/ath/athstats/statfoo.h create mode 100644 tools/tools/net80211/wlanstats/main.c create mode 100644 tools/tools/net80211/wlanstats/statfoo.c create mode 100644 tools/tools/net80211/wlanstats/statfoo.h create mode 100644 tools/tools/net80211/wlanstats/wlanstats.h (limited to 'tools') diff --git a/tools/tools/ath/athstats/athstats.h b/tools/tools/ath/athstats/athstats.h new file mode 100644 index 000000000000..03a9b7cde29b --- /dev/null +++ b/tools/tools/ath/athstats/athstats.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2002-2006 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. + * + * 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$ + */ + +#ifndef _ATHSTATS_H_ +#define _ATHSTATS_H_ + +#include "statfoo.h" + +/* + * ath statistics class. + */ +struct athstatfoo { + struct statfoo base; + + STATFOO_DECL_METHODS(struct athstatfoo *); + + /* set the network interface name for collection */ + void (*setifname)(struct athstatfoo *, const char *ifname); + /* set the mac address of the associated station/ap */ + void (*setstamac)(struct athstatfoo *, const uint8_t mac[]); +}; + +struct athstatfoo *athstats_new(const char *ifname, const char *fmtstring); +#endif /* _ATHSTATS_H_ */ diff --git a/tools/tools/ath/athstats/main.c b/tools/tools/ath/athstats/main.c new file mode 100644 index 000000000000..b775b1a3a326 --- /dev/null +++ b/tools/tools/ath/athstats/main.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2002-2006 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] [-l] [-o fmtstring] [interval] + * + * (default interface is ath0). If interval is specified a rolling output + * a la netstat -i is displayed every interval seconds. The format of + * the rolling display can be controlled a la ps. The -l option will + * print a list of all possible statistics for use with the -o option. + */ + +#include +#include +#include +#include + +#include "athstats.h" + +#define S_DEFAULT \ + "input,output,altrate,short,long,xretry,crcerr,crypt,phyerr,rssi,rate" + +static int signalled; + +static void +catchalarm(int signo __unused) +{ + signalled = 1; +} + +int +main(int argc, char *argv[]) +{ + struct athstatfoo *wf; + int c; + + wf = athstats_new("ath0", S_DEFAULT); + while ((c = getopt(argc, argv, "i:lo:")) != -1) { + switch (c) { + case 'i': + wf->setifname(wf, optarg); + break; + case 'l': + wf->print_fields(wf, stdout); + return 0; + case 'o': + wf->setfmt(wf, optarg); + break; + default: + errx(-1, "usage: %s [-a] [-i ifname] [-l] [-o fmt] [interval]\n", argv[0]); + /*NOTREACHED*/ + } + } + argc -= optind; + argv += optind; + + if (argc > 0) { + u_long interval = strtoul(argv[0], NULL, 0); + int line, omask; + + if (interval < 1) + interval = 1; + signal(SIGALRM, catchalarm); + signalled = 0; + alarm(interval); + banner: + wf->print_header(wf, stdout); + line = 0; + loop: + if (line != 0) { + wf->collect_cur(wf); + wf->print_current(wf, stdout); + wf->update_tot(wf); + } else { + wf->collect_tot(wf); + wf->print_total(wf, stdout); + } + 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 { + wf->collect_tot(wf); + wf->print_verbose(wf, stdout); + } + return 0; +} diff --git a/tools/tools/ath/athstats/statfoo.c b/tools/tools/ath/athstats/statfoo.c new file mode 100644 index 000000000000..99c616b9c9e6 --- /dev/null +++ b/tools/tools/ath/athstats/statfoo.c @@ -0,0 +1,191 @@ +/*- + * Copyright (c) 2002-2006 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$ + */ + +#include +#include + +#include "statfoo.h" + +static void +statfoo_setfmt(struct statfoo *sf, const char *fmt0) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + char fmt[4096]; + char *fp, *tok; + int i, j; + + j = 0; + strlcpy(fmt, fmt0, sizeof(fmt)); + for (fp = fmt; (tok = strsep(&fp, ", ")) != NULL;) { + for (i = 0; i < sf->nstats; i++) + if (strcasecmp(tok, sf->stats[i].name) == 0) + break; + if (i >= sf->nstats) { + fprintf(stderr, "%s: unknown statistic name \"%s\" " + "skipped\n", sf->name, tok); + continue; + } + if (j+3 > sizeof(sf->fmts)) { + fprintf(stderr, "%s: not enough room for all stats; " + "stopped at %s\n", sf->name, tok); + break; + } + if (j != 0) + sf->fmts[j++] = ' '; + sf->fmts[j++] = 0x80 | i; + } + sf->fmts[j] = '\0'; +#undef N +} + +static void +statfoo_collect(struct statfoo *sf) +{ + fprintf(stderr, "%s: don't know how to collect data\n", sf->name); +} + +static void +statfoo_update_tot(struct statfoo *sf) +{ + fprintf(stderr, "%s: don't know how to update total data\n", sf->name); +} + +static int +statfoo_get(struct statfoo *sf, int s, char b[], size_t bs) +{ + fprintf(stderr, "%s: don't know how to get stat #%u\n", sf->name, s); + return 0; +} + +static void +statfoo_print_header(struct statfoo *sf, FILE *fd) +{ + const unsigned char *cp; + + for (cp = sf->fmts; *cp != '\0'; cp++) { + if (*cp & 0x80) { + const struct fmt *f = &sf->stats[*cp &~ 0x80]; + fprintf(fd, "%*s", f->width, f->label); + } else + putc(*cp, fd); + } + putc('\n', fd); +} + +static void +statfoo_print_current(struct statfoo *sf, FILE *fd) +{ + char buf[32]; + const unsigned char *cp; + + for (cp = sf->fmts; *cp != '\0'; cp++) { + if (*cp & 0x80) { + const struct fmt *f = &sf->stats[*cp &~ 0x80]; + if (sf->get_curstat(sf, *cp &~ 0x80, buf, sizeof(buf))) + fprintf(fd, "%*s", f->width, buf); + } else + putc(*cp, fd); + } + putc('\n', fd); +} + +static void +statfoo_print_total(struct statfoo *sf, FILE *fd) +{ + char buf[32]; + const unsigned char *cp; + + for (cp = sf->fmts; *cp != '\0'; cp++) { + if (*cp & 0x80) { + const struct fmt *f = &sf->stats[*cp &~ 0x80]; + if (sf->get_totstat(sf, *cp &~ 0x80, buf, sizeof(buf))) + fprintf(fd, "%*s", f->width, buf); + } else + putc(*cp, fd); + } + putc('\n', fd); +} + +static void +statfoo_print_verbose(struct statfoo *sf, FILE *fd) +{ + char s[32]; + int i; + + for (i = 0; i < sf->nstats; i++) { + if (sf->get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) + fprintf(fd, "%s %s\n", s, sf->stats[i].desc); + } +} + +static void +statfoo_print_fields(struct statfoo *sf, FILE *fd) +{ + int i, w, width; + + width = 0; + for (i = 0; i < sf->nstats; i++) { + w = strlen(sf->stats[i].name); + if (w > width) + width = w; + } + for (i = 0; i < sf->nstats; i++) { + const struct fmt *f = &sf->stats[i]; + if (f->width != 0) + fprintf(fd, "%-*s %s\n", width, f->name, f->desc); + } +} + +void +statfoo_init(struct statfoo *sf, const char *name, const struct fmt *stats, int nstats) +{ + sf->name = name; + sf->stats = stats; + sf->nstats = nstats; + sf->setfmt = statfoo_setfmt; + sf->collect_cur = statfoo_collect; + sf->collect_tot = statfoo_collect; + sf->update_tot = statfoo_update_tot; + sf->get_curstat = statfoo_get; + sf->get_totstat = statfoo_get; + sf->print_header = statfoo_print_header; + sf->print_current = statfoo_print_current; + sf->print_total = statfoo_print_total; + sf->print_verbose = statfoo_print_verbose; + sf->print_fields = statfoo_print_fields; +} diff --git a/tools/tools/ath/athstats/statfoo.h b/tools/tools/ath/athstats/statfoo.h new file mode 100644 index 000000000000..4575946bceed --- /dev/null +++ b/tools/tools/ath/athstats/statfoo.h @@ -0,0 +1,127 @@ +/*- + * Copyright (c) 2002-2006 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. + * + * 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$ + */ + +#ifndef _STATFOO_H_ +#define _STATFOO_H_ +/* + * Base class for managing+displaying periodically collected statistics. + */ + +/* + * Statistic definition/description. The are defined + * for stats that correspond 1-1 w/ a collected stat + * and for stats that are calculated indirectly. + */ +struct fmt { + int width; /* printed field width */ + const char* name; /* stat field name referenced by user */ + const char* label; /* printed header label */ + const char* desc; /* verbose description */ +}; + +#define STATFOO_DECL_METHODS(_p) \ + /* set the format of the statistics to display */ \ + void (*setfmt)(_p, const char *); \ + /* collect+store ``current statistics'' */ \ + void (*collect_cur)(_p); \ + /* collect+store ``total statistics'' */ \ + void (*collect_tot)(_p); \ + /* update ``total statistics'' if necessary from current */ \ + void (*update_tot)(_p); \ + /* format a statistic from the current stats */ \ + int (*get_curstat)(_p, int, char [], size_t); \ + /* format a statistic from the total stats */ \ + int (*get_totstat)(_p, int, char [], size_t); \ + /* print field headers terminated by a \n */ \ + void (*print_header)(_p, FILE *); \ + /* print current statistics terminated by a \n */ \ + void (*print_current)(_p, FILE *); \ + /* print total statistics terminated by a \n */ \ + void (*print_total)(_p, FILE *); \ + /* print total statistics in a verbose (1 stat/line) format */ \ + void (*print_verbose)(_p, FILE *); \ + /* print available statistics */ \ + void (*print_fields)(_p, FILE *) + +/* + * Statistics base class. This class is not usable; only + * classes derived from it are useful. + */ +struct statfoo { + const char *name; /* statistics name, e.g. wlanstats */ + const struct fmt *stats; /* statistics in class */ + int nstats; /* number of stats */ + unsigned char fmts[4096]; /* private: compiled stats to display */ + + STATFOO_DECL_METHODS(struct statfoo *); +}; + +void statfoo_init(struct statfoo *, const char *name, + const struct fmt *stats, int nstats); + +#define STATFOO_DEFINE_BOUNCE(_t) \ +static void _t##_setfmt(struct _t *wf, const char *fmt0) \ + { wf->base.setfmt(&wf->base, fmt0); } \ +static void _t##_collect_cur(struct _t *wf) \ + { wf->base.collect_cur(&wf->base); } \ +static void _t##_collect_tot(struct _t *wf) \ + { wf->base.collect_tot(&wf->base); } \ +static void _t##_update_tot(struct _t *wf) \ + { wf->base.update_tot(&wf->base); } \ +static int _t##_get_curstat(struct _t *wf, int s, char b[], size_t bs) \ + { return wf->base.get_curstat(&wf->base, s, b, bs); } \ +static int _t##_get_totstat(struct _t *wf, int s, char b[], size_t bs) \ + { return wf->base.get_totstat(&wf->base, s, b, bs); } \ +static void _t##_print_header(struct _t *wf, FILE *fd) \ + { wf->base.print_header(&wf->base, fd); } \ +static void _t##_print_current(struct _t *wf, FILE *fd) \ + { wf->base.print_current(&wf->base, fd); } \ +static void _t##_print_total(struct _t *wf, FILE *fd) \ + { wf->base.print_total(&wf->base, fd); } \ +static void _t##_print_verbose(struct _t *wf, FILE *fd) \ + { wf->base.print_verbose(&wf->base, fd); } \ +static void _t##_print_fields(struct _t *wf, FILE *fd) \ + { wf->base.print_fields(&wf->base, fd); } + +#define STATFOO_BOUNCE(_p, _t) do { \ + _p->base.setfmt = _t##_setfmt; \ + _p->base.collect_cur = _t##_collect_cur; \ + _p->base.collect_tot = _t##_collect_tot; \ + _p->base.update_tot = _t##_update_tot; \ + _p->base.get_curstat = _t##_get_curstat; \ + _p->base.get_totstat = _t##_get_totstat; \ + _p->base.print_header = _t##_print_header; \ + _p->base.print_current = _t##_print_current; \ + _p->base.print_total = _t##_print_total; \ + _p->base.print_verbose = _t##_print_verbose; \ + _p->base.print_fields = _t##_print_fields; \ +} while (0) +#endif /* _STATFOO_H_ */ diff --git a/tools/tools/net80211/wlanstats/main.c b/tools/tools/net80211/wlanstats/main.c new file mode 100644 index 000000000000..f3276d157f7d --- /dev/null +++ b/tools/tools/net80211/wlanstats/main.c @@ -0,0 +1,255 @@ +/*- + * Copyright (c) 2002-2006 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$ + */ + +/* + * wlanstats [-i interface] + * (default interface is ath0). + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "wlanstats.h" + +#define S_DEFAULT \ + "input,output,rx_ucast,rx_mcast,tx_ucast,tx_mcast,signal,noise,rate" + +static int signalled; + +static void +catchalarm(int signo __unused) +{ + signalled = 1; +} + +#if 0 +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 +} +#endif + +int +main(int argc, char *argv[]) +{ + struct wlanstatfoo *wf; + struct ether_addr *ea; + const uint8_t *mac = NULL; + int allnodes = 0; + int c, mode; + + wf = wlanstats_new("ath0", S_DEFAULT); + while ((c = getopt(argc, argv, "ai:lm:o:")) != -1) { + switch (c) { + case 'a': + allnodes++; + break; + case 'i': + wf->setifname(wf, optarg); + break; + case 'l': + wf->print_fields(wf, stdout); + return 0; + case 'm': + ea = ether_aton(optarg); + if (!ea) + errx(1, "%s: invalid ethernet address", optarg); + mac = ea->octet; + break; + case 'o': + wf->setfmt(wf, optarg); + break; + default: + errx(-1, "usage: %s [-a] [-i ifname] [-l] [-o fmt] [interval]\n", argv[0]); + /*NOTREACHED*/ + } + } + argc -= optind; + argv += optind; + + mode = wf->getopmode(wf); + wf->setstamac(wf, mac); + + if (argc > 0) { + u_long interval = strtoul(argv[0], NULL, 0); + int line, omask; + + if (interval < 1) + interval = 1; + signal(SIGALRM, catchalarm); + signalled = 0; + alarm(interval); + banner: + wf->print_header(wf, stdout); + line = 0; + loop: + if (line != 0) { + wf->collect_cur(wf); + wf->print_current(wf, stdout); + wf->update_tot(wf); + } else { + wf->collect_tot(wf); + wf->print_total(wf, stdout); + } + fflush(stdout); + omask = sigblock(sigmask(SIGALRM)); + if (!signalled) + sigpause(0); + sigsetmask(omask); + signalled = 0; + alarm(interval); + line++; + /* refresh every display in case sta roams */ + if (mac == NULL && mode == IEEE80211_M_STA) + wf->setstamac(wf, NULL); + if (line == 21) /* XXX tty line count */ + goto banner; + else + goto loop; + /*NOTREACHED*/ +#if 0 + } else if (allnodes) { + struct ieee80211req_sta_info *si; + union { + struct ieee80211req_sta_req req; + uint8_t buf[24*1024]; + } u; + uint8_t *cp; + struct ieee80211req ireq; + int len; + + /* + * 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; + memset(&u.req.macaddr, 0xff, sizeof(u.req.macaddr)); + ireq.i_data = &u; + ireq.i_len = sizeof(u); + 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 = u.req.info; + do { + si = (struct ieee80211req_sta_info *) cp; + if (si->isi_len < sizeof(*si)) + break; + print_sta_stats(stdout, si->isi_macaddr); + cp += si->isi_len, len -= si->isi_len; + } while (len >= sizeof(struct ieee80211req_sta_info)); + } +#endif + } else { + wf->collect_tot(wf); + wf->print_verbose(wf, stdout); + } + return 0; +} diff --git a/tools/tools/net80211/wlanstats/statfoo.c b/tools/tools/net80211/wlanstats/statfoo.c new file mode 100644 index 000000000000..99c616b9c9e6 --- /dev/null +++ b/tools/tools/net80211/wlanstats/statfoo.c @@ -0,0 +1,191 @@ +/*- + * Copyright (c) 2002-2006 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$ + */ + +#include +#include + +#include "statfoo.h" + +static void +statfoo_setfmt(struct statfoo *sf, const char *fmt0) +{ +#define N(a) (sizeof(a)/sizeof(a[0])) + char fmt[4096]; + char *fp, *tok; + int i, j; + + j = 0; + strlcpy(fmt, fmt0, sizeof(fmt)); + for (fp = fmt; (tok = strsep(&fp, ", ")) != NULL;) { + for (i = 0; i < sf->nstats; i++) + if (strcasecmp(tok, sf->stats[i].name) == 0) + break; + if (i >= sf->nstats) { + fprintf(stderr, "%s: unknown statistic name \"%s\" " + "skipped\n", sf->name, tok); + continue; + } + if (j+3 > sizeof(sf->fmts)) { + fprintf(stderr, "%s: not enough room for all stats; " + "stopped at %s\n", sf->name, tok); + break; + } + if (j != 0) + sf->fmts[j++] = ' '; + sf->fmts[j++] = 0x80 | i; + } + sf->fmts[j] = '\0'; +#undef N +} + +static void +statfoo_collect(struct statfoo *sf) +{ + fprintf(stderr, "%s: don't know how to collect data\n", sf->name); +} + +static void +statfoo_update_tot(struct statfoo *sf) +{ + fprintf(stderr, "%s: don't know how to update total data\n", sf->name); +} + +static int +statfoo_get(struct statfoo *sf, int s, char b[], size_t bs) +{ + fprintf(stderr, "%s: don't know how to get stat #%u\n", sf->name, s); + return 0; +} + +static void +statfoo_print_header(struct statfoo *sf, FILE *fd) +{ + const unsigned char *cp; + + for (cp = sf->fmts; *cp != '\0'; cp++) { + if (*cp & 0x80) { + const struct fmt *f = &sf->stats[*cp &~ 0x80]; + fprintf(fd, "%*s", f->width, f->label); + } else + putc(*cp, fd); + } + putc('\n', fd); +} + +static void +statfoo_print_current(struct statfoo *sf, FILE *fd) +{ + char buf[32]; + const unsigned char *cp; + + for (cp = sf->fmts; *cp != '\0'; cp++) { + if (*cp & 0x80) { + const struct fmt *f = &sf->stats[*cp &~ 0x80]; + if (sf->get_curstat(sf, *cp &~ 0x80, buf, sizeof(buf))) + fprintf(fd, "%*s", f->width, buf); + } else + putc(*cp, fd); + } + putc('\n', fd); +} + +static void +statfoo_print_total(struct statfoo *sf, FILE *fd) +{ + char buf[32]; + const unsigned char *cp; + + for (cp = sf->fmts; *cp != '\0'; cp++) { + if (*cp & 0x80) { + const struct fmt *f = &sf->stats[*cp &~ 0x80]; + if (sf->get_totstat(sf, *cp &~ 0x80, buf, sizeof(buf))) + fprintf(fd, "%*s", f->width, buf); + } else + putc(*cp, fd); + } + putc('\n', fd); +} + +static void +statfoo_print_verbose(struct statfoo *sf, FILE *fd) +{ + char s[32]; + int i; + + for (i = 0; i < sf->nstats; i++) { + if (sf->get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0")) + fprintf(fd, "%s %s\n", s, sf->stats[i].desc); + } +} + +static void +statfoo_print_fields(struct statfoo *sf, FILE *fd) +{ + int i, w, width; + + width = 0; + for (i = 0; i < sf->nstats; i++) { + w = strlen(sf->stats[i].name); + if (w > width) + width = w; + } + for (i = 0; i < sf->nstats; i++) { + const struct fmt *f = &sf->stats[i]; + if (f->width != 0) + fprintf(fd, "%-*s %s\n", width, f->name, f->desc); + } +} + +void +statfoo_init(struct statfoo *sf, const char *name, const struct fmt *stats, int nstats) +{ + sf->name = name; + sf->stats = stats; + sf->nstats = nstats; + sf->setfmt = statfoo_setfmt; + sf->collect_cur = statfoo_collect; + sf->collect_tot = statfoo_collect; + sf->update_tot = statfoo_update_tot; + sf->get_curstat = statfoo_get; + sf->get_totstat = statfoo_get; + sf->print_header = statfoo_print_header; + sf->print_current = statfoo_print_current; + sf->print_total = statfoo_print_total; + sf->print_verbose = statfoo_print_verbose; + sf->print_fields = statfoo_print_fields; +} diff --git a/tools/tools/net80211/wlanstats/statfoo.h b/tools/tools/net80211/wlanstats/statfoo.h new file mode 100644 index 000000000000..4575946bceed --- /dev/null +++ b/tools/tools/net80211/wlanstats/statfoo.h @@ -0,0 +1,127 @@ +/*- + * Copyright (c) 2002-2006 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. + * + * 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$ + */ + +#ifndef _STATFOO_H_ +#define _STATFOO_H_ +/* + * Base class for managing+displaying periodically collected statistics. + */ + +/* + * Statistic definition/description. The are defined + * for stats that correspond 1-1 w/ a collected stat + * and for stats that are calculated indirectly. + */ +struct fmt { + int width; /* printed field width */ + const char* name; /* stat field name referenced by user */ + const char* label; /* printed header label */ + const char* desc; /* verbose description */ +}; + +#define STATFOO_DECL_METHODS(_p) \ + /* set the format of the statistics to display */ \ + void (*setfmt)(_p, const char *); \ + /* collect+store ``current statistics'' */ \ + void (*collect_cur)(_p); \ + /* collect+store ``total statistics'' */ \ + void (*collect_tot)(_p); \ + /* update ``total statistics'' if necessary from current */ \ + void (*update_tot)(_p); \ + /* format a statistic from the current stats */ \ + int (*get_curstat)(_p, int, char [], size_t); \ + /* format a statistic from the total stats */ \ + int (*get_totstat)(_p, int, char [], size_t); \ + /* print field headers terminated by a \n */ \ + void (*print_header)(_p, FILE *); \ + /* print current statistics terminated by a \n */ \ + void (*print_current)(_p, FILE *); \ + /* print total statistics terminated by a \n */ \ + void (*print_total)(_p, FILE *); \ + /* print total statistics in a verbose (1 stat/line) format */ \ + void (*print_verbose)(_p, FILE *); \ + /* print available statistics */ \ + void (*print_fields)(_p, FILE *) + +/* + * Statistics base class. This class is not usable; only + * classes derived from it are useful. + */ +struct statfoo { + const char *name; /* statistics name, e.g. wlanstats */ + const struct fmt *stats; /* statistics in class */ + int nstats; /* number of stats */ + unsigned char fmts[4096]; /* private: compiled stats to display */ + + STATFOO_DECL_METHODS(struct statfoo *); +}; + +void statfoo_init(struct statfoo *, const char *name, + const struct fmt *stats, int nstats); + +#define STATFOO_DEFINE_BOUNCE(_t) \ +static void _t##_setfmt(struct _t *wf, const char *fmt0) \ + { wf->base.setfmt(&wf->base, fmt0); } \ +static void _t##_collect_cur(struct _t *wf) \ + { wf->base.collect_cur(&wf->base); } \ +static void _t##_collect_tot(struct _t *wf) \ + { wf->base.collect_tot(&wf->base); } \ +static void _t##_update_tot(struct _t *wf) \ + { wf->base.update_tot(&wf->base); } \ +static int _t##_get_curstat(struct _t *wf, int s, char b[], size_t bs) \ + { return wf->base.get_curstat(&wf->base, s, b, bs); } \ +static int _t##_get_totstat(struct _t *wf, int s, char b[], size_t bs) \ + { return wf->base.get_totstat(&wf->base, s, b, bs); } \ +static void _t##_print_header(struct _t *wf, FILE *fd) \ + { wf->base.print_header(&wf->base, fd); } \ +static void _t##_print_current(struct _t *wf, FILE *fd) \ + { wf->base.print_current(&wf->base, fd); } \ +static void _t##_print_total(struct _t *wf, FILE *fd) \ + { wf->base.print_total(&wf->base, fd); } \ +static void _t##_print_verbose(struct _t *wf, FILE *fd) \ + { wf->base.print_verbose(&wf->base, fd); } \ +static void _t##_print_fields(struct _t *wf, FILE *fd) \ + { wf->base.print_fields(&wf->base, fd); } + +#define STATFOO_BOUNCE(_p, _t) do { \ + _p->base.setfmt = _t##_setfmt; \ + _p->base.collect_cur = _t##_collect_cur; \ + _p->base.collect_tot = _t##_collect_tot; \ + _p->base.update_tot = _t##_update_tot; \ + _p->base.get_curstat = _t##_get_curstat; \ + _p->base.get_totstat = _t##_get_totstat; \ + _p->base.print_header = _t##_print_header; \ + _p->base.print_current = _t##_print_current; \ + _p->base.print_total = _t##_print_total; \ + _p->base.print_verbose = _t##_print_verbose; \ + _p->base.print_fields = _t##_print_fields; \ +} while (0) +#endif /* _STATFOO_H_ */ diff --git a/tools/tools/net80211/wlanstats/wlanstats.h b/tools/tools/net80211/wlanstats/wlanstats.h new file mode 100644 index 000000000000..9f38098a0862 --- /dev/null +++ b/tools/tools/net80211/wlanstats/wlanstats.h @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2002-2006 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. + * + * 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$ + */ + +#ifndef _WLANSTATS_H_ +#define _WLANSTATS_H_ + +#include "statfoo.h" + +/* + * wlan statistics class. + */ +struct wlanstatfoo { + struct statfoo base; + + STATFOO_DECL_METHODS(struct wlanstatfoo *); + + /* set the network interface name for collection */ + void (*setifname)(struct wlanstatfoo *, const char *ifname); + /* get the network interface name */ + const char *(*getifname)(struct wlanstatfoo *); + /* get the wireless operating mode */ + int (*getopmode)(struct wlanstatfoo *); + /* set the mac address of the associated station/ap */ + void (*setstamac)(struct wlanstatfoo *, const uint8_t mac[]); +}; + +struct wlanstatfoo *wlanstats_new(const char *ifname, const char *fmtstring); +#endif /* _WLANSTATS_H_ */ -- cgit v1.3