much longer keepalive timer (don't start probes for 2 hr);
authorMike Karels <karels@ucbvax.Berkeley.EDU>
Thu, 17 Mar 1988 01:05:25 +0000 (17:05 -0800)
committerMike Karels <karels@ucbvax.Berkeley.EDU>
Thu, 17 Mar 1988 01:05:25 +0000 (17:05 -0800)
fix input window test again (accept acks from FINS at left edge and responses
to keepalives, but dropafterack otherwise; also fixes Phil Karn's problem
with failure to respond to new SYN to left of window); can't use tcp_drop
after RST, or we'll send RST in response

SCCS-vsn: sys/netinet/tcp_input.c 7.17
SCCS-vsn: sys/netinet/tcp_timer.c 7.12
SCCS-vsn: sys/netinet/tcp_timer.h 7.5
SCCS-vsn: sys/netinet/tcp_usrreq.c 7.8

usr/src/sys/netinet/tcp_input.c
usr/src/sys/netinet/tcp_timer.c
usr/src/sys/netinet/tcp_timer.h
usr/src/sys/netinet/tcp_usrreq.c

index 6833eab..4dd745e 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 1982, 1986 Regents of the University of California.
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms are permitted
@@ -9,7 +9,7 @@
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
- *     @(#)tcp_input.c 7.16 (Berkeley) %G%
+ *     @(#)tcp_input.c 7.17 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -331,7 +331,7 @@ findpcb:
         * Reset idle time and keep-alive timer.
         */
        tp->t_idle = 0;
         * Reset idle time and keep-alive timer.
         */
        tp->t_idle = 0;
-       tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
+       tp->t_timer[TCPT_KEEP] = tcp_keepidle;
 
        /*
         * Process options if not in LISTEN state,
 
        /*
         * Process options if not in LISTEN state,
@@ -420,7 +420,7 @@ findpcb:
                tcp_rcvseqinit(tp);
                tp->t_flags |= TF_ACKNOW;
                tp->t_state = TCPS_SYN_RECEIVED;
                tcp_rcvseqinit(tp);
                tp->t_flags |= TF_ACKNOW;
                tp->t_state = TCPS_SYN_RECEIVED;
-               tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
+               tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
                dropsocket = 0;         /* committed to socket */
                tcpstat.tcps_accepts++;
                goto trimthenstep6;
                dropsocket = 0;         /* committed to socket */
                tcpstat.tcps_accepts++;
                goto trimthenstep6;
@@ -529,18 +529,28 @@ trimthenstep6:
                }
                if (todrop > ti->ti_len ||
                    todrop == ti->ti_len && (tiflags&TH_FIN) == 0) {
                }
                if (todrop > ti->ti_len ||
                    todrop == ti->ti_len && (tiflags&TH_FIN) == 0) {
-#ifdef TCP_COMPAT_42
+                       tcpstat.tcps_rcvduppack++;
+                       tcpstat.tcps_rcvdupbyte += ti->ti_len;
                        /*
                        /*
-                        * Don't toss RST in response to 4.2-style keepalive.
+                        * If segment is just one to the left of the window,
+                        * check two special cases:
+                        * 1. Don't toss RST in response to 4.2-style keepalive.
+                        * 2. If the only thing to drop is a FIN, we can drop
+                        *    it, but check the ACK or we will get into FIN
+                        *    wars if our FINs crossed (both CLOSING).
+                        * In either case, send ACK to resynchronize,
+                        * but keep on processing for RST or ACK.
                         */
                         */
-                       if (ti->ti_seq == tp->rcv_nxt - 1 && tiflags & TH_RST)
-                               goto do_rst;
+                       if ((tiflags & TH_FIN && todrop == ti->ti_len + 1)
+#ifdef TCP_COMPAT_42
+                         || (tiflags & TH_RST && ti->ti_seq == tp->rcv_nxt - 1)
 #endif
 #endif
-                       tcpstat.tcps_rcvduppack++;
-                       tcpstat.tcps_rcvdupbyte += ti->ti_len;
-                       todrop = ti->ti_len;
-                       tiflags &= ~TH_FIN;
-                       tp->t_flags |= TF_ACKNOW;
+                          ) {
+                               todrop = ti->ti_len;
+                               tiflags &= ~TH_FIN;
+                               tp->t_flags |= TF_ACKNOW;
+                       } else
+                               goto dropafterack;
                } else {
                        tcpstat.tcps_rcvpartduppack++;
                        tcpstat.tcps_rcvpartdupbyte += todrop;
                } else {
                        tcpstat.tcps_rcvpartduppack++;
                        tcpstat.tcps_rcvpartdupbyte += todrop;
@@ -557,7 +567,7 @@ trimthenstep6:
        }
 
        /*
        }
 
        /*
-        * If new data is received on a connection after the
+        * If new data are received on a connection after the
         * user processes are gone, then RST the other end.
         */
        if ((so->so_state & SS_NOFDREF) &&
         * user processes are gone, then RST the other end.
         */
        if ((so->so_state & SS_NOFDREF) &&
@@ -618,9 +628,6 @@ trimthenstep6:
                tiflags &= ~(TH_PUSH|TH_FIN);
        }
 
                tiflags &= ~(TH_PUSH|TH_FIN);
        }
 
-#ifdef TCP_COMPAT_42
-do_rst:
-#endif
        /*
         * If the RST bit is set examine the state:
         *    SYN_RECEIVED STATE:
        /*
         * If the RST bit is set examine the state:
         *    SYN_RECEIVED STATE:
@@ -634,14 +641,18 @@ do_rst:
        if (tiflags&TH_RST) switch (tp->t_state) {
 
        case TCPS_SYN_RECEIVED:
        if (tiflags&TH_RST) switch (tp->t_state) {
 
        case TCPS_SYN_RECEIVED:
-               tp = tcp_drop(tp, ECONNREFUSED);
-               goto drop;
+               so->so_error = ECONNREFUSED;
+               goto close;
 
        case TCPS_ESTABLISHED:
        case TCPS_FIN_WAIT_1:
        case TCPS_FIN_WAIT_2:
        case TCPS_CLOSE_WAIT:
 
        case TCPS_ESTABLISHED:
        case TCPS_FIN_WAIT_1:
        case TCPS_FIN_WAIT_2:
        case TCPS_CLOSE_WAIT:
-               tp = tcp_drop(tp, ECONNRESET);
+               so->so_error = ECONNRESET;
+       close:
+               tp->t_state = TCPS_CLOSED;
+               tcpstat.tcps_drops++;
+               tp = tcp_close(tp);
                goto drop;
 
        case TCPS_CLOSING:
                goto drop;
 
        case TCPS_CLOSING:
@@ -788,8 +799,7 @@ do_rst:
                                 * (srtt = rtt/8 + srtt*7/8 in fixed point).
                                 * Adjust t_rtt to origin 0.
                                 */
                                 * (srtt = rtt/8 + srtt*7/8 in fixed point).
                                 * Adjust t_rtt to origin 0.
                                 */
-                               tp->t_rtt--;
-                               delta = tp->t_rtt - (tp->t_srtt >> 3);
+                               delta = tp->t_rtt - 1 - (tp->t_srtt >> 3);
                                if ((tp->t_srtt += delta) <= 0)
                                        tp->t_srtt = 1;
                                /*
                                if ((tp->t_srtt += delta) <= 0)
                                        tp->t_srtt = 1;
                                /*
@@ -885,7 +895,7 @@ do_rst:
                                 */
                                if (so->so_state & SS_CANTRCVMORE) {
                                        soisdisconnected(so);
                                 */
                                if (so->so_state & SS_CANTRCVMORE) {
                                        soisdisconnected(so);
-                                       tp->t_timer[TCPT_2MSL] = TCPTV_MAXIDLE;
+                                       tp->t_timer[TCPT_2MSL] = tcp_maxidle;
                                }
                                tp->t_state = TCPS_FIN_WAIT_2;
                        }
                                }
                                tp->t_state = TCPS_FIN_WAIT_2;
                        }
