PERFORCE change 65931 for review

Sam Leffler sam at FreeBSD.org
Sat Nov 27 11:35:53 PST 2004


http://perforce.freebsd.org/chv.cgi?CH=65931

Change 65931 by sam at sam_ebb on 2004/11/27 19:35:45

	crude per-station stats reporting

Affected files ...

.. //depot/projects/wifi/tools/tools/ath/80211stats.c#4 edit

Differences ...

==== //depot/projects/wifi/tools/tools/ath/80211stats.c#4 (text+ko) ====

@@ -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"
 
@@ -144,30 +147,142 @@
 #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 && strcmp(argv[1], "-i") == 0) {
-		if (argc < 2) {
-			fprintf(stderr, "%s: missing interface name for -i\n",
-				argv[0]);
-			exit(-1);
+	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*/
 		}
-		strncpy(ifr.ifr_name, argv[2], sizeof (ifr.ifr_name));
-		argc -= 2, argv += 2;
-	} else
-		strncpy(ifr.ifr_name, "ath0", sizeof (ifr.ifr_name));
+
+	if (argc == optind && !allnodes) {
+		struct ieee80211_stats stats;
 
-	ifr.ifr_data = (caddr_t) &stats;
-	if (ioctl(s, SIOCG80211STATS, &ifr) < 0)
-		err(1, ifr.ifr_name);
-	printstats(stdout, &stats);
-	return 0;
+		/* 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);
+		}
+	}
 }


More information about the p4-projects mailing list