mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
tcp: fix mishandling when the sack compression is deferred.
[ Upstream commit30c6f0bf95] In this patch, we mainly try to handle sending a compressed ack correctly if it's deferred. Here are more details in the old logic: When sack compression is triggered in the tcp_compressed_ack_kick(), if the sock is owned by user, it will set TCP_DELACK_TIMER_DEFERRED and then defer to the release cb phrase. Later once user releases the sock, tcp_delack_timer_handler() should send a ack as expected, which, however, cannot happen due to lack of ICSK_ACK_TIMER flag. Therefore, the receiver would not sent an ack until the sender's retransmission timeout. It definitely increases unnecessary latency. Fixes:5d9f4262b7("tcp: add SACK compression") Suggested-by: Eric Dumazet <edumazet@google.com> Signed-off-by: fuyuanli <fuyuanli@didiglobal.com> Signed-off-by: Jason Xing <kerneljasonxing@gmail.com> Link: https://lore.kernel.org/netdev/20230529113804.GA20300@didi-ThinkCentre-M920t-N000/ Reviewed-by: Eric Dumazet <edumazet@google.com> Link: https://lore.kernel.org/r/20230531080150.GA20424@didi-ThinkCentre-M920t-N000 Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
eac615ed3c
commit
c3fc733798
@@ -632,6 +632,7 @@ void tcp_reset(struct sock *sk, struct sk_buff *skb);
|
|||||||
void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb);
|
void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb);
|
||||||
void tcp_fin(struct sock *sk);
|
void tcp_fin(struct sock *sk);
|
||||||
void tcp_check_space(struct sock *sk);
|
void tcp_check_space(struct sock *sk);
|
||||||
|
void tcp_sack_compress_send_ack(struct sock *sk);
|
||||||
|
|
||||||
/* tcp_timer.c */
|
/* tcp_timer.c */
|
||||||
void tcp_init_xmit_timers(struct sock *);
|
void tcp_init_xmit_timers(struct sock *);
|
||||||
|
|||||||
@@ -4529,7 +4529,7 @@ static void tcp_sack_maybe_coalesce(struct tcp_sock *tp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcp_sack_compress_send_ack(struct sock *sk)
|
void tcp_sack_compress_send_ack(struct sock *sk)
|
||||||
{
|
{
|
||||||
struct tcp_sock *tp = tcp_sk(sk);
|
struct tcp_sock *tp = tcp_sk(sk);
|
||||||
|
|
||||||
|
|||||||
@@ -290,9 +290,19 @@ static int tcp_write_timeout(struct sock *sk)
|
|||||||
void tcp_delack_timer_handler(struct sock *sk)
|
void tcp_delack_timer_handler(struct sock *sk)
|
||||||
{
|
{
|
||||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||||
|
struct tcp_sock *tp = tcp_sk(sk);
|
||||||
|
|
||||||
if (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ||
|
if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))
|
||||||
!(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
|
return;
|
||||||
|
|
||||||
|
/* Handling the sack compression case */
|
||||||
|
if (tp->compressed_ack) {
|
||||||
|
tcp_mstamp_refresh(tp);
|
||||||
|
tcp_sack_compress_send_ack(sk);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(icsk->icsk_ack.pending & ICSK_ACK_TIMER))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (time_after(icsk->icsk_ack.timeout, jiffies)) {
|
if (time_after(icsk->icsk_ack.timeout, jiffies)) {
|
||||||
@@ -312,7 +322,7 @@ void tcp_delack_timer_handler(struct sock *sk)
|
|||||||
inet_csk_exit_pingpong_mode(sk);
|
inet_csk_exit_pingpong_mode(sk);
|
||||||
icsk->icsk_ack.ato = TCP_ATO_MIN;
|
icsk->icsk_ack.ato = TCP_ATO_MIN;
|
||||||
}
|
}
|
||||||
tcp_mstamp_refresh(tcp_sk(sk));
|
tcp_mstamp_refresh(tp);
|
||||||
tcp_send_ack(sk);
|
tcp_send_ack(sk);
|
||||||
__NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKS);
|
__NET_INC_STATS(sock_net(sk), LINUX_MIB_DELAYEDACKS);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user