Author: silby
Date: Wed Sep 16 05:33:15 2009
New Revision: 197244
URL: http://svn.freebsd.org/changeset/base/197244

Log:
  Add the ability to see TCP timers via netstat -x.  This can be a useful
  feature when you have a seemingly stuck socket and want to figure
  out why it has not been closed yet.
  
  No plans to MFC this, as it changes the netstat sysctl ABI.
  
  Reviewed by:  andre, rwatson, Eric Van Gyzen

Modified:
  head/sys/netinet/tcp_subr.c
  head/sys/netinet/tcp_timer.c
  head/sys/netinet/tcp_timer.h
  head/sys/netinet/tcp_var.h
  head/usr.bin/netstat/inet.c
  head/usr.bin/netstat/netstat.1

Modified: head/sys/netinet/tcp_subr.c
==============================================================================
--- head/sys/netinet/tcp_subr.c Wed Sep 16 03:49:54 2009        (r197243)
+++ head/sys/netinet/tcp_subr.c Wed Sep 16 05:33:15 2009        (r197244)
@@ -1151,8 +1151,11 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
                        else if (inp->inp_flags & INP_TIMEWAIT) {
                                bzero((char *) &xt.xt_tp, sizeof xt.xt_tp);
                                xt.xt_tp.t_state = TCPS_TIME_WAIT;
-                       } else
+                       } else {
                                bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp);
+                               if (xt.xt_tp.t_timers)
+                                       tcp_timer_to_xtimer(&xt.xt_tp, 
xt.xt_tp.t_timers, &xt.xt_timer);
+                       }
                        if (inp->inp_socket != NULL)
                                sotoxsocket(inp->inp_socket, &xt.xt_socket);
                        else {

Modified: head/sys/netinet/tcp_timer.c
==============================================================================
--- head/sys/netinet/tcp_timer.c        Wed Sep 16 03:49:54 2009        
(r197243)
+++ head/sys/netinet/tcp_timer.c        Wed Sep 16 05:33:15 2009        
(r197244)
@@ -659,3 +659,24 @@ tcp_timer_active(struct tcpcb *tp, int t
                }
        return callout_active(t_callout);
 }
+
+#define        ticks_to_msecs(t)       (1000*(t) / hz)
+
+void
+tcp_timer_to_xtimer(struct tcpcb *tp, struct tcp_timer *timer, struct 
xtcp_timer *xtimer)
+{
+       bzero(xtimer, sizeof(struct xtcp_timer));
+       if (timer == NULL)
+               return;
+       if (callout_active(&timer->tt_delack))
+               xtimer->tt_delack = ticks_to_msecs(timer->tt_delack.c_time - 
ticks);
+       if (callout_active(&timer->tt_rexmt))
+               xtimer->tt_rexmt = ticks_to_msecs(timer->tt_rexmt.c_time - 
ticks);
+       if (callout_active(&timer->tt_persist))
+               xtimer->tt_persist = ticks_to_msecs(timer->tt_persist.c_time - 
ticks);
+       if (callout_active(&timer->tt_keep))
+               xtimer->tt_keep = ticks_to_msecs(timer->tt_keep.c_time - ticks);
+       if (callout_active(&timer->tt_2msl))
+               xtimer->tt_2msl = ticks_to_msecs(timer->tt_2msl.c_time - ticks);
+       xtimer->t_rcvtime = ticks_to_msecs(ticks - tp->t_rcvtime);
+}

Modified: head/sys/netinet/tcp_timer.h
==============================================================================
--- head/sys/netinet/tcp_timer.h        Wed Sep 16 03:49:54 2009        
(r197243)
+++ head/sys/netinet/tcp_timer.h        Wed Sep 16 05:33:15 2009        
(r197244)
@@ -141,6 +141,8 @@ static const char *tcptimers[] =
 
 #ifdef _KERNEL
 
