]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/tcp_newreno.c
xnu-3248.40.184.tar.gz
[apple/xnu.git] / bsd / netinet / tcp_newreno.c
index 5c9db2de9c4b336b5987c0bdb5d76340b7525379..f2de1c010877404ab7391cdff64797c5aaa51f0b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Apple Inc. All rights reserved.
+ * Copyright (c) 2010-2014 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
+/*
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
+ * $FreeBSD: src/sys/netinet/tcp_input.c,v 1.107.2.16 2001/08/22 00:59:12 silby Exp $
+ */
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/protosw.h>
+#include <sys/socketvar.h>
 
 #include <net/route.h>
 #include <netinet/in.h>
@@ -50,9 +86,9 @@
 int tcp_newreno_init(struct tcpcb *tp);
 int tcp_newreno_cleanup(struct tcpcb *tp);
 void tcp_newreno_cwnd_init_or_reset(struct tcpcb *tp);
-void tcp_newreno_inseq_ack_rcvd(struct tcpcb *tp, struct tcphdr *th);
+void tcp_newreno_congestion_avd(struct tcpcb *tp, struct tcphdr *th);
 void tcp_newreno_ack_rcvd(struct tcpcb *tp, struct tcphdr *th);
-void tcp_newreno_pre_fr(struct tcpcb *tp, struct tcphdr *th);
+void tcp_newreno_pre_fr(struct tcpcb *tp);
 void tcp_newreno_post_fr(struct tcpcb *tp, struct tcphdr *th);
 void tcp_newreno_after_idle(struct tcpcb *tp);
 void tcp_newreno_after_timeout(struct tcpcb *tp);
