tcp: do not delay ACK in DCTCP upon CE status change
[linux-2.6-microblaze.git] / net / ipv4 / tcp_dctcp.c
index 078328a..8b637f9 100644 (file)
@@ -129,12 +129,15 @@ static void dctcp_ce_state_0_to_1(struct sock *sk)
        struct dctcp *ca = inet_csk_ca(sk);
        struct tcp_sock *tp = tcp_sk(sk);
 
-       /* State has changed from CE=0 to CE=1 and delayed
-        * ACK has not sent yet.
-        */
-       if (!ca->ce_state &&
-           inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER)
-               __tcp_send_ack(sk, ca->prior_rcv_nxt);
+       if (!ca->ce_state) {
+               /* State has changed from CE=0 to CE=1, force an immediate
+                * ACK to reflect the new CE state. If an ACK was delayed,
+                * send that first to reflect the prior CE state.
+                */
+               if (inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER)
+                       __tcp_send_ack(sk, ca->prior_rcv_nxt);
+               tcp_enter_quickack_mode(sk, 1);
+       }
 
        ca->prior_rcv_nxt = tp->rcv_nxt;
        ca->ce_state = 1;
@@ -147,12 +150,15 @@ static void dctcp_ce_state_1_to_0(struct sock *sk)
        struct dctcp *ca = inet_csk_ca(sk);
        struct tcp_sock *tp = tcp_sk(sk);
 
-       /* State has changed from CE=1 to CE=0 and delayed
-        * ACK has not sent yet.
-        */
-       if (ca->ce_state &&
-           inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER)
-               __tcp_send_ack(sk, ca->prior_rcv_nxt);
+       if (ca->ce_state) {
+               /* State has changed from CE=1 to CE=0, force an immediate
+                * ACK to reflect the new CE state. If an ACK was delayed,
+                * send that first to reflect the prior CE state.
+                */
+               if (inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER)
+                       __tcp_send_ack(sk, ca->prior_rcv_nxt);
+               tcp_enter_quickack_mode(sk, 1);
+       }
 
        ca->prior_rcv_nxt = tp->rcv_nxt;
        ca->ce_state = 0;