aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/rtnetlink.h2
-rw-r--r--net/ipv4/tcp_input.c5
-rw-r--r--net/ipv4/tcp_output.c6
3 files changed, 10 insertions, 3 deletions
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 7a2144e1afae..eb0f1a554d7b 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -386,6 +386,8 @@ enum {
386#define RTAX_RTO_MIN RTAX_RTO_MIN 386#define RTAX_RTO_MIN RTAX_RTO_MIN
387 RTAX_INITRWND, 387 RTAX_INITRWND,
388#define RTAX_INITRWND RTAX_INITRWND 388#define RTAX_INITRWND RTAX_INITRWND
389 RTAX_QUICKACK,
390#define RTAX_QUICKACK RTAX_QUICKACK
389 __RTAX_MAX 391 __RTAX_MAX
390}; 392};
391 393
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 46271cdcf088..28af45abe062 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3717,6 +3717,7 @@ void tcp_reset(struct sock *sk)
3717static void tcp_fin(struct sock *sk) 3717static void tcp_fin(struct sock *sk)
3718{ 3718{
3719 struct tcp_sock *tp = tcp_sk(sk); 3719 struct tcp_sock *tp = tcp_sk(sk);
3720 const struct dst_entry *dst;
3720 3721
3721 inet_csk_schedule_ack(sk); 3722 inet_csk_schedule_ack(sk);
3722 3723
@@ -3728,7 +3729,9 @@ static void tcp_fin(struct sock *sk)
3728 case TCP_ESTABLISHED: 3729 case TCP_ESTABLISHED:
3729 /* Move to CLOSE_WAIT */ 3730 /* Move to CLOSE_WAIT */
3730 tcp_set_state(sk, TCP_CLOSE_WAIT); 3731 tcp_set_state(sk, TCP_CLOSE_WAIT);
3731 inet_csk(sk)->icsk_ack.pingpong = 1; 3732 dst = __sk_dst_get(sk);
3733 if (!dst || !dst_metric(dst, RTAX_QUICKACK))
3734 inet_csk(sk)->icsk_ack.pingpong = 1;
3732 break; 3735 break;
3733 3736
3734 case TCP_CLOSE_WAIT: 3737 case TCP_CLOSE_WAIT:
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index e2c1333ee318..3d609490f118 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -160,6 +160,7 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
160{ 160{
161 struct inet_connection_sock *icsk = inet_csk(sk); 161 struct inet_connection_sock *icsk = inet_csk(sk);
162 const u32 now = tcp_time_stamp; 162 const u32 now = tcp_time_stamp;
163 const struct dst_entry *dst = __sk_dst_get(sk);
163 164
164 if (sysctl_tcp_slow_start_after_idle && 165 if (sysctl_tcp_slow_start_after_idle &&
165 (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto)) 166 (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto))
@@ -170,8 +171,9 @@ static void tcp_event_data_sent(struct tcp_sock *tp,
170 /* If it is a reply for ato after last received 171 /* If it is a reply for ato after last received
171 * packet, enter pingpong mode. 172 * packet, enter pingpong mode.
172 */ 173 */
173 if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato) 174 if ((u32)(now - icsk->icsk_ack.lrcvtime) < icsk->icsk_ack.ato &&
174 icsk->icsk_ack.pingpong = 1; 175 (!dst || !dst_metric(dst, RTAX_QUICKACK)))
176 icsk->icsk_ack.pingpong = 1;
175} 177}
176 178
177/* Account for an ACK we sent. */ 179/* Account for an ACK we sent. */