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$ 30 */ 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <signal.h> 35 #include <unistd.h> 36 #include <string.h> 37 #include <err.h> 38 #include <net/if.h> 39 #include <sys/endian.h> 40 41 #include "net80211/ieee80211_ioctl.h" 42 #include "net80211/ieee80211_radiotap.h" 43 44 #include "if_iwn_ioctl.h" 45 #include "if_iwnreg.h" 46 #include "iwnstats.h" 47 #include "iwn_ioctl.h" 48 49 #define IWN_DEFAULT_IF "iwn0" 50 51 struct iwnstats * 52 iwnstats_new(const char *ifname) 53 { 54 struct iwnstats *is; 55 56 is = calloc(1, sizeof(struct iwnstats)); 57 if (is == NULL) 58 return (NULL); 59 60 is->s = socket(AF_INET, SOCK_DGRAM, 0); 61 if (is->s < 0) 62 err(1, "socket"); 63 64 iwn_setifname(is, ifname); 65 return (is); 66 } 67 68 static void 69 iwn_stats_phy_print(struct iwnstats *is, struct iwn_rx_phy_stats *rxphy, 70 const char *prefix) 71 { 72 73 printf("%s: %s: ina=%d, fina=%d, bad_plcp=%d, bad_crc32=%d, overrun=%d, eoverrun=%d\n", 74 __func__, 75 prefix, 76 le32toh(rxphy->ina), 77 le32toh(rxphy->fina), 78 le32toh(rxphy->bad_plcp), 79 le32toh(rxphy->bad_crc32), 80 le32toh(rxphy->overrun), 81 le32toh(rxphy->eoverrun)); 82 83 printf("%s: %s: fa=%d, bad_fina_sync=%d, sfd_timeout=%d, fina_timeout=%d, no_rts_ack=%d\n", 84 __func__, 85 prefix, 86 le32toh(rxphy->fa), 87 le32toh(rxphy->bad_fina_sync), 88 le32toh(rxphy->sfd_timeout), 89 le32toh(rxphy->fina_timeout), 90 le32toh(rxphy->no_rts_ack)); 91 92 printf("%s: %s: rxe_limit=%d, ack=%d, cts=%d, ba_resp=%d, dsp_kill=%d, bad_mh=%d, rssi_sum=%d\n", 93 __func__, 94 prefix, 95 le32toh(rxphy->rxe_limit), 96 le32toh(rxphy->ack), 97 le32toh(rxphy->cts), 98 le32toh(rxphy->ba_resp), 99 le32toh(rxphy->dsp_kill), 100 le32toh(rxphy->bad_mh), 101 le32toh(rxphy->rssi_sum)); 102 } 103 104 static void 105 iwn_stats_rx_general_print(struct iwnstats *is, struct iwn_rx_general_stats *g) 106 { 107 108 printf("%s: bad_cts=%d, bad_ack=%d, not_bss=%d, filtered=%d, bad_chan=%d, beacons=%d\n", 109 __func__, 110 le32toh(g->bad_cts), 111 le32toh(g->bad_ack), 112 le32toh(g->not_bss), 113 le32toh(g->filtered), 114 le32toh(g->bad_chan), 115 le32toh(g->beacons)); 116 117 /* XXX it'd be nice to have adc/ina saturated as a % of time */ 118 printf("%s: missed_beacons=%d, adc_saturated=%d, ina_searched=%d\n", 119 __func__, 120 le32toh(g->missed_beacons), 121 le32toh(g->adc_saturated), 122 le32toh(g->ina_searched)); 123 124 printf("%s: noise=[%d, %d, %d] flags=0x%08x, load=%d, fa=%d\n", 125 __func__, 126 le32toh(g->noise[0]), 127 le32toh(g->noise[1]), 128 le32toh(g->noise[2]), 129 le32toh(g->flags), 130 le32toh(g->load), 131 le32toh(g->fa)); 132 133 printf("%s: rssi=[%d, %d, %d] energy=[%d %d %d]\n", 134 __func__, 135 le32toh(g->rssi[0]), 136 le32toh(g->rssi[1]), 137 le32toh(g->rssi[2]), 138 le32toh(g->energy[0]), 139 le32toh(g->energy[1]), 140 le32toh(g->energy[2])); 141 } 142 143 static void 144 iwn_stats_tx_print(struct iwnstats *is, struct iwn_tx_stats *tx) 145 { 146 147 printf("%s: preamble=%d, rx_detected=%d, bt_defer=%d, bt_kill=%d, short_len=%d\n", 148 __func__, 149 le32toh(tx->preamble), 150 le32toh(tx->rx_detected), 151 le32toh(tx->bt_defer), 152 le32toh(tx->bt_kill), 153 le32toh(tx->short_len)); 154 155 printf("%s: cts_timeout=%d, ack_timeout=%d, exp_ack=%d, ack=%d, msdu=%d\n", 156 __func__, 157 le32toh(tx->cts_timeout), 158 le32toh(tx->ack_timeout), 159 le32toh(tx->exp_ack), 160 le32toh(tx->ack), 161 le32toh(tx->msdu)); 162 163 printf("%s: burst_err1=%d, burst_err2=%d, cts_collision=%d, ack_collision=%d\n", 164 __func__, 165 le32toh(tx->burst_err1), 166 le32toh(tx->burst_err2), 167 le32toh(tx->cts_collision), 168 le32toh(tx->ack_collision)); 169 170 printf("%s: ba_timeout=%d, ba_resched=%d, query_ampdu=%d, query=%d, query_ampdu_frag=%d\n", 171 __func__, 172 le32toh(tx->ba_timeout), 173 le32toh(tx->ba_resched), 174 le32toh(tx->query_ampdu), 175 le32toh(tx->query), 176 le32toh(tx->query_ampdu_frag)); 177 178 printf("%s: query_mismatch=%d, not_ready=%d, underrun=%d, bt_ht_kill=%d, rx_ba_resp=%d\n", 179 __func__, 180 le32toh(tx->query_mismatch), 181 le32toh(tx->not_ready), 182 le32toh(tx->underrun), 183 le32toh(tx->bt_ht_kill), 184 le32toh(tx->rx_ba_resp)); 185 } 186 187 static void 188 iwn_stats_ht_phy_print(struct iwnstats *is, struct iwn_rx_ht_phy_stats *ht) 189 { 190 191 printf("%s: bad_plcp=%d, overrun=%d, eoverrun=%d, good_crc32=%d, bad_crc32=%d\n", 192 __func__, 193 le32toh(ht->bad_plcp), 194 le32toh(ht->overrun), 195 le32toh(ht->eoverrun), 196 le32toh(ht->good_crc32), 197 le32toh(ht->bad_crc32)); 198 199 printf("%s: bad_mh=%d, good_ampdu_crc32=%d, ampdu=%d, fragment=%d\n", 200 __func__, 201 le32toh(ht->bad_plcp), 202 le32toh(ht->good_ampdu_crc32), 203 le32toh(ht->ampdu), 204 le32toh(ht->fragment)); 205 } 206 207 208 static void 209 iwn_stats_general_print(struct iwnstats *is, struct iwn_stats *stats) 210 { 211 212 /* General */ 213 printf("%s: temp=%d, temp_m=%d, burst_check=%d, burst=%d, sleep=%d, slot_out=%d, slot_idle=%d\n", 214 __func__, 215 le32toh(stats->general.temp), 216 le32toh(stats->general.temp_m), 217 le32toh(stats->general.burst_check), 218 le32toh(stats->general.burst), 219 le32toh(stats->general.sleep), 220 le32toh(stats->general.slot_out), 221 le32toh(stats->general.slot_idle)); 222 printf("%s: slot_out=%d, ttl_tstamp=0x%08x, tx_ant_a=%d, tx_ant_b=%d, exec=%d, probe=%d\n", 223 __func__, 224 le32toh(stats->general.slot_out), 225 le32toh(stats->general.ttl_tstamp), 226 le32toh(stats->general.tx_ant_a), 227 le32toh(stats->general.tx_ant_b), 228 le32toh(stats->general.exec), 229 le32toh(stats->general.probe)); 230 printf("%s: rx_enabled=%d\n", 231 __func__, 232 le32toh(stats->general.rx_enabled)); 233 } 234 235 static void 236 iwn_print(struct iwnstats *is) 237 { 238 struct iwn_stats *s; 239 240 s = &is->st; 241 242 iwn_stats_general_print(is, s); 243 244 /* RX */ 245 iwn_stats_phy_print(is, &s->rx.ofdm, "ofdm"); 246 iwn_stats_phy_print(is, &s->rx.cck, "cck"); 247 iwn_stats_ht_phy_print(is, &s->rx.ht); 248 iwn_stats_rx_general_print(is, &s->rx.general); 249 250 /* TX */ 251 iwn_stats_tx_print(is, &s->tx); 252 printf("--\n"); 253 } 254 255 int 256 main(int argc, const char *argv[]) 257 { 258 struct iwnstats *is; 259 260 is = iwnstats_new(IWN_DEFAULT_IF); 261 262 if (is == NULL) { 263 fprintf(stderr, "%s: couldn't allocate new stats structure\n", 264 argv[0]); 265 exit(127); 266 } 267 268 /* begin fetching data */ 269 while (1) { 270 if (iwn_collect(is) != 0) { 271 fprintf(stderr, "%s: fetch failed\n", argv[0]); 272 goto next; 273 } 274 275 iwn_print(is); 276 277 next: 278 usleep(100 * 1000); 279 } 280 281 exit(0); 282 } 283