aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_timer.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2018-05-17 17:47:26 -0400
committerDavid S. Miller <davem@davemloft.net>2018-05-18 11:40:27 -0400
commit5d9f4262b7ea41ca9981cc790e37cca6e37c789e (patch)
treecae663c7a66f7a37aeb26d1587012b9d91fb1a2c /net/ipv4/tcp_timer.c
parenta3893637e1eb0ef5eb1bbc52b3a8d2dfa317a35d (diff)
tcp: add SACK compression
When TCP receives an out-of-order packet, it immediately sends a SACK packet, generating network load but also forcing the receiver to send 1-MSS pathological packets, increasing its RTX queue length/depth, and thus processing time. Wifi networks suffer from this aggressive behavior, but generally speaking, all these SACK packets add fuel to the fire when networks are under congestion. This patch adds a high resolution timer and tp->compressed_ack counter. Instead of sending a SACK, we program this timer with a small delay, based on RTT and capped to 1 ms : delay = min ( 5 % of RTT, 1 ms) If subsequent SACKs need to be sent while the timer has not yet expired, we simply increment tp->compressed_ack. When timer expires, a SACK is sent with the latest information. Whenever an ACK is sent (if data is sent, or if in-order data is received) timer is canceled. Note that tcp_sack_new_ofo_skb() is able to force a SACK to be sent if the sack blocks need to be shuffled, even if the timer has not expired. A new SNMP counter is added in the following patch. Two other patches add sysctls to allow changing the 1,000,000 and 44 values that this commit hard-coded. Signed-off-by: Eric Dumazet <edumazet@google.com> Acked-by: Neal Cardwell <ncardwell@google.com> Acked-by: Yuchung Cheng <ycheng@google.com> Acked-by: Toke Høiland-Jørgensen <toke@toke.dk> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp_timer.c')
-rw-r--r--net/ipv4/tcp_timer.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 92bdf64fffae..3b3611729928 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -708,6 +708,27 @@ out:
708 sock_put(sk); 708 sock_put(sk);
709} 709}
710 710
711static enum hrtimer_restart tcp_compressed_ack_kick(struct hrtimer *timer)
712{
713 struct tcp_sock *tp = container_of(timer, struct tcp_sock, compressed_ack_timer);
714 struct sock *sk = (struct sock *)tp;
715
716 bh_lock_sock(sk);
717 if (!sock_owned_by_user(sk)) {
718 if (tp->compressed_ack)
719 tcp_send_ack(sk);
720 } else {
721 if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED,
722 &sk->sk_tsq_flags))
723 sock_hold(sk);
724 }
725 bh_unlock_sock(sk);
726
727 sock_put(sk);
728
729 return HRTIMER_NORESTART;
730}
731
711void tcp_init_xmit_timers(struct sock *sk) 732void tcp_init_xmit_timers(struct sock *sk)
712{ 733{
713 inet_csk_init_xmit_timers(sk, &tcp_write_timer, &tcp_delack_timer, 734 inet_csk_init_xmit_timers(sk, &tcp_write_timer, &tcp_delack_timer,
@@ -715,4 +736,8 @@ void tcp_init_xmit_timers(struct sock *sk)
715 hrtimer_init(&tcp_sk(sk)->pacing_timer, CLOCK_MONOTONIC, 736 hrtimer_init(&tcp_sk(sk)->pacing_timer, CLOCK_MONOTONIC,
716 HRTIMER_MODE_ABS_PINNED_SOFT); 737 HRTIMER_MODE_ABS_PINNED_SOFT);
717 tcp_sk(sk)->pacing_timer.function = tcp_pace_kick; 738 tcp_sk(sk)->pacing_timer.function = tcp_pace_kick;
739
740 hrtimer_init(&tcp_sk(sk)->compressed_ack_timer, CLOCK_MONOTONIC,
741 HRTIMER_MODE_REL_PINNED_SOFT);
742 tcp_sk(sk)->compressed_ack_timer.function = tcp_compressed_ack_kick;
718} 743}