tcp: add receive queue awareness in tcp_rcv_space_adjust()
authorEric Dumazet <edumazet@google.com>
Tue, 13 May 2025 19:39:12 +0000 (19:39 +0000)
committerJakub Kicinski <kuba@kernel.org>
Thu, 15 May 2025 18:30:08 +0000 (11:30 -0700)
If the application can not drain fast enough a TCP socket queue,
tcp_rcv_space_adjust() can overestimate tp->rcvq_space.space.

Then sk->sk_rcvbuf can grow and hit tcp_rmem[2] for no good reason.

Fix this by taking into acount the number of available bytes.

Keeping sk->sk_rcvbuf at the right size allows better cache efficiency.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Wei Wang <weiwan@google.com>
Link: https://patch.msgid.link/20250513193919.1089692-5-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/linux/tcp.h
net/ipv4/tcp_input.c

index a8af71623ba7ca16f211cb9884f431fc9462ce9e..29f59d50dc73f8c433865e6bc116cb1bac4eafb7 100644 (file)
@@ -340,7 +340,7 @@ struct tcp_sock {
        } rcv_rtt_est;
 /* Receiver queue space */
        struct {
-               u32     space;
+               int     space;
                u32     seq;
                u64     time;
        } rcvq_space;
index f799200db26492730fbd042a68c8d206d85455d4..5d64a6ecfc8f78de3665afdea112d62c417cee27 100644 (file)
@@ -780,8 +780,7 @@ static void tcp_rcvbuf_grow(struct sock *sk)
 void tcp_rcv_space_adjust(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
-       u32 copied;
-       int time;
+       int time, inq, copied;
 
        trace_tcp_rcv_space_adjust(sk);
 
@@ -792,6 +791,9 @@ void tcp_rcv_space_adjust(struct sock *sk)
 
        /* Number of bytes copied to user in last RTT */
        copied = tp->copied_seq - tp->rcvq_space.seq;
+       /* Number of bytes in receive queue. */
+       inq = tp->rcv_nxt - tp->copied_seq;
+       copied -= inq;
        if (copied <= tp->rcvq_space.space)
                goto new_measure;