diff options
author | Eric Dumazet <edumazet@google.com> | 2015-10-02 14:43:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-10-03 07:32:41 -0400 |
commit | 079096f103faca2dd87342cca6f23d4b34da8871 (patch) | |
tree | fa3fb0fdc064f1611c464384e70a7a402179808f /net/ipv6/inet6_connection_sock.c | |
parent | 2feda34192a379f8b35a7c6c5826b2f23e884f32 (diff) |
tcp/dccp: install syn_recv requests into ehash table
In this patch, we insert request sockets into TCP/DCCP
regular ehash table (where ESTABLISHED and TIMEWAIT sockets
are) instead of using the per listener hash table.
ACK packets find SYN_RECV pseudo sockets without having
to find and lock the listener.
In nominal conditions, this halves pressure on listener lock.
Note that this will allow for SO_REUSEPORT refinements,
so that we can select a listener using cpu/numa affinities instead
of the prior 'consistent hash', since only SYN packets will
apply this selection logic.
We will shrink listen_sock in the following patch to ease
code review.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ying Cai <ycai@google.com>
Cc: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/inet6_connection_sock.c')
-rw-r--r-- | net/ipv6/inet6_connection_sock.c | 67 |
1 files changed, 0 insertions, 67 deletions
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index ea915aa5e4e2..5d1c7cee2cb2 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -94,73 +94,6 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk, | |||
94 | } | 94 | } |
95 | EXPORT_SYMBOL(inet6_csk_route_req); | 95 | EXPORT_SYMBOL(inet6_csk_route_req); |
96 | 96 | ||
97 | /* | ||
98 | * request_sock (formerly open request) hash tables. | ||
99 | */ | ||
100 | static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport, | ||
101 | const u32 rnd, const u32 synq_hsize) | ||
102 | { | ||
103 | u32 c; | ||
104 | |||
105 | c = jhash_3words((__force u32)raddr->s6_addr32[0], | ||
106 | (__force u32)raddr->s6_addr32[1], | ||
107 | (__force u32)raddr->s6_addr32[2], | ||
108 | rnd); | ||
109 | |||
110 | c = jhash_2words((__force u32)raddr->s6_addr32[3], | ||
111 | (__force u32)rport, | ||
112 | c); | ||
113 | |||
114 | return c & (synq_hsize - 1); | ||
115 | } | ||
116 | |||
117 | struct request_sock *inet6_csk_search_req(struct sock *sk, | ||
118 | const __be16 rport, | ||
119 | const struct in6_addr *raddr, | ||
120 | const struct in6_addr *laddr, | ||
121 | const int iif) | ||
122 | { | ||
123 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
124 | struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt; | ||
125 | struct request_sock *req; | ||
126 | u32 hash = inet6_synq_hash(raddr, rport, lopt->hash_rnd, | ||
127 | lopt->nr_table_entries); | ||
128 | |||
129 | spin_lock(&icsk->icsk_accept_queue.syn_wait_lock); | ||
130 | for (req = lopt->syn_table[hash]; req != NULL; req = req->dl_next) { | ||
131 | const struct inet_request_sock *ireq = inet_rsk(req); | ||
132 | |||
133 | if (ireq->ir_rmt_port == rport && | ||
134 | req->rsk_ops->family == AF_INET6 && | ||
135 | ipv6_addr_equal(&ireq->ir_v6_rmt_addr, raddr) && | ||
136 | ipv6_addr_equal(&ireq->ir_v6_loc_addr, laddr) && | ||
137 | (!ireq->ir_iif || ireq->ir_iif == iif)) { | ||
138 | atomic_inc(&req->rsk_refcnt); | ||
139 | WARN_ON(req->sk != NULL); | ||
140 | break; | ||
141 | } | ||
142 | } | ||
143 | spin_unlock(&icsk->icsk_accept_queue.syn_wait_lock); | ||
144 | |||
145 | return req; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(inet6_csk_search_req); | ||
148 | |||
149 | void inet6_csk_reqsk_queue_hash_add(struct sock *sk, | ||
150 | struct request_sock *req, | ||
151 | const unsigned long timeout) | ||
152 | { | ||
153 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
154 | struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt; | ||
155 | const u32 h = inet6_synq_hash(&inet_rsk(req)->ir_v6_rmt_addr, | ||
156 | inet_rsk(req)->ir_rmt_port, | ||
157 | lopt->hash_rnd, lopt->nr_table_entries); | ||
158 | |||
159 | reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, timeout); | ||
160 | inet_csk_reqsk_queue_added(sk); | ||
161 | } | ||
162 | EXPORT_SYMBOL_GPL(inet6_csk_reqsk_queue_hash_add); | ||
163 | |||
164 | void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr) | 97 | void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr) |
165 | { | 98 | { |
166 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) uaddr; | 99 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) uaddr; |