]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet/tcp_sack.c
xnu-2050.24.15.tar.gz
[apple/xnu.git] / bsd / netinet / tcp_sack.c
index 0ea4185500e7ed7493a86dfb5caf6d968f1dd0d4..69fb8a7d08f36d2fa2aa7dbba5095765afe467c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2004,2007 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -72,6 +72,8 @@
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 
+#include <kern/zalloc.h>
+
 #include <net/route.h>
 
 #include <netinet/in.h>
 #endif /*IPSEC*/
 
 int    tcp_do_sack = 1;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, sack, CTLFLAG_RW, &tcp_do_sack, 0,
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, sack, CTLFLAG_RW | CTLFLAG_LOCKED, &tcp_do_sack, 0,
        "Enable/Disable TCP SACK support");
 static int tcp_sack_maxholes = 128;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, sack_maxholes, CTLFLAG_RW,
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, sack_maxholes, CTLFLAG_RW | CTLFLAG_LOCKED,
        &tcp_sack_maxholes, 0, 
     "Maximum number of TCP SACK holes allowed per connection");
 
 static int tcp_sack_globalmaxholes = 65536;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, sack_globalmaxholes, CTLFLAG_RW,
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, sack_globalmaxholes, CTLFLAG_RW | CTLFLAG_LOCKED,
        &tcp_sack_globalmaxholes, 0, 
     "Global maximum number of TCP SACK holes");
 
 static int tcp_sack_globalholes = 0;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, sack_globalholes, CTLFLAG_RD,
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, sack_globalholes, CTLFLAG_RD | CTLFLAG_LOCKED,
     &tcp_sack_globalholes, 0,
     "Global number of TCP SACK holes currently allocated");
 
@@ -201,6 +203,18 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end)
 
        /* Save the number of SACK blocks. */
        tp->rcv_numsacks = num_head + num_saved;
+
+       /* If we are requesting SACK recovery, reset the stretch-ack state
+        * so that connection will generate more acks after recovery and
+        * sender's cwnd will open.
+        */
+       if ((tp->t_flags & TF_STRETCHACK) != 0 && tp->rcv_numsacks > 0)
+               tcp_reset_stretch_ack(tp);
+
+#if TRAFFIC_MGT
+       if (tp->acc_iaj > 0 && tp->rcv_numsacks > 0) 
+               reset_acc_iaj(tp);
+#endif /* TRAFFIC_MGT */
 }
 
 /*
@@ -209,13 +223,8 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end)
 void
 tcp_clean_sackreport( struct tcpcb *tp)
 {
-/*
-       int i;
 
        tp->rcv_numsacks = 0;
-       for (i = 0; i < MAX_SACK_BLKS; i++)
-               tp->sackblks[i].start = tp->sackblks[i].end=0;
-*/
        bzero(&tp->sackblks[0], sizeof (struct sackblk) * MAX_SACK_BLKS);
 }
 
@@ -326,16 +335,20 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack)
        }
        /*
         * Append received valid SACK blocks to sack_blocks[].
+        * Check that the SACK block range is valid.
         */
-       for (i = 0; i < to->to_nsacks; i++) {
-               bcopy((to->to_sacks + i * TCPOLEN_SACK), &sack, sizeof(sack));
-               sack.start = ntohl(sack.start);
-               sack.end = ntohl(sack.end);
-               if (SEQ_GT(sack.end, sack.start) &&
-                   SEQ_GT(sack.start, tp->snd_una) &&
-                   SEQ_GT(sack.start, th_ack) &&
-                   SEQ_LEQ(sack.end, tp->snd_max))
-                       sack_blocks[num_sack_blks++] = sack;
+               for (i = 0; i < to->to_nsacks; i++) {
+                       bcopy((to->to_sacks + i * TCPOLEN_SACK),
+                           &sack, sizeof(sack));
+                       sack.start = ntohl(sack.start);
+                       sack.end = ntohl(sack.end);
+                       if (SEQ_GT(sack.end, sack.start) &&
+                           SEQ_GT(sack.start, tp->snd_una) &&
+                           SEQ_GT(sack.start, th_ack) &&
+                           SEQ_LT(sack.start, tp->snd_max) &&
+                           SEQ_GT(sack.end, tp->snd_una) &&
+                           SEQ_LEQ(sack.end, tp->snd_max))
+                               sack_blocks[num_sack_blks++] = sack;
        }
 
        /*
@@ -502,6 +515,8 @@ tcp_free_sackholes(struct tcpcb *tp)
        while ((q = TAILQ_FIRST(&tp->snd_holes)) != NULL)
                tcp_sackhole_remove(tp, q);
        tp->sackhint.sack_bytes_rexmit = 0;
+       tp->sackhint.nexthole = NULL;
+       tp->sack_newdata = 0;
 
 }