aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorJon Maxwell <jmaxwell37@gmail.com>2015-07-07 20:12:28 -0400
committerDavid S. Miller <davem@davemloft.net>2015-07-09 17:15:44 -0400
commit2251ae46af72d013a6a537e7681e94b18b63e332 (patch)
tree3e8b0e566214e4ec0a13367d1081c3dd4d13cc4a /net/ipv4/tcp_input.c
parent77a58c741df1b91258cc4df3e6893ff61e8293a4 (diff)
tcp: v1 always send a quick ack when quickacks are enabled
V1 of this patch contains Eric Dumazet's suggestion to move the per dst RTAX_QUICKACK check into tcp_in_quickack_mode(). Thanks Eric. I ran some tests and after setting the "ip route change quickack 1" knob there were still many delayed ACKs sent. This occured because when icsk_ack.quick=0 the !icsk_ack.pingpong value is subsequently ignored as tcp_in_quickack_mode() checks both these values. The condition for a quick ack to trigger requires that both icsk_ack.quick != 0 and icsk_ack.pingpong=0. Currently only icsk_ack.pingpong is controlled by the knob. But the icsk_ack.quick value changes dynamically depending on heuristics. The crux of the matter is that delayed acks still cannot be entirely disabled even with the RTAX_QUICKACK per dst knob enabled. This patch ensures that a quick ack is always sent when the RTAX_QUICKACK per dst knob is turned on. The "ip route change quickack 1" knob was recently added to enable quickacks. It was modeled around the TCP_QUICKACK setsockopt() option. This issue is that even with "ip route change quickack 1" enabled we still see delayed ACKs under some conditions. It would be nice to be able to completely disable delayed ACKs. Here is an example: # netstat -s|grep dela 3 delayed acks sent For all routes enable the knob # ip route change quickack 1 Generate some traffic across a slow link and we still see the delayed acks. # netstat -s|grep dela 106 delayed acks sent 1 delayed acks further delayed because of locked socket The issue is that both the "ip route change quickack 1" knob and the TCP_QUICKACK option set the icsk_ack.pingpong variable to 0. However at the business end in the __tcp_ack_snd_check() routine, tcp_in_quickack_mode() checks that both icsk_ack.quick != 0 and icsk_ack.pingpong=0 in order to trigger a quickack. As icsk_ack.quick is determined by heuristics it can be 0. When that occurs the icsk_ack.pingpong value is ignored and a delayed ACK is sent regardless. This patch moves the RTAX_QUICKACK per dst check into the tcp_in_quickack_mode() routine which ensures that a quickack is always sent when the quickack knob is enabled for that dst. Signed-off-by: Jon Maxwell <jmaxwell37@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ad1482dd215e..7f4a8d5f6eb0 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -197,11 +197,13 @@ static void tcp_enter_quickack_mode(struct sock *sk)
197 * and the session is not interactive. 197 * and the session is not interactive.
198 */ 198 */
199 199
200static inline bool tcp_in_quickack_mode(const struct sock *sk) 200static bool tcp_in_quickack_mode(struct sock *sk)
201{ 201{
202 const struct inet_connection_sock *icsk = inet_csk(sk); 202 const struct inet_connection_sock *icsk = inet_csk(sk);
203 const struct dst_entry *dst = __sk_dst_get(sk);
203 204
204 return icsk->icsk_ack.quick && !icsk->icsk_ack.pingpong; 205 return (dst && dst_metric(dst, RTAX_QUICKACK)) ||
206 (icsk->icsk_ack.quick && !icsk->icsk_ack.pingpong);
205} 207}
206 208
207static void tcp_ecn_queue_cwr(struct tcp_sock *tp) 209static void tcp_ecn_queue_cwr(struct tcp_sock *tp)
@@ -3951,7 +3953,6 @@ void tcp_reset(struct sock *sk)
3951static void tcp_fin(struct sock *sk) 3953static void tcp_fin(struct sock *sk)
3952{ 3954{
3953 struct tcp_sock *tp = tcp_sk(sk); 3955 struct tcp_sock *tp = tcp_sk(sk);
3954 const struct dst_entry *dst;
3955 3956
3956 inet_csk_schedule_ack(sk); 3957 inet_csk_schedule_ack(sk);
3957 3958
@@ -3963,9 +3964,7 @@ static void tcp_fin(struct sock *sk)
3963 case TCP_ESTABLISHED: 3964 case TCP_ESTABLISHED:
3964 /* Move to CLOSE_WAIT */ 3965 /* Move to CLOSE_WAIT */
3965 tcp_set_state(sk, TCP_CLOSE_WAIT); 3966 tcp_set_state(sk, TCP_CLOSE_WAIT);
3966 dst = __sk_dst_get(sk); 3967 inet_csk(sk)->icsk_ack.pingpong = 1;
3967 if (!dst || !dst_metric(dst, RTAX_QUICKACK))
3968 inet_csk(sk)->icsk_ack.pingpong = 1;
3969 break; 3968 break;
3970 3969
3971 case TCP_CLOSE_WAIT: 3970 case TCP_CLOSE_WAIT: