Thread (13 messages) flat view 13 messages, 3 authors, 2025-07-17

Re: [PATCH v2 net-next 1/2] tcp: account for memory pressure signaled by cgroup

From: Shakeel Butt <shakeel.butt@linux.dev>
Date: 2025-07-16 16:50:04
Also in: linux-mm

On Mon, Jul 14, 2025 at 04:36:12PM +0200, Daniel Sedlak wrote:
quoted hunk ↗ jump to hunk
This patch is a result of our long-standing debug sessions, where it all
started as "networking is slow", and TCP network throughput suddenly
dropped from tens of Gbps to few Mbps, and we could not see anything in
the kernel log or netstat counters.

Currently, we have two memory pressure counters for TCP sockets [1],
which we manipulate only when the memory pressure is signalled through
the proto struct [2]. However, the memory pressure can also be signaled
through the cgroup memory subsystem, which we do not reflect in the
netstat counters. In the end, when the cgroup memory subsystem signals
that it is under pressure, we silently reduce the advertised TCP window
with tcp_adjust_rcv_ssthresh() to 4*advmss, which causes a significant
throughput reduction.

So this patch adds a new counter to account for memory pressure
signaled by the memory cgroup, so it is much easier to spot.

Link: https://elixir.bootlin.com/linux/v6.15.4/source/include/uapi/linux/snmp.h#L231-L232 [1]
Link: https://elixir.bootlin.com/linux/v6.15.4/source/include/net/sock.h#L1300-L1301 [2]
Co-developed-by: Matyas Hurtik <redacted>
Signed-off-by: Matyas Hurtik <redacted>
Signed-off-by: Daniel Sedlak <redacted>
---
 Documentation/networking/net_cachelines/snmp.rst |  1 +
 include/net/tcp.h                                | 14 ++++++++------
 include/uapi/linux/snmp.h                        |  1 +
 net/ipv4/proc.c                                  |  1 +
 4 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/Documentation/networking/net_cachelines/snmp.rst b/Documentation/networking/net_cachelines/snmp.rst
index bd44b3eebbef..ed17ff84e39c 100644
--- a/Documentation/networking/net_cachelines/snmp.rst
+++ b/Documentation/networking/net_cachelines/snmp.rst
@@ -76,6 +76,7 @@ unsigned_long  LINUX_MIB_TCPABORTONLINGER
 unsigned_long  LINUX_MIB_TCPABORTFAILED
 unsigned_long  LINUX_MIB_TCPMEMORYPRESSURES
 unsigned_long  LINUX_MIB_TCPMEMORYPRESSURESCHRONO
+unsigned_long  LINUX_MIB_TCPCGROUPSOCKETPRESSURE
 unsigned_long  LINUX_MIB_TCPSACKDISCARD
 unsigned_long  LINUX_MIB_TCPDSACKIGNOREDOLD
 unsigned_long  LINUX_MIB_TCPDSACKIGNOREDNOUNDO
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 761c4a0ad386..aae3efe24282 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -267,6 +267,11 @@ extern long sysctl_tcp_mem[3];
 #define TCP_RACK_STATIC_REO_WND  0x2 /* Use static RACK reo wnd */
 #define TCP_RACK_NO_DUPTHRESH    0x4 /* Do not use DUPACK threshold in RACK */
 
+#define TCP_INC_STATS(net, field)	SNMP_INC_STATS((net)->mib.tcp_statistics, field)
+#define __TCP_INC_STATS(net, field)	__SNMP_INC_STATS((net)->mib.tcp_statistics, field)
+#define TCP_DEC_STATS(net, field)	SNMP_DEC_STATS((net)->mib.tcp_statistics, field)
+#define TCP_ADD_STATS(net, field, val)	SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val)
+
 extern atomic_long_t tcp_memory_allocated;
 DECLARE_PER_CPU(int, tcp_memory_per_cpu_fw_alloc);
 
@@ -277,8 +282,10 @@ extern unsigned long tcp_memory_pressure;
 static inline bool tcp_under_memory_pressure(const struct sock *sk)
 {
 	if (mem_cgroup_sockets_enabled && sk->sk_memcg &&
-	    mem_cgroup_under_socket_pressure(sk->sk_memcg))
+	    mem_cgroup_under_socket_pressure(sk->sk_memcg)) {
+		TCP_INC_STATS(sock_net(sk), LINUX_MIB_TCPCGROUPSOCKETPRESSURE);
 		return true;
Incrementing it here will give a very different semantic to this stat
compared to LINUX_MIB_TCPMEMORYPRESSURES. Here the increments mean the
number of times the kernel check if a given socket is under memcg
pressure for a net namespace. Is that what we want?
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help