From nobody@FreeBSD.org  Thu Nov  4 13:56:40 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 66C461065672
	for <freebsd-gnats-submit@FreeBSD.org>; Thu,  4 Nov 2010 13:56:40 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 54CB68FC26
	for <freebsd-gnats-submit@FreeBSD.org>; Thu,  4 Nov 2010 13:56:40 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id oA4Due1s025175
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 4 Nov 2010 13:56:40 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id oA4DueAH025158;
	Thu, 4 Nov 2010 13:56:40 GMT
	(envelope-from nobody)
Message-Id: <201011041356.oA4DueAH025158@www.freebsd.org>
Date: Thu, 4 Nov 2010 13:56:40 GMT
From: Mykola Zubach <zuborg@example.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [patch] netstat(1) utility lack support of displaying rtt related counters of tcp sockets
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         151937
>Category:       bin
>Synopsis:       [patch] netstat(1) utility lack support of displaying rtt related counters of tcp sockets
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Nov 04 14:00:17 UTC 2010
>Closed-Date:    
>Last-Modified:  Sun Jul  1 16:30:05 UTC 2012
>Originator:     Mykola Zubach
>Release:        FreeBSD 8.1
>Organization:
AdvancedHosters.com
>Environment:
>Description:
RTT (round-trip time) timings are useful to investigate networking issues.
There are a lot of various tools to measure rtt (like ping/mtr etc), but it would be also helpful to have possibility to see current values of rtt for some tcp socket.

Here is a patch for netstat(1) utility which adds four optional columns for tcp sockets:
RTT - smoothed rtt value (tp->t_srtt / hz / TCP_RTT_SCALE)
RTT-DEV - smoothed rtt variance (tp->t_rttvar / hz / TCP_RTTVAR_SCALE)
RTT-LOW - smallest observed rtt (tp->t_rttlow / hz)
RTT-CNT - number of times rtt sampled (tp->t_rttupdated)

First three columns provide timings, measured in seconds, with precision 0.001 s.

'-T' option is free at the moment, so I chose it for this patch since it is related to 'T'imings
>How-To-Repeat:

>Fix:


Patch attached with submission follows:

--- /usr/src/usr.bin/netstat/main.c	2010-06-14 05:09:06.000000000 +0300
+++ main.c	2010-11-03 17:55:49.000000000 +0200
@@ -338,6 +338,7 @@
 static int pflag;	/* show given protocol */
 int	rflag;		/* show routing tables (or routing stats) */
 int	sflag;		/* show protocol statistics */
+int	Tflag;		/* show rtt counters of tcp sockets */
 int	tflag;		/* show i/f watchdog timers */
 int	Wflag;		/* wide display */
 int	xflag;		/* extra information, includes all socket buffer info */
@@ -359,7 +360,7 @@
 
 	af = AF_UNSPEC;
 
