tcp: Don't allow persist timer if TCP connection is not established yet
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 21 Dec 2010 08:26:34 +0000 (16:26 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 21 Dec 2010 09:07:22 +0000 (17:07 +0800)
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...

sys/netinet/tcp_output.c

index 37bd350..17b4b9a 100644 (file)
@@ -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");
        /*