aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_output.c
diff options
context:
space:
mode:
authorYuchung Cheng <ycheng@google.com>2018-07-18 16:56:35 -0400
committerDavid S. Miller <davem@davemloft.net>2018-07-20 17:32:23 -0400
commit27cde44a259c380a3c09066fc4b42de7dde9b1ad (patch)
tree2f0249f49428f487fcda2249b5dab4d82dd8e514 /net/ipv4/tcp_output.c
parent2987babb6982306509380fc11b450227a844493b (diff)
tcp: do not cancel delay-AcK on DCTCP special ACK
Currently when a DCTCP receiver delays an ACK and receive a data packet with a different CE mark from the previous one's, it sends two immediate ACKs acking previous and latest sequences respectly (for ECN accounting). Previously sending the first ACK may mark off the delayed ACK timer (tcp_event_ack_sent). This may subsequently prevent sending the second ACK to acknowledge the latest sequence (tcp_ack_snd_check). The culprit is that tcp_send_ack() assumes it always acknowleges the latest sequence, which is not true for the first special ACK. The fix is to not make the assumption in tcp_send_ack and check the actual ack sequence before cancelling the delayed ACK. Further it's safer to pass the ack sequence number as a local variable into tcp_send_ack routine, instead of intercepting tp->rcv_nxt to avoid future bugs like this. Reported-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: Yuchung Cheng <ycheng@google.com> Acked-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r--net/ipv4/tcp_output.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index ee1b0705321d..c4172c1fb198 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -160,7 +160,8 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
160} 160}
161 161
162/* Account for an ACK we sent. */ 162/* Account for an ACK we sent. */
163static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts) 163static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts,
164 u32 rcv_nxt)
164{ 165{
165 struct tcp_sock *tp = tcp_sk(sk); 166 struct tcp_sock *tp = tcp_sk(sk);
166 167
@@ -171,6 +172,9 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts)
171 if (hrtimer_try_to_cancel(&tp->compressed_ack_timer) == 1) 172 if (hrtimer_try_to_cancel(&tp->compressed_ack_timer) == 1)
172 __sock_put(sk); 173 __sock_put(sk);
173 } 174 }
175
176 if (unlikely(rcv_nxt != tp->rcv_nxt))
177 return; /* Special ACK sent by DCTCP to reflect ECN */
174 tcp_dec_quickack_mode(sk, pkts); 178 tcp_dec_quickack_mode(sk, pkts);
175 inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); 179 inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
176} 180}
@@ -1141,7 +1145,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
1141 icsk->icsk_af_ops->send_check(sk, skb); 1145 icsk->icsk_af_ops->send_check(sk, skb);
1142 1146
1143 if (likely(tcb->tcp_flags & TCPHDR_ACK)) 1147 if (likely(tcb->tcp_flags & TCPHDR_ACK))
1144 tcp_event_ack_sent(sk, tcp_skb_pcount(skb)); 1148 tcp_event_ack_sent(sk, tcp_skb_pcount(skb), rcv_nxt);
1145 1149
1146 if (skb->len != tcp_header_size) { 1150 if (skb->len != tcp_header_size) {
1147 tcp_event_data_sent(tp, sk); 1151 tcp_event_data_sent(tp, sk);
@@ -3613,12 +3617,12 @@ void __tcp_send_ack(struct sock *sk, u32 rcv_nxt)
3613 /* Send it off, this clears delayed acks for us. */ 3617 /* Send it off, this clears delayed acks for us. */
3614 __tcp_transmit_skb(sk, buff, 0, (__force gfp_t)0, rcv_nxt); 3618 __tcp_transmit_skb(sk, buff, 0, (__force gfp_t)0, rcv_nxt);
3615} 3619}
3620EXPORT_SYMBOL_GPL(__tcp_send_ack);
3616 3621
3617void tcp_send_ack(struct sock *sk) 3622void tcp_send_ack(struct sock *sk)
3618{ 3623{
3619 __tcp_send_ack(sk, tcp_sk(sk)->rcv_nxt); 3624 __tcp_send_ack(sk, tcp_sk(sk)->rcv_nxt);
3620} 3625}
3621EXPORT_SYMBOL_GPL(tcp_send_ack);
3622 3626
3623/* This routine sends a packet with an out of date sequence 3627/* This routine sends a packet with an out of date sequence
3624 * number. It assumes the other end will try to ack it. 3628 * number. It assumes the other end will try to ack it.