svn commit: r192661 - in head/tools/tools: . npe npe/npestats

Sam Leffler sam at FreeBSD.org
Sat May 23 19:16:35 UTC 2009


Author: sam
Date: Sat May 23 19:16:34 2009
New Revision: 192661
URL: http://svn.freebsd.org/changeset/base/192661

Log:
  add npe tools; first is npestats which reports device statistics

Added:
  head/tools/tools/npe/
  head/tools/tools/npe/Makefile   (contents, props changed)
  head/tools/tools/npe/npestats/
  head/tools/tools/npe/npestats/Makefile   (contents, props changed)
  head/tools/tools/npe/npestats/main.c   (contents, props changed)
  head/tools/tools/npe/npestats/npestats.c   (contents, props changed)
  head/tools/tools/npe/npestats/npestats.h   (contents, props changed)
  head/tools/tools/npe/npestats/statfoo.c   (contents, props changed)
  head/tools/tools/npe/npestats/statfoo.h   (contents, props changed)
Modified:
  head/tools/tools/README

Modified: head/tools/tools/README
==============================================================================
--- head/tools/tools/README	Sat May 23 19:14:20 2009	(r192660)
+++ head/tools/tools/README	Sat May 23 19:16:34 2009	(r192661)
@@ -47,6 +47,7 @@ mfc		Merge a directory from HEAD to a br
 		already exist and other MFC related script(s).
 mid	 	Create a Message-ID database for mailing lists.
 ncpus		Count the number of processors
+npe		Tools specific to the Intel IXP4XXX NPE device
 nxge		A diagnostic tool for the nxge(4) driver
 pciid		Generate src/share/misc/pci_vendors.
 pciroms		A tool for dumping PCI ROM images. WARNING: alpha quality.

Added: head/tools/tools/npe/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/npe/Makefile	Sat May 23 19:16:34 2009	(r192661)
@@ -0,0 +1,5 @@
+#	$FreeBSD$
+
+SUBDIR=	npestats
+
+.include <bsd.subdir.mk>

Added: head/tools/tools/npe/npestats/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/npe/npestats/Makefile	Sat May 23 19:16:34 2009	(r192661)
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+PROG=	npestats
+SRCS=	main.c statfoo.c npestats.c
+BINDIR=	/usr/local/bin
+NO_MAN=	true
+
+.include <bsd.prog.mk>

