aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/timer.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-03-19 22:04:20 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-20 12:40:25 -0400
commitfa76ce7328b289b6edd476e24eb52fd634261720 (patch)
tree2e4c116a4e299700c185d73018bbb3518e46e1bb /net/dccp/timer.c
parent52452c542559ac980b48dbf22a30ee7fa0af507c (diff)
inet: get rid of central tcp/dccp listener timer
One of the major issue for TCP is the SYNACK rtx handling, done by inet_csk_reqsk_queue_prune(), fired by the keepalive timer of a TCP_LISTEN socket. This function runs for awful long times, with socket lock held, meaning that other cpus needing this lock have to spin for hundred of ms. SYNACK are sent in huge bursts, likely to cause severe drops anyway. This model was OK 15 years ago when memory was very tight. We now can afford to have a timer per request sock. Timer invocations no longer need to lock the listener, and can be run from all cpus in parallel. With following patch increasing somaxconn width to 32 bits, I tested a listener with more than 4 million active request sockets, and a steady SYNFLOOD of ~200,000 SYN per second. Host was sending ~830,000 SYNACK per second. This is ~100 times more what we could achieve before this patch. Later, we will get rid of the listener hash and use ehash instead. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/timer.c')
-rw-r--r--net/dccp/timer.c24
1 files changed, 1 insertions, 23 deletions
diff --git a/net/dccp/timer.c b/net/dccp/timer.c
index 1cd46a345cb0..3ef7acef3ce8 100644
--- a/net/dccp/timer.c
+++ b/net/dccp/timer.c
@@ -161,33 +161,11 @@ out:
161 sock_put(sk); 161 sock_put(sk);
162} 162}
163 163
164/*
165 * Timer for listening sockets
166 */
167static void dccp_response_timer(struct sock *sk)
168{
169 inet_csk_reqsk_queue_prune(sk, TCP_SYNQ_INTERVAL, DCCP_TIMEOUT_INIT,
170 DCCP_RTO_MAX);
171}
172
173static void dccp_keepalive_timer(unsigned long data) 164static void dccp_keepalive_timer(unsigned long data)
174{ 165{
175 struct sock *sk = (struct sock *)data; 166 struct sock *sk = (struct sock *)data;
176 167
177 /* Only process if socket is not in use. */ 168 pr_err("dccp should not use a keepalive timer !\n");
178 bh_lock_sock(sk);
179 if (sock_owned_by_user(sk)) {
180 /* Try again later. */
181 inet_csk_reset_keepalive_timer(sk, HZ / 20);
182 goto out;
183 }
184
185 if (sk->sk_state == DCCP_LISTEN) {
186 dccp_response_timer(sk);
187 goto out;
188 }
189out:
190 bh_unlock_sock(sk);
191 sock_put(sk); 169 sock_put(sk);
192} 170}
193 171