]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/tcp_newreno.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / bsd / netinet / tcp_newreno.c
index f2de1c010877404ab7391cdff64797c5aaa51f0b..2da158e2d614f74160cf34a2e72a7c1517e753bd 100644 (file)
@@ -71,9 +71,7 @@
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
 
-#if INET6
 #include <netinet/ip6.h>
-#endif
 #include <netinet/ip_var.h>
 #include <netinet/tcp.h>
 #include <netinet/tcp_fsm.h>
@@ -110,13 +108,17 @@ struct tcp_cc_algo tcp_cc_newreno = {
        .switch_to = tcp_newreno_switch_cc
 };
 
-int tcp_newreno_init(struct tcpcb *tp) {
+int
+tcp_newreno_init(struct tcpcb *tp)
+{
 #pragma unused(tp)
        OSIncrementAtomic((volatile SInt32 *)&tcp_cc_newreno.num_sockets);
        return 0;
 }
 
-int tcp_newreno_cleanup(struct tcpcb *tp) {
+int
+tcp_newreno_cleanup(struct tcpcb *tp)
+{
 #pragma unused(tp)
        OSDecrementAtomic((volatile SInt32 *)&tcp_cc_newreno.num_sockets);
        return 0;
@@ -132,7 +134,8 @@ int tcp_newreno_cleanup(struct tcpcb *tp) {
  * this is a local network or not.
  */
 void
-tcp_newreno_cwnd_init_or_reset(struct tcpcb *tp) {
+tcp_newreno_cwnd_init_or_reset(struct tcpcb *tp)
+{
        tcp_cc_cwnd_init_or_reset(tp);
 }
 
@@ -141,7 +144,8 @@ tcp_newreno_cwnd_init_or_reset(struct tcpcb *tp) {
  * This will get called from header prediction code.
  */
 void
-tcp_newreno_congestion_avd(struct tcpcb *tp, struct tcphdr *th) {
+tcp_newreno_congestion_avd(struct tcpcb *tp, struct tcphdr *th)
+{
        uint32_t acked = 0;
        acked = BYTES_ACKED(th, tp);
        /*
@@ -159,7 +163,8 @@ tcp_newreno_congestion_avd(struct tcpcb *tp, struct tcphdr *th) {
 /* Function to process an ack.
  */
 void
-tcp_newreno_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) {
+tcp_newreno_ack_rcvd(struct tcpcb *tp, struct tcphdr *th)
+{
        /*
         * RFC 3465 - Appropriate Byte Counting.
         *
@@ -173,70 +178,60 @@ tcp_newreno_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) {
         * greater than or equal to the congestion window.
         */
 
-       register u_int cw = tp->snd_cwnd;
-       register u_int incr = tp->t_maxseg;
-       int acked = 0;
+       uint32_t cw = tp->snd_cwnd;
+       uint32_t incr = tp->t_maxseg;
+       uint32_t acked = 0;
 
        acked = BYTES_ACKED(th, tp);
-       if (tcp_do_rfc3465) {
-
-               if (cw >= tp->snd_ssthresh) {
-                       tp->t_bytes_acked += acked;
-                       if (tp->t_bytes_acked >= cw) {
-                               /* Time to increase the window. */
-                               tp->t_bytes_acked -= cw;
-                       } else {
-                               /* No need to increase yet. */
-                               incr = 0;
-                       }
+       if (cw >= tp->snd_ssthresh) {
+               tp->t_bytes_acked += acked;
+               if (tp->t_bytes_acked >= cw) {
+                       /* Time to increase the window. */
+                       tp->t_bytes_acked -= cw;
                } else {
-                       /*
-                        * If the user explicitly enables RFC3465
-                        * use 2*SMSS for the "L" param.  Otherwise
-                        * use the more conservative 1*SMSS.
-                        *
-                        * (See RFC 3465 2.3 Choosing the Limit)
-                        */
-                       uint32_t abc_lim;
-                       abc_lim = (tcp_do_rfc3465_lim2 &&
-                               tp->snd_nxt == tp->snd_max) ? incr * 2 
-                               : incr;
-
-                       incr = lmin(acked, abc_lim);
+                       /* No need to increase yet. */
+                       incr = 0;
                }
        } else {
                /*
-                * If the window gives us less than ssthresh packets
-                * in flight, open exponentially (segsz per packet).
-                * Otherwise open linearly: segsz per window
-                * (segsz^2 / cwnd per packet).
+                * If the user explicitly enables RFC3465
+                * use 2*SMSS for the "L" param.  Otherwise
+                * use the more conservative 1*SMSS.
+                *
+                * (See RFC 3465 2.3 Choosing the Limit)
                 */
+               uint32_t abc_lim;
+               abc_lim = (tp->snd_nxt == tp->snd_max) ? incr * 2 : incr;
 
-               if (cw >= tp->snd_ssthresh)
-                       incr = max((incr * incr / cw), 1);
+               incr = ulmin(acked, abc_lim);
        }
-       tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<<tp->snd_scale);
+       tp->snd_cwnd = min(cw + incr, TCP_MAXWIN << tp->snd_scale);
 }
 
 void
-tcp_newreno_pre_fr(struct tcpcb *tp) {
-
+tcp_newreno_pre_fr(struct tcpcb *tp)
+{
        uint32_t win;
 
-       win = min(tp->snd_wnd, tp->snd_cwnd) / 
-               2 / tp->t_maxseg;
-       if ( win < 2 )
+       win = min(tp->snd_wnd, tp->snd_cwnd) /
+           2 / tp->t_maxseg;
+       if (win < 2) {
                win = 2;
-       tp->snd_ssthresh = win * tp->t_maxseg; 
+       }
+       tp->snd_ssthresh = win * tp->t_maxseg;
        tcp_cc_resize_sndbuf(tp);
-
 }
 
 void
-tcp_newreno_post_fr(struct tcpcb *tp, struct tcphdr *th) {
+tcp_newreno_post_fr(struct tcpcb *tp, struct tcphdr *th)
+{
        int32_t ss;
 
-       ss = tp->snd_max - th->th_ack;
+       if (th) {
+               ss = tp->snd_max - th->th_ack;
+       } else {
+               ss = tp->snd_max - tp->snd_una;
+       }
 
        /*
         * Complete ack.  Inflate the congestion window to
@@ -247,22 +242,24 @@ tcp_newreno_post_fr(struct tcpcb *tp, struct tcphdr *th) {
         * 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 
+        * 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)
+       if (ss < (int32_t)tp->snd_ssthresh) {
                tp->snd_cwnd = max(ss, tp->t_maxseg) + tp->t_maxseg;
-       else
+       } else {
                tp->snd_cwnd = tp->snd_ssthresh;
+       }
        tp->t_bytes_acked = 0;
 }
 
-/* Function to change the congestion window when the retransmit 
+/* Function to change the congestion window when the retransmit
  * timer fires.
  */
 void
-tcp_newreno_after_timeout(struct tcpcb *tp) {
+tcp_newreno_after_timeout(struct tcpcb *tp)
+{
        /*
         * Close the congestion window down to one segment
         * (we'll open it by one segment for each ack we get).
@@ -287,10 +284,11 @@ tcp_newreno_after_timeout(struct tcpcb *tp) {
         * growth is 2 mss.  We don't allow the threshhold
         * to go below this.)
         */
-       if (tp->t_state >=  TCPS_ESTABLISHED) {
+       if (tp->t_state >= TCPS_ESTABLISHED) {
                u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
-               if (win < 2)
+               if (win < 2) {
                        win = 2;
+               }
                tp->snd_ssthresh = win * tp->t_maxseg;
 
                tp->snd_cwnd = tp->t_maxseg;
@@ -301,44 +299,46 @@ tcp_newreno_after_timeout(struct tcpcb *tp) {
 /*
  * Indicate whether this ack should be delayed.
  * We can delay the ack if:
- *  - delayed acks are enabled and set to 1, same as when value is set to 2. 
+ *  - delayed acks are enabled and set to 1, same as when value is set to 2.
  *    We kept this for binary compatibility.
  *  - delayed acks are enabled and set to 2, will "ack every other packet"
  *      - if our last ack wasn't a 0-sized window.
- *      - if the peer hasn't sent us a TH_PUSH data packet (this solves 3649245). 
- *             If TH_PUSH is set, take this as a clue that we need to ACK 
- *             with no delay. This helps higher level protocols who won't send
- *             us more data even if the window is open because their 
+ *      - if the peer hasn't sent us a TH_PUSH data packet (this solves 3649245).
+ *             If TH_PUSH is set, take this as a clue that we need to ACK
+ *              with no delay. This helps higher level protocols who won't send
+ *             us more data even if the window is open because their
  *             last "segment" hasn't been ACKed
- *  - delayed acks are enabled and set to 3,  will do "streaming detection" 
+ *  - delayed acks are enabled and set to 3,  will do "streaming detection"
  *    (see the comment in tcp_input.c) and
  *      - if we receive more than "maxseg_unacked" full packets in the last 100ms
- *     - if the connection is not in slow-start or idle or loss/recovery states
+ *      - if the connection is not in slow-start or idle or loss/recovery states
  *      - if those criteria aren't met, it will ack every other packet.
  */
 
 int
-tcp_newreno_delay_ack(struct tcpcb *tp, struct tcphdr *th) {
-       return (tcp_cc_delay_ack(tp, th));
+tcp_newreno_delay_ack(struct tcpcb *tp, struct tcphdr *th)
+{
+       return tcp_cc_delay_ack(tp, th);
 }
 
 /* Switch to newreno from a different CC. If the connection is in
  * congestion avoidance state, it can continue to use the current
  * congestion window because it is going to be conservative. But
  * if the connection is in slow-start, we will halve the congestion
- * window and let newreno work from there. 
+ * window and let newreno work from there.
  */
 void
-tcp_newreno_switch_cc(struct tcpcb *tp, uint16_t old_index) {
+tcp_newreno_switch_cc(struct tcpcb *tp, uint16_t old_index)
+{
 #pragma unused(old_index)
 
        uint32_t cwnd = min(tp->snd_wnd, tp->snd_cwnd);
        if (tp->snd_cwnd >= tp->snd_ssthresh) {
                cwnd = cwnd / tp->t_maxseg;
-       } else { 
+       } else {
                cwnd = cwnd / 2 / tp->t_maxseg;
        }
-       tp->snd_cwnd = max(TCP_CC_CWND_INIT_BYTES, cwnd * tp->t_maxseg);
+       tp->snd_cwnd = max(tcp_initial_cwnd(tp), cwnd * tp->t_maxseg);
 
        /* Start counting bytes for RFC 3465 again */
        tp->t_bytes_acked = 0;