Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 Mar 2007 06:51:57 GMT
From:      Bruce Becker<hostmaster@whois.gts.net>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   misc/110426: rpc.rstatd returns bad info
Message-ID:  <200703170651.l2H6pvHA053831@www.freebsd.org>
Resent-Message-ID: <200703170700.l2H70GqJ092179@freefall.freebsd.org>

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

>Number:         110426
>Category:       misc
>Synopsis:       rpc.rstatd returns bad info
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Mar 17 07:00:11 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Bruce Becker
>Release:        4.11
>Organization:
G.T.S.
>Environment:
FreeBSD infra-gw 4.11-STABLE FreeBSD 4.11-STABLE #3: Wed Feb  7 16:21:26 EST 2007     root@infra-gw:/usr/obj/usr/src/sys/FW-YQ  i386

>Description:
4.x & 3.x seem to have issues with opackets systcl mib (always returns 0)

this fix uses the kmem interface as well as fixes some code botches

>How-To-Repeat:
view using SunOS/Solaris perfmeter or sysutils/xsysstats port
>Fix:
Patch included

Patch attached with submission follows:

--- rstat_proc.c~	Fri Apr  2 01:56:09 2004
+++ rstat_proc.c	Sat Jan 28 22:24:19 2006
@@ -63,7 +63,7 @@
 #include <devstat.h>
 
 #include <net/if.h>
-#include <net/if_mib.h>
+#include <net/if_var.h>
 
 #undef FSHIFT			 /* Use protocol's shift and scale values */
 #undef FSCALE
@@ -79,6 +79,8 @@
 	{ "_cp_time" },
 #define	X_CNT		1
 	{ "_cnt" },
+#define	X_IFNET		2
+	{ "_ifnet" },
 	{ "" },
 };
 
@@ -87,6 +89,8 @@
 void setup __P((void));
 int stats_service();
 
+int firstifnet, numintfs;
+
 extern int from_inetd;
 int sincelastreq = 0;		/* number of alarms since last request */
 extern int closedown;
@@ -140,6 +144,7 @@
     if (! stat_is_init)
         stat_init();
     sincelastreq = 0;
+    stats_all.s2.if_opackets = stats_all.s3.if_opackets;
     return(&stats_all.s2);
 }
 
@@ -151,6 +156,7 @@
     if (! stat_is_init)
         stat_init();
     sincelastreq = 0;
+    stats_all.s1.if_opackets = stats_all.s3.if_opackets;
     return(&stats_all.s1);
 }
 
@@ -187,10 +193,11 @@
 void
 updatestat()
 {
+	long off;
 	int i, hz;
 	struct clockinfo clockrate;
 	struct vmmeter cnt;
-	struct ifmibdata ifmd;
+	struct ifnet ifnet;
 	double avrun[3];
 	struct timeval tm, btm;
 	int mib[6];
@@ -229,13 +236,13 @@
 		exit(1);
 	}
 	for(i = 0; i < RSTAT_CPUSTATES ; i++)
-		stats_all.s1.cp_time[i] = bsd_cp_time[cp_time_xlat[i]];
+		stats_all.s3.cp_time[i] = bsd_cp_time[cp_time_xlat[i]];
 
         (void)getloadavg(avrun, sizeof(avrun) / sizeof(avrun[0]));
 
-	stats_all.s2.avenrun[0] = avrun[0] * FSCALE;
-	stats_all.s2.avenrun[1] = avrun[1] * FSCALE;
-	stats_all.s2.avenrun[2] = avrun[2] * FSCALE;
+	stats_all.s3.avenrun[0] = avrun[0] * FSCALE;
+	stats_all.s3.avenrun[1] = avrun[1] * FSCALE;
+	stats_all.s3.avenrun[2] = avrun[2] * FSCALE;
 
 	mib[0] = CTL_KERN;
 	mib[1] = KERN_BOOTTIME;
@@ -245,13 +252,13 @@
 		exit(1);
 	}
 
