Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Sep 2020 17:02:49 +0000 (UTC)
From:      Michael Reifenberger <mr@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r365364 - stable/12/usr.bin/systat
Message-ID:  <202009051702.085H2nWR041800@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mr
Date: Sat Sep  5 17:02:48 2020
New Revision: 365364
URL: https://svnweb.freebsd.org/changeset/base/365364

Log:
  MFC r363095:
  Handle device removal and removal+add cases to fix infinity rate.
  
  PR:		219829
  Submitted by:	ota@j.email.ne.jp
  Reported by:	rezo@live.cn
  Differential Revision:	https://reviews.freebsd.org/D25226

Modified:
  stable/12/usr.bin/systat/ifcmds.c
  stable/12/usr.bin/systat/ifstat.c
  stable/12/usr.bin/systat/systat.1
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/usr.bin/systat/ifcmds.c
==============================================================================
--- stable/12/usr.bin/systat/ifcmds.c	Sat Sep  5 16:44:37 2020	(r365363)
+++ stable/12/usr.bin/systat/ifcmds.c	Sat Sep  5 17:02:48 2020	(r365364)
@@ -74,6 +74,8 @@ ifcmd(const char *cmd, const char *args)
 		}
 	} else if (prefix(cmd, "pps"))
 		showpps = !showpps;
+	else
+		return (0);
 
 	return (1);
 }

Modified: stable/12/usr.bin/systat/ifstat.c
==============================================================================
--- stable/12/usr.bin/systat/ifstat.c	Sat Sep  5 16:44:37 2020	(r365363)
+++ stable/12/usr.bin/systat/ifstat.c	Sat Sep  5 17:02:48 2020	(r365364)
@@ -37,6 +37,7 @@
 #include <net/if.h>
 #include <net/if_mib.h>
 
+#include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
 #include <err.h>
@@ -67,7 +68,8 @@ SLIST_HEAD(, if_stat_disp)	displist;
 
 struct if_stat {
 	SLIST_ENTRY(if_stat)	 link;
-	char	if_name[IF_NAMESIZE];
+	char	display_name[IF_NAMESIZE];
+	char	dev_name[IFNAMSIZ]; 	/* copied from ifmibdata */
 	struct	ifmibdata if_mib;
 	struct	timeval tv;
 	struct	timeval tv_lastchanged;
@@ -81,7 +83,7 @@ struct if_stat {
 	uint64_t if_out_pps_peak;
 	u_int	if_row;			/* Index into ifmib sysctl */
 	int 	if_ypos;		/* -1 if not being displayed */
-	u_int	display;
+	bool	display;
 	u_int	match;
 };
 
@@ -91,11 +93,13 @@ extern	 int showpps;
 extern	 int needsort;
 
 static	 int needclear = 0;
+static	 bool displayall = false;
 
-static	 void  right_align_string(struct if_stat *);
-static	 void  getifmibdata(const int, struct ifmibdata *);
+static	 void  format_device_name(struct if_stat *);
+static	 int   getifmibdata(const int, struct ifmibdata *);
 static	 void  sort_interface_list(void);
 static	 u_int getifnum(void);
+static	 void  clearifstat(void);
 
 #define IFSTAT_ERR(n, s)	do {					\
 	putchar('\014');						\
@@ -165,7 +169,7 @@ static	 u_int getifnum(void);
 } while (0)
 
 #define PUTNAME(p) do {							\
-	mvprintw(p->if_ypos, 0, "%s", p->if_name);			\
+	mvprintw(p->if_ypos, 0, "%s", p->display_name);			\
 	mvprintw(p->if_ypos, col2-3, "%s", (const char *)"in");		\
 	mvprintw(p->if_ypos+1, col2-3, "%s", (const char *)"out");	\
 } while (0)