Added: head/tools/tools/npe/npestats/main.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/npe/npestats/main.c	Sat May 23 19:16:34 2009	(r192661)
@@ -0,0 +1,143 @@
+/*-
+ * Copyright (c) 2009 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$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <strings.h>
+#include <unistd.h>
+#include <err.h>
+
+#include "npestats.h"
+
+static struct {
+	const char *tag;
+	const char *fmt;
+} tags[] = {
+  { "default",
+    "align,fcs,macrx,overrun,learn,large,stp,badsrc,underflow,collision1,collisionM,deferred,late,excessive,mactx,carrier,toobig"
+  },
+};
+
+static const char *
+getfmt(const char *tag)
+{
+#define	N(a)	(sizeof(a)/sizeof(a[0]))
+	int i;
+	for (i = 0; i < N(tags); i++)
+		if (strcasecmp(tags[i].tag, tag) == 0)
+			return tags[i].fmt;
+	return tag;
+#undef N
+}
+
+static int signalled;
+
+static void
+catchalarm(int signo __unused)
+{
+	signalled = 1;
+}
+
+int
+main(int argc, char *argv[])
+{
+	struct npestatfoo *wf;
+	const char *ifname;
+	int c, banner = 1;
+
+	ifname = getenv("NPE");
+	if (ifname == NULL)
+		ifname = "npe0";
+	wf = npestats_new(ifname, getfmt("default"));
+	while ((c = getopt(argc, argv, "bi:lo:z")) != -1) {
+		switch (c) {
+		case 'b':
+			banner = 0;
+			break;
+		case 'i':
+			wf->setifname(wf, optarg);
+			break;
+		case 'l':
+			wf->print_fields(wf, stdout);
+			return 0;
+		case 'o':
+			wf->setfmt(wf, getfmt(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:
+		if (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;
+}

Added: head/tools/tools/npe/npestats/npestats.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/npe/npestats/npestats.c	Sat May 23 19:16:34 2009	(r192661)
@@ -0,0 +1,278 @@
+/*-
+ * Copyright (c) 2009 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$
+ */
+
+/*
+ * npe statistics class.
+ */
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+
+#include "npestats.h"
+
+#define	AFTER(prev)	((prev)+1)
+
+static const struct fmt npestats[] = {
+#define	S_ALIGN		0
+	{ 7,	"align",	"align",	"alignment errors" },
+#define	S_FCS		AFTER(S_ALIGN)
+	{ 7,	"fcs",		"fcs",		"FCS errors" },
+#define	S_MACRX		AFTER(S_FCS)
+	{ 7,	"macrx",	"macrx",	"internal MAC rx errors" },
+#define	S_RXORN		AFTER(S_MACRX)
+	{ 6,	"overrun",	"overrun",	"rx overrun discards" },
+#define	S_LEARN		AFTER(S_RXORN)
+	{ 5,	"learn",	"learn",	"rx learned entry discards" },
+#define	S_LARGE		AFTER(S_LEARN)
+	{ 5,	"large",	"large",	"rx large frame discards" },
+#define	S_STP		AFTER(S_LARGE)
+	{ 5,	"stp",		"stp",		"rx STP blocked discards" },
+#define	S_RX_VLAN_TYPE	AFTER(S_STP)
+	{ 5,	"rx_vlan_type",	"rx_vlant",	"rx VLAN type filter discards" },
+#define	S_RX_VLAN_ID	AFTER(S_RX_VLAN_TYPE)
+	{ 5,	"rx_vlan_id",	"rx_vlani",	"rx VLAN Id filter discards" },
+#define	S_BADSRC	AFTER(S_RX_VLAN_ID)
+	{ 5,	"badsrc",	"badsrc",	"rx invalid source discards" },
+#define	S_BLACKLIST	AFTER(S_BADSRC)
+	{ 5,	"blacklist",	"blacklist",	"rx black list discards" },
+#define	S_WHITELIST	AFTER(S_BLACKLIST)
+	{ 5,	"whitelist",	"whitelist",	"rx white list discards" },
+#define	S_UNDERFLOW	AFTER(S_WHITELIST)
+	{ 5,	"underflow",	"underflow",	"rx underflow entry discards" },
+#define	S_COLL_SINGLE	AFTER(S_UNDERFLOW)
+	{ 5,	"collision1",	"collision1",	"single collision frames" },
+#define	S_COLL_MULTI	AFTER(S_COLL_SINGLE)
+	{ 5,	"collisionM",	"collisionM",	"multiple collision frames" },
+#define	S_DEFERRED	AFTER(S_COLL_MULTI)
+	{ 5,	"deferred",	"deferred",	"deferred transmissions" },
+#define	S_LATE		AFTER(S_DEFERRED)
+	{ 5,	"late",		"late",		"late collisions" },
+#define	S_EXCESSIVE	AFTER(S_LATE)
+	{ 5,	"excessive",	"excessive",	"excessive collisions" },
+#define	S_MACTX		AFTER(S_EXCESSIVE)
+	{ 7,	"mactx",	"mactx",	"internal MAC tx errors" },
+#define	S_CARRIER	AFTER(S_MACTX)
+	{ 7,	"carrier",	"carrier",	"carrier sense errors" },
+#define	S_TOOBIG	AFTER(S_CARRIER)
+	{ 7,	"toobig",	"toobig",	"tx large frame discards" },
+#define	S_TX_VLAN_ID	AFTER(S_TOOBIG)
+	{ 7,	"tx_vlan_id",	"tx_vlani",	"tx VLAN Id filter discards" },
+};
+#define	S_LAST		S_TX_VLAN_ID
+
+/*
+ * Stat block returned by NPE with NPE_GETSTATS msg.
+ */
+struct npestats {
+	uint32_t dot3StatsAlignmentErrors;
+	uint32_t dot3StatsFCSErrors;
+	uint32_t dot3StatsInternalMacReceiveErrors;
+	uint32_t RxOverrunDiscards;
+	uint32_t RxLearnedEntryDiscards;
+	uint32_t RxLargeFramesDiscards;
+	uint32_t RxSTPBlockedDiscards;
+	uint32_t RxVLANTypeFilterDiscards;
+	uint32_t RxVLANIdFilterDiscards;
+	uint32_t RxInvalidSourceDiscards;
+	uint32_t RxBlackListDiscards;
+	uint32_t RxWhiteListDiscards;
+	uint32_t RxUnderflowEntryDiscards;
+	uint32_t dot3StatsSingleCollisionFrames;
+	uint32_t dot3StatsMultipleCollisionFrames;
+	uint32_t dot3StatsDeferredTransmissions;
+	uint32_t dot3StatsLateCollisions;
+	uint32_t dot3StatsExcessiveCollisions;
+	uint32_t dot3StatsInternalMacTransmitErrors;
+	uint32_t dot3StatsCarrierSenseErrors;
+	uint32_t TxLargeFrameDiscards;
+	uint32_t TxVLANIdFilterDiscards;
+};
+
+struct npestatfoo_p {
+	struct npestatfoo base;
+	char oid[80];
+	int mib[4];
+	struct npestats cur;
+	struct npestats total;
+};
+
+static void
+npe_setifname(struct npestatfoo *wf0, const char *ifname)
+{
+	struct npestatfoo_p *wf = (struct npestatfoo_p *) wf0;
+	size_t len;
+
+	snprintf(wf->oid, sizeof(wf->oid), "dev.npe.%s.stats", ifname+3);
+	len = 4;
+	if (sysctlnametomib(wf->oid, wf->mib, &len) < 0)
+		err(1, "sysctlnametomib: %s", wf->oid);
+}
+
+static void
+npe_collect(struct npestatfoo_p *wf, struct npestats *stats)
+{
+	size_t len = sizeof(struct npestats);
+	if (sysctl(wf->mib, 4, stats, &len, NULL, 0) < 0)
+		err(1, "sysctl: %s", wf->oid);
+}
+
+static void
+npe_collect_cur(struct statfoo *sf)
+{
+	struct npestatfoo_p *wf = (struct npestatfoo_p *) sf;
+
+	npe_collect(wf, &wf->cur);
+}
+
+static void
+npe_collect_tot(struct statfoo *sf)
+{
+	struct npestatfoo_p *wf = (struct npestatfoo_p *) sf;
+
+	npe_collect(wf, &wf->total);
+}
+
+static void
+npe_update_tot(struct statfoo *sf)
+{
+	struct npestatfoo_p *wf = (struct npestatfoo_p *) sf;
+
+	wf->total = wf->cur;
+}
+
+static int
+npe_get_curstat(struct statfoo *sf, int s, char b[], size_t bs)
+{
+	struct npestatfoo_p *wf = (struct npestatfoo_p *) sf;
+#define	STAT(x) \
+	snprintf(b, bs, "%u", wf->cur.x - wf->total.x); return 1
+
+	switch (s) {
+	case S_ALIGN:		STAT(dot3StatsAlignmentErrors);
+	case S_FCS:		STAT(dot3StatsFCSErrors);
+	case S_MACRX:		STAT(dot3StatsInternalMacReceiveErrors);
+	case S_RXORN:		STAT(RxOverrunDiscards);
+	case S_LEARN:		STAT(RxLearnedEntryDiscards);
+	case S_LARGE:		STAT(RxLargeFramesDiscards);
+	case S_STP:		STAT(RxSTPBlockedDiscards);
+	case S_RX_VLAN_TYPE:	STAT(RxVLANTypeFilterDiscards);
+	case S_RX_VLAN_ID:	STAT(RxVLANIdFilterDiscards);
+	case S_BADSRC:		STAT(RxInvalidSourceDiscards);
+	case S_BLACKLIST:	STAT(RxBlackListDiscards);
+	case S_WHITELIST:	STAT(RxWhiteListDiscards);
+	case S_UNDERFLOW:	STAT(RxUnderflowEntryDiscards);
+	case S_COLL_SINGLE:	STAT(dot3StatsSingleCollisionFrames);
+	case S_COLL_MULTI:	STAT(dot3StatsMultipleCollisionFrames);
+	case S_DEFERRED:	STAT(dot3StatsDeferredTransmissions);
+	case S_LATE:		STAT(dot3StatsLateCollisions);
+	case S_EXCESSIVE:	STAT(dot3StatsExcessiveCollisions);
+	case S_MACTX:		STAT(dot3StatsInternalMacTransmitErrors);
+	case S_CARRIER:		STAT(dot3StatsCarrierSenseErrors);
+	case S_TOOBIG:		STAT(TxLargeFrameDiscards);
+	case S_TX_VLAN_ID:	STAT(TxVLANIdFilterDiscards);
+	}
+	b[0] = '\0';
+	return 0;
+#undef STAT
+}
+
+static int
+npe_get_totstat(struct statfoo *sf, int s, char b[], size_t bs)
+{
+	struct npestatfoo_p *wf = (struct npestatfoo_p *) sf;
+#define	STAT(x) \
+	snprintf(b, bs, "%u", wf->total.x); return 1
+
+	switch (s) {
+	case S_ALIGN:		STAT(dot3StatsAlignmentErrors);
+	case S_FCS:		STAT(dot3StatsFCSErrors);
+	case S_MACRX:		STAT(dot3StatsInternalMacReceiveErrors);
+	case S_RXORN:		STAT(RxOverrunDiscards);
+	case S_LEARN:		STAT(RxLearnedEntryDiscards);
+	case S_LARGE:		STAT(RxLargeFramesDiscards);
+	case S_STP:		STAT(RxSTPBlockedDiscards);
+	case S_RX_VLAN_TYPE:	STAT(RxVLANTypeFilterDiscards);
+	case S_RX_VLAN_ID:	STAT(RxVLANIdFilterDiscards);
+	case S_BADSRC:		STAT(RxInvalidSourceDiscards);
+	case S_BLACKLIST:	STAT(RxBlackListDiscards);
+	case S_WHITELIST:	STAT(RxWhiteListDiscards);
+	case S_UNDERFLOW:	STAT(RxUnderflowEntryDiscards);
+	case S_COLL_SINGLE:	STAT(dot3StatsSingleCollisionFrames);
+	case S_COLL_MULTI:	STAT(dot3StatsMultipleCollisionFrames);
+	case S_DEFERRED:	STAT(dot3StatsDeferredTransmissions);
+	case S_LATE:		STAT(dot3StatsLateCollisions);
+	case S_EXCESSIVE:	STAT(dot3StatsExcessiveCollisions);
+	case S_MACTX:		STAT(dot3StatsInternalMacTransmitErrors);
+	case S_CARRIER:		STAT(dot3StatsCarrierSenseErrors);
+	case S_TOOBIG:		STAT(TxLargeFrameDiscards);
+	case S_TX_VLAN_ID:	STAT(TxVLANIdFilterDiscards);
+	}
+	b[0] = '\0';
+	return 0;
+#undef STAT
+}
+
+STATFOO_DEFINE_BOUNCE(npestatfoo)
+
+struct npestatfoo *
+npestats_new(const char *ifname, const char *fmtstring)
+{
+#define	N(a)	(sizeof(a) / sizeof(a[0]))
+	struct npestatfoo_p *wf;
+
+	wf = calloc(1, sizeof(struct npestatfoo_p));
+	if (wf != NULL) {
+		statfoo_init(&wf->base.base, "npestats", npestats, N(npestats));
+		/* override base methods */
+		wf->base.base.collect_cur = npe_collect_cur;
+		wf->base.base.collect_tot = npe_collect_tot;
+		wf->base.base.get_curstat = npe_get_curstat;
+		wf->base.base.get_totstat = npe_get_totstat;
+		wf->base.base.update_tot = npe_update_tot;
+
+		/* setup bounce functions for public methods */
+		STATFOO_BOUNCE(wf, npestatfoo);
+
+		/* setup our public methods */
+		wf->base.setifname = npe_setifname;
+
+		npe_setifname(&wf->base, ifname);
+		wf->base.setfmt(&wf->base, fmtstring);
+	}
+	return &wf->base;
+#undef N
+}

