PERFORCE change 166616 for review

Gabor Pali pgj at FreeBSD.org
Mon Jul 27 13:18:20 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=166616

Change 166616 by pgj at petymeg-current on 2009/07/27 13:17:25

	Make netstat(1) to use libnetstat(3) for displaying and resetting
	TCP statistics.

Affected files ...

.. //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/extern.h#10 edit
.. //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/inet.c#24 edit
.. //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/main.c#18 edit

Differences ...

==== //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/extern.h#10 (text+ko) ====

@@ -74,7 +74,7 @@
 void	inetpr(void *, int, int);
 void	inetppr(const struct socket_type *);
 void	unixdomainpr(const struct socket_type *);
-void	tcp_stats(u_long, const char *, int, int);
+void	tcp_stats(void *, const char *);
 void	udp_stats(u_long, const char *, int, int);
 #ifdef SCTP
 void	sctp_protopr(u_long, const char *, int, int);

==== //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/inet.c#24 (text+ko) ====

@@ -242,10 +242,11 @@
  * Dump TCP statistics structure.
  */
 void
-tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+tcp_stats(void *kvmd, const char *name)
 {
-	struct tcpstat tcpstat, zerostat;
-	size_t len = sizeof tcpstat;
+	const struct tcp_stat *s;
+	struct stat_type *sttp;
+	int stt_flags;
 
 #ifdef INET6
 	if (tcp_done != 0)
@@ -254,125 +255,139 @@
 		tcp_done = 1;
 #endif
 
-	if (live) {
-		if (zflag)
-			memset(&zerostat, 0, len);
-		if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len,
-		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
-			warn("sysctl: net.inet.tcp.stats");
-			return;
-		}
-	} else
-		kread(off, &tcpstat, len);
+	if (zflag) {
+		netstat_zerostat(stat_TCP);
+		return;
+	}
+
+	stt_flags = 0;
+	if (!live)
+		stt_flags |= NETSTAT_STAT_KVM;
+
+	sttp = netstat_stat_alloc();
+	if (sttp == NULL) {
+		warn("netstat_stat_alloc");
+		return;
+	}
+
+	if (netstat_stat(stat_TCP, sttp, stt_flags, kvmd) < 0) {
+		return;
+	}
+
+	s = netstat_get_tcpstats(sttp);
 
 	printf ("%s:\n", name);
 
