Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 4 Jan 2003 10:19:50 -0600
From:      Trent Nelson <trent@arpa.com>
To:        freebsd-current@freebsd.org
Subject:   systat -ifstat patch
Message-ID:  <20030104161950.GA56080@arpa.com>

next in thread | raw e-mail | index | archive | help

--fdj2RfSjLxBAspz7
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline


    I've written an extension to systat that allows you to monitor the
    traffic through active network interfaces on the system, akin to
    netstat -I.  I've attached the patch to this e-mail, but it can also be
    found at http://arpa.com/~trent/systat-ifstat-current.patch[.tar.gz].

    All comments on code, style or functionality are welcome.

    Regards,

        Trent.

--fdj2RfSjLxBAspz7
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="systat-ifstat-current.patch"

Common subdirectories: /shared/data/trent/src/src/usr.bin/systat/CVS and /usr/src/usr.bin/systat/CVS
diff -uBN /shared/data/trent/src/src/usr.bin/systat/Makefile /usr/src/usr.bin/systat/Makefile
--- /shared/data/trent/src/src/usr.bin/systat/Makefile	Fri Feb  8 23:07:35 2002
+++ /usr/src/usr.bin/systat/Makefile	Sat Dec 28 16:23:57 2002
@@ -4,7 +4,7 @@
 PROG=	systat
 SRCS=	cmds.c cmdtab.c devs.c fetch.c iostat.c keyboard.c main.c \
 	mbufs.c netcmds.c netstat.c pigs.c swap.c icmp.c mode.c ip.c tcp.c \
-	vmstat.c
+	vmstat.c convtbl.c ifcmds.c ifstat.c
 DPADD=	${LIBCURSES} ${LIBM} ${LIBKVM} ${LIBDEVSTAT}
 LDADD=	-lcurses -lm -lkvm -ldevstat
 
diff -uBN /shared/data/trent/src/src/usr.bin/systat/cmds.c /usr/src/usr.bin/systat/cmds.c
--- /shared/data/trent/src/src/usr.bin/systat/cmds.c	Wed Dec 12 00:13:37 2001
+++ /usr/src/usr.bin/systat/cmds.c	Sat Jan  4 14:11:32 2003
@@ -119,6 +119,7 @@
 			goto done;
                 alarm(0);
 		(*curcmd->c_close)(wnd);
+		curcmd->c_flags &= ~CF_INIT;
 		wnd = (*p->c_open)();
 		if (wnd == 0) {
 			error("Couldn't open new display");
diff -uBN /shared/data/trent/src/src/usr.bin/systat/cmdtab.c /usr/src/usr.bin/systat/cmdtab.c
--- /shared/data/trent/src/src/usr.bin/systat/cmdtab.c	Wed Dec 12 00:13:37 2001
+++ /usr/src/usr.bin/systat/cmdtab.c	Sat Dec 28 16:30:52 2002
@@ -71,6 +71,9 @@
 	{ "tcp",	showtcp,	fetchtcp,	labeltcp,
 	  inittcp,	opentcp,	closetcp,	cmdmode,
 	  resettcp,	0 },
+	{ "ifstat",	showifstat,	fetchifstat,	labelifstat,
+	  initifstat,	openifstat,	closeifstat,	cmdifstat,
+	  0,		CF_LOADAV },
         { NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0 }
 };
 struct  cmdtab *curcmd = &cmdtab[0];
