Blame view
net/core/request_sock.c
3.52 KB
0e87506fc [NET] Generalise ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * NET Generic infrastructure for Network protocols. * * Authors: Arnaldo Carvalho de Melo <acme@conectiva.com.br> * * From code originally in include/net/tcp.h * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <linux/module.h> #include <linux/random.h> #include <linux/slab.h> #include <linux/string.h> |
72a3effaf [NET]: Size liste... |
18 |
#include <linux/vmalloc.h> |
0e87506fc [NET] Generalise ... |
19 20 |
#include <net/request_sock.h> |
e52c1f17e [NET]: Move sysct... |
21 22 23 24 25 26 27 |
/* * Maximum number of SYN_RECV sockets in queue per LISTEN socket. * One SYN_RECV socket costs about 80bytes on a 32bit machine. * It would be better to replace it with a global counter for all sockets * but then some measure against one socket starving all other sockets * would be needed. * |
99b53bdd8 ipv4:correct desc... |
28 |
* The minimum value of it is 128. Experiments with real servers show that |
e52c1f17e [NET]: Move sysct... |
29 |
* it is absolutely not enough even at 100conn/sec. 256 cures most |
99b53bdd8 ipv4:correct desc... |
30 31 32 |
* of problems. * This value is adjusted to 128 for low memory machines, * and it will increase in proportion to the memory of machine. |
72a3effaf [NET]: Size liste... |
33 |
* Note : Dont forget somaxconn that may limit backlog too. |
e52c1f17e [NET]: Move sysct... |
34 35 |
*/ int sysctl_max_syn_backlog = 256; |
493f377d6 tcp: Add timewait... |
36 |
EXPORT_SYMBOL(sysctl_max_syn_backlog); |
e52c1f17e [NET]: Move sysct... |
37 |
|
0e87506fc [NET] Generalise ... |
38 |
int reqsk_queue_alloc(struct request_sock_queue *queue, |
72a3effaf [NET]: Size liste... |
39 |
unsigned int nr_table_entries) |
0e87506fc [NET] Generalise ... |
40 |
{ |
72a3effaf [NET]: Size liste... |
41 42 43 44 45 46 47 48 |
size_t lopt_size = sizeof(struct listen_sock); struct listen_sock *lopt; nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog); nr_table_entries = max_t(u32, nr_table_entries, 8); nr_table_entries = roundup_pow_of_two(nr_table_entries + 1); lopt_size += nr_table_entries * sizeof(struct request_sock *); if (lopt_size > PAGE_SIZE) |
7a1c8e5ab net: allow GFP_HI... |
49 |
lopt = vzalloc(lopt_size); |
72a3effaf [NET]: Size liste... |
50 51 |
else lopt = kzalloc(lopt_size, GFP_KERNEL); |
0e87506fc [NET] Generalise ... |
52 53 |
if (lopt == NULL) return -ENOMEM; |
72a3effaf [NET]: Size liste... |
54 55 |
for (lopt->max_qlen_log = 3; (1 << lopt->max_qlen_log) < nr_table_entries; |
0e87506fc [NET] Generalise ... |
56 57 58 59 |
lopt->max_qlen_log++); get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); rwlock_init(&queue->syn_wait_lock); |
3eb4801d7 [NET]: drop dupli... |
60 |
queue->rskq_accept_head = NULL; |
83e3609eb [REQSK]: Move the... |
61 |
lopt->nr_table_entries = nr_table_entries; |
0e87506fc [NET] Generalise ... |
62 63 64 65 66 67 68 |
write_lock_bh(&queue->syn_wait_lock); queue->listen_opt = lopt; write_unlock_bh(&queue->syn_wait_lock); return 0; } |
dab6ba368 [INET]: Fix poten... |
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
void __reqsk_queue_destroy(struct request_sock_queue *queue) { struct listen_sock *lopt; size_t lopt_size; /* * this is an error recovery path only * no locking needed and the lopt is not NULL */ lopt = queue->listen_opt; lopt_size = sizeof(struct listen_sock) + lopt->nr_table_entries * sizeof(struct request_sock *); if (lopt_size > PAGE_SIZE) vfree(lopt); else kfree(lopt); } |
dab6ba368 [INET]: Fix poten... |
88 89 90 91 92 93 94 95 96 97 98 99 |
static inline struct listen_sock *reqsk_queue_yank_listen_sk( struct request_sock_queue *queue) { struct listen_sock *lopt; write_lock_bh(&queue->syn_wait_lock); lopt = queue->listen_opt; queue->listen_opt = NULL; write_unlock_bh(&queue->syn_wait_lock); return lopt; } |
83e3609eb [REQSK]: Move the... |
100 101 102 103 |
void reqsk_queue_destroy(struct request_sock_queue *queue) { /* make all the listen_opt local to us */ struct listen_sock *lopt = reqsk_queue_yank_listen_sk(queue); |
72a3effaf [NET]: Size liste... |
104 105 |
size_t lopt_size = sizeof(struct listen_sock) + lopt->nr_table_entries * sizeof(struct request_sock *); |
83e3609eb [REQSK]: Move the... |
106 107 |
if (lopt->qlen != 0) { |
72a3effaf [NET]: Size liste... |
108 |
unsigned int i; |
83e3609eb [REQSK]: Move the... |
109 110 111 112 113 114 115 116 117 118 119 |
for (i = 0; i < lopt->nr_table_entries; i++) { struct request_sock *req; while ((req = lopt->syn_table[i]) != NULL) { lopt->syn_table[i] = req->dl_next; lopt->qlen--; reqsk_free(req); } } } |
547b792ca net: convert BUG_... |
120 |
WARN_ON(lopt->qlen != 0); |
72a3effaf [NET]: Size liste... |
121 122 123 124 |
if (lopt_size > PAGE_SIZE) vfree(lopt); else kfree(lopt); |
83e3609eb [REQSK]: Move the... |
125 |
} |