tcp: Support settable IW parameters
[dragonfly.git] / sys / netinet / tcp_subr.c
index c848fe3..79dafc2 100644 (file)
@@ -65,7 +65,6 @@
  *
  *     @(#)tcp_subr.c  8.2 (Berkeley) 5/24/95
  * $FreeBSD: src/sys/netinet/tcp_subr.c,v 1.73.2.31 2003/01/24 05:11:34 sam Exp $
- * $DragonFly: src/sys/netinet/tcp_subr.c,v 1.63 2008/11/11 10:46:58 sephe Exp $
  */
 
 #include "opt_compat.h"
 #if !defined(KTR_TCP)
 #define KTR_TCP                KTR_ALL
 #endif
-KTR_INFO_MASTER(tcp);
 /*
+KTR_INFO_MASTER(tcp);
 KTR_INFO(KTR_TCP, tcp, rxmsg, 0, "tcp getmsg", 0);
 KTR_INFO(KTR_TCP, tcp, wait, 1, "tcp waitmsg", 0);
 KTR_INFO(KTR_TCP, tcp, delayed, 2, "tcp execute delayed ops", 0);
-*/
 #define logtcp(name)   KTR_LOG(tcp_ ## name)
+*/
 
 struct inpcbinfo tcbinfo[MAXCPU];
 struct tcpcbackqhead tcpcbackq[MAXCPU];
@@ -247,6 +246,23 @@ static int tcp_inflight_stab = 50;
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, inflight_stab, CTLFLAG_RW,
     &tcp_inflight_stab, 0, "Slop in maximal packets / 10 (20 = 3 packets)");
 
+static int tcp_do_rfc3390 = 1;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, rfc3390, CTLFLAG_RW,
+    &tcp_do_rfc3390, 0,
+    "Enable RFC 3390 (Increasing TCP's Initial Congestion Window)");
+
+static u_long tcp_iw_maxsegs = 4;
+SYSCTL_ULONG(_net_inet_tcp, OID_AUTO, iwmaxsegs, CTLFLAG_RW,
+    &tcp_iw_maxsegs, 0, "TCP IW segments max");
+
+static u_long tcp_iw_capsegs = 3;
+SYSCTL_ULONG(_net_inet_tcp, OID_AUTO, iwcapsegs, CTLFLAG_RW,
+    &tcp_iw_capsegs, 0, "TCP IW segments");
+
+int tcp_low_rtobase = 1;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, low_rtobase, CTLFLAG_RW,
+    &tcp_low_rtobase, 0, "Lowering the Initial RTO (RFC 6298)");
+
 static MALLOC_DEFINE(M_TCPTEMP, "tcptemp", "TCP Templates for Keepalives");
 static struct malloc_pipe tcptemp_mpipe;
 
@@ -695,6 +711,12 @@ tcp_newtcpcb(struct inpcb *inp)
        tp->tt_msg = &it->inp_tp_timermsg;
        bzero(tp->tt_msg, sizeof(*tp->tt_msg));
 
+       tp->t_keepinit = tcp_keepinit;
+       tp->t_keepidle = tcp_keepidle;
+       tp->t_keepintvl = tcp_keepintvl;
+       tp->t_keepcnt = tcp_keepcnt;
+       tp->t_maxidle = tp->t_keepintvl * tp->t_keepcnt;
+
        if (tcp_do_rfc1323)
                tp->t_flags = (TF_REQ_SCALE | TF_REQ_TSTMP);
        tp->t_inpcb = inp;      /* XXX */
@@ -952,7 +974,7 @@ no_valid_rt:
        while((q = LIST_FIRST(&tp->t_segq)) != NULL) {
                LIST_REMOVE(q, tqe_q);
                m_freem(q->tqe_m);
-               FREE(q, M_TSEGQ);
+               kfree(q, M_TSEGQ);
                atomic_add_int(&tcp_reass_qsize, -1);
        }
        /* throw away SACK blocks in scoreboard*/
@@ -1004,7 +1026,7 @@ tcp_drain_oncpu(struct inpcbhead *head)
                    (te = LIST_FIRST(&tcpb->t_segq)) != NULL) {
                        LIST_REMOVE(te, tqe_q);
                        m_freem(te->tqe_m);
-                       FREE(te, M_TSEGQ);
+                       kfree(te, M_TSEGQ);
                        atomic_add_int(&tcp_reass_qsize, -1);
                        /* retry */
                } else {
@@ -1950,6 +1972,52 @@ tcp_xmit_bandwidth_limit(struct tcpcb *tp, tcp_seq ack_seq)
        tp->snd_bwnd = bwnd;
 }
 
+u_long
+tcp_initial_window(const struct tcpcb *tp)
+{
+       if (tcp_do_rfc3390) {
+               /*
+                * RFC3390:
+                * "If the SYN or SYN/ACK is lost, the initial window
+                *  used by a sender after a correctly transmitted SYN
+                *  MUST be one segment consisting of MSS bytes."
+                *
+                * However, we do something a little bit more aggressive
+                * then RFC3390 here:
+                * - Only if time spent in the SYN or SYN|ACK retransmition
+                *   >= 3 seconds, the IW is reduced.  We do this mainly
+                *   because when RFC3390 is published, the initial RTO is
+                *   still 3 seconds (the threshold we test here), while
+                *   after RFC6298, the initial RTO is 1 second.  This
+                *   behaviour probably still falls within the spirit of
+                *   RFC3390.
+                * - When IW is reduced, 2*MSS is used instead of 1*MSS.
+                *   Mainly to avoid sender and receiver deadlock until
+                *   delayed ACK timer expires.  And even RFC2581 does not
+                *   try to reduce IW upon SYN or SYN|ACK retransmition
+                *   timeout.
+                *
+                * See also:
+                * http://tools.ietf.org/html/draft-ietf-tcpm-initcwnd-03
+                */
+               if (tp->t_rxtsyn >= TCPTV_RTOBASE3) {
+                       return (2 * tp->t_maxseg);
+               } else {
+                       return min(tcp_iw_maxsegs * tp->t_maxseg,
+                                  max(2 * tp->t_maxseg,
+                                      tcp_iw_capsegs * 1460));
+               }
+       } else {
+               /*
+                * Even RFC2581 (back to 1999) allows 2*SMSS IW.
+                *
+                * Mainly to avoid sender and receiver deadlock
+                * until delayed ACK timer expires.
+                */
+               return (2 * tp->t_maxseg);
+       }
+}
+
 #ifdef TCP_SIGNATURE
 /*
  * Compute TCP-MD5 hash of a TCP segment. (RFC2385)