diff -uBN /shared/data/trent/src/src/usr.bin/systat/convtbl.c /usr/src/usr.bin/systat/convtbl.c
--- /shared/data/trent/src/src/usr.bin/systat/convtbl.c	Thu Jan  1 01:00:00 1970
+++ /usr/src/usr.bin/systat/convtbl.c	Sat Jan  4 00:13:11 2003
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2003, Trent Nelson, <trent@arpa.com>.
+ * 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.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include "convtbl.h"
+
+struct	convtbl convtbl[] = {
+	/* mul, scale, str */
+	{ BYTE, BYTES, "bytes" },	/* SC_BYTE	(0) */
+	{ BYTE, KILO, "KB" },		/* SC_KILOBYTE	(1) */
+	{ BYTE, MEGA, "MB" },		/* SC_MEGABYTE	(2) */
+	{ BYTE, GIGA, "GB" },		/* SC_GIGABYTE	(3) */
+
+	{ BIT, BITS, "b" },		/* SC_BITS	(4) */
+	{ BIT, KILO, "Kb" },		/* SC_KILOBITS	(5) */
+	{ BIT, MEGA, "Mb" },		/* SC_MEGABITS	(6) */
+	{ BIT, GIGA, "Gb" },		/* SC_GIGABITS	(7) */
+
+	{ 0, 0, "" }			/* SC_AUTO	(8) */
+
+};
+
+
+static __inline__
+struct convtbl *
+get_tbl_ptr(const u_long size, const u_int scale)
+{
+	struct	convtbl *tbl_ptr = NULL;
+	u_long	tmp = 0;
+	u_int	index = scale;
+
+	/* If our index is out of range, default to auto-scaling. */
+	if (index > SC_AUTO)
+		index = SC_AUTO;
+
+	if (index == SC_AUTO)
+		/*
+		 * Simple but elegant algorithm.  Count how many times
+		 * we can shift our size value right by a factor of ten,
+		 * incrementing an index each time.  We then use the
+		 * index as the array index into the conversion table.
+		 */
+		for (tmp = size, index = SC_KILOBYTE;
+		     tmp >= MEGA && index <= SC_GIGABYTE;
+		     tmp >>= 10, index++);
+
+	tbl_ptr = &convtbl[index];
+	return tbl_ptr;
+}
+
+double
+convert(const u_long size, const u_int scale)
+{
+	struct	convtbl	*tp = NULL;
+
+	tp = get_tbl_ptr(size, scale);
+
+	return ((double)size * tp->mul / tp->scale);
+
+}
+
+char *
+get_string(const u_long size, const u_int scale)
+{
+	struct	convtbl *tp = NULL;
+
+	tp = get_tbl_ptr(size, scale);
+
+	return tp->str;
+}
diff -uBN /shared/data/trent/src/src/usr.bin/systat/convtbl.h /usr/src/usr.bin/systat/convtbl.h
--- /shared/data/trent/src/src/usr.bin/systat/convtbl.h	Thu Jan  1 01:00:00 1970
+++ /usr/src/usr.bin/systat/convtbl.h	Sat Jan  4 00:13:11 2003
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2003, Trent Nelson, <trent@arpa.com>.
+ * 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.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ * $Id$
+ */
+
+#ifndef _CONVTBL_H_
+#define _CONVTBL_H_
+
+#include <sys/types.h>
+
+#define BITS	(1)
+#define BYTES	(1)
+#define KILO	(1024)
+#define	MEGA	(KILO * 1024)
+#define GIGA	(MEGA * 1024)
+
+#define SC_BYTE		(0)
+#define SC_KILOBYTE	(1)
+#define SC_MEGABYTE	(2)
+#define SC_GIGABYTE	(3)
+#define SC_BIT		(4)
+#define	SC_KILOBIT	(5)
+#define	SC_MEGABIT	(6)
+#define SC_GIGABIT	(7)
+#define SC_AUTO		(8)
+
+#define BIT	(8)
+#define BYTE	(1)
+
+struct convtbl {
+	u_int	 mul;
+	u_int	 scale;
+	char	*str;
+};
+
+extern	struct convtbl convtbl[];
+
+extern	double 	 convert(const u_long, const u_int);
+extern	char	*get_string(const u_long, const u_int);
+
+#endif		/* ! _CONVTBL_H_ */
diff -uBN /shared/data/trent/src/src/usr.bin/systat/extern.h /usr/src/usr.bin/systat/extern.h
--- /shared/data/trent/src/src/usr.bin/systat/extern.h	Fri Mar 22 01:42:31 2002
+++ /usr/src/usr.bin/systat/extern.h	Sat Dec 28 16:35:36 2002
@@ -72,8 +72,9 @@
 
 int	 checkhost(struct inpcb *);
 int	 checkport(struct inpcb *);
