NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: bin/51204: add
The following reply was made to PR bin/51204; it has been noted by GNATS.
From: scole_mail%gmx.com@localhost
To: gnats-bugs%NetBSD.org@localhost
Cc:
Subject: Re: bin/51204: add
Date: Tue, 31 May 2016 11:24:34 -0400
Sorry about the subject line, that was supposed to be
"add ifstat to systat command"
Here is a patch:
--- /dev/null 2016-05-31 11:09:13.000000000 -0400
+++ convtbl.c 2014-11-11 15:03:22.000000000 -0500
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2003, Trent Nelson, <trent%arpa.com@localhost>.
+ * 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.
+ *
+ * $FreeBSD: releng/10.1/usr.bin/systat/convtbl.c 175387 2008-01-16 19:27:43Z delphij $
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include "convtbl.h"
+
+#define BIT (8)
+#define BITS (1)
+#define KILOBIT (1000LL)
+#define MEGABIT (KILOBIT * 1000)
+#define GIGABIT (MEGABIT * 1000)
+#define TERABIT (GIGABIT * 1000)
+
+#define BYTE (1)
+#define BYTES (1)
+#define KILOBYTE (1024LL)
+#define MEGABYTE (KILOBYTE * 1024)
+#define GIGABYTE (MEGABYTE * 1024)
+#define TERABYTE (GIGABYTE * 1024)
+
+struct convtbl {
+ uintmax_t mul;
+ uintmax_t scale;
+ const char *str;
+ const char *name;
+};
+
+static struct convtbl convtbl[] = {
+ /* mul, scale, str, name */
+ [SC_BYTE] = { BYTE, BYTES, "B", "byte" },
+ [SC_KILOBYTE] = { BYTE, KILOBYTE, "KB", "kbyte" },
+ [SC_MEGABYTE] = { BYTE, MEGABYTE, "MB", "mbyte" },
+ [SC_GIGABYTE] = { BYTE, GIGABYTE, "GB", "gbyte" },
+ [SC_TERABYTE] = { BYTE, TERABYTE, "TB", "tbyte" },
+
+ [SC_BIT] = { BIT, BITS, "b", "bit" },
+ [SC_KILOBIT] = { BIT, KILOBIT, "Kb", "kbit" },
+ [SC_MEGABIT] = { BIT, MEGABIT, "Mb", "mbit" },
+ [SC_GIGABIT] = { BIT, GIGABIT, "Gb", "gbit" },
+ [SC_TERABIT] = { BIT, TERABIT, "Tb", "tbit" },
+
+ [SC_AUTO] = { 0, 0, "", "auto" }
+};
+
+static
+struct convtbl *
+get_tbl_ptr(const uintmax_t size, const int scale)
+{
+ uintmax_t tmp;
+ int idx;
+
+ /* If our index is out of range, default to auto-scaling. */
+ idx = scale < SC_AUTO ? scale : SC_AUTO;
+
+ if (idx == 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, idx = SC_KILOBYTE;
+ tmp >= MEGABYTE && idx < SC_BIT - 1;
+ tmp >>= 10, idx++);
+
+ return (&convtbl[idx]);
+}
+
+double
+convert(const uintmax_t size, const int scale)
+{
+ struct convtbl *tp;
+
+ tp = get_tbl_ptr(size, scale);
+ return ((double)size * tp->mul / tp->scale);
+
+}
+
+const char *
+get_string(const uintmax_t size, const int scale)
+{
+ struct convtbl *tp;
+
+ tp = get_tbl_ptr(size, scale);
+ return (tp->str);
+}
+
+int
+get_scale(const char *name)
+{
+ int i;
+
+ for (i = 0; i <= SC_AUTO; i++)
+ if (strcmp(convtbl[i].name, name) == 0)
+ return (i);
+ return (-1);
+}
+
+const char *
+get_helplist(void)
+{
+ int i;
+ size_t len;
+ static char *buf;
+
+ if (buf == NULL) {
+ len = 0;
+ for (i = 0; i <= SC_AUTO; i++)
+ len += strlen(convtbl[i].name) + 2;
+ if ((buf = malloc(len)) != NULL) {
+ buf[0] = '\0';
+ for (i = 0; i <= SC_AUTO; i++) {
+ strcat(buf, convtbl[i].name);
+ if (i < SC_AUTO)
+ strcat(buf, ", ");
+ }
+ } else
+ return ("");
+ }
+ return (buf);
+}
--- /dev/null 2016-05-31 11:09:13.000000000 -0400
+++ convtbl.h 2014-11-11 15:03:22.000000000 -0500
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003, Trent Nelson, <trent%arpa.com@localhost>.
+ * 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.
+ *
+ * $FreeBSD: releng/10.1/usr.bin/systat/convtbl.h 164675 2006-11-27 16:33:44Z yar $
+ */
+
+#ifndef _CONVTBL_H_
+#define _CONVTBL_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+
+/*
+ * Keep the order in the enum.
+ */
+enum scale {
+ SC_BYTE,
+ SC_KILOBYTE,
+ SC_MEGABYTE,
+ SC_GIGABYTE,
+ SC_TERABYTE,
+ SC_BIT,
+ SC_KILOBIT,
+ SC_MEGABIT,
+ SC_GIGABIT,
+ SC_TERABIT,
+ SC_AUTO /* KEEP THIS LAST */
+};
+
+extern double convert(const uintmax_t, const int);
+extern const char *get_helplist(void);
+extern int get_scale(const char *);
+extern const char *get_string(const uintmax_t, const int);
+
+#endif /* ! _CONVTBL_H_ */
--- /dev/null 2016-05-31 11:09:13.000000000 -0400
+++ ifcmds.c 2016-05-31 10:30:20.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2003, Trent Nelson, <trent%arpa.com@localhost>.
+ * 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.
+ *
+ * $FreeBSD: releng/10.1/usr.bin/systat/ifcmds.c 247037 2013-02-20 14:19:09Z melifaro $
+ */
+
+#include <sys/types.h>
+
+#include "systat.h"
+#include "extern.h"
+#include "convtbl.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+int curscale = SC_AUTO;
+char *matchline = NULL;
+int showpps = 0;
+int needsort = 0;
+
+int
+ifcmd(const char *cmd, const char *args)
+{
+ int scale;
+
+ if (prefix(cmd, "scale")) {
+ if ((scale = get_scale(args)) != -1)
+ curscale = scale;
+ else {
+ move(CMDLINE, 0);
+ clrtoeol();
+ addstr("what scale? ");
+ addstr(get_helplist());
+ }
+ } else if (prefix(cmd, "match")) {
+ if (args != NULL && *args != '\0' && memcmp(args, "*", 2) != 0) {
+ /* We got a valid match line */
+ if (matchline != NULL)
+ free(matchline);
+ needsort = 1;
+ matchline = strdup(args);
+ } else {
+ /* Empty or * pattern, turn filtering off */
+ if (matchline != NULL)
+ free(matchline);
+ needsort = 1;
+ matchline = NULL;
+ }
+ } else if (prefix(cmd, "pps"))
+ showpps = !showpps;
+
+ return (1);
+}
--- /dev/null 2016-05-31 11:09:13.000000000 -0400
+++ ifstat.c 2016-05-31 10:57:57.000000000 -0400
@@ -0,0 +1,539 @@
+/*
+ * Copyright (c) 2003, Trent Nelson, <trent%arpa.com@localhost>.
+ * 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.
+ *
+ * $FreeBSD: releng/10.1/usr.bin/systat/ifstat.c 247037 2013-02-20 14:19:09Z melifaro $
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <net/if.h>
+
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <errno.h>
+#include <fnmatch.h>
+
+#include "systat.h"
+#include "extern.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 const int col0 = 0;
+static const int col1 = C1;
+static const int col2 = C2;
+static const int col3 = C3;
+static const int col4 = C4;
+static const int col5 = C5;
+
+SLIST_HEAD(, if_stat) curlist;
+
+struct if_stat {
+ SLIST_ENTRY(if_stat) link;
+ char if_name[IF_NAMESIZE];
+ struct ifdatareq 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_long if_in_curpps;
+ u_long if_out_curpps;
+ u_long if_in_pps_peak;
+ u_long if_out_pps_peak;
+ u_int if_row; /* Index into ifmib sysctl */
+ u_int if_ypos; /* 0 if not being displayed */
+ u_int display;
+ u_int match;
+};
+
+extern int curscale;
+extern char *matchline;
+extern int showpps;
+extern int needsort;
+
+static int needclear = 0;
+
+static void right_align_string(struct if_stat *);
+static void getifmibdata(const int, struct ifdatareq *);
+static void sort_interface_list(void);
+static u_int getifnum(void);
+
+#define IFSTAT_ERR(n, s) do { \
+ putchar('\014'); \
+ closeifstat(wnd); \
+ err((n), (s)); \
+} while (0)
+
+#define TOPLINE 5
+#define TOPLABEL \
+" Interface Traffic Peak Total"
+
+#define STARTING_ROW (TOPLINE + 1)
+#define ROW_SPACING (3)
+
+#define IN_col2 (showpps ? ifp->if_in_curpps : ifp->if_in_curtraffic)
+#define OUT_col2 (showpps ? ifp->if_out_curpps : ifp->if_out_curtraffic)
+#define IN_col3 (showpps ? \
+ ifp->if_in_pps_peak : ifp->if_in_traffic_peak)
+#define OUT_col3 (showpps ? \
+ ifp->if_out_pps_peak : ifp->if_out_traffic_peak)
+#define IN_col4 (showpps ? \
+ ifp->if_mib.ifdr_data.ifi_ipackets : ifp->if_mib.ifdr_data.ifi_ibytes)
+#define OUT_col4 (showpps ? \
+ ifp->if_mib.ifdr_data.ifi_opackets : ifp->if_mib.ifdr_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); \
+ if (showpps) { \
+ mvprintw(r, (c), "%10.3f %cp%s ", \
+ convert(d##_##c, curscale), \
+ *get_string(d##_##c, curscale), \
+ "/s"); \
+ } \
+ else { \
+ 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)); \
+ if (showpps) { \
+ mvprintw((r), (c), "%12.3f %cp ", \
+ convert(d##_##c, SC_AUTO), \
+ *get_string(d##_##c, SC_AUTO)); \
+ } \
+ else { \
+ 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, -1, 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 || (ifp->match == 0) ||
+ ifp->if_ypos > (u_int)(LINES - 3 - 1))
+ 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 *)calloc(1, sizeof(struct if_stat));
+ if (p == NULL)
+ IFSTAT_ERR(1, "out of memory");
+ SLIST_INSERT_HEAD(&curlist, p, link);
+ p->if_row = i+1;
+ getifmibdata(p->if_row, &p->if_mib);
+ right_align_string(p);
+ p->match = 1;
+
+ /*
+ * Initially, we only display interfaces that have
+ * received some traffic.
+ */
+ if (p->if_mib.ifdr_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 new_inp, new_outp, old_inp, old_outp = 0;
+
+ SLIST_FOREACH(ifp, &curlist, link) {
+ /*
+ * Grab a copy of the old input/output values before we
+ * call getifmibdata().
+ */
+ old_inb = ifp->if_mib.ifdr_data.ifi_ibytes;
+ old_outb = ifp->if_mib.ifdr_data.ifi_obytes;
+ old_inp = ifp->if_mib.ifdr_data.ifi_ipackets;
+ old_outp = ifp->if_mib.ifdr_data.ifi_opackets;
+ TIMESPEC_TO_TIMEVAL(&ifp->tv_lastchanged, &ifp->if_mib.ifdr_data.ifi_lastchange);
+
+ (void)gettimeofday(&new_tv, NULL);
+ (void)getifmibdata(ifp->if_row, &ifp->if_mib);
+
+ new_inb = ifp->if_mib.ifdr_data.ifi_ibytes;
+ new_outb = ifp->if_mib.ifdr_data.ifi_obytes;
+ new_inp = ifp->if_mib.ifdr_data.ifi_ipackets;
+ new_outp = ifp->if_mib.ifdr_data.ifi_opackets;
+
+ /* Display interface if it's received some traffic. */
+ if (new_inb > 0 && old_inb == 0) {
+ ifp->display = 1;
+ needsort = 1;
+ }
+
+ /*
+ * 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;
+
+ ifp->if_in_curpps = new_inp - old_inp;
+ ifp->if_out_curpps = new_outp - old_outp;
+
+ /*
+ * 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;
+ ifp->if_in_curpps /= elapsed;
+ ifp->if_out_curpps /= 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;
+
+ if (ifp->if_in_curpps > ifp->if_in_pps_peak)
+ ifp->if_in_pps_peak = ifp->if_in_curpps;
+
+ if (ifp->if_out_curpps > ifp->if_out_pps_peak)
+ ifp->if_out_pps_peak = ifp->if_out_curpps;
+
+ ifp->tv.tv_sec = new_tv.tv_sec;
+ ifp->tv.tv_usec = new_tv.tv_usec;
+
+ }
+
+ if (needsort)
+ 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(struct if_stat *ifp)
+{
+ int str_len = 0, pad_len = 0;
+ char *newstr = NULL, *ptr = NULL;
+
+ if (ifp == NULL || ifp->if_mib.ifdr_name == NULL)
+ return;
+ else {
+ /* string length + '\0' */
+ str_len = strlen(ifp->if_mib.ifdr_name)+1;
+ pad_len = IF_NAMESIZE-(str_len);
+
+ newstr = ifp->if_name;
+ ptr = newstr + pad_len;
+ (void)memset((void *)newstr, (int)' ', IF_NAMESIZE);
+ (void)strncpy(ptr, (const char *)&ifp->if_mib.ifdr_name,
+ str_len);
+ }
+
+ return;
+}
+
+static int
+check_match(const char *ifname)
+{
+ char *p = matchline, *c, t;
+ int match = 0, mlen;
+
+ if (matchline == NULL)
+ return (0);
+
+ /* Strip leading whitespaces */
+ while (*p == ' ')
+ p ++;
+
+ c = p;
+ while ((mlen = strcspn(c, " ;,")) != 0) {
+ p = c + mlen;
+ t = *p;
+ if (p - c > 0) {
+ *p = '\0';
+ if (fnmatch(c, ifname, FNM_CASEFOLD) == 0) {
+ *p = t;
+ return (1);
+ }
+ *p = t;
+ c = p + strspn(p, " ;,");
+ }
+ else {
+ c = p + strspn(p, " ;,");
+ }
+ }
+
+ return (match);
+}
+
+/*
+ * 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 = STARTING_ROW;
+
+ SLIST_FOREACH(ifp, &curlist, link) {
+ if (matchline && !check_match(ifp->if_mib.ifdr_name))
+ ifp->match = 0;
+ else
+ ifp->match = 1;
+ if (ifp->display && ifp->match) {
+ ifp->if_ypos = y;
+ y += ROW_SPACING;
+ }
+ }
+
+ needsort = 0;
+ needclear = 1;
+}
+
+static
+unsigned int
+getifnum(void)
+{
+ struct ifaddrs *ifaddrs = NULL;
+ struct ifaddrs *ifa = NULL;
+ int num = 0;
+
+ if (getifaddrs(&ifaddrs) == 0) {
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_LINK)
+ num++;
+ }
+
+ freeifaddrs(ifaddrs);
+ }
+
+ return num;
+}
+
+static void
+getifmibdata(int row, struct ifdatareq *data)
+{
+ struct ifaddrs *ifaddrs = NULL;
+ struct ifaddrs *ifa = NULL;
+ int found = 0;
+ int num = 0;
+
+ if (getifaddrs(&ifaddrs) != 0) {
+ IFSTAT_ERR(2, "getifmibdata() error getting interface data");
+ return;
+ }
+
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_LINK) {
+ num++;
+
+ /*
+ * expecting rows to start with 1 not 0,
+ * see freebsd "man ifmib"
+ */
+ if (num == row) {
+ found = 1;
+ data->ifdr_data = *(struct if_data *)ifa->ifa_data;
+ strncpy(data->ifdr_name, ifa->ifa_name, IF_NAMESIZE);
+ break;
+ }
+ }
+ }
+
+ freeifaddrs(ifaddrs);
+
+ if (!found) {
+ IFSTAT_ERR(2, "getifmibdata() error finding row");
+ }
+}
+
+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();
+ if (needclear) {
+ werase(wnd);
+ labelifstat();
+ needclear = 0;
+ }
+ }
+
+ return (retval);
+}
+
+void
+ifstat_scale(char* args)
+{
+ cmdifstat("scale", args ? args : "");
+}
+
+void
+ifstat_pps(char* args)
+{
+ cmdifstat("pps", "");
+}
+
+void
+ifstat_match(char* args)
+{
+ cmdifstat("match", args ? args : "");
+
+ /*
+ * force erase after match command because it is possible for
+ * another command to be sent in the interval before the window
+ * finishes redrawing completely. That stale data remains in window
+ * and never gets overwritten because there are fewer interfaces
+ * being drawn on screen. Only an issue for match command because
+ * pps and scale don't change the number of interfaces being drawn.
+ */
+ werase(wnd);
+ labelifstat();
+}
Index: Makefile
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/Makefile,v
retrieving revision 1.38
diff -b -u -r1.38 Makefile
--- Makefile 23 Jan 2016 21:22:50 -0000 1.38
+++ Makefile 31 May 2016 15:09:13 -0000
@@ -14,7 +14,7 @@
SRCS= bufcache.c cmds.c cmdtab.c disks.c df.c drvstats.c fetch.c \
globalcmds.c icmp.c iostat.c ip.c keyboard.c main.c mbufs.c \
netcmds.c netstat.c pigs.c ps.c swap.c tcp.c vmstat.c utmpentry.c \
- syscall.c
+ ifcmds.c convtbl.c ifstat.c syscall.c
DPADD= ${LIBCURSES} ${LIBTERMINFO} ${LIBM} ${LIBKVM}
LDADD= -lutil -lcurses -lterminfo -lm -lkvm
BINGRP= kmem
Index: cmds.c
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/cmds.c,v
retrieving revision 1.28
diff -b -u -r1.28 cmds.c
--- cmds.c 4 Nov 2004 07:18:47 -0000 1.28
+++ cmds.c 31 May 2016 15:09:13 -0000
@@ -152,3 +152,15 @@
{
error("Showing %s, refresh every %d seconds.", curmode->c_name, naptime);
}
+
+int
+prefix(const char *s1, const char *s2)
+{
+
+ while (*s1 == *s2) {
+ if (*s1 == '\0')
+ return (1);
+ s1++, s2++;
+ }
+ return (*s1 == '\0');
+}
Index: cmdtab.c
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/cmdtab.c,v
retrieving revision 1.24
diff -b -u -r1.24 cmdtab.c
--- cmdtab.c 6 Jan 2012 14:08:08 -0000 1.24
+++ cmdtab.c 31 May 2016 15:09:13 -0000
@@ -69,6 +69,13 @@
{ .c_name = NULL }
};
+struct command ifstat_commands[] = {
+ { "scale", ifstat_scale, "modify scale of display"},
+ { "pps", ifstat_pps, "toggle packets per second display"},
+ { "match", ifstat_match, "display matching interfaces"},
+ { .c_name = NULL }
+};
+
struct command iostat_commands[] = {
{ "bars", iostat_bars, "show io stats as a bar graph"},
{ "numbers", iostat_numbers, "show io stats numerically"},
@@ -159,6 +166,9 @@
{ "df", showdf, fetchdf, labeldf,
initdf, opendf, closedf, df_commands,
CF_LOADAV },
+ { "ifstat", showifstat, fetchifstat, labelifstat,
+ initifstat, openifstat, closeifstat, ifstat_commands,
+ CF_LOADAV },
{ "inet.icmp", showicmp, fetchicmp, labelicmp,
initicmp, openicmp, closeicmp, icmp_commands,
CF_LOADAV },
Index: extern.h
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/extern.h,v
retrieving revision 1.44
diff -b -u -r1.44 extern.h
--- extern.h 23 Aug 2015 18:33:15 -0000 1.44
+++ extern.h 31 May 2016 15:09:13 -0000
@@ -75,6 +75,7 @@
void closebufcache(WINDOW *);
void closedf(WINDOW *);
void closeicmp(WINDOW *);
+void closeifstat(WINDOW *);
void closeiostat(WINDOW *);
void closeip(WINDOW *);
void closevmstat(WINDOW *);
@@ -84,6 +85,7 @@
void closepigs(WINDOW *);
void closeswap(WINDOW *);
void closetcp(WINDOW *);
+int cmdifstat(const char *, const char *);
void command(char *);
void df_all(char *);
void df_some(char *);
@@ -97,6 +99,7 @@
void fetchbufcache(void);
void fetchdf(void);
void fetchicmp(void);
+void fetchifstat(void);
void fetchiostat(void);
void fetchip(void);
void fetchvmstat(void);
@@ -116,9 +119,14 @@
void icmp_run(char *);
void icmp_time(char *);
void icmp_zero(char *);
+int ifcmd(const char *cmd, const char *args);
+void ifstat_match(char*);
+void ifstat_pps(char*);
+void ifstat_scale(char*);
int initbufcache(void);
int initdf(void);
int initicmp(void);
+int initifstat(void);
int initiostat(void);
int initip(void);
int initvmstat(void);
@@ -142,6 +150,7 @@
void labelbufcache(void);
void labeldf(void);
void labelicmp(void);
+void labelifstat(void);
void labeliostat(void);
void labelip(void);
void labelvmstat(void);
@@ -167,6 +176,7 @@
WINDOW *openbufcache(void);
WINDOW *opendf(void);
WINDOW *openicmp(void);
+WINDOW *openifstat(void);
WINDOW *openiostat(void);
WINDOW *openip(void);
WINDOW *openvmstat(void);
@@ -176,11 +186,13 @@
WINDOW *openpigs(void);
WINDOW *openswap(void);
WINDOW *opentcp(void);
+int prefix(const char *, const char *);
void ps_user(char *);
void redraw(void);
void showbufcache(void);
void showdf(void);
void showicmp(void);
+void showifstat(void);
void showiostat(void);
void showip(void);
void showvmstat(void);
Index: systat.1
===================================================================
RCS file: /cvsroot/src/usr.bin/systat/systat.1,v
retrieving revision 1.44
diff -b -u -r1.44 systat.1
--- systat.1 12 Mar 2016 02:39:01 -0000 1.44
+++ systat.1 31 May 2016 15:09:13 -0000
@@ -73,7 +73,7 @@
.Xr iostat 8 ) ,
virtual memory statistics (a la
.Xr vmstat 1 ) ,
-network ``mbuf'' utilization, and network connections (a la
+network ``mbuf'' utilization, network 'ifstat' traffic, and network connections (a la
.Xr netstat 1 ) .
.Pp
Input is interpreted at two different levels.
@@ -115,6 +115,7 @@
.Ic all ,
.Ic bufcache ,
.Ic df ,
+.Ic ifstat ,
.Ic inet.icmp ,
.Ic inet.ip ,
.Ic inet.tcp ,
@@ -226,6 +227,54 @@
.It Cm some
Suppress information about procfs, kernfs and null-mounts (default).
.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.
+.Bl -tag -width ".Cm scale Op Ar units"
+.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.
+.It Cm pps
+Show statistics in packets per second instead of bytes/bits per second.
+A subsequent call of
+.Ic pps
+switches this mode off.
+.It Cm match Op Ar patterns
+Display only interfaces that match pattern provided as an argument.
+Patterns should be in shell syntax separated by whitespaces or commas.
+If this command is called without arguments then all interfaces are displayed.
+For example:
+.Pp
+.Dl match re0, bge1
+.Pp
+This will display re0 and bge1 interfaces.
+.Pp
+.Dl match re*, bge*, lo0
+.Pp
+This will display all
+.Ic re
+interfaces, all
+.Ic bge
+interfaces and the loopback interface.
+.El
+.Pp
.It Ic inet.icmp
Display ICMP statistics.
.It Ic inet.ip
Home |
Main Index |
Thread Index |
Old Index