main.c revision 262766
1/*- 2 * Copyright (c) 2014 Adrian Chadd <adrian@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 * 29 * $FreeBSD: head/tools/tools/iwn/iwnstats/main.c 262766 2014-03-05 01:41:10Z eadler $ 30 */ 31 32#include <stdbool.h> 33#include <stdio.h> 34#include <stdlib.h> 35#include <signal.h> 36#include <unistd.h> 37#include <string.h> 38#include <err.h> 39#include <net/if.h> 40#include <sys/endian.h> 41 42#include "net80211/ieee80211_ioctl.h" 43#include "net80211/ieee80211_radiotap.h" 44 45#include "if_iwn_ioctl.h" 46#include "if_iwnreg.h" 47#include "iwnstats.h" 48#include "iwn_ioctl.h" 49 50#define IWN_DEFAULT_IF "iwn0" 51 52struct iwnstats * 53iwnstats_new(const char *ifname) 54{ 55 struct iwnstats *is; 56 57 is = calloc(1, sizeof(struct iwnstats)); 58 if (is == NULL) 59 return (NULL); 60 61 is->s = socket(AF_INET, SOCK_DGRAM, 0); 62 if (is->s < 0) 63 err(1, "socket"); 64 65 iwn_setifname(is, ifname); 66 return (is); 67} 68 69static void 70iwn_stats_phy_print(struct iwnstats *is, struct iwn_rx_phy_stats *rxphy, 71 const char *prefix) 72{ 73 74 printf("%s: %s: ina=%d, fina=%d, bad_plcp=%d, bad_crc32=%d, overrun=%d, eoverrun=%d\n", 75 __func__, 76 prefix, 77 le32toh(rxphy->ina), 78 le32toh(rxphy->fina), 79 le32toh(rxphy->bad_plcp), 80 le32toh(rxphy->bad_crc32), 81 le32toh(rxphy->overrun), 82 le32toh(rxphy->eoverrun)); 83 84 printf("%s: %s: fa=%d, bad_fina_sync=%d, sfd_timeout=%d, fina_timeout=%d, no_rts_ack=%d\n", 85 __func__, 86 prefix, 87 le32toh(rxphy->fa), 88 le32toh(rxphy->bad_fina_sync), 89 le32toh(rxphy->sfd_timeout), 90 le32toh(rxphy->fina_timeout), 91 le32toh(rxphy->no_rts_ack)); 92 93 printf("%s: %s: rxe_limit=%d, ack=%d, cts=%d, ba_resp=%d, dsp_kill=%d, bad_mh=%d, rssi_sum=%d\n", 94 __func__, 95 prefix, 96 le32toh(rxphy->rxe_limit), 97 le32toh(rxphy->ack), 98 le32toh(rxphy->cts), 99 le32toh(rxphy->ba_resp), 100 le32toh(rxphy->dsp_kill), 101 le32toh(rxphy->bad_mh), 102 le32toh(rxphy->rssi_sum)); 103} 104 105static void 106iwn_stats_rx_general_print(struct iwnstats *is, struct iwn_rx_general_stats *g) 107{ 108 109 printf("%s: bad_cts=%d, bad_ack=%d, not_bss=%d, filtered=%d, bad_chan=%d, beacons=%d\n", 110 __func__, 111 le32toh(g->bad_cts), 112 le32toh(g->bad_ack), 113 le32toh(g->not_bss), 114 le32toh(g->filtered), 115 le32toh(g->bad_chan), 116 le32toh(g->beacons)); 117 118 /* XXX it'd be nice to have adc/ina saturated as a % of time */ 119 printf("%s: missed_beacons=%d, adc_saturated=%d, ina_searched=%d\n", 120 __func__, 121 le32toh(g->missed_beacons), 122 le32toh(g->adc_saturated), 123 le32toh(g->ina_searched)); 124 125 printf("%s: noise=[%d, %d, %d] flags=0x%08x, load=%d, fa=%d\n", 126 __func__, 127 le32toh(g->noise[0]), 128 le32toh(g->noise[1]), 129 le32toh(g->noise[2]), 130 le32toh(g->flags), 131 le32toh(g->load), 132 le32toh(g->fa)); 133 134 printf("%s: rssi=[%d, %d, %d] energy=[%d %d %d]\n", 135 __func__, 136 le32toh(g->rssi[0]), 137 le32toh(g->rssi[1]), 138 le32toh(g->rssi[2]), 139 le32toh(g->energy[0]), 140 le32toh(g->energy[1]), 141 le32toh(g->energy[2])); 142} 143 144static void 145iwn_stats_tx_print(struct iwnstats *is, struct iwn_tx_stats *tx) 146{ 147 148 printf("%s: preamble=%d, rx_detected=%d, bt_defer=%d, bt_kill=%d, short_len=%d\n", 149 __func__, 150 le32toh(tx->preamble), 151 le32toh(tx->rx_detected), 152 le32toh(tx->bt_defer), 153 le32toh(tx->bt_kill), 154 le32toh(tx->short_len)); 155 156 printf("%s: cts_timeout=%d, ack_timeout=%d, exp_ack=%d, ack=%d, msdu=%d\n", 157 __func__, 158 le32toh(tx->cts_timeout), 159 le32toh(tx->ack_timeout), 160 le32toh(tx->exp_ack), 161 le32toh(tx->ack), 162 le32toh(tx->msdu)); 163 164 printf("%s: burst_err1=%d, burst_err2=%d, cts_collision=%d, ack_collision=%d\n", 165 __func__, 166 le32toh(tx->burst_err1), 167 le32toh(tx->burst_err2), 168 le32toh(tx->cts_collision), 169 le32toh(tx->ack_collision)); 170 171 printf("%s: ba_timeout=%d, ba_resched=%d, query_ampdu=%d, query=%d, query_ampdu_frag=%d\n", 172 __func__, 173 le32toh(tx->ba_timeout), 174 le32toh(tx->ba_resched), 175 le32toh(tx->query_ampdu), 176 le32toh(tx->query), 177 le32toh(tx->query_ampdu_frag)); 178 179 printf("%s: query_mismatch=%d, not_ready=%d, underrun=%d, bt_ht_kill=%d, rx_ba_resp=%d\n", 180 __func__, 181 le32toh(tx->query_mismatch), 182 le32toh(tx->not_ready), 183 le32toh(tx->underrun), 184 le32toh(tx->bt_ht_kill), 185 le32toh(tx->rx_ba_resp)); 186} 187 188static void 189iwn_stats_ht_phy_print(struct iwnstats *is, struct iwn_rx_ht_phy_stats *ht) 190{ 191 192 printf("%s: bad_plcp=%d, overrun=%d, eoverrun=%d, good_crc32=%d, bad_crc32=%d\n", 193 __func__, 194 le32toh(ht->bad_plcp), 195 le32toh(ht->overrun), 196 le32toh(ht->eoverrun), 197 le32toh(ht->good_crc32), 198 le32toh(ht->bad_crc32)); 199 200 printf("%s: bad_mh=%d, good_ampdu_crc32=%d, ampdu=%d, fragment=%d\n", 201 __func__, 202 le32toh(ht->bad_plcp), 203 le32toh(ht->good_ampdu_crc32), 204 le32toh(ht->ampdu), 205 le32toh(ht->fragment)); 206} 207 208 209static void 210iwn_stats_general_print(struct iwnstats *is, struct iwn_stats *stats) 211{ 212 213 /* General */ 214 printf("%s: temp=%d, temp_m=%d, burst_check=%d, burst=%d, sleep=%d, slot_out=%d, slot_idle=%d\n", 215 __func__, 216 le32toh(stats->general.temp), 217 le32toh(stats->general.temp_m), 218 le32toh(stats->general.burst_check), 219 le32toh(stats->general.burst), 220 le32toh(stats->general.sleep), 221 le32toh(stats->general.slot_out), 222 le32toh(stats->general.slot_idle)); 223 printf("%s: slot_out=%d, ttl_tstamp=0x%08x, tx_ant_a=%d, tx_ant_b=%d, exec=%d, probe=%d\n", 224 __func__, 225 le32toh(stats->general.slot_out), 226 le32toh(stats->general.ttl_tstamp), 227 le32toh(stats->general.tx_ant_a), 228 le32toh(stats->general.tx_ant_b), 229 le32toh(stats->general.exec), 230 le32toh(stats->general.probe)); 231 printf("%s: rx_enabled=%d\n", 232 __func__, 233 le32toh(stats->general.rx_enabled)); 234} 235 236static void 237iwn_print(struct iwnstats *is) 238{ 239 struct iwn_stats *s; 240 241 s = &is->st; 242 243 iwn_stats_general_print(is, s); 244 245 /* RX */ 246 iwn_stats_phy_print(is, &s->rx.ofdm, "ofdm"); 247 iwn_stats_phy_print(is, &s->rx.cck, "cck"); 248 iwn_stats_ht_phy_print(is, &s->rx.ht); 249 iwn_stats_rx_general_print(is, &s->rx.general); 250 251 /* TX */ 252 iwn_stats_tx_print(is, &s->tx); 253 printf("--\n"); 254} 255 256static void 257usage(void) 258{ 259 printf("Usage: iwnstats [-h] [-i ifname]\n"); 260 printf(" -h: Help\n"); 261 printf(" -i <ifname>: Use ifname (default %s)\n", 262 IWN_DEFAULT_IF); 263} 264 265int 266main(int argc, char *argv[]) 267{ 268 struct iwnstats *is; 269 int ch; 270 char *ifname; 271 bool first; 272 273 ifname = strdup(IWN_DEFAULT_IF); 274 275 /* Parse command line arguments */ 276 while ((ch = getopt(argc, argv, 277 "hi:")) != -1) { 278 switch (ch) { 279 case 'i': 280 if (ifname) 281 free(ifname); 282 ifname = strdup(optarg); 283 break; 284 default: 285 case '?': 286 case 'h': 287 usage(); 288 exit(1); 289 } 290 } 291 292 is = iwnstats_new(ifname); 293 294 if (is == NULL) { 295 fprintf(stderr, "%s: couldn't allocate new stats structure\n", 296 argv[0]); 297 exit(127); 298 } 299 300 /* begin fetching data */ 301 first = true; 302 while (1) { 303 if (iwn_collect(is) != 0) { 304 fprintf(stderr, "%s: fetch failed\n", argv[0]); 305 if (first) 306 return 1; 307 goto next; 308 } 309 310 iwn_print(is); 311 312 next: 313 usleep(100 * 1000); 314 first = false; 315 } 316 317 exit(0); 318} 319