summaryrefslogtreecommitdiff
path: root/usr.bin/systat
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2004-11-16 09:52:34 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2004-11-16 09:52:34 +0000
commitdc7846e62c6ac62ebf9919e61a103acda804bf2e (patch)
tree5527cb1e22172b934c443618bffddecd101c2fa9 /usr.bin/systat
parent6fd089cc630259f0e715a2173767d25fd646d117 (diff)
print network interface stats with 'systat ifstat'; ok deraadt, mickey
Diffstat (limited to 'usr.bin/systat')
-rw-r--r--usr.bin/systat/Makefile4
-rw-r--r--usr.bin/systat/cmdtab.c7
-rw-r--r--usr.bin/systat/extern.h9
-rw-r--r--usr.bin/systat/if.c251
-rw-r--r--usr.bin/systat/systat.140
5 files changed, 290 insertions, 21 deletions
diff --git a/usr.bin/systat/Makefile b/usr.bin/systat/Makefile
index 44612b558f6..ada225f1cf4 100644
--- a/usr.bin/systat/Makefile
+++ b/usr.bin/systat/Makefile
@@ -1,11 +1,11 @@
-# $OpenBSD: Makefile,v 1.15 2004/09/29 21:59:28 deraadt Exp $
+# $OpenBSD: Makefile,v 1.16 2004/11/16 09:52:33 markus Exp $
PROG= systat
.PATH: ${.CURDIR}/../../usr.bin/vmstat
CPPFLAGS+=-I${.CURDIR}/../../usr.bin/vmstat
-SRCS= cmds.c cmdtab.c disks.c dkstats.c fetch.c iostat.c keyboard.c \
+SRCS= cmds.c cmdtab.c disks.c dkstats.c fetch.c if.c iostat.c keyboard.c \
main.c mbufs.c netcmds.c netstat.c pigs.c swap.c vmstat.c
DPADD= ${LIBCURSES} ${LIBM} ${LIBKVM}
LDADD= -lcurses -lm -lkvm
diff --git a/usr.bin/systat/cmdtab.c b/usr.bin/systat/cmdtab.c
index 22e2874f79a..0f77e0214ef 100644
--- a/usr.bin/systat/cmdtab.c
+++ b/usr.bin/systat/cmdtab.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmdtab.c,v 1.6 2003/06/03 02:56:17 millert Exp $ */
+/* $OpenBSD: cmdtab.c,v 1.7 2004/11/16 09:52:33 markus Exp $ */
/* $NetBSD: cmdtab.c,v 1.2 1995/01/20 08:51:51 jtc Exp $ */
/*-
@@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93";
#endif
-static char rcsid[] = "$OpenBSD: cmdtab.c,v 1.6 2003/06/03 02:56:17 millert Exp $";
+static char rcsid[] = "$OpenBSD: cmdtab.c,v 1.7 2004/11/16 09:52:33 markus Exp $";
#endif /* not lint */
#include <sys/types.h>
@@ -62,6 +62,9 @@ struct cmdtab cmdtab[] = {
{ "netstat", shownetstat, fetchnetstat, labelnetstat,
initnetstat, opennetstat, closenetstat, cmdnetstat,
CF_LOADAV },
+ { "ifstat", showifstat, fetchifstat, labelifstat,
+ initifstat, openifstat, closeifstat, cmdifstat,
+ CF_LOADAV },
{ 0 }
};
struct cmdtab *curcmd = &cmdtab[0];
diff --git a/usr.bin/systat/extern.h b/usr.bin/systat/extern.h
index 911807695ce..fb63eea98d3 100644
--- a/usr.bin/systat/extern.h
+++ b/usr.bin/systat/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.13 2004/04/26 19:22:30 itojun Exp $ */
+/* $OpenBSD: extern.h,v 1.14 2004/11/16 09:52:33 markus Exp $ */
/* $NetBSD: extern.h,v 1.3 1996/05/10 23:16:34 thorpej Exp $ */
/*-
@@ -61,12 +61,14 @@ struct inpcb;
int checkhost(struct inpcb *);
int checkport(struct inpcb *);
+void closeifstat(WINDOW *);
void closeiostat(WINDOW *);
void closekre(WINDOW *);
void closembufs(WINDOW *);
void closenetstat(WINDOW *);
void closepigs(WINDOW *);
void closeswap(WINDOW *);
+int cmdifstat(char *, char *);
int cmdiostat(char *, char *);
int cmdkre(char *, char *);
int cmdnetstat(char *, char *);
@@ -80,12 +82,14 @@ void display(void);
int dkinit(int);
int dkcmd(char *, char *);
void error(const char *fmt, ...);
+void fetchifstat(void);
void fetchiostat(void);
void fetchkre(void);
void fetchmbufs(void);
void fetchnetstat(void);
void fetchpigs(void);
void fetchswap(void);
+int initifstat(void);
int initiostat(void);
int initkre(void);
int initmbufs(void);
@@ -94,6 +98,7 @@ int initpigs(void);
int initswap(void);
void keyboard(void);
int kvm_ckread(void *, void *, int);
+void labelifstat(void);
void labeliostat(void);
void labelkre(void);
void labelmbufs(void);
@@ -104,6 +109,7 @@ void labelswap(void);
void load(void);
int netcmd(char *, char *);
void nlisterr(struct nlist []);
+WINDOW *openifstat(void);
WINDOW *openiostat(void);
WINDOW *openkre(void);
WINDOW *openmbufs(void);
@@ -112,6 +118,7 @@ WINDOW *openpigs(void);
WINDOW *openswap(void);
int prefix(char *, char *);
void sigwinch(int);
+void showifstat(void);
void showiostat(void);
void showkre(void);
void showmbufs(void);
diff --git a/usr.bin/systat/if.c b/usr.bin/systat/if.c
new file mode 100644
index 00000000000..0045695b85e
--- /dev/null
+++ b/usr.bin/systat/if.c
@@ -0,0 +1,251 @@
+/* $OpenBSD: if.c,v 1.1 2004/11/16 09:52:33 markus Exp $ */
+/*
+ * Copyright (c) 2004 Markus Friedl <markus@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <stdlib.h>
+
+#include "systat.h"
+#include "extern.h"
+
+static enum state { BOOT, TIME, RUN } state = TIME;
+
+struct ifcount {
+ u_long ifc_ib; /* input bytes */
+ u_long ifc_ip; /* input packets */
+ u_long ifc_ie; /* input errors */
+ u_long ifc_ob; /* output bytes */
+ u_long ifc_op; /* output packets */
+ u_long ifc_oe; /* output errors */
+ u_long ifc_co; /* collisions */
+} sum;
+
+struct ifstat {
+ char ifs_name[IFNAMSIZ]; /* interface name */
+ struct ifcount ifs_cur;
+ struct ifcount ifs_old;
+ struct ifcount ifs_now;
+} *ifstats;
+
+static int nifs = 0;
+
+WINDOW *
+openifstat(void)
+{
+
+ return (subwin(stdscr, LINES-5-1, 0, 5, 0));
+}
+
+void
+closeifstat(WINDOW *w)
+{
+
+ if (w == NULL)
+ return;
+ wclear(w);
+ wrefresh(w);
+ delwin(w);
+}
+
+int
+initifstat(void)
+{
+
+ fetchifstat();
+ return(1);
+}
+
+#define UPDATE(x, y) do { \
+ ifs->ifs_now.x = ifm->y; \
+ ifs->ifs_cur.x = ifs->ifs_now.x - ifs->ifs_old.x; \
+ sum.x += ifs->ifs_cur.x; \
+ if (state == TIME) \
+ ifs->ifs_old.x = ifs->ifs_now.x; \
+ } while(0)
+
+
+void
+rt_getaddrinfo(struct sockaddr *sa, int addrs, struct sockaddr **info)
+{
+ int i;
+
+ for (i = 0; i < RTAX_MAX; i++) {
+ if (addrs & (1 << i)) {
+ info[i] = sa;
+ sa = (struct sockaddr *) ((char *)(sa) +
+ roundup(sa->sa_len, sizeof(long)));
+ } else
+ info[i] = NULL;
+ }
+}
+
+void
+fetchifstat(void)
+{
+ struct ifstat *newstats, *ifs;
+ struct if_msghdr *ifm;
+ struct sockaddr *info[RTAX_MAX];
+ struct sockaddr_dl *sdl;
+ char *buf, *next, *lim;
+ int mib[6], i;
+ size_t need;
+
+ mib[0] = CTL_NET;
+ mib[1] = AF_ROUTE;
+ mib[2] = 0;
+ mib[3] = 0;
+ mib[4] = NET_RT_IFLIST;
+ mib[5] = 0;
+
+ if (sysctl(mib, 6, NULL, &need, NULL, 0) == -1)
+ return;
+ if ((buf = malloc(need)) == NULL)
+ return;
+ if (sysctl(mib, 6, buf, &need, NULL, 0) == -1) {
+ free(buf);
+ return;
+ }
+
+ bzero(&sum, sizeof(sum));
+
+ lim = buf + need;
+ for (next = buf; next < lim; next += ifm->ifm_msglen) {
+ ifm = (struct if_msghdr *)next;
+ if (ifm->ifm_type != RTM_IFINFO ||
+ !(ifm->ifm_addrs & RTA_IFP))
+ continue;
+ if (ifm->ifm_index >= nifs) {
+ if ((newstats = realloc(ifstats, (ifm->ifm_index + 4) *
+ sizeof(struct ifstat))) == NULL)
+ continue;
+ ifstats = newstats;
+ for (; nifs < ifm->ifm_index + 4; nifs++)
+ ifstats[nifs].ifs_name[0] = '\0';
+ }
+ ifs = &ifstats[ifm->ifm_index];
+ if (ifs->ifs_name[0] == '\0') {
+ bzero(&info, sizeof(info));
+ rt_getaddrinfo((struct sockaddr *)(ifm + 1),
+ ifm->ifm_addrs, info);
+ if ((sdl = (struct sockaddr_dl *)info[RTAX_IFP])) {
+ if (sdl->sdl_family == AF_LINK &&
+ sdl->sdl_nlen > 0)
+ strlcpy(ifs->ifs_name,
+ sdl->sdl_data,
+ sizeof(ifs->ifs_name));
+ }
+ if (ifs->ifs_name[0] == '\0')
+ continue;
+ }
+ UPDATE(ifc_ip, ifm_data.ifi_ipackets);
+ UPDATE(ifc_ib, ifm_data.ifi_ibytes);
+ UPDATE(ifc_ie, ifm_data.ifi_ierrors);
+ UPDATE(ifc_op, ifm_data.ifi_opackets);
+ UPDATE(ifc_ob, ifm_data.ifi_obytes);
+ UPDATE(ifc_oe, ifm_data.ifi_oerrors);
+ UPDATE(ifc_co, ifm_data.ifi_collisions);
+ }
+ free(buf);
+}
+
+#define INSET 0
+
+void
+labelifstat(void)
+{
+
+ wmove(wnd, 0, 0); wclrtobot(wnd);
+
+ mvwaddstr(wnd, 1, INSET, "Interfaces");
+ mvwaddstr(wnd, 1, INSET+15, "Ibytes");
+ mvwaddstr(wnd, 1, INSET+27, "Ipkts");
+ mvwaddstr(wnd, 1, INSET+34, "Ierrs");
+ mvwaddstr(wnd, 1, INSET+46, "Obytes");
+ mvwaddstr(wnd, 1, INSET+58, "Opkts");
+ mvwaddstr(wnd, 1, INSET+65, "Oerrs");
+ mvwaddstr(wnd, 1, INSET+74, "Colls");
+}
+
+#define FMT "%-10.10s %10lu %10lu %6lu %10lu %10lu %6lu %6lu "
+
+void
+showifstat(void)
+{
+ int row;
+ struct ifstat *ifs;
+
+ row = 2;
+ wmove(wnd, 0, 0); wclrtoeol(wnd);
+ for (ifs = ifstats; ifs < ifstats + nifs; ifs++) {
+ if (ifs->ifs_name[0] == '\0')
+ continue;
+ mvwprintw(wnd, row++, INSET, FMT,
+ ifs->ifs_name,
+ ifs->ifs_cur.ifc_ib,
+ ifs->ifs_cur.ifc_ip,
+ ifs->ifs_cur.ifc_ie,
+ ifs->ifs_cur.ifc_ob,
+ ifs->ifs_cur.ifc_op,
+ ifs->ifs_cur.ifc_oe,
+ ifs->ifs_cur.ifc_co);
+ }
+ mvwprintw(wnd, row++, INSET, FMT,
+ "Totals",
+ sum.ifc_ib,
+ sum.ifc_ip,
+ sum.ifc_ie,
+ sum.ifc_ob,
+ sum.ifc_op,
+ sum.ifc_oe,
+ sum.ifc_co);
+}
+
+int
+cmdifstat(char *cmd, char *args)
+{
+ struct ifstat *ifs;
+
+ if (prefix(cmd, "run")) {
+ if (state != RUN)
+ for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
+ ifs->ifs_old = ifs->ifs_now;
+ state = RUN;
+ return (1);
+ }
+ if (prefix(cmd, "boot")) {
+ state = BOOT;
+ for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
+ bzero(&ifs->ifs_old, sizeof(ifs->ifs_old));
+ return (1);
+ }
+ if (prefix(cmd, "time")) {
+ state = TIME;
+ return (1);
+ }
+ if (prefix(cmd, "zero")) {
+ if (state == RUN)
+ for (ifs = ifstats; ifs < ifstats + nifs; ifs++)
+ ifs->ifs_old = ifs->ifs_now;
+ return (1);
+ }
+ return (1);
+}
diff --git a/usr.bin/systat/systat.1 b/usr.bin/systat/systat.1
index ebe97d73a87..3358708771b 100644
--- a/usr.bin/systat/systat.1
+++ b/usr.bin/systat/systat.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: systat.1,v 1.34 2004/04/26 19:22:30 itojun Exp $
+.\" $OpenBSD: systat.1,v 1.35 2004/11/16 09:52:33 markus Exp $
.\" $NetBSD: systat.1,v 1.6 1996/05/10 23:16:39 thorpej Exp $
.\"
.\" Copyright (c) 1985, 1990, 1993
@@ -99,7 +99,8 @@ argument expects to be one of:
.Ic iostat ,
.Ic swap ,
.Ic mbufs ,
-.Ic vmstat
+.Ic vmstat ,
+.Ic ifstat
or
.Ic netstat .
These displays can also be requested interactively and are described in
@@ -372,21 +373,10 @@ period, such as from boot time (see the
.Cm boot
option below).
.Pp
-The following commands are specific to the
-.Ic vmstat
-display; the minimum unambiguous prefix may be supplied.
+.It Ic ifstat
+Display, in the lower window, interface statistics.
+See below for more options.
.Pp
-.Bl -tag -width Ds -compact
-.It Cm boot
-Display cumulative statistics since the system was booted.
-.It Cm run
-Display statistics as a running total from the point this
-command is given.
-.It Cm time
-Display statistics averaged over the refresh interval (the default).
-.It Cm zero
-Reset running statistics to zero.
-.El
.It Ic netstat
Display, in the lower window, network connections.
By default, network servers awaiting requests are not displayed.
@@ -453,6 +443,24 @@ Reset the port, host, and protocol matching mechanisms to the default
.El
.El
.Pp
+The following commands are specific to the
+.Ic vmstat
+and
+.Ic ifstat
+displays; the minimum unambiguous prefix may be supplied.
+.Pp
+.Bl -tag -width Ds -compact
+.It Cm boot
+Display cumulative statistics since the system was booted.
+.It Cm run
+Display statistics as a running total from the point this
+command is given.
+.It Cm time
+Display statistics averaged over the refresh interval (the default).
+.It Cm zero
+Reset running statistics to zero.
+.El
+.Pp
Commands to switch between displays may be abbreviated to the
minimum unambiguous prefix; for example,
.Dq io