-void	 closeiostat(WINDOW *);
 void	 closeicmp(WINDOW *);
+void	 closeifstat(WINDOW *);
+void	 closeiostat(WINDOW *);
 void	 closeip(WINDOW *);
 void	 closekre(WINDOW *);
 void	 closembufs(WINDOW *);
@@ -81,6 +82,7 @@
 void	 closepigs(WINDOW *);
 void	 closeswap(WINDOW *);
 void	 closetcp(WINDOW *);
+int	 cmdifstat(const char *, const char *);
 int	 cmdiostat(const char *, const char *);
 int	 cmdkre(const char *, const char *);
 int	 cmdnetstat(const char *, const char *);
@@ -92,6 +94,7 @@
 int	 dkcmd(char *, char *);
 void	 error(const char *fmt, ...) __printflike(1, 2);
 void	 fetchicmp(void);
+void	 fetchifstat(void);
 void	 fetchip(void);
 void	 fetchiostat(void);
 void	 fetchkre(void);
@@ -102,6 +105,7 @@
 void	 fetchtcp(void);
 void	 getsysctl(const char *, void *, size_t);
 int	 initicmp(void);
+int	 initifstat(void);
 int	 initip(void);
 int	 initiostat(void);
 int	 initkre(void);
@@ -113,6 +117,7 @@
 int	 keyboard(void);
 int	 kvm_ckread(void *, void *, int);
 void	 labelicmp(void);
+void	 labelifstat(void);
 void	 labelip(void);
 void	 labeliostat(void);
 void	 labelkre(void);
@@ -126,6 +131,7 @@
 int	 netcmd(const char *, const char *);
 void	 nlisterr(struct nlist []);
 WINDOW	*openicmp(void);
+WINDOW	*openifstat(void);
 WINDOW	*openip(void);
 WINDOW	*openiostat(void);
 WINDOW	*openkre(void);
@@ -139,6 +145,7 @@
 void	 resetip(void);
 void	 resettcp(void);
 void	 showicmp(void);
+void	 showifstat(void);
 void	 showip(void);
 void	 showiostat(void);
 void	 showkre(void);
