diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2004-11-16 09:52:34 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2004-11-16 09:52:34 +0000 |
commit | dc7846e62c6ac62ebf9919e61a103acda804bf2e (patch) | |
tree | 5527cb1e22172b934c443618bffddecd101c2fa9 /usr.bin/systat | |
parent | 6fd089cc630259f0e715a2173767d25fd646d117 (diff) |
print network interface stats with 'systat ifstat'; ok deraadt, mickey
Diffstat (limited to 'usr.bin/systat')
-rw-r--r-- | usr.bin/systat/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/systat/cmdtab.c | 7 | ||||
-rw-r--r-- | usr.bin/systat/extern.h | 9 | ||||
-rw-r--r-- | usr.bin/systat/if.c | 251 | ||||
-rw-r--r-- | usr.bin/systat/systat.1 | 40 |
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 |