-	stats_all.s2.boottime.tv_sec = btm.tv_sec;
-	stats_all.s2.boottime.tv_usec = btm.tv_usec;
+	stats_all.s3.boottime.tv_sec = btm.tv_sec;
+	stats_all.s3.boottime.tv_usec = btm.tv_usec;
 
 
 #ifdef DEBUG
-	fprintf(stderr, "%d %d %d %d\n", stats_all.s1.cp_time[0],
-	    stats_all.s1.cp_time[1], stats_all.s1.cp_time[2], stats_all.s1.cp_time[3]);
+	fprintf(stderr, "%d %d %d %d\n", stats_all.s3.cp_time[0],
+	    stats_all.s3.cp_time[1], stats_all.s3.cp_time[2], stats_all.s3.cp_time[3]);
 #endif
 
 	/* XXX - should use sysctl */
@@ -259,54 +266,40 @@
 		syslog(LOG_ERR, "rstat: can't read cnt from kmem");
 		exit(1);
 	}
-	stats_all.s1.v_pgpgin = cnt.v_vnodepgsin;
-	stats_all.s1.v_pgpgout = cnt.v_vnodepgsout;
-	stats_all.s1.v_pswpin = cnt.v_swappgsin;
-	stats_all.s1.v_pswpout = cnt.v_swappgsout;
-	stats_all.s1.v_intr = cnt.v_intr;
+	stats_all.s3.v_pgpgin = cnt.v_vnodepgsin;
+	stats_all.s3.v_pgpgout = cnt.v_vnodepgsout;
+	stats_all.s3.v_pswpin = cnt.v_swappgsin;
+	stats_all.s3.v_pswpout = cnt.v_swappgsout;
+	stats_all.s3.v_intr = cnt.v_intr;
 	gettimeofday(&tm, (struct timezone *) 0);
-	stats_all.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
+	stats_all.s3.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
 	    hz*(tm.tv_usec - btm.tv_usec)/1000000;
-	stats_all.s2.v_swtch = cnt.v_swtch;
+	stats_all.s3.v_swtch = cnt.v_swtch;
 
 	/* update disk transfers */
-	updatexfers(RSTAT_DK_NDRIVE, stats_all.s1.dk_xfer);
+	updatexfers(RSTAT_DK_NDRIVE, stats_all.s3.dk_xfer);
 
-	mib[0] = CTL_NET;
-	mib[1] = PF_LINK;
-	mib[2] = NETLINK_GENERIC;
-	mib[3] = IFMIB_SYSTEM;
-	mib[4] = IFMIB_IFCOUNT;
-	len = sizeof ifcount;
-	if (sysctl(mib, 5, &ifcount, &len, 0, 0) < 0) {
-		syslog(LOG_ERR, "sysctl(net.link.generic.system.ifcount): %m");
-		exit(1);
-	}
-
-	stats_all.s1.if_ipackets = 0;
-	stats_all.s1.if_opackets = 0;
-	stats_all.s1.if_ierrors = 0;
-	stats_all.s1.if_oerrors = 0;
-	stats_all.s1.if_collisions = 0;
-	for (i = 1; i <= ifcount; i++) {
-		len = sizeof ifmd;
-		mib[3] = IFMIB_IFDATA;
-		mib[4] = i;
-		mib[5] = IFDATA_GENERAL;
-		if (sysctl(mib, 6, &ifmd, &len, 0, 0) < 0) {
-			syslog(LOG_ERR, "sysctl(net.link.ifdata.%d.general)"
-			       ": %m", i);
-			exit(1);
+	stats_all.s3.if_ipackets = 0;
+	stats_all.s3.if_opackets = 0;
+	stats_all.s3.if_ierrors = 0;
+	stats_all.s3.if_oerrors = 0;
+	stats_all.s3.if_collisions = 0;
+	for (off = firstifnet, i = 0; off && i < numintfs; i++) {
+		if (kvm_read(kd, off, (char *)&ifnet, sizeof ifnet) != sizeof ifnet) {
+			syslog(LOG_ERR, "can't read ifnet from kmem");
+			exit(1);
+		}
+		stats_all.s3.if_ipackets += ifnet.if_data.ifi_ipackets;
+		stats_all.s3.if_opackets += ifnet.if_data.ifi_opackets;
+		stats_all.s3.if_ierrors += ifnet.if_data.ifi_ierrors;
+		stats_all.s3.if_oerrors += ifnet.if_data.ifi_oerrors;
+		stats_all.s3.if_collisions += ifnet.if_data.ifi_collisions;
+		off = (long)ifnet.if_list.tqe_next;
 		}
 
-		stats_all.s1.if_ipackets += ifmd.ifmd_data.ifi_ipackets;
-		stats_all.s1.if_opackets += ifmd.ifmd_data.ifi_opackets;
-		stats_all.s1.if_ierrors += ifmd.ifmd_data.ifi_ierrors;
-		stats_all.s1.if_oerrors += ifmd.ifmd_data.ifi_oerrors;
-		stats_all.s1.if_collisions += ifmd.ifmd_data.ifi_collisions;
-	}
-	gettimeofday((struct timeval *)&stats_all.s3.curtime,
-		(struct timezone *) 0);
+	gettimeofday(&tm, (struct timezone *) 0);
+	stats_all.s3.curtime.tv_sec = tm.tv_sec;
+	stats_all.s3.curtime.tv_usec = tm.tv_usec;
 	alarm(1);
 }
 