@@ -214,7 +218,7 @@ showifstat(void)
 	
 	SLIST_FOREACH(ifp, &curlist, link) {
 		if (ifp->if_ypos < LINES - 3 && ifp->if_ypos != -1)
-			if (ifp->display == 0 || ifp->match == 0) {
+			if (!ifp->display || ifp->match == 0) {
 					wmove(wnd, ifp->if_ypos, 0);
 					wclrtoeol(wnd);
 					wmove(wnd, ifp->if_ypos + 1, 0);
@@ -235,7 +239,7 @@ int
 initifstat(void)
 {
 	struct   if_stat *p = NULL;
-	u_int	 n = 0, i = 0;
+	u_int	 n, i;
 
 	n = getifnum();
 	if (n <= 0)
@@ -247,18 +251,21 @@ initifstat(void)
 		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);
+		if (getifmibdata(p->if_row, &p->if_mib) == -1) {
+			free(p);
+			continue;
+		}
+		SLIST_INSERT_HEAD(&curlist, p, link);
+		format_device_name(p);
 		p->match = 1;
 
 		/*
 		 * Initially, we only display interfaces that have
-		 * received some traffic.
+		 * received some traffic unless display-all is on.
 		 */
-		if (p->if_mib.ifmd_data.ifi_ibytes != 0)
-			p->display = 1;
+		if (displayall || p->if_mib.ifmd_data.ifi_ibytes != 0)
+			p->display = true;
 	}
 
 	sort_interface_list();
@@ -269,13 +276,13 @@ initifstat(void)
 void
 fetchifstat(void)
 {
-	struct	if_stat *ifp = NULL;
+	struct	if_stat *ifp = NULL, *temp_var;
 	struct	timeval tv, new_tv, old_tv;
 	double	elapsed = 0.0;
 	uint64_t new_inb, new_outb, old_inb, old_outb = 0;
 	uint64_t new_inp, new_outp, old_inp, old_outp = 0;
 
-	SLIST_FOREACH(ifp, &curlist, link) {
+	SLIST_FOREACH_SAFE(ifp, &curlist, link, temp_var) {
 		/*
 		 * Grab a copy of the old input/output values before we
 		 * call getifmibdata().
@@ -287,7 +294,22 @@ fetchifstat(void)
 		ifp->tv_lastchanged = ifp->if_mib.ifmd_data.ifi_lastchange;
 
 		(void)gettimeofday(&new_tv, NULL);
-		(void)getifmibdata(ifp->if_row, &ifp->if_mib);
+		if (getifmibdata(ifp->if_row, &ifp->if_mib) == -1 ) {
+			/* if a device was removed */
+			SLIST_REMOVE(&curlist, ifp, if_stat, link);
+			free(ifp);
+			needsort = 1;
+			clearifstat();
+		} else if (strcmp(ifp->dev_name, ifp->if_mib.ifmd_name) != 0 ) {
+			/* a device was removed and another one was added */
+			format_device_name(ifp);
+			/* clear to the current value for the new device */
+			old_inb = ifp->if_mib.ifmd_data.ifi_ibytes;
+			old_outb = ifp->if_mib.ifmd_data.ifi_obytes;
+			old_inp = ifp->if_mib.ifmd_data.ifi_ipackets;
+			old_outp = ifp->if_mib.ifmd_data.ifi_opackets;
+			needsort = 1;
+		}
 
 		new_inb = ifp->if_mib.ifmd_data.ifi_ibytes;
 		new_outb = ifp->if_mib.ifmd_data.ifi_obytes;
@@ -295,8 +317,8 @@ fetchifstat(void)
 		new_outp = ifp->if_mib.ifmd_data.ifi_opackets;
 
 		/* Display interface if it's received some traffic. */
-		if (new_inb > 0 && old_inb == 0) {
-			ifp->display = 1;
+		if (!ifp->display && new_inb > 0 && old_inb == 0) {
+			ifp->display = true;
 			needsort = 1;
 		}
 
@@ -351,28 +373,18 @@ fetchifstat(void)
 /*
  * We want to right justify our interface names against the first column
  * (first sixteen or so characters), so we need to do some alignment.
+ * We save original name so that we can find a same spot is take by a
+ * different device.
  */
 static void
-right_align_string(struct if_stat *ifp)
+format_device_name(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 = 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);
+	if (ifp != NULL ) {
+		snprintf(ifp->display_name, IF_NAMESIZE, "%*s", IF_NAMESIZE-1,
+		    ifp->if_mib.ifmd_name);
+		strcpy(ifp->dev_name, ifp->if_mib.ifmd_name);
 	}
-
-	return;
 }
 
 static int
@@ -461,9 +473,10 @@ getifnum(void)
 	return (data);
 }
 
-static void
+static int
 getifmibdata(int row, struct ifmibdata *data)
 {
+	int	ret = 0;
 	size_t	datalen = 0;
 	static	int name[] = { CTL_NET,
 			       PF_LINK,
@@ -474,9 +487,12 @@ getifmibdata(int row, struct ifmibdata *data)
 	datalen = sizeof(*data);
 	name[4] = row;
 
-	if ((sysctl(name, 6, (void *)data, (size_t *)&datalen, (void *)NULL,
-	    (size_t)0) != 0) && (errno != ENOENT))
+	ret = sysctl(name, 6, (void *)data, (size_t *)&datalen, (void *)NULL,
+	    (size_t)0);
+	if ((ret != 0) && (errno != ENOENT))
 		IFSTAT_ERR(2, "sysctl error getting interface data");
+
+	return (ret);
 }
 
 int
@@ -487,13 +503,23 @@ cmdifstat(const char *cmd, const char *args)
 	retval = ifcmd(cmd, args);
 	/* ifcmd() returns 1 on success */
 	if (retval == 1) {
-		if (needclear) {
-			showifstat();
-			refresh();
-			werase(wnd);
-			labelifstat();
-			needclear = 0;
-		}
+		if (needclear)
+			clearifstat();
 	}
+	else if (prefix(cmd, "all")) {
+		retval = 1;
+		displayall = true;
+	}
 	return (retval);
+}
+
+static void
+clearifstat(void)
+{
+
+	showifstat();
+	refresh();
+	werase(wnd);
+	labelifstat();
+	needclear = 0;
 }

Modified: stable/12/usr.bin/systat/systat.1
==============================================================================
--- stable/12/usr.bin/systat/systat.1	Sat Sep  5 16:44:37 2020	(r365363)
+++ stable/12/usr.bin/systat/systat.1	Sat Sep  5 17:02:48 2020	(r365364)
@@ -680,6 +680,7 @@ in Silicon Graphics'
 system.
 .Sh BUGS
 Certain displays presume a minimum of 80 characters per line.
+Ifstat does not detect new interfaces.
 The
 .Ic vmstat
 display looks out of place because it is (it was added in as



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