Added: head/tools/tools/npe/npestats/npestats.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/npe/npestats/npestats.h	Sat May 23 19:16:34 2009	(r192661)
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2009 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 _NPESTATS_H_
+#define	_NPESTATS_H_
+
+#include "statfoo.h"
+
+/*
+ * npe statistics class.
+ */
+struct npestatfoo {
+	struct statfoo base;
+
+	STATFOO_DECL_METHODS(struct npestatfoo *);
+
+	/* set the network interface name for collection */
+	void (*setifname)(struct npestatfoo *, const char *ifname);
+};
+
+struct npestatfoo *npestats_new(const char *ifname, const char *fmtstring);
+#endif /* _NPESTATS_H_ */

Added: head/tools/tools/npe/npestats/statfoo.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/npe/npestats/statfoo.c	Sat May 23 19:16:34 2009	(r192661)
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 2002-2007 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$
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#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)
+{
+	const struct fmt *f;
+	char s[32];
+	int i, width;
+
+	width = 0;
+	for (i = 0; i < sf->nstats; i++) {
+		f = &sf->stats[i];
+		if (f->width > width)
+			width = f->width;
+	}
+	for (i = 0; i < sf->nstats; i++) {
+		f = &sf->stats[i];
+		if (sf->get_totstat(sf, i, s, sizeof(s)) && strcmp(s, "0"))
+			fprintf(fd, "%-*s %s\n", width, s, f->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;
+}

Added: head/tools/tools/npe/npestats/statfoo.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/tools/npe/npestats/statfoo.h	Sat May 23 19:16:34 2009	(r192661)
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2002-2007 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_ */


More information about the svn-src-head mailing list