diff -uBN /shared/data/trent/src/src/usr.bin/systat/ifcmds.c /usr/src/usr.bin/systat/ifcmds.c
--- /shared/data/trent/src/src/usr.bin/systat/ifcmds.c	Thu Jan  1 01:00:00 1970
+++ /usr/src/usr.bin/systat/ifcmds.c	Sat Jan  4 00:13:11 2003
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2003, Trent Nelson, <trent@arpa.com>.
+ * 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.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, 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 DAMAGE.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+#include <net/if.h>
+#include <net/if_mib.h>
+#include <net/if_types.h>	/* For IFT_ETHER */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <float.h>
+#include <err.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+#include "convtbl.h"
+
+int	curscale = SC_AUTO;
+
+static	int selectscale(const char *);
+
+int
+ifcmd(const char *cmd, const char *args)
+{
+	if (prefix((char *)cmd, (char *)"scale")) {
+		if (*args != '\0' && selectscale(args) != -1)
+			;
+		else {
+			move(CMDLINE, 0);
+			clrtoeol();
+			addstr("what scale? kbit, kbyte, mbit, mbyte, " \
+			       "gbit, gbyte, auto");
+		} 
+	}
+	return 1;
+}
+
+static int
+selectscale(const char *args)
+{
+	int	retval = 0;
+
+#define streq(a,b)	(strcmp(a,b) == 0)
+	if (streq(args, "default") || streq(args, "auto"))
+		curscale = SC_AUTO;
+	else if (streq(args, "kbit"))
+		curscale = SC_KILOBIT;
+	else if (streq(args, "kbyte"))
+		curscale = SC_KILOBYTE;
+	else if (streq(args, "mbit"))
+		curscale = SC_MEGABIT;
+	else if (streq(args, "mbyte"))
+		curscale = SC_MEGABYTE;
+	else if (streq(args, "gbit"))
+		curscale = SC_GIGABIT;
+	else if (streq(args, "gbyte"))
+		curscale = SC_GIGABYTE;
+	else
+		retval = -1;
+
+	return retval;
+}
diff -uBN /shared/data/trent/src/src/usr.bin/systat/ifstat.c /usr/src/usr.bin/systat/ifstat.c
--- /shared/data/trent/src/src/usr.bin/systat/ifstat.c	Thu Jan  1 01:00:00 1970
+++ /usr/src/usr.bin/systat/ifstat.c	Sat Jan  4 15:57:12 2003
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2003, Trent Nelson, <trent@arpa.com>.
+ * 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.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTIFSTAT_ERRUPTION)
+ * 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 DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+#include <net/if.h>
+#include <net/if_mib.h>
+#include <net/if_types.h>	/* For IFT_ETHER */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <float.h>
+#include <err.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "mode.h"
+#include "convtbl.h"
+
+                                /* Column numbers */
+
+#define C1	0		/*  0-19 */
+#define C2	20		/* 20-39 */ 
+#define C3	40		/* 40-59 */
+#define C4	60		/* 60-80 */
+#define C5	80		/* Used for label positioning. */
+
+static	int col0 = 0;
+static	int col1 = C1;
+static	int col2 = C2;
+static	int col3 = C3;
+static	int col4 = C4;
+static	int col5 = C5;
+
+
+SLIST_HEAD(, if_stat)		curlist;	
+SLIST_HEAD(, if_stat_disp)	displist;
+
+struct if_stat {
+	SLIST_ENTRY(if_stat)	 link;
+	char	if_name[IF_NAMESIZE];
+	struct	ifmibdata if_mib;
+	struct	timeval tv;
+	struct	timeval tv_lastchanged;
+	u_long	if_in_curtraffic;
+	u_long	if_out_curtraffic;
+	u_long	if_in_traffic_peak;
+	u_long	if_out_traffic_peak;
+	u_int	if_row;			/* Index into ifmib sysctl */
+	u_int	if_ypos;		/* 0 if not being displayed */
+	u_int	display;
+};
+
+extern	 u_int curscale;
+
+static	 void  right_align_string(const struct if_stat *);
+static	 void  getifmibdata(const int, struct ifmibdata *);
+static	 void  sort_interface_list(void);
+static	 u_int getifnum(void);
+
+#define IFSTAT_ERR(n, s)	do {					\
+	putchar('');							\
+	closeifstat(wnd);						\
+	err((n), (s));							\
+} while (0)
+
+#define STARTING_ROW	(8)
+#define ROW_SPACING	(3)
+
+#define TOPLINE 5
+#define TOPLABEL \
+"      Interface           Traffic               Peak                Total"
+
+#define CLEAR_LINE(y, x)	do {					\
+	wmove(wnd, y, x);						\
+	wclrtoeol(wnd);							\
+} while (0)
+
+#define IN_col2		(ifp->if_in_curtraffic)
+#define OUT_col2	(ifp->if_out_curtraffic)
+#define IN_col3		(ifp->if_in_traffic_peak)
+#define OUT_col3	(ifp->if_out_traffic_peak)
+#define IN_col4		(ifp->if_mib.ifmd_data.ifi_ibytes)
+#define OUT_col4	(ifp->if_mib.ifmd_data.ifi_obytes)
+
+#define EMPTY_COLUMN 	"                    "
+#define CLEAR_COLUMN(y, x)	mvprintw((y), (x), "%20s", EMPTY_COLUMN);
+
+#define DOPUTRATE(c, r, d)	do {					\
+	CLEAR_COLUMN(r, c);						\
+	mvprintw(r, (c), "%10.3f %s%s  ",				\
+		 convert(d##_##c, curscale),				\
+		 get_string(d##_##c, curscale),				\
+		 "/s");							\
+} while (0)
+
+#define DOPUTTOTAL(c, r, d)	do {					\
+ 	CLEAR_COLUMN((r), (c));						\
+ 	mvprintw((r), (c), "%12.3f %s  ",				\
+ 		 convert(d##_##c, SC_AUTO),				\
+		 get_string(d##_##c, SC_AUTO));				\
+} while (0)
+
+#define PUTRATE(c, r)	do {						\
+	DOPUTRATE(c, (r), IN);						\
+	DOPUTRATE(c, (r)+1, OUT);					\
+} while (0)
+
+#define PUTTOTAL(c, r)	do {						\
+	DOPUTTOTAL(c, (r), IN);						\
+	DOPUTTOTAL(c, (r)+1, OUT);					\
+} while (0)
+
+#define PUTNAME(p) do {							\
+	mvprintw(p->if_ypos, 0, "%s", p->if_name);			\
+	mvprintw(p->if_ypos, col2-3, "%s", (const char *)"in");		\
+	mvprintw(p->if_ypos+1, col2-3, "%s", (const char *)"out");	\
+} while (0)
+
+
+WINDOW *
+openifstat(void)
+{
+	return (subwin(stdscr, LINES-1-5, 0, 5, 0));
+}
+
+void
+closeifstat(WINDOW *w)
+{
+	struct if_stat	*node = NULL;
+
+	while (!SLIST_EMPTY(&curlist)) {
+		node = SLIST_FIRST(&curlist);
+		SLIST_REMOVE_HEAD(&curlist, link);
+		free(node);
+	}
+
+	if (w != NULL) {
+		wclear(w);
+		wrefresh(w);
+		delwin(w);
+	}
+
+	return;
+}
+
+
+void
+labelifstat(void)
+{
+
+	wmove(wnd, TOPLINE, 0);
+	wclrtoeol(wnd);
+	mvprintw(TOPLINE, 0, "%s", TOPLABEL);
+
+	return;
+}
+
+void
+showifstat(void)
+{
+	struct	if_stat *ifp = NULL;
+	SLIST_FOREACH(ifp, &curlist, link) {
+		if (ifp->display == 0)
+			continue;
+		PUTNAME(ifp);
+		PUTRATE(col2, ifp->if_ypos);
+		PUTRATE(col3, ifp->if_ypos);
+		PUTTOTAL(col4, ifp->if_ypos);
+	}
+
+	return;
+}
+
+int 
+initifstat(void)
+{
+	struct   if_stat *p = NULL;
+	u_int	 n = 0, i = 0;
+
+	n = getifnum();
+	if (n <= 0)
+		return -1;
+
+	SLIST_INIT(&curlist);
+
+	for (i = 0; i < n; i++) {
+		p = (struct if_stat *)malloc(sizeof(struct if_stat));
+		if (p == NULL)
+			IFSTAT_ERR(1, "out of memory");
+		memset((void *)p, 0, sizeof(struct if_stat));
+		SLIST_INSERT_HEAD(&curlist, p, link);
+		p->if_row = i+1;
+		getifmibdata(p->if_row, &p->if_mib);
+		right_align_string(p);
+
+		/* 
+		 * Initially, we only display interfaces that have
+		 * received some traffic.
+		 */
+		if (p->if_mib.ifmd_data.ifi_ibytes != 0)
+			p->display = 1;
+	}
+
+	sort_interface_list();
+
+	return 1;
+}
+
+void
+fetchifstat(void)
+{
+	struct	if_stat *ifp = NULL;
+	struct	timeval tv, new_tv, old_tv;
+	double	elapsed = 0.0;
+	u_int	new_inb, new_outb, old_inb, old_outb = 0;
+	u_int	error = 0;
+	u_int	we_need_to_sort_interface_list = 0;
+
+	SLIST_FOREACH(ifp, &curlist, link) {
+		/* 
+		 * Grab a copy of the old input/output values before we
+		 * call getifmibdata().
+		 */
+		old_inb = ifp->if_mib.ifmd_data.ifi_ibytes;		
+		old_outb = ifp->if_mib.ifmd_data.ifi_obytes;
+		ifp->tv_lastchanged = ifp->if_mib.ifmd_data.ifi_lastchange;
+
+		error = gettimeofday(&new_tv, (struct timezone *)0);
+		if (error) 
+			IFSTAT_ERR(2, "error getting time of day");
+		(void)getifmibdata(ifp->if_row, &ifp->if_mib);
+
+
+                new_inb = ifp->if_mib.ifmd_data.ifi_ibytes;
+                new_outb = ifp->if_mib.ifmd_data.ifi_obytes;
+
+		/* Display interface if it's received some traffic. */
+		if (new_inb > 0 && old_inb == 0) {
+			ifp->display = 1;
+			we_need_to_sort_interface_list++;
+		} 
+
+		/*
+		 * The rest is pretty trivial.  Calculate the new values
+		 * for our current traffic rates, and while we're there,
+		 * see if we have new peak rates.
+		 */
+                old_tv = ifp->tv;
+                timersub(&new_tv, &old_tv, &tv);
+                elapsed = tv.tv_sec + (tv.tv_usec * 1e-6);
+
+		ifp->if_in_curtraffic = new_inb - old_inb;
+		ifp->if_out_curtraffic = new_outb - old_outb;
+
+		/*
+		 * Rather than divide by the time specified on the comm-
+		 * and line, we divide by ``elapsed'' as this is likely
+		 * to be more accurate.
+		 */
+                ifp->if_in_curtraffic /= elapsed;
+                ifp->if_out_curtraffic /= elapsed;
+
+		if (ifp->if_in_curtraffic > ifp->if_in_traffic_peak)
+			ifp->if_in_traffic_peak = ifp->if_in_curtraffic;
+
+		if (ifp->if_out_curtraffic > ifp->if_out_traffic_peak)
+			ifp->if_out_traffic_peak = ifp->if_out_curtraffic;
+
+		ifp->tv.tv_sec = new_tv.tv_sec;
+		ifp->tv.tv_usec = new_tv.tv_usec;
+
+	}
+
+	if (we_need_to_sort_interface_list)
+		sort_interface_list();
+
+	return;
+}
+
+/* 
+ * We want to right justify our interface names against the first column
+ * (first sixteen or so characters), so we need to do some alignment.
+ */
+static void
+right_align_string(const struct if_stat *ifp)
+{
+	int	 str_len = 0, pad_len = 0;
+	char	*newstr = NULL, *ptr = NULL;
+
+	if (ifp == NULL || ifp->if_mib.ifmd_name == NULL)
+		return;
+	else {
+		/* string length + '\0' */
+		str_len = strlen(ifp->if_mib.ifmd_name)+1;
+		pad_len = IF_NAMESIZE-(str_len);
+
+		newstr = (char *)ifp->if_name;
+		ptr = newstr + pad_len;
+		(void)memset((void *)newstr, (int)' ', IF_NAMESIZE);
+		(void)strncpy(ptr, (const char *)&ifp->if_mib.ifmd_name,
+			      str_len);
+	}
+
+	return;
+}
+
+/*
+ * This function iterates through our list of interfaces, identifying
+ * those that are to be displayed (ifp->display = 1).  For each interf-
+ * rface that we're displaying, we generate an appropriate position for
+ * it on the screen (ifp->if_ypos).
+ *
+ * This function is called any time a change is made to an interface's
+ * ``display'' state.
+ */
+void
+sort_interface_list(void)
+{
+	struct	if_stat	*ifp = NULL;
+	u_int	y = 0;	
+
+	y = STARTING_ROW;
+	SLIST_FOREACH(ifp, &curlist, link) {
+		if (ifp->display) {
+			ifp->if_ypos = y;
+			y += ROW_SPACING;
+		}
+	}
+}
+
+static
+unsigned int
+getifnum(void)
+{
+	int	error   = 0;
+	u_int	data    = 0;
+	size_t	datalen = 0;
+	static	int name[] = { CTL_NET,
+			       PF_LINK,
+			       NETLINK_GENERIC,
+			       IFMIB_SYSTEM,
+			       IFMIB_IFCOUNT };
+
+	datalen = sizeof(data);
+	error = sysctl(name, 
+		       5,
+		       (void *)&data,
+		       (size_t *)&datalen,
+		       (void *)NULL,
+		       (size_t)0);
+	if (error)
+		IFSTAT_ERR(1, "sysctl error");
+	return data;
+}
+
+static void 
+getifmibdata(int row, struct ifmibdata *data)
+{
+	int	error   = 0;
+	size_t	datalen = 0;
+	static	int name[] = { CTL_NET,
+			       PF_LINK,
+			       NETLINK_GENERIC,
+			       IFMIB_IFDATA,
+			       0,
+			       IFDATA_GENERAL };
+	datalen = sizeof(*data);
+	name[4] = row;
+
+	error = sysctl(name,
+		       6,
+		       (void *)data,
+		       (size_t *)&datalen,
+		       (void *)NULL,
+		       (size_t)0);
+	if (error)
+		IFSTAT_ERR(2, "sysctl error getting interface data");
+}
+
+int
+cmdifstat(const char *cmd, const char *args)
+{
+	int	retval = 0;
+
+	retval = ifcmd(cmd, args);
+	/* ifcmd() returns 1 on success */
+	if (retval == 1) {
+		showifstat();
+		refresh();
+	}
+
+	return retval;
+}
diff -uBN /shared/data/trent/src/src/usr.bin/systat/systat.1 /usr/src/usr.bin/systat/systat.1
--- /shared/data/trent/src/src/usr.bin/systat/systat.1	Fri Dec 27 12:15:35 2002
+++ /usr/src/usr.bin/systat/systat.1	Sat Jan  4 14:31:06 2003
@@ -30,7 +30,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	@(#)systat.1	8.2 (Berkeley) 12/30/93
-.\" $FreeBSD: src/usr.bin/systat/systat.1,v 1.36 2002/12/27 12:15:35 schweikh Exp $
+.\" $FreeBSD: src/usr.bin/systat/systat.1,v 1.23.2.9 2002/12/29 16:35:40 schweikh Exp $
 .\"
 .Dd September 9, 1997
 .Dt SYSTAT 1
@@ -88,6 +88,7 @@
 .Ar display
 to be one of:
 .Ic icmp ,
+.Ic ifstat ,
 .Ic iostat ,
 .Ic ip ,
 .Ic mbufs ,
@@ -432,6 +433,27 @@
 Reset the port, host, and protocol matching mechanisms to the default
 (any protocol, port, or host).
 .El
+.It Ic ifstat
+Display the network traffic going through active interfaces on the
+system.  Idle interfaces will not be displayed until they receive some
+traffic.
+.Pp
+For each interface being displayed, the current, peak and total 
+statistics are displayed for incoming and outgoing traffic.  By default,
+the 
+.Ic ifstat
+display will automatically scale the units being used so that they are
+in a human-readable format.  The scaling units used for the current and peak
+traffic columns can be altered by the 
+.Ic scale
+command.  
+.Pp
+.Bl -tag -width Ar -compact
+.It Cm scale Op Ar units
+Modify the scale used to display the current and peak traffic over all
+interfaces.  The following units are recognised: kbit, kbyte, mbit,
+mbyte, gbit, gbyte and auto.
+.El
 .El
 .Pp
 Commands to switch between displays may be abbreviated to the
@@ -500,8 +522,8 @@
 .Xr iostat 8 ,
 .Xr vmstat 8
 .Sh FILES
-.Bl -tag -width /boot/kernel/kernel -compact
-.It Pa /boot/kernel/kernel
+.Bl -tag -width /etc/networks -compact
+.It Pa /kernel
 For the namelist.
 .It Pa /dev/kmem
 For information in main memory.

--fdj2RfSjLxBAspz7--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030104161950.GA56080>