+struct xtcp_timer;
+
 struct tcp_timer {
        struct  callout tt_rexmt;       /* retransmit timer */
        struct  callout tt_persist;     /* retransmit persistence */
@@ -177,6 +179,8 @@ void        tcp_timer_keep(void *xtp);
 void   tcp_timer_persist(void *xtp);
 void   tcp_timer_rexmt(void *xtp);
 void   tcp_timer_delack(void *xtp);
+void   tcp_timer_to_xtimer(struct tcpcb *tp, struct tcp_timer *timer,
+       struct xtcp_timer *xtimer);
 
 #endif /* _KERNEL */
 

Modified: head/sys/netinet/tcp_var.h
==============================================================================
--- head/sys/netinet/tcp_var.h  Wed Sep 16 03:49:54 2009        (r197243)
+++ head/sys/netinet/tcp_var.h  Wed Sep 16 05:33:15 2009        (r197244)
@@ -495,11 +495,20 @@ void      kmod_tcpstat_inc(int statnum);
  * included.  Not all of our clients do.
  */
 #if defined(_NETINET_IN_PCB_H_) && defined(_SYS_SOCKETVAR_H_)
+struct xtcp_timer {
+       int tt_rexmt;   /* retransmit timer */
+       int tt_persist; /* retransmit persistence */
+       int tt_keep;    /* keepalive */
+       int tt_2msl;    /* 2*msl TIME_WAIT timer */
+       int tt_delack;  /* delayed ACK timer */
+       int t_rcvtime;  /* Time since last packet received */
+};
 struct xtcpcb {
        size_t  xt_len;
        struct  inpcb   xt_inp;
        struct  tcpcb   xt_tp;
        struct  xsocket xt_socket;
+       struct  xtcp_timer xt_timer;
        u_quad_t        xt_alignment_hack;
 };
 #endif

Modified: head/usr.bin/netstat/inet.c
==============================================================================
--- head/usr.bin/netstat/inet.c Wed Sep 16 03:49:54 2009        (r197243)
+++ head/usr.bin/netstat/inet.c Wed Sep 16 05:33:15 2009        (r197244)
@@ -313,6 +313,7 @@ protopr(u_long off, const char *name, in
        struct inpcb *inp;
        struct xinpgen *xig, *oxig;
        struct xsocket *so;
+       struct xtcp_timer *timer;
 
        istcp = 0;
        switch (proto) {
@@ -347,6 +348,7 @@ protopr(u_long off, const char *name, in
             xig->xig_len > sizeof(struct xinpgen);
             xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
                if (istcp) {
+                       timer = &((struct xtcpcb *)xig)->xt_timer;
                        tp = &((struct xtcpcb *)xig)->xt_tp;
                        inp = &((struct xtcpcb *)xig)->xt_inp;
                        so = &((struct xtcpcb *)xig)->xt_socket;
@@ -414,14 +416,17 @@ protopr(u_long off, const char *name, in
                                       "%-5.5s %-6.6s %-6.6s  %-22.22s 
%-22.22s",
                                       "Proto", "Recv-Q", "Send-Q",
                                       "Local Address", "Foreign Address");
-                               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",
+                               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 ",
                                                "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
+                                               "S-BCNT", "R-BMAX", "S-BMAX");
+                                       printf("%7.7s %7.7s %7.7s %7.7s %7.7s 
%7.7s %s\n",
+                                               "rexmt", "persist", "keep",
+                                               "2msl", "delack", "rcvtime",
+                                               "(state)");
+                               } else
                                        printf("(state)\n");
                        }
                        first = 0;
@@ -516,7 +521,7 @@ protopr(u_long off, const char *name, in
                                       so->so_rcv.sb_lowat, so->so_snd.sb_lowat,
                                       so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt,
                                       so->so_rcv.sb_mbmax, 
so->so_snd.sb_mbmax);
-                       else
+                       else {
                                printf("%6u %6u %6u %6u %6u %6u %6u %6u %6u %6u 
%6u %6u ",
                                       so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt,
                                       so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt,
@@ -524,6 +529,14 @@ protopr(u_long off, const char *name, in
                                       so->so_rcv.sb_lowat, so->so_snd.sb_lowat,
                                       so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt,
                                       so->so_rcv.sb_mbmax, 
so->so_snd.sb_mbmax);
+                               printf("%4d.%02d %4d.%02d %4d.%02d %4d.%02d 
%4d.%02d %4d.%02d ",
+                                       timer->tt_rexmt / 1000, 
(timer->tt_rexmt % 1000) / 10,
+                                       timer->tt_persist / 1000, 
(timer->tt_persist % 1000) / 10,
+                                       timer->tt_keep / 1000, (timer->tt_keep 
% 1000) / 10,
+                                       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 (istcp && !Lflag) {
                        if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)

Modified: head/usr.bin/netstat/netstat.1
==============================================================================
--- head/usr.bin/netstat/netstat.1      Wed Sep 16 03:49:54 2009        
(r197243)
+++ head/usr.bin/netstat/netstat.1      Wed Sep 16 05:33:15 2009        
(r197244)
@@ -87,7 +87,7 @@ show network addresses as numbers (as wi
 but show ports symbolically.
 If
 .Fl x
-is present display full socket buffer statistics for each internet socket.
+is present, display socket buffer and tcp timer statistics for each internet 
socket.
 .It Xo
 .Bk -words
 .Nm
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to