diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index f5622b250665..cc2ac5346b92 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -4249,6 +4249,8 @@ static void tcp_sack_new_ofo_skb(struct sock *sk, u32 seq, u32 end_seq) | |||
4249 | * If the sack array is full, forget about the last one. | 4249 | * If the sack array is full, forget about the last one. |
4250 | */ | 4250 | */ |
4251 | if (this_sack >= TCP_NUM_SACKS) { | 4251 | if (this_sack >= TCP_NUM_SACKS) { |
4252 | if (tp->compressed_ack) | ||
4253 | tcp_send_ack(sk); | ||
4252 | this_sack--; | 4254 | this_sack--; |
4253 | tp->rx_opt.num_sacks--; | 4255 | tp->rx_opt.num_sacks--; |
4254 | sp--; | 4256 | sp--; |
@@ -5081,6 +5083,7 @@ static inline void tcp_data_snd_check(struct sock *sk) | |||
5081 | static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) | 5083 | static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) |
5082 | { | 5084 | { |
5083 | struct tcp_sock *tp = tcp_sk(sk); | 5085 | struct tcp_sock *tp = tcp_sk(sk); |
5086 | unsigned long rtt, delay; | ||
5084 | 5087 | ||
5085 | /* More than one full frame received... */ | 5088 | /* More than one full frame received... */ |
5086 | if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss && | 5089 | if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss && |
@@ -5092,15 +5095,35 @@ static void __tcp_ack_snd_check(struct sock *sk, int ofo_possible) | |||
5092 | (tp->rcv_nxt - tp->copied_seq < sk->sk_rcvlowat || | 5095 | (tp->rcv_nxt - tp->copied_seq < sk->sk_rcvlowat || |
5093 | __tcp_select_window(sk) >= tp->rcv_wnd)) || | 5096 | __tcp_select_window(sk) >= tp->rcv_wnd)) || |
5094 | /* We ACK each frame or... */ | 5097 | /* We ACK each frame or... */ |
5095 | tcp_in_quickack_mode(sk) || | 5098 | tcp_in_quickack_mode(sk)) { |
5096 | /* We have out of order data. */ | 5099 | send_now: |
5097 | (ofo_possible && !RB_EMPTY_ROOT(&tp->out_of_order_queue))) { | ||
5098 | /* Then ack it now */ | ||
5099 | tcp_send_ack(sk); | 5100 | tcp_send_ack(sk); |
5100 | } else { | 5101 | return; |
5101 | /* Else, send delayed ack. */ | 5102 | } |
5103 | |||
5104 | if (!ofo_possible || RB_EMPTY_ROOT(&tp->out_of_order_queue)) { | ||
5102 | tcp_send_delayed_ack(sk); | 5105 | tcp_send_delayed_ack(sk); |
5106 | return; | ||
5103 | } | 5107 | } |
5108 | |||
5109 | if (!tcp_is_sack(tp) || tp->compressed_ack >= 44) | ||
5110 | goto send_now; | ||
5111 | tp->compressed_ack++; | ||
5112 | |||
5113 | if (hrtimer_is_queued(&tp->compressed_ack_timer)) | ||
5114 | return; | ||
5115 | |||
5116 | /* compress ack timer : 5 % of rtt, but no more than 1 ms */ | ||
5117 | |||
5118 | rtt = tp->rcv_rtt_est.rtt_us; | ||
5119 | if (tp->srtt_us && tp->srtt_us < rtt) | ||
5120 | rtt = tp->srtt_us; | ||
5121 | |||
5122 | delay = min_t(unsigned long, NSEC_PER_MSEC, | ||
5123 | rtt * (NSEC_PER_USEC >> 3)/20); | ||
5124 | sock_hold(sk); | ||
5125 | hrtimer_start(&tp->compressed_ack_timer, ns_to_ktime(delay), | ||
5126 | HRTIMER_MODE_REL_PINNED_SOFT); | ||
5104 | } | 5127 | } |
5105 | 5128 | ||
5106 | static inline void tcp_ack_snd_check(struct sock *sk) | 5129 | static inline void tcp_ack_snd_check(struct sock *sk) |