-#define	p(f, m) if (tcpstat.f || sflag <= 1) \
-    printf(m, tcpstat.f, plural(tcpstat.f))
-#define	p1a(f, m) if (tcpstat.f || sflag <= 1) \
-    printf(m, tcpstat.f)
-#define	p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
-    printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
-#define	p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
-    printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
-#define	p3(f, m) if (tcpstat.f || sflag <= 1) \
-    printf(m, tcpstat.f, pluralies(tcpstat.f))
+#define	p(f, m) if (netstat_tcps_get_##f(s) || sflag <= 1) \
+    printf(m, netstat_tcps_get_##f(s), plural(netstat_tcps_get_##f(s)))
+#define	p1a(f, m) if (netstat_tcps_get_##f(s) || sflag <= 1) \
+    printf(m, netstat_tcps_get_##f(s))
+#define	p2(f1, f2, m) if (netstat_tcps_get_##f1(s) || netstat_tcps_get_##f2(s) || sflag <= 1) \
+    printf(m, netstat_tcps_get_##f1(s), plural(netstat_tcps_get_##f1(s)), \
+	netstat_tcps_get_##f2(s), plural(netstat_tcps_get_##f2(s)))
+#define	p2a(f1, f2, m) if (netstat_tcps_get_##f1(s) || netstat_tcps_get_##f2(s) || sflag <= 1) \
+    printf(m, netstat_tcps_get_##f1(s), plural(netstat_tcps_get_##f1(s)), \
+	netstat_tcps_get_##f2(s))
+#define	p3(f, m) if (netstat_tcps_get_##f(s) || sflag <= 1) \
+    printf(m, netstat_tcps_get_##f(s), plural(netstat_tcps_get_##f(s)))
+
+	p(sndtotal, "\t%ju packet%s sent\n");
+	p2(sndpack,sndbyte, "\t\t%ju data packet%s (%ju byte%s)\n");
+	p2(sndrexmitpack, sndrexmitbyte,
+	    "\t\t%ju data packet%s (%ju byte%s) retransmitted\n");
+	p(sndrexmitbad,
+	    "\t\t%ju data packet%s unnecessarily retransmitted\n");
+	p(mturesent, "\t\t%ju resend%s initiated by MTU discovery\n");
+	p2a(sndacks, delack,
+	    "\t\t%ju ack-only packet%s (%ju delayed)\n");
+	p(sndurg, "\t\t%ju URG only packet%s\n");
+	p(sndprobe, "\t\t%ju window probe packet%s\n");
+	p(sndwinup, "\t\t%ju window update packet%s\n");
+	p(sndctrl, "\t\t%ju control packet%s\n");
+	p(rcvtotal, "\t%ju packet%s received\n");
+	p2(rcvackpack, rcvackbyte,
+	    "\t\t%ju ack%s (for %ju byte%s)\n");
+	p(rcvdupack, "\t\t%ju duplicate ack%s\n");
+	p(rcvacktoomuch, "\t\t%ju ack%s for unsent data\n");
+	p2(rcvpack, rcvbyte,
+	    "\t\t%ju packet%s (%ju byte%s) received in-sequence\n");
+	p2(rcvduppack, rcvdupbyte,
+	    "\t\t%ju completely duplicate packet%s (%ju byte%s)\n");
+	p(pawsdrop, "\t\t%ju old duplicate packet%s\n");
+	p2(rcvpartduppack, rcvpartdupbyte,
+	    "\t\t%ju packet%s with some dup. data (%ju byte%s duped)\n");
+	p2(rcvoopack, rcvoobyte,
+	    "\t\t%ju out-of-order packet%s (%ju byte%s)\n");
+	p2(rcvpackafterwin, rcvbyteafterwin,
+	    "\t\t%ju packet%s (%ju byte%s) of data after window\n");
+	p(rcvwinprobe, "\t\t%ju window probe%s\n");
+	p(rcvwinupd, "\t\t%ju window update packet%s\n");
+	p(rcvafterclose, "\t\t%ju packet%s received after close\n");
+	p(rcvbadsum, "\t\t%ju discarded for bad checksum%s\n");
+	p(rcvbadoff, "\t\t%ju discarded for bad header offset field%s\n");
+	p1a(rcvshort, "\t\t%ju discarded because packet too short\n");
+	p1a(rcvmemdrop, "\t\t%ju discarded due to memory problems\n");
+	p(connattempt, "\t%ju connection request%s\n");
+	p(accepts, "\t%ju connection accept%s\n");
+	p(badsyn, "\t%ju bad connection attempt%s\n");
+	p(listendrop, "\t%ju listen queue overflow%s\n");
+	p(badrst, "\t%ju ignored RSTs in the window%s\n");
+	p(connects, "\t%ju connection%s established (including accepts)\n");
+	p2(closed, drops,
+	    "\t%ju connection%s closed (including %ju drop%s)\n");
+	p(cachedrtt, "\t\t%ju connection%s updated cached RTT on close\n");
+	p(cachedrttvar,
+	    "\t\t%ju connection%s updated cached RTT variance on close\n");
+	p(cachedssthresh,
+	    "\t\t%ju connection%s updated cached ssthresh on close\n");
+	p(conndrops, "\t%ju embryonic connection%s dropped\n");
+	p2(rttupdated, segstimed,
+	    "\t%ju segment%s updated rtt (of %ju attempt%s)\n");
+	p(rexmttimeo, "\t%ju retransmit timeout%s\n");
+	p(timeoutdrop, "\t\t%ju connection%s dropped by rexmit timeout\n");
+	p(persisttimeo, "\t%ju persist timeout%s\n");
+	p(persistdrop, "\t\t%ju connection%s dropped by persist timeout\n");
+	p(finwait2_drops,
+	    "\t%ju Connection%s (fin_wait_2) dropped because of timeout\n");
+	p(keeptimeo, "\t%ju keepalive timeout%s\n");
+	p(keepprobe, "\t\t%ju keepalive probe%s sent\n");
+	p(keepdrops, "\t\t%ju connection%s dropped by keepalive\n");
+	p(predack, "\t%ju correct ACK header prediction%s\n");
+	p(preddat, "\t%ju correct data packet header prediction%s\n");
 
-	p(tcps_sndtotal, "\t%lu packet%s sent\n");
-	p2(tcps_sndpack,tcps_sndbyte, "\t\t%lu data packet%s (%lu byte%s)\n");
-	p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
-	    "\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
-	p(tcps_sndrexmitbad,
-	    "\t\t%lu data packet%s unnecessarily retransmitted\n");
-	p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
-	p2a(tcps_sndacks, tcps_delack,
-	    "\t\t%lu ack-only packet%s (%lu delayed)\n");
-	p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
-	p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
-	p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
-	p(tcps_sndctrl, "\t\t%lu control packet%s\n");
-	p(tcps_rcvtotal, "\t%lu packet%s received\n");
-	p2(tcps_rcvackpack, tcps_rcvackbyte,
-	    "\t\t%lu ack%s (for %lu byte%s)\n");
-	p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
-	p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
-	p2(tcps_rcvpack, tcps_rcvbyte,
-	    "\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
-	p2(tcps_rcvduppack, tcps_rcvdupbyte,
-	    "\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
-	p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
-	p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
-	    "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
-	p2(tcps_rcvoopack, tcps_rcvoobyte,
-	    "\t\t%lu out-of-order packet%s (%lu byte%s)\n");
-	p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
-	    "\t\t%lu packet%s (%lu byte%s) of data after window\n");
-	p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
-	p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
-	p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
-	p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
-	p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
-	p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
-	p1a(tcps_rcvmemdrop, "\t\t%lu discarded due to memory problems\n");
-	p(tcps_connattempt, "\t%lu connection request%s\n");
-	p(tcps_accepts, "\t%lu connection accept%s\n");
-	p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
-	p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
-	p(tcps_badrst, "\t%lu ignored RSTs in the window%s\n");
-	p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
-	p2(tcps_closed, tcps_drops,
-	    "\t%lu connection%s closed (including %lu drop%s)\n");
-	p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
-	p(tcps_cachedrttvar,
-	    "\t\t%lu connection%s updated cached RTT variance on close\n");
-	p(tcps_cachedssthresh,
-	    "\t\t%lu connection%s updated cached ssthresh on close\n");
-	p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
-	p2(tcps_rttupdated, tcps_segstimed,
-	    "\t%lu segment%s updated rtt (of %lu attempt%s)\n");
-	p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
-	p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
-	p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
-	p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
-	p(tcps_finwait2_drops,
-	    "\t%lu Connection%s (fin_wait_2) dropped because of timeout\n");
-	p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
-	p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
-	p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
-	p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
-	p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
+	p3(sc_added, "\t%ju syncache entr%s added\n");
+	p1a(sc_retransmitted, "\t\t%ju retransmitted\n");
+	p1a(sc_dupsyn, "\t\t%ju dupsyn\n");
+	p1a(sc_dropped, "\t\t%ju dropped\n");
+	p1a(sc_completed, "\t\t%ju completed\n");
+	p1a(sc_bucketoverflow, "\t\t%ju bucket overflow\n");
+	p1a(sc_cacheoverflow, "\t\t%ju cache overflow\n");
+	p1a(sc_reset, "\t\t%ju reset\n");
+	p1a(sc_stale, "\t\t%ju stale\n");
+	p1a(sc_aborted, "\t\t%ju aborted\n");
+	p1a(sc_badack, "\t\t%ju badack\n");
+	p1a(sc_unreach, "\t\t%ju unreach\n");
+	p(sc_zonefail, "\t\t%ju zone failure%s\n");
+	p(sc_sendcookie, "\t%ju cookie%s sent\n");
+	p(sc_recvcookie, "\t%ju cookie%s received\n");
 
-	p3(tcps_sc_added, "\t%lu syncache entr%s added\n");
-	p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n");
-	p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n");
-	p1a(tcps_sc_dropped, "\t\t%lu dropped\n");
-	p1a(tcps_sc_completed, "\t\t%lu completed\n");
-	p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n");
-	p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n");
-	p1a(tcps_sc_reset, "\t\t%lu reset\n");
-	p1a(tcps_sc_stale, "\t\t%lu stale\n");
-	p1a(tcps_sc_aborted, "\t\t%lu aborted\n");
-	p1a(tcps_sc_badack, "\t\t%lu badack\n");
-	p1a(tcps_sc_unreach, "\t\t%lu unreach\n");
-	p(tcps_sc_zonefail, "\t\t%lu zone failure%s\n");
-	p(tcps_sc_sendcookie, "\t%lu cookie%s sent\n");
-	p(tcps_sc_recvcookie, "\t%lu cookie%s received\n");
+	p(sack_recovery_episode, "\t%ju SACK recovery episode%s\n");
+	p(sack_rexmits,
+	    "\t%ju segment rexmit%s in SACK recovery episodes\n");
+	p(sack_rexmit_bytes,
+	    "\t%ju byte rexmit%s in SACK recovery episodes\n");
+	p(sack_rcv_blocks,
+	    "\t%ju SACK option%s (SACK blocks) received\n");
+	p(sack_send_blocks, "\t%ju SACK option%s (SACK blocks) sent\n");
+	p1a(sack_sboverflow, "\t%ju SACK scoreboard overflow\n");
 
-	p(tcps_sack_recovery_episode, "\t%lu SACK recovery episode%s\n");
-	p(tcps_sack_rexmits,
-	    "\t%lu segment rexmit%s in SACK recovery episodes\n");
-	p(tcps_sack_rexmit_bytes,
-	    "\t%lu byte rexmit%s in SACK recovery episodes\n");
-	p(tcps_sack_rcv_blocks,
-	    "\t%lu SACK option%s (SACK blocks) received\n");
-	p(tcps_sack_send_blocks, "\t%lu SACK option%s (SACK blocks) sent\n");
-	p1a(tcps_sack_sboverflow, "\t%lu SACK scoreboard overflow\n");
+	p(ecn_ce, "\t%ju packet%s with ECN CE bit set\n");
+	p(ecn_ect0, "\t%ju packet%s with ECN ECT(0) bit set\n");
+	p(ecn_ect1, "\t%ju packet%s with ECN ECT(1) bit set\n");
+	p(ecn_shs, "\t%ju successful ECN handshake%s\n");
+	p(ecn_rcwnd, "\t%ju time%s ECN reduced the congestion window\n");
 
-	p(tcps_ecn_ce, "\t%lu packet%s with ECN CE bit set\n");
-	p(tcps_ecn_ect0, "\t%lu packet%s with ECN ECT(0) bit set\n");
-	p(tcps_ecn_ect1, "\t%lu packet%s with ECN ECT(1) bit set\n");
-	p(tcps_ecn_shs, "\t%lu successful ECN handshake%s\n");
-	p(tcps_ecn_rcwnd, "\t%lu time%s ECN reduced the congestion window\n");
+	netstat_stat_free(sttp);
 #undef p
 #undef p1a
 #undef p2

==== //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/main.c#18 (text+ko) ====

@@ -129,23 +129,21 @@
 	{ .n_name = "_espstat" },
 #define	N_IPCOMPSTAT	25
 	{ .n_name = "_ipcompstat" },
-#define	N_TCPSTAT	26
-	{ .n_name = "_tcpstat" },
-#define	N_UDPSTAT	27
+#define	N_UDPSTAT	26
 	{ .n_name = "_udpstat" },
-#define	N_IPSTAT	28
+#define	N_IPSTAT	27
 	{ .n_name = "_ipstat" },
-#define	N_ICMPSTAT	29
+#define	N_ICMPSTAT	28
 	{ .n_name = "_icmpstat" },
-#define	N_IGMPSTAT	30
+#define	N_IGMPSTAT	29
 	{ .n_name = "_igmpstat" },
-#define	N_PIMSTAT	31
+#define	N_PIMSTAT	30
 	{ .n_name = "_pimstat" },
-#define	N_RIP6STAT	32
+#define	N_RIP6STAT	31
 	{ .n_name = "_rip6stat" },
-#define	N_SCTPSTAT	33
+#define	N_SCTPSTAT	32
 	{ .n_name = "_sctpstat" },
-#define	N_MFCTABLESIZE	34
+#define	N_MFCTABLESIZE	33
 	{ .n_name = "_mfctablesize" },
 	{ .n_name = NULL },
 };
@@ -163,8 +161,8 @@
 	int	pr_usesysctl;		/* non-zero if we use sysctl, not kvm */
 	int	pr_protocol;
 } protox[] = {
-	{ 0,		N_TCPSTAT,	1,	NULL,
-	  tcp_stats,	NULL,		"tcp",	1,	IPPROTO_TCP },
+	{ 0,		0,		1,	NULL,
+	  NULL,		NULL,		"tcp",	1,	IPPROTO_TCP },
 	{ 0,		N_UDPSTAT,	1,	NULL,
 	  udp_stats,	NULL,		"udp",	1,	IPPROTO_UDP },
 #ifdef SCTP
@@ -201,8 +199,8 @@
 
 #ifdef INET6
 struct protox ip6protox[] = {
-	{ 0,		N_TCPSTAT,	1,	NULL,
-	  tcp_stats,	NULL,		"tcp",	1,	IPPROTO_TCP },
+	{ 0,		0,	    	1,	NULL,
+	  NULL,		NULL,		"tcp",	1,	IPPROTO_TCP },
 	{ 0,		N_UDPSTAT,	1,	NULL,
 	  udp_stats,	NULL,		"udp",	1,	IPPROTO_UDP },
 	{ 0,		N_IP6STAT,	1,	NULL,
@@ -534,6 +532,8 @@
 	}
 
 	if (tp) {
+		if (!live)
+			kread(0, NULL, 0);
 		printproto(tp, tp->pr_name);
 		exit(0);
 	}
@@ -561,11 +561,11 @@
 			kread(0, NULL, 0);
 		unixpr(kvmd);
 	}
-	if (af == AF_UNSPEC || af == AF_INET
+	if ((af == AF_UNSPEC || af == AF_INET
 #ifdef INET6
 	    || af == AF_INET6
 #endif 
-	    ) {
+	    ) && !sflag) {
 		stlp = netstat_stl_alloc();
 		if (stlp == NULL) {
 			warn("netstat_stl_alloc");
@@ -603,6 +603,14 @@
 		netstat_sti_free(stip);
 		netstat_stl_free(stlp);
 	}
+
+	if (sflag && af == AF_UNSPEC) {
+		if (!live)
+			kread(0, NULL, 0);
+		for (tp = protox; tp->pr_name; tp++)
+			printproto(tp, tp->pr_name);
+	}
+
 	exit(0);
 }
 
@@ -644,23 +652,31 @@
 				    tp->pr_name);
 			return;
 		} else {
-			pr = tp->pr_stats;
-			if (!pr) {
-				if (pflag)
-					printf("%s: no stats routine\n",
-					    tp->pr_name);
-				return;
+			/* XXX: temp. hack */
+			switch (tp->pr_protocol) {
+			case IPPROTO_TCP:
+				tcp_stats(kvmd, "tcp");
+				break;
+			default:
+				pr = tp->pr_stats;
+				if (!pr) {
+					if (pflag)
+						printf("%s: no stats routine\n",
+						    tp->pr_name);
+					return;
+				}
+				if (tp->pr_usesysctl && live)
+					off = 0;
+				else if (tp->pr_sindex < 0) {
+					if (pflag)
+						printf(
+					    "%s: stats routine doesn't work on cores\n",
+						    tp->pr_name);
+					return;
+				} else
+					off = nl[tp->pr_sindex].n_value;
+				break;
 			}
-			if (tp->pr_usesysctl && live)
-				off = 0;
-			else if (tp->pr_sindex < 0) {
-				if (pflag)
-					printf(
-				    "%s: stats routine doesn't work on cores\n",
-					    tp->pr_name);
-				return;
-			} else
-				off = nl[tp->pr_sindex].n_value;
 		}
 	} else {
 		pr = tp->pr_cblocks;
@@ -675,6 +691,10 @@
 		} else
 			off = nl[tp->pr_index].n_value;
 	}
+
+	if (sflag)
+		return;
+
 	if ((off || (live && tp->pr_usesysctl) ||
 	    af != AF_UNSPEC)) {
 		/* XXX: temp. hack */


More information about the p4-projects mailing list