From: Sepherosa Ziehau Date: Tue, 21 Dec 2010 08:26:34 +0000 (+0800) Subject: tcp: Don't allow persist timer if TCP connection is not established yet X-Git-Tag: v2.11.0~431 X-Git-Url: http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/94603b1beafe1a82c4e61c095b5dcd978c5e8d58 tcp: Don't allow persist timer if TCP connection is not established yet This probably could move the un-updated snd_nxt panic earlier. The dump of the panic in http://bugs.dragonflybsd.org/issue1939 shows - snd_nxt is less than snd_una - A persist timer was fired (frame 16, tp->tt_msg->tt_prev_tasks). - The TCP segment triggered the panic has SYN|ACK (frame 17, th->th_flags). This TCP segment is considered as valid (frame 17, list), so tp->t_state was SYN_SENT. This explains why snd_nxt is less than snd_una: If tcp_output() is called by persist timer, then the persist timer is active and the "forced" is turned on, this causes the snd_nxt not updated at all. MISSING CHIAN IN THE LINK: How is the persist timer got set in the SYN_SENT in the first place? Hope the new panic could lift the veil... --- diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 37bd350de3..17b4b9adad 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -933,7 +933,7 @@ send: */ int xlen = len; if (flags & TH_SYN) - ++xlen; + panic("tcp_output: persist timer to send SYN\n"); if (flags & TH_FIN) { ++xlen; tp->t_flags |= TF_SENTFIN; @@ -1081,6 +1081,9 @@ tcp_setpersist(struct tcpcb *tp) int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; int tt; + if (tp->t_state < TCPS_ESTABLISHED) + panic("tcp_setpersist: not established yet\n"); + if (tcp_callout_active(tp, tp->tt_rexmt)) panic("tcp_setpersist: retransmit pending"); /*