net: tcp: Adjust the transmit queue limit
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 19 Jun 2017 15:18:37 +0000 (11:18 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 20 Jul 2017 12:19:46 +0000 (08:19 -0400)
If we don't grow the queue limit as the cwnd grows, TCP blocks on waiting
for more data from the user.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/src/net/tcp.c

index ee76d4a..053d417 100644 (file)
@@ -1805,6 +1805,29 @@ void tcpsynackrtt(struct conv *s)
        tcphalt(tpriv, &tcb->rtt_timer);
 }
 
        tcphalt(tpriv, &tcb->rtt_timer);
 }
 
+/* For LFNs (long/fat), our default tx queue doesn't hold enough data, and TCP
+ * blocks on the application - even if the app already has the data ready to go.
+ * We need to hold the sent, unacked data (1x cwnd), plus all the data we might
+ * send next RTT (1x cwnd).  Note this is called after cwnd was expanded. */
+static void adjust_tx_qio_limit(struct conv *s)
+{
+       Tcpctl *tcb = (Tcpctl *) s->ptcl;
+       size_t ideal_limit = tcb->cwind * 2;
+
+       /* This is called for every ACK, and it's not entirely free to update the
+        * limit (locks, CVs, taps).  Updating in chunks of mss seems reasonable.
+        * During SS, we'll update this on most ACKs (given each ACK increased the
+        * cwind by > MSS).
+        *
+        * We also don't want a lot of tiny blocks from the user, but the way qio
+        * works, you can put in as much as you want (Maxatomic) and then get
+        * flow-controlled. */
+       if (qgetlimit(s->wq) + tcb->mss < ideal_limit)
+               qsetlimit(s->wq, ideal_limit);
+       /* TODO: we could shrink the qio limit too, if we had a better idea what the
+        * actual threshold was.  We want the limit to be the 'stable' cwnd * 2. */
+}
+
 void update(struct conv *s, Tcp * seg)
 {
        int rtt, delta;
 void update(struct conv *s, Tcp * seg)
 {
        int rtt, delta;
@@ -1913,6 +1936,7 @@ void update(struct conv *s, Tcp * seg)
                        expand = tcb->snd.wnd - tcb->cwind;
                tcb->cwind += expand;
        }
                        expand = tcb->snd.wnd - tcb->cwind;
                tcb->cwind += expand;
        }
+       adjust_tx_qio_limit(s);
 
        /* Adjust the timers according to the round trip time */
        if (tcb->rtt_timer.state == TcptimerON && seq_ge(seg->ack, tcb->rttseq)) {
 
        /* Adjust the timers according to the round trip time */
        if (tcb->rtt_timer.state == TcptimerON && seq_ge(seg->ack, tcb->rttseq)) {