diff options
author | Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> | 2006-09-19 15:52:50 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:19:05 -0400 |
commit | 1ef9696c909060ccdae3ade245ca88692b49285b (patch) | |
tree | 3a2df5bbd6b448a4f873125ab5dd7c7a0cc7ae05 | |
parent | 4eb327b517cf85f6cb7dcd5691e7b748cbe8c343 (diff) |
[TCP]: Send ACKs each 2nd received segment.
It does not affect either mss-sized connections (obviously) or
connections controlled by Nagle (because there is only one small
segment in flight).
The idea is to record the fact that a small segment arrives on a
connection, where one small segment has already been received and
still not-ACKed. In this case ACK is forced after tcp_recvmsg() drains
receive buffer.
In other words, it is a "soft" each-2nd-segment ACK, which is enough
to preserve ACK clock even when ABC is enabled.
Signed-off-by: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/inet_connection_sock.h | 3 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 7 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 2 |
3 files changed, 9 insertions, 3 deletions
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 9bf73fe50948..de4e83b6da4b 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h | |||
@@ -147,7 +147,8 @@ extern struct sock *inet_csk_clone(struct sock *sk, | |||
147 | enum inet_csk_ack_state_t { | 147 | enum inet_csk_ack_state_t { |
148 | ICSK_ACK_SCHED = 1, | 148 | ICSK_ACK_SCHED = 1, |
149 | ICSK_ACK_TIMER = 2, | 149 | ICSK_ACK_TIMER = 2, |
150 | ICSK_ACK_PUSHED = 4 | 150 | ICSK_ACK_PUSHED = 4, |
151 | ICSK_ACK_PUSHED2 = 8 | ||
151 | }; | 152 | }; |
152 | 153 | ||
153 | extern void inet_csk_init_xmit_timers(struct sock *sk, | 154 | extern void inet_csk_init_xmit_timers(struct sock *sk, |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 29e3d606db78..66e9a729f6df 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -955,8 +955,11 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied) | |||
955 | * receive buffer and there was a small segment | 955 | * receive buffer and there was a small segment |
956 | * in queue. | 956 | * in queue. |
957 | */ | 957 | */ |
958 | (copied > 0 && (icsk->icsk_ack.pending & ICSK_ACK_PUSHED) && | 958 | (copied > 0 && |
959 | !icsk->icsk_ack.pingpong && !atomic_read(&sk->sk_rmem_alloc))) | 959 | ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED2) || |
960 | ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED) && | ||
961 | !icsk->icsk_ack.pingpong)) && | ||
962 | !atomic_read(&sk->sk_rmem_alloc))) | ||
960 | time_to_ack = 1; | 963 | time_to_ack = 1; |
961 | } | 964 | } |
962 | 965 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 511b738f118a..b3def0df14fb 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -156,6 +156,8 @@ static void tcp_measure_rcv_mss(struct sock *sk, | |||
156 | return; | 156 | return; |
157 | } | 157 | } |
158 | } | 158 | } |
159 | if (icsk->icsk_ack.pending & ICSK_ACK_PUSHED) | ||
160 | icsk->icsk_ack.pending |= ICSK_ACK_PUSHED2; | ||
159 | icsk->icsk_ack.pending |= ICSK_ACK_PUSHED; | 161 | icsk->icsk_ack.pending |= ICSK_ACK_PUSHED; |
160 | } | 162 | } |
161 | } | 163 | } |