-	while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:q:rSstuWw:xz")) != -1)
+	while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:q:rSsTtuWw:xz")) != -1)
 		switch(ch) {
 		case 'A':
 			Aflag = 1;
@@ -459,6 +460,9 @@
 		case 'S':
 			numeric_addr = 1;
 			break;
+		case 'T':
+			Tflag = 1;
+			break;
 		case 't':
 			tflag = 1;
 			break;
--- /usr/src/usr.bin/netstat/netstat.h	2010-06-14 05:09:06.000000000 +0300
+++ netstat.h	2010-11-03 17:56:08.000000000 +0200
@@ -50,6 +50,7 @@
 extern int	numeric_port;	/* show ports numerically */
 extern int	rflag;	/* show routing tables (or routing stats) */
 extern int	sflag;	/* show protocol statistics */
+extern int	Tflag;	/* show rtt counters of tcp sockets */
 extern int	tflag;	/* show i/f watchdog timers */
 extern int	Wflag;	/* wide display */
 extern int	xflag;	/* extended display, includes all socket buffer info */
--- /usr/src/usr.bin/netstat/inet.c	2010-06-14 05:09:06.000000000 +0300
+++ inet.c	2010-11-04 15:31:45.000000000 +0200
@@ -47,6 +47,7 @@
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/sysctl.h>
+#include <sys/time.h>
 
 #include <net/route.h>
 #include <net/if_arp.h>
@@ -313,6 +314,21 @@
 	struct inpcb *inp;
 	struct xinpgen *xig, *oxig;
 	struct xsocket *so;
+	struct clockinfo clockinfo;
+	int mib[2];
+	size_t ci_size;
+	int hz = 1;
+	float rtt, rtt_var, rtt_low;
+
+	ci_size = sizeof(clockinfo);
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_CLOCKRATE;
+	if (sysctl(mib, 2, &clockinfo, &ci_size, NULL, 0) < 0)
+		warn("sysctl: kern.clockrate");
+	else if (clockinfo.hz == 0)
+		warn("sysctl: kern.clockrate: hz = 0");
+	else
+ 		hz = clockinfo.hz;
 
 	istcp = 0;
 	switch (proto) {
@@ -414,15 +430,17 @@
 				       "%-5.5s %-6.6s %-6.6s  %-22.22s %-22.22s",
 				       "Proto", "Recv-Q", "Send-Q",
 				       "Local Address", "Foreign Address");
+				if (Tflag)
+					printf("%-6.6s %-7.7s %-7.7s %-7.7s ",
+					       	"   RTT", "RTT-VAR",
+						"RTT-LOW", "RTT-CNT");
 				if (xflag)
-					printf("%-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %s\n",
+					printf("%-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s ",
 					       	"R-MBUF", "S-MBUF", "R-CLUS", 
 						"S-CLUS", "R-HIWA", "S-HIWA", 
 						"R-LOWA", "S-LOWA", "R-BCNT", 
-						"S-BCNT", "R-BMAX", "S-BMAX",
-					       "(state)");
-				else
-					printf("(state)\n");
+						"S-BCNT", "R-BMAX", "S-BMAX");
+				printf("(state)\n");
 			}
 			first = 0;
 		}
@@ -506,6 +524,14 @@
 			} /* else nothing printed now */
 #endif /* INET6 */
 		}
