net: tcp: Scale the TCP backlog queue to absorb packet bursts
authorHarout Hedeshian <harouth@codeaurora.org>
Mon, 2 Feb 2015 20:30:42 +0000 (13:30 -0700)
committerDanny Wood <danwood76@gmail.com>
Tue, 28 Jul 2020 08:47:02 +0000 (09:47 +0100)
A large momentary influx of packets flooding the TCP layer may cause
packets to get dropped at the socket's backlog queue. Bump this up to
prevent these drops. Note that this change may cause the socket memory
accounting to allow the total backlog queue length to exceed the user
space configured values, sometimes by a substantial amount, which can
lead to out of order packets to be dropped instead of being queued. To
avoid these ofo drops, the condition to drop an out of order packet is
modified to allow out of order queuing to continue as long as it falls
within the now increased backlog queue limit.

Change-Id: I447ffc8560cb149fe84193c72bf693862f7ec740
Signed-off-by: Harout Hedeshian <harouth@codeaurora.org>
include/net/sock.h
net/ipv4/tcp_input.c

index 44cafc6fdbc9ace34f230b0e581b4dc0b574f573..25001eeba4996a596ca8da55aa8da12324114069 100644 (file)
@@ -78,6 +78,8 @@
 #include <net/dst.h>
 #include <net/checksum.h>
 
+#define TCP_BACKLOG_SCALE 4
+
 struct cgroup;
 struct cgroup_subsys;
 #ifdef CONFIG_NET
@@ -795,7 +797,7 @@ static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff
 static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb,
                                              unsigned int limit)
 {
-       if (sk_rcvqueues_full(sk, skb, limit))
+       if (sk_rcvqueues_full(sk, skb, limit * TCP_BACKLOG_SCALE))
                return -ENOBUFS;
 
        /*
index a081f6226c59ccaf27a00688a2599cb13a31b1e9..b0441424af4b3136b33b4d5bb3d01adf91767f7b 100644 (file)
@@ -4105,7 +4105,8 @@ static int tcp_prune_queue(struct sock *sk);
 static int tcp_try_rmem_schedule(struct sock *sk, struct sk_buff *skb,
                                 unsigned int size)
 {
-       if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
+       if (atomic_read(&sk->sk_rmem_alloc)
+                                    > ((sk->sk_rcvbuf + sk->sk_sndbuf) * 4) ||
            !sk_rmem_schedule(sk, skb, size)) {
 
                if (tcp_prune_queue(sk) < 0)