@@ -64,7 +100,7 @@ struct tcp_cc_algo tcp_cc_newreno = {
        .init = tcp_newreno_init,
        .cleanup = tcp_newreno_cleanup,
        .cwnd_init = tcp_newreno_cwnd_init_or_reset,
-       .inseq_ack_rcvd = tcp_newreno_inseq_ack_rcvd,
+       .congestion_avd = tcp_newreno_congestion_avd,
        .ack_rcvd = tcp_newreno_ack_rcvd,
        .pre_fr = tcp_newreno_pre_fr,
        .post_fr = tcp_newreno_post_fr,
@@ -74,10 +110,6 @@ struct tcp_cc_algo tcp_cc_newreno = {
        .switch_to = tcp_newreno_switch_cc
 };
 
-extern int tcp_do_rfc3465;
-extern int tcp_do_rfc3465_lim2;
-extern int maxseg_unacked;
-
 int tcp_newreno_init(struct tcpcb *tp) {
 #pragma unused(tp)
        OSIncrementAtomic((volatile SInt32 *)&tcp_cc_newreno.num_sockets);
@@ -101,22 +133,7 @@ int tcp_newreno_cleanup(struct tcpcb *tp) {
  */
 void
 tcp_newreno_cwnd_init_or_reset(struct tcpcb *tp) {
-       if ( tp->t_flags & TF_LOCAL )
-               tp->snd_cwnd = tp->t_maxseg * ss_fltsz_local;
-        else {
-               /* Calculate initial cwnd according to RFC3390,
-                * - On a standard link, this will result in a higher cwnd
-                * and improve initial transfer rate.
-                * - Keep the old ss_fltsz sysctl for ABI compabitility issues.
-                * but it will be overriden if tcp_do_rfc3390 sysctl is set.
-                */
-
-               if (tcp_do_rfc3390) 
-                       tp->snd_cwnd = min(4 * tp->t_maxseg, max(2 * tp->t_maxseg, 4380));
-
-               else
-                       tp->snd_cwnd = tp->t_maxseg * ss_fltsz;
-       }
+       tcp_cc_cwnd_init_or_reset(tp);
 }
 
 
@@ -124,9 +141,9 @@ tcp_newreno_cwnd_init_or_reset(struct tcpcb *tp) {
  * This will get called from header prediction code.
  */
 void
-tcp_newreno_inseq_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) {
-       int acked = 0;
-       acked = th->th_ack - tp->snd_una;
+tcp_newreno_congestion_avd(struct tcpcb *tp, struct tcphdr *th) {
+       uint32_t acked = 0;
+       acked = BYTES_ACKED(th, tp);
        /*
         * Grow the congestion window, if the
         * connection is cwnd bound.
@@ -160,7 +177,7 @@ tcp_newreno_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) {
        register u_int incr = tp->t_maxseg;
        int acked = 0;
 
-       acked = th->th_ack - tp->snd_una;
+       acked = BYTES_ACKED(th, tp);
        if (tcp_do_rfc3465) {
 
                if (cw >= tp->snd_ssthresh) {
@@ -180,10 +197,10 @@ tcp_newreno_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) {
                         *
                         * (See RFC 3465 2.3 Choosing the Limit)
                         */
-                       u_int abc_lim;
-
+                       uint32_t abc_lim;
                        abc_lim = (tcp_do_rfc3465_lim2 &&
-                               tp->snd_nxt == tp->snd_max) ? incr * 2 : incr;
+                               tp->snd_nxt == tp->snd_max) ? incr * 2 
+                               : incr;
 
                        incr = lmin(acked, abc_lim);
                }
@@ -202,8 +219,7 @@ tcp_newreno_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) {
 }
 
 void
-tcp_newreno_pre_fr(struct tcpcb *tp, struct tcphdr *th) {
-#pragma unused(th)
+tcp_newreno_pre_fr(struct tcpcb *tp) {
 
        uint32_t win;
 
@@ -212,6 +228,8 @@ tcp_newreno_pre_fr(struct tcpcb *tp, struct tcphdr *th) {
        if ( win < 2 )
                win = 2;
        tp->snd_ssthresh = win * tp->t_maxseg; 
+       tcp_cc_resize_sndbuf(tp);
+
 }
 
 void
@@ -228,9 +246,13 @@ tcp_newreno_post_fr(struct tcpcb *tp, struct tcphdr *th) {
         * snd_ssthresh outstanding data.  But in case we
         * would be inclined to send a burst, better to do
         * it via the slow start mechanism.
+        *
+        * If the flight size is zero, then make congestion 
+        * window to be worth at least 2 segments to avoid 
+        * delayed acknowledgement (draft-ietf-tcpm-rfc3782-bis-05).
         */
        if (ss < (int32_t)tp->snd_ssthresh)
-               tp->snd_cwnd = ss + tp->t_maxseg;
+               tp->snd_cwnd = max(ss, tp->t_maxseg) + tp->t_maxseg;
        else
                tp->snd_cwnd = tp->snd_ssthresh;
        tp->t_bytes_acked = 0;
@@ -269,10 +291,10 @@ tcp_newreno_after_timeout(struct tcpcb *tp) {
                u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
                if (win < 2)
                        win = 2;
-               tp->snd_cwnd = tp->t_maxseg;
                tp->snd_ssthresh = win * tp->t_maxseg;
-               tp->t_bytes_acked = 0;
-               tp->t_dupacks = 0;
+
+               tp->snd_cwnd = tp->t_maxseg;
+               tcp_cc_resize_sndbuf(tp);
        }
 }
 
@@ -297,24 +319,7 @@ tcp_newreno_after_timeout(struct tcpcb *tp) {
 
 int
 tcp_newreno_delay_ack(struct tcpcb *tp, struct tcphdr *th) {
-       switch (tcp_delack_enabled) {
-       case 1:
-       case 2:
-               if ((tp->t_flags & TF_RXWIN0SENT) == 0 &&
-                       (th->th_flags & TH_PUSH) == 0 &&
-                       (tp->t_flags & TF_DELACK) == 0)
-                       return(1);
-               break;
-       case 3:
-               if ((tp->t_flags & TF_RXWIN0SENT) == 0 &&
-                       (th->th_flags & TH_PUSH) == 0 &&
-                       ((tp->t_unacksegs == 0) ||
-                       ((tp->t_flags & TF_STRETCHACK) != 0 &&
-                       tp->t_unacksegs < (maxseg_unacked - 1))))
-                       return(1);
-               break;
-       }
-       return(0);
+       return (tcp_cc_delay_ack(tp, th));
 }
 
 /* Switch to newreno from a different CC. If the connection is in
@@ -333,9 +338,7 @@ tcp_newreno_switch_cc(struct tcpcb *tp, uint16_t old_index) {
        } else { 
                cwnd = cwnd / 2 / tp->t_maxseg;
        }
-       if (cwnd < 1)
-               cwnd = 1;
-       tp->snd_cwnd = cwnd * tp->t_maxseg;
+       tp->snd_cwnd = max(TCP_CC_CWND_INIT_BYTES, cwnd * tp->t_maxseg);
 
        /* Start counting bytes for RFC 3465 again */
        tp->t_bytes_acked = 0;