@@ -314,18 +307,46 @@
 setup()
 {
 	char errbuf[_POSIX2_LINE_MAX];
-
 	int en;
-
-	if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) {
-		syslog(LOG_ERR, "rpc.rstatd, %s", errbuf);
-		exit(1);
+	struct ifnet ifnet;
+	long off;
+	static int is_kd_setup = 0;
+
+	/*  setup() is called after each dormant->active
+	 *  transition.  Since we never close the kvm files
+	 *  (there's no reason), make sure we don't open them
+	 *  each time, as that can lead to exhaustion of all open
+	 *  files!  */
+	if (!is_kd_setup) {
+		kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
+		if (kd == NULL) {
+		syslog(LOG_ERR, "%s", errbuf);
+		exit (1);
+		}
+		is_kd_setup = 1;
 	}
 
 	if ((en = kvm_nlist(kd, nl)) != 0) {
 		syslog(LOG_ERR, "rstatd: Can't get namelist. %d", en);
 		exit (1);
         }
+
+	if (kvm_read(kd, (long)nl[X_IFNET].n_value, &firstifnet,
+		    sizeof(int)) != sizeof(int))  {
+		syslog(LOG_ERR, "can't read firstifnet from kmem");
+		exit(1);
+	}
+
+	numintfs = 0;
+	for (off = firstifnet; off;) {
+		if (kvm_read(kd, off, (char *)&ifnet, sizeof ifnet) != sizeof ifnet) {
+			syslog(LOG_ERR, "can't read ifnet from kmem for ifcount");
+			exit(1);
+		}
+		numintfs++;
+		off = (long)ifnet.if_list.tqe_next;
+	}
+
 }
 
 /*
@@ -449,7 +470,7 @@
 
 	switch (rqstp->rq_proc) {
 	case NULLPROC:
-		(void)svc_sendreply(transp, xdr_void, (char *)NULL);
+		(void)svc_sendreply(transp, (xdrproc_t)xdr_void, (char *)NULL);
 		goto leave;
 
 	case RSTATPROC_STATS:
@@ -497,15 +518,15 @@
 		goto leave;
 	}
 	bzero((char *)&argument, sizeof(argument));
-	if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
+	if (!svc_getargs(transp, (xdrproc_t)xdr_argument, (caddr_t)&argument)) {
 		svcerr_decode(transp);
 		goto leave;
 	}
 	result = (*local)(&argument, rqstp);
-	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+	if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) {
 		svcerr_systemerr(transp);
 	}
-	if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument))
+	if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (caddr_t)&argument))
 		errx(1, "unable to free arguments");
 leave:
         if (from_inetd)

>Release-Note:
>Audit-Trail:
>Unformatted:



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