diff options
author | Eric Dumazet <dada1@cosmosbay.com> | 2006-11-16 05:30:37 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:21:44 -0500 |
commit | 72a3effaf633bcae9034b7e176bdbd78d64a71db (patch) | |
tree | b7a331527f1b15335a358f97809134f35587e57a /net/ipv4 | |
parent | 3c62f75aac7348ee262b1295cfcfeb3473f76815 (diff) |
[NET]: Size listen hash tables using backlog hint
We currently allocate a fixed size (TCP_SYNQ_HSIZE=512) slots hash table for
each LISTEN socket, regardless of various parameters (listen backlog for
example)
On x86_64, this means order-1 allocations (might fail), even for 'small'
sockets, expecting few connections. On the contrary, a huge server wanting a
backlog of 50000 is slowed down a bit because of this fixed limit.
This patch makes the sizing of listen hash table a dynamic parameter,
depending of :
- net.core.somaxconn tunable (default is 128)
- net.ipv4.tcp_max_syn_backlog tunable (default : 256, 1024 or 128)
- backlog value given by user application (2nd parameter of listen())
For large allocations (bigger than PAGE_SIZE), we use vmalloc() instead of
kmalloc().
We still limit memory allocation with the two existing tunables (somaxconn &
tcp_max_syn_backlog). So for standard setups, this patch actually reduce RAM
usage.
Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/af_inet.c | 2 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 6 |
3 files changed, 5 insertions, 5 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index edcf0932ac6d..4a81d54a7569 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -204,7 +204,7 @@ int inet_listen(struct socket *sock, int backlog) | |||
204 | * we can only allow the backlog to be adjusted. | 204 | * we can only allow the backlog to be adjusted. |
205 | */ | 205 | */ |
206 | if (old_state != TCP_LISTEN) { | 206 | if (old_state != TCP_LISTEN) { |
207 | err = inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); | 207 | err = inet_csk_listen_start(sk, backlog); |
208 | if (err) | 208 | if (err) |
209 | goto out; | 209 | goto out; |
210 | } | 210 | } |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 96bbe2a0aa1b..9d68837888d3 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -343,7 +343,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk, | |||
343 | EXPORT_SYMBOL_GPL(inet_csk_route_req); | 343 | EXPORT_SYMBOL_GPL(inet_csk_route_req); |
344 | 344 | ||
345 | static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, | 345 | static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, |
346 | const u32 rnd, const u16 synq_hsize) | 346 | const u32 rnd, const u32 synq_hsize) |
347 | { | 347 | { |
348 | return jhash_2words((__force u32)raddr, (__force u32)rport, rnd) & (synq_hsize - 1); | 348 | return jhash_2words((__force u32)raddr, (__force u32)rport, rnd) & (synq_hsize - 1); |
349 | } | 349 | } |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 22ef8bd26620..5fbf96552cac 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -715,7 +715,7 @@ static struct ip_options *tcp_v4_save_options(struct sock *sk, | |||
715 | return dopt; | 715 | return dopt; |
716 | } | 716 | } |
717 | 717 | ||
718 | struct request_sock_ops tcp_request_sock_ops = { | 718 | struct request_sock_ops tcp_request_sock_ops __read_mostly = { |
719 | .family = PF_INET, | 719 | .family = PF_INET, |
720 | .obj_size = sizeof(struct tcp_request_sock), | 720 | .obj_size = sizeof(struct tcp_request_sock), |
721 | .rtx_syn_ack = tcp_v4_send_synack, | 721 | .rtx_syn_ack = tcp_v4_send_synack, |
@@ -1385,7 +1385,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) | |||
1385 | if (st->state == TCP_SEQ_STATE_OPENREQ) { | 1385 | if (st->state == TCP_SEQ_STATE_OPENREQ) { |
1386 | struct request_sock *req = cur; | 1386 | struct request_sock *req = cur; |
1387 | 1387 | ||
1388 | icsk = inet_csk(st->syn_wait_sk); | 1388 | icsk = inet_csk(st->syn_wait_sk); |
1389 | req = req->dl_next; | 1389 | req = req->dl_next; |
1390 | while (1) { | 1390 | while (1) { |
1391 | while (req) { | 1391 | while (req) { |
@@ -1395,7 +1395,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) | |||
1395 | } | 1395 | } |
1396 | req = req->dl_next; | 1396 | req = req->dl_next; |
1397 | } | 1397 | } |
1398 | if (++st->sbucket >= TCP_SYNQ_HSIZE) | 1398 | if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries) |
1399 | break; | 1399 | break; |
1400 | get_req: | 1400 | get_req: |
1401 | req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket]; | 1401 | req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket]; |