+		if (istcp && Tflag && !Lflag) {
+			rtt = (float)tp->t_srtt / hz / TCP_RTT_SCALE;
+			rtt_var = (float)tp->t_rttvar / hz / TCP_RTTVAR_SCALE;
+			rtt_low = (float)tp->t_rttlow / hz;
+			printf("%6.3f %7.3f %7.3f %7lu ",
+				rtt, rtt_var, rtt_low,
+				tp->t_rttupdated);
+		}
 		if (xflag) {
 			if (Lflag)
 				printf("%21s %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ",


>Release-Note:
>Audit-Trail:

From: Mikolaj Golub <trociny@freebsd.org>
To: Mykola Zubach <zuborg@example.com>, freebsd-net@FreeBSD.org
Cc: Robert Watson <rwatson@FreeBSD.org>, bug-followup@FreeBSD.org
Subject: Re: bin/151937: [patch] netstat(1) utility lack support of displaying rtt related counters of tcp sockets
Date: Sun, 01 Jul 2012 19:20:11 +0300

 --=-=-=
 
 Hi,
 
 Mykola, thank you for the report and the provided patch. Displaying rtt
 related counters per connection looks useful for me too.
 
 I am attaching the modified version of the patch to discuss (and commit if
 there are no objections or other suggestions).
 
 The differences from your version:
 
 1) '-T' option is already used. Also, I don't like very much adding yet
 another option, so I added the statistics to '-x' option. Or it can be added
 to '-T' statistics.
 
 2) As counter names I used names that are close to field names in the tcpcb
 structure.
 
 3) To get hz, instead of kern.clockrate, I use kern.hz sysctl (as it
 simplifies the code a little) and for !live case read it from the dump.
 
 4) The trick with printing to buf is used to pad the counters on the right, as
 it is with other counters.
 
 Also, it might be enough to display only srtt and rttvar statistics?
 
 -- 
 Mikolaj Golub
 
 --=-=-=
 Content-Type: text/x-patch
 Content-Disposition: attachment; filename=netstat.rtt.2.patch
 
 Index: usr.bin/netstat/inet.c
 ===================================================================
 --- usr.bin/netstat/inet.c	(revision 237835)
 +++ usr.bin/netstat/inet.c	(working copy)
 @@ -293,6 +293,28 @@ fail:
  #undef KREAD
  }
  
 +static const char *
 +humanize_rtt(int val, int scale)
 +{
 +	size_t len;
 +	static int hz;
 +	static char buf[16];
 +
 +	if (hz == 0) {
 +		hz = 1;
 +		if (live) {
 +			len = sizeof(hz);
 +			if (sysctlbyname("kern.hz", &hz, &len, NULL, 0) == -1)
 +				warn("sysctl: kern.hz");
 +		} else {
 +			kread(hz_addr, &hz, sizeof(hz));
 +		}
 +	}
 +	snprintf(buf, sizeof(buf), "%.3f", (float)val / (scale * hz));
 +
 +	return (buf);
 +}
 +
  /*
   * Print a summary of connections related to an Internet
   * protocol.  For TCP, also give state of connection.
 @@ -441,6 +463,8 @@ protopr(u_long off, const char *name, int af1, int
  				printf(" %7.7s %7.7s %7.7s %7.7s %7.7s %7.7s",
  				       "rexmt", "persist", "keep",
  				       "2msl", "delack", "rcvtime");
 +				printf(" %7.7s %7.7s %7.7s %9.9s",
 +				       "srtt", "rttvar", "rttlow", "rttupdate");
  			}
  			putchar('\n');
  			first = 0;
 @@ -548,6 +572,14 @@ protopr(u_long off, const char *name, int af1, int
  				    timer->tt_2msl / 1000, (timer->tt_2msl % 1000) / 10,
  				    timer->tt_delack / 1000, (timer->tt_delack % 1000) / 10,
  				    timer->t_rcvtime / 1000, (timer->t_rcvtime % 1000) / 10);
 +			if (tp != NULL) {
 +				printf(" %7s", humanize_rtt(tp->t_srtt,
 +				    TCP_RTT_SCALE));
 +				printf(" %7s", humanize_rtt(tp->t_rttvar,
 +				    TCP_RTTVAR_SCALE));
 +				printf(" %7s", humanize_rtt(tp->t_rttlow, 1));
 +				printf(" %9lu ", tp->t_rttupdated);
 +			}
  		}
  		if (istcp && !Lflag && !xflag && !Tflag) {
  			if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
 Index: usr.bin/netstat/main.c
 ===================================================================
 --- usr.bin/netstat/main.c	(revision 237835)
 +++ usr.bin/netstat/main.c	(working copy)
 @@ -184,6 +184,8 @@ static struct nlist nl[] = {
  	{ .n_name = "_arpstat" },
  #define	N_UNP_SPHEAD	56
  	{ .n_name = "unp_sphead" },
 +#define	N_HZ		57
 +	{ .n_name = "_hz" },
  	{ .n_name = NULL },
  };
  
 @@ -358,6 +360,8 @@ int	unit;		/* unit number for above */
  int	af;		/* address family */
  int	live;		/* true if we are examining a live system */
  
 +u_long	hz_addr;	/* address of hz variable in kernel memory */
 +
  int
  main(int argc, char *argv[])
  {
 @@ -563,6 +567,7 @@ main(int argc, char *argv[])
  	 */
  #endif
  	kread(0, NULL, 0);
 +	hz_addr = nl[N_HZ].n_value;
  	if (iflag && !sflag) {
  		intpr(interval, nl[N_IFNET].n_value, NULL);
  		exit(0);
 Index: usr.bin/netstat/netstat.h
 ===================================================================
 --- usr.bin/netstat/netstat.h	(revision 237835)
 +++ usr.bin/netstat/netstat.h	(working copy)
 @@ -59,6 +59,8 @@ extern int	unit;	/* unit number for above */
  extern int	af;	/* address family */
  extern int	live;	/* true if we are examining a live system */
  
 +extern u_long	hz_addr;	/* address of hz variable in kernel memory */
 +
  int	kread(u_long addr, void *buf, size_t size);
  const char *plural(uintmax_t);
  const char *plurales(uintmax_t);
 
 --=-=-=--
>Unformatted:
