| | 1 | {{{ |
| | 2 | /*- |
| | 3 | * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting |
| | 4 | * All rights reserved. |
| | 5 | * |
| | 6 | * Redistribution and use in source and binary forms, with or without |
| | 7 | * modification, are permitted provided that the following conditions |
| | 8 | * are met: |
| | 9 | * 1. Redistributions of source code must retain the above copyright |
| | 10 | * notice, this list of conditions and the following disclaimer, |
| | 11 | * without modification. |
| | 12 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
| | 13 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any |
| | 14 | * redistribution must be conditioned upon including a substantially |
| | 15 | * similar Disclaimer requirement for further binary redistribution. |
| | 16 | * 3. Neither the names of the above-listed copyright holders nor the names |
| | 17 | * of any contributors may be used to endorse or promote products derived |
| | 18 | * from this software without specific prior written permission. |
| | 19 | * |
| | 20 | * Alternatively, this software may be distributed under the terms of the |
| | 21 | * GNU General Public License ("GPL") version 2 as published by the Free |
| | 22 | * Software Foundation. |
| | 23 | * |
| | 24 | * NO WARRANTY |
| | 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| | 26 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| | 27 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY |
| | 28 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
| | 29 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, |
| | 30 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| | 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| | 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
| | 33 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| | 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| | 35 | * THE POSSIBILITY OF SUCH DAMAGES. |
| | 36 | * |
| | 37 | * $FreeBSD: src/tools/tools/ath/athstats.c,v 1.4 2003/12/07 21:40:52 sam Exp $ |
| | 38 | */ |
| | 39 | |
| | 40 | /* |
| | 41 | * Simple Atheros-specific tool to inspect and monitor network traffic |
| | 42 | * statistics. |
| | 43 | * athstats [--interface interface] [--interval interval] |
| | 44 | * (default interface is ath0 and default interval is 1 second). |
| | 45 | * If interval is specified a rolling output is displayed every interval msec. |
| | 46 | */ |
| | 47 | |
| | 48 | /* Modified by Kishore Ramachandran - kishore@winlab.rutgers.edu. |
| | 49 | Oct 14 2005 |
| | 50 | */ |
| | 51 | |
| | 52 | #include <sys/types.h> |
| | 53 | #include <sys/file.h> |
| | 54 | #include <sys/ioctl.h> |
| | 55 | #include <sys/socket.h> |
| | 56 | #include <linux/wireless.h> |
| | 57 | |
| | 58 | #include <stdio.h> |
| | 59 | #include <signal.h> |
| | 60 | #include <string.h> |
| | 61 | #include <stdlib.h> |
| | 62 | #include <err.h> |
| | 63 | #include <unistd.h> |
| | 64 | #include <sys/time.h> // For setitimer |
| | 65 | |
| | 66 | #include "ah_desc.h" |
| | 67 | #include "ieee80211_radiotap.h" |
| | 68 | #include "if_athioctl.h" |
| | 69 | #include "include/oml_orbit_winlab_athstats.h" // For OML |
| | 70 | |
| | 71 | static int signalled; |
| | 72 | |
| | 73 | static void |
| | 74 | catchalarm(int signo) |
| | 75 | { |
| | 76 | signalled = 1; |
| | 77 | } |
| | 78 | |
| | 79 | int |
| | 80 | main(int argc, char *argv[]) |
| | 81 | { |
| | 82 | struct ifreq ifr; |
| | 83 | struct itimerval it_val; |
| | 84 | struct ath_stats cur, total; |
| | 85 | u_long interval, off, icur, ocur, itot, otot; |
| | 86 | int s, line, omask; |
| | 87 | sigset_t oset1, oset2, *oset1_p, *oset2_p; |
| | 88 | |
| | 89 | if (argc < 5) { |
| | 90 | fprintf(stderr, "Usage: ./athfstats --interface name_of_interface --interval how often to query the driver in ms.\n"); |
| | 91 | fprintf(stderr, "E.g. : ./athfstats --interface ath0 --interval 100\n"); |
| | 92 | exit(-1); |
| | 93 | } |
| | 94 | |
| | 95 | if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) |
| | 96 | err(1, "socket"); |
| | 97 | |
| | 98 | if (strcmp(argv[1], "--interface") == 0) { |
| | 99 | if (!(strcmp(argv[2], "ath0")) || !(strcmp(argv[2], "ath1"))) |
| | 100 | strncpy(ifr.ifr_name, argv[2], sizeof (ifr.ifr_name)); |
| | 101 | else { |
| | 102 | fprintf(stderr, "Expecting madwifi to name interfaces as ath0 or ath1. Using ath0 as default.\n"); |
| | 103 | strncpy(ifr.ifr_name, "ath0", sizeof (ifr.ifr_name)); |
| | 104 | } |
| | 105 | } else { |
| | 106 | fprintf(stderr, "Usage: ./athstats-oml --interface name_of_interface --interval interval_in_ms\n"); |
| | 107 | exit(-1); |
| | 108 | } |
| | 109 | |
| | 110 | if (strcmp(argv[3], "--interval") == 0) { |
| | 111 | if ((interval = strtoul(argv[4], NULL, 0)) < 1) { |
| | 112 | fprintf(stderr, "Expecting interval value greater than or equal to 1. Using 100ms as default.\n"); |
| | 113 | interval = 100; |
| | 114 | } |
| | 115 | } else { |
| | 116 | fprintf(stderr, "Usage: ./athstats-oml --interface name_of_interface --interval interval_in_ms\n"); |
| | 117 | exit(-1); |
| | 118 | } |
| | 119 | |
| | 120 | signal(SIGALRM, catchalarm); |
| | 121 | signalled = 0; |
| | 122 | it_val.it_value.tv_sec = interval/1000; |
| | 123 | it_val.it_value.tv_usec = (interval*1000) % 1000000; |
| | 124 | it_val.it_interval = it_val.it_value; |
| | 125 | if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) { |
| | 126 | perror("error calling setitimer()"); |
| | 127 | exit(-1); |
| | 128 | } |
| | 129 | |
| | 130 | initialize_oml(&argc, (const char **)argv, NULL); |
| | 131 | |
| | 132 | line = 0; |
| | 133 | |
| | 134 | // loop: |
| | 135 | while (1) { |
| | 136 | if (line != 0) { |
| | 137 | ifr.ifr_data = (caddr_t) &cur; |
| | 138 | if (ioctl(s, SIOCGATHSTATS, &ifr) < 0) |
| | 139 | err(1, ifr.ifr_name); |
| | 140 | |
| | 141 | oml_queryport(cur.ast_tx_packets - total.ast_tx_packets, |
| | 142 | cur.ast_tx_xretries - total.ast_tx_xretries, |
| | 143 | cur.ast_tx_fifoerr - total.ast_tx_fifoerr, |
| | 144 | cur.ast_tx_filtered - total.ast_tx_filtered, |
| | 145 | cur.ast_tx_shortretry - total.ast_tx_shortretry, |
| | 146 | cur.ast_tx_longretry - total.ast_tx_longretry, |
| | 147 | cur.ast_rx_packets - total.ast_rx_packets, |
| | 148 | cur.ast_rx_crcerr - total.ast_rx_crcerr, |
| | 149 | cur.ast_rx_fifoerr - total.ast_rx_fifoerr, |
| | 150 | cur.ast_rx_phyerr - total.ast_rx_phyerr |
| | 151 | ); |
| | 152 | |
| | 153 | total = cur; |
| | 154 | itot = icur; |
| | 155 | otot = ocur; |
| | 156 | } else { |
| | 157 | ifr.ifr_data = (caddr_t) &total; |
| | 158 | if (ioctl(s, SIOCGATHSTATS, &ifr) < 0) |
| | 159 | err(1, ifr.ifr_name); |
| | 160 | |
| | 161 | oml_queryport(total.ast_tx_packets, |
| | 162 | total.ast_tx_xretries, |
| | 163 | total.ast_tx_fifoerr, |
| | 164 | total.ast_tx_filtered, |
| | 165 | total.ast_tx_shortretry, |
| | 166 | total.ast_tx_longretry, |
| | 167 | total.ast_rx_packets, |
| | 168 | total.ast_rx_crcerr, |
| | 169 | total.ast_rx_fifoerr, |
| | 170 | total.ast_rx_phyerr |
| | 171 | ); |
| | 172 | } |
| | 173 | |
| | 174 | oset1_p = &oset1; |
| | 175 | oset2_p = &oset2; |
| | 176 | sigemptyset(oset1_p); |
| | 177 | sigemptyset(oset2_p); |
| | 178 | sigaddset(oset1_p, SIGALRM); |
| | 179 | sigprocmask(SIG_BLOCK, oset1_p, oset2_p); |
| | 180 | if (!signalled) |
| | 181 | sigsuspend(oset2_p); |
| | 182 | sigprocmask(SIG_SETMASK, oset2_p, NULL); |
| | 183 | signalled = 0; |
| | 184 | it_val.it_value.tv_sec = interval/1000; |
| | 185 | it_val.it_value.tv_usec = (interval*1000) % 1000000; |
| | 186 | it_val.it_interval = it_val.it_value; |
| | 187 | if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) { |
| | 188 | perror("error calling setitimer()"); |
| | 189 | exit(-1); |
| | 190 | } |
| | 191 | line++; |
| | 192 | } |
| | 193 | // goto loop; |
| | 194 | |
| | 195 | /*NOTREACHED*/ |
| | 196 | return 0; |
| | 197 | } |
| | 198 | |
| | 199 | |
| | 200 | }}} |