From ded53b4033d64348edff9f7b9fe6d19d8d418ad2 Mon Sep 17 00:00:00 2001 From: silby Date: Wed, 16 Sep 2009 05:33:15 +0000 Subject: 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 --- sys/netinet/tcp_subr.c | 5 ++++- sys/netinet/tcp_timer.c | 21 +++++++++++++++++++++ sys/netinet/tcp_timer.h | 4 ++++ sys/netinet/tcp_var.h | 9 +++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) (limited to 'sys/netinet') diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 22b2ace..d0b2e0e 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -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 { diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 7f5d159..8ead3dc 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -659,3 +659,24 @@ tcp_timer_active(struct tcpcb *tp, int timer_type) } 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); +} diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h index ff455b6..1ab0b7b 100644 --- a/sys/netinet/tcp_timer.h +++ b/sys/netinet/tcp_timer.h @@ -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 */ diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 96353f3..93d3feb 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -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 -- cgit v1.1