index ca92942..493d38f 100644 (file)
@@ -9,7 +9,7 @@
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
- *     @(#)tcp_timer.c 7.11.1.1 (Berkeley) %G%
+ *     @(#)tcp_timer.c 7.12 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -36,6 +36,9 @@
 #include "tcpip.h"
 
 int    tcpnodelack = 0;
 #include "tcpip.h"
 
 int    tcpnodelack = 0;
+int    tcp_keepidle = TCPTV_KEEP_IDLE;
+int    tcp_keepintvl = TCPTV_KEEPINTVL;
+int    tcp_maxidle;
 /*
  * Fast timeout routine for processing delayed acks
  */
 /*
  * Fast timeout routine for processing delayed acks
  */
@@ -70,6 +73,7 @@ tcp_slowtimo()
        int s = splnet();
        register int i;
 
        int s = splnet();
        register int i;
 
+       tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;
        /*
         * Search through tcb's and update active timers.
         */
        /*
         * Search through tcb's and update active timers.
         */
@@ -141,8 +145,8 @@ tcp_timers(tp, timer)
         */
        case TCPT_2MSL:
                if (tp->t_state != TCPS_TIME_WAIT &&
         */
        case TCPT_2MSL:
                if (tp->t_state != TCPS_TIME_WAIT &&
-                   tp->t_idle <= TCPTV_MAXIDLE)
-                       tp->t_timer[TCPT_2MSL] = TCPTV_KEEP;
+                   tp->t_idle <= tcp_maxidle)
+                       tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
                else
                        tp = tcp_close(tp);
                break;
                else
                        tp = tcp_close(tp);
                break;
@@ -240,7 +244,7 @@ tcp_timers(tp, timer)
                        goto dropit;
                if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE &&
                    tp->t_state <= TCPS_CLOSE_WAIT) {
                        goto dropit;
                if (tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE &&
                    tp->t_state <= TCPS_CLOSE_WAIT) {
-                       if (tp->t_idle >= TCPTV_MAXIDLE)
+                       if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
                                goto dropit;
                        /*
                         * Send a packet designed to force a response
                                goto dropit;
                        /*
                         * Send a packet designed to force a response
@@ -266,8 +270,9 @@ tcp_timers(tp, timer)
                        tcp_respond(tp, tp->t_template,
                            tp->rcv_nxt, tp->snd_una - 1, 0);
 #endif
                        tcp_respond(tp, tp->t_template,
                            tp->rcv_nxt, tp->snd_una - 1, 0);
 #endif
-               }
-               tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
+                       tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
+               } else
+                       tp->t_timer[TCPT_KEEP] = tcp_keepidle;
                break;
        dropit:
                tcpstat.tcps_keepdrops++;
                break;
        dropit:
                tcpstat.tcps_keepdrops++;
index a122a07..17eb118 100644 (file)
@@ -9,7 +9,7 @@
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
- *     @(#)tcp_timer.h 7.4 (Berkeley) %G%
+ *     @(#)tcp_timer.h 7.5 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
  * a window update from the peer.
  *
  * The TCPT_KEEP timer is used to keep connections alive.  If an
  * a window update from the peer.
  *
  * The TCPT_KEEP timer is used to keep connections alive.  If an
- * connection is idle (no segments received) for TCPTV_KEEP amount of time,
- * but not yet established, then we drop the connection.  If the connection
- * is established, then we force the peer to send us a segment by sending:
+ * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time,
+ * but not yet established, then we drop the connection.  Once the connection
+ * is established, if the connection is idle for TCPTV_KEEP_IDLE time
+ * (and keepalives have been enabled on the socket), we begin to probe
+ * the connection.  We force the peer to send us a segment by sending:
  *     <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>
  * This segment is (deliberately) outside the window, and should elicit
  * an ack segment in response from the peer.  If, despite the TCPT_KEEP
  * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE
  *     <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>
  * This segment is (deliberately) outside the window, and should elicit
  * an ack segment in response from the peer.  If, despite the TCPT_KEEP
  * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE
- * amount of time, then we drop the connection.
+ * amount of time probing, then we drop the connection.
  */
 
 #define        TCP_TTL         30              /* default time to live for TCP segs */
  */
 
 #define        TCP_TTL         30              /* default time to live for TCP segs */
-int    tcp_ttl;                        /* time to live for TCP segs */
 /*
  * Time constants.
  */
 /*
  * Time constants.
  */
-#define        TCPTV_MSL       ( 15*PR_SLOWHZ)         /* max seg lifetime */
+#define        TCPTV_MSL       ( 30*PR_SLOWHZ)         /* max seg lifetime (hah!) */
 #define        TCPTV_SRTTBASE  0                       /* base roundtrip time;
                                                   if 0, no idea yet */
 #define        TCPTV_SRTTDFLT  (  3*PR_SLOWHZ)         /* assumed RTT if no info */
 #define        TCPTV_SRTTBASE  0                       /* base roundtrip time;
                                                   if 0, no idea yet */
 #define        TCPTV_SRTTDFLT  (  3*PR_SLOWHZ)         /* assumed RTT if no info */
@@ -70,9 +71,10 @@ int  tcp_ttl;                        /* time to live for TCP segs */
 #define        TCPTV_PERSMIN   (  5*PR_SLOWHZ)         /* retransmit persistance */
 #define        TCPTV_PERSMAX   ( 60*PR_SLOWHZ)         /* maximum persist interval */
 
 #define        TCPTV_PERSMIN   (  5*PR_SLOWHZ)         /* retransmit persistance */
 #define        TCPTV_PERSMAX   ( 60*PR_SLOWHZ)         /* maximum persist interval */
 
-#define        TCPTV_KEEP      ( 75*PR_SLOWHZ)         /* keep alive - 75 secs */
-#define        TCPTV_MAXIDLE   (  8*TCPTV_KEEP)        /* maximum allowable idle
-                                                  time before drop conn */
+#define        TCPTV_KEEP_INIT ( 75*PR_SLOWHZ)         /* initial connect keep alive */
+#define        TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ)      /* dflt time before probing */
+#define        TCPTV_KEEPINTVL ( 75*PR_SLOWHZ)         /* default probe interval */
+#define        TCPTV_KEEPCNT   8                       /* max probes before drop */
 
 #define        TCPTV_MIN       (  1*PR_SLOWHZ)         /* minimum allowable value */
 #define        TCPTV_REXMTMAX  ( 64*PR_SLOWHZ)         /* max allowable REXMT value */
 
 #define        TCPTV_MIN       (  1*PR_SLOWHZ)         /* minimum allowable value */
 #define        TCPTV_REXMTMAX  ( 64*PR_SLOWHZ)         /* max allowable REXMT value */
@@ -98,5 +100,9 @@ char *tcptimers[] =
 }
 
 #ifdef KERNEL
 }
 
 #ifdef KERNEL
+extern int tcp_keepidle;               /* time before keepalive probes begin */
+extern int tcp_keepintvl;              /* time between keepalive probes */
+extern int tcp_maxidle;                        /* time to drop after starting probes */
+extern int tcp_ttl;                    /* time to live for TCP segs */
 extern int tcp_backoff[];
 #endif
 extern int tcp_backoff[];
 #endif
index 6877d59..48f3fb4 100644 (file)
@@ -9,7 +9,7 @@
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
  * software without specific prior written permission. This software
  * is provided ``as is'' without express or implied warranty.
  *
- *     @(#)tcp_usrreq.c        7.7.1.1 (Berkeley) %G%
+ *     @(#)tcp_usrreq.c        7.8 (Berkeley) %G%
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -168,7 +168,7 @@ tcp_usrreq(so, req, m, nam, rights)
                soisconnecting(so);
                tcpstat.tcps_connattempt++;
                tp->t_state = TCPS_SYN_SENT;
                soisconnecting(so);
                tcpstat.tcps_connattempt++;
                tp->t_state = TCPS_SYN_SENT;
-               tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
+               tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
                tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
                tcp_sendseqinit(tp);
                error = tcp_output(tp);
                tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
                tcp_sendseqinit(tp);
                error = tcp_output(tp);