diff options
| author | Hannes Frederic Sowa <hannes@stressinduktion.org> | 2013-10-19 15:48:57 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-10-19 19:45:35 -0400 |
| commit | 1bbdceef1e535add893bf71d7b7ab102e4eb69eb (patch) | |
| tree | e2eed21c778d0a6458f8350ce5f6fbfc6c58810e | |
| parent | b23a002fc6f0c19846ee0382f019429af54a27e9 (diff) | |
inet: convert inet_ehash_secret and ipv6_hash_secret to net_get_random_once
Initialize the ehash and ipv6_hash_secrets with net_get_random_once.
Each compilation unit gets its own secret now:
ipv4/inet_hashtables.o
ipv4/udp.o
ipv6/inet6_hashtables.o
ipv6/udp.o
rds/connection.o
The functions still get inlined into the hashing functions. In the fast
path we have at most two (needed in ipv6) if (unlikely(...)).
Cc: Eric Dumazet <edumazet@google.com>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/net/inet_sock.h | 4 | ||||
| -rw-r--r-- | net/ipv4/af_inet.c | 27 | ||||
| -rw-r--r-- | net/ipv4/inet_hashtables.c | 4 | ||||
| -rw-r--r-- | net/ipv4/udp.c | 6 | ||||
| -rw-r--r-- | net/ipv6/af_inet6.c | 5 | ||||
| -rw-r--r-- | net/ipv6/inet6_hashtables.c | 15 | ||||
| -rw-r--r-- | net/ipv6/udp.c | 17 | ||||
| -rw-r--r-- | net/rds/connection.c | 12 |
8 files changed, 44 insertions, 46 deletions
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 7a6c7f80a8fd..1833c3f389ee 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h | |||
| @@ -204,10 +204,6 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to, | |||
| 204 | 204 | ||
| 205 | int inet_sk_rebuild_header(struct sock *sk); | 205 | int inet_sk_rebuild_header(struct sock *sk); |
| 206 | 206 | ||
| 207 | extern u32 inet_ehash_secret; | ||
| 208 | extern u32 ipv6_hash_secret; | ||
| 209 | void build_ehash_secret(void); | ||
| 210 | |||
| 211 | static inline unsigned int __inet_ehashfn(const __be32 laddr, | 207 | static inline unsigned int __inet_ehashfn(const __be32 laddr, |
| 212 | const __u16 lport, | 208 | const __u16 lport, |
| 213 | const __be32 faddr, | 209 | const __be32 faddr, |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 4049906010f7..9433a6186f54 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -245,29 +245,6 @@ out: | |||
| 245 | } | 245 | } |
| 246 | EXPORT_SYMBOL(inet_listen); | 246 | EXPORT_SYMBOL(inet_listen); |
| 247 | 247 | ||
| 248 | u32 inet_ehash_secret __read_mostly; | ||
| 249 | EXPORT_SYMBOL(inet_ehash_secret); | ||
| 250 | |||
| 251 | u32 ipv6_hash_secret __read_mostly; | ||
| 252 | EXPORT_SYMBOL(ipv6_hash_secret); | ||
| 253 | |||
| 254 | /* | ||
| 255 | * inet_ehash_secret must be set exactly once, and to a non nul value | ||
| 256 | * ipv6_hash_secret must be set exactly once. | ||
| 257 | */ | ||
| 258 | void build_ehash_secret(void) | ||
| 259 | { | ||
| 260 | u32 rnd; | ||
| 261 | |||
| 262 | do { | ||
| 263 | get_random_bytes(&rnd, sizeof(rnd)); | ||
| 264 | } while (rnd == 0); | ||
| 265 | |||
| 266 | if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0) | ||
| 267 | get_random_bytes(&ipv6_hash_secret, sizeof(ipv6_hash_secret)); | ||
| 268 | } | ||
| 269 | EXPORT_SYMBOL(build_ehash_secret); | ||
| 270 | |||
| 271 | /* | 248 | /* |
| 272 | * Create an inet socket. | 249 | * Create an inet socket. |
| 273 | */ | 250 | */ |
| @@ -284,10 +261,6 @@ static int inet_create(struct net *net, struct socket *sock, int protocol, | |||
| 284 | int try_loading_module = 0; | 261 | int try_loading_module = 0; |
| 285 | int err; | 262 | int err; |
| 286 | 263 | ||
| 287 | if (unlikely(!inet_ehash_secret)) | ||
| 288 | if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) | ||
| 289 | build_ehash_secret(); | ||
| 290 | |||
| 291 | sock->state = SS_UNCONNECTED; | 264 | sock->state = SS_UNCONNECTED; |
| 292 | 265 | ||
| 293 | /* Look for the requested type/protocol pair. */ | 266 | /* Look for the requested type/protocol pair. */ |
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 18aa668d0cc9..8b9cf279450d 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
| @@ -28,6 +28,10 @@ static unsigned int inet_ehashfn(struct net *net, const __be32 laddr, | |||
| 28 | const __u16 lport, const __be32 faddr, | 28 | const __u16 lport, const __be32 faddr, |
| 29 | const __be16 fport) | 29 | const __be16 fport) |
| 30 | { | 30 | { |
| 31 | static u32 inet_ehash_secret __read_mostly; | ||
| 32 | |||
| 33 | net_get_random_once(&inet_ehash_secret, sizeof(inet_ehash_secret)); | ||
| 34 | |||
| 31 | return __inet_ehashfn(laddr, lport, faddr, fport, | 35 | return __inet_ehashfn(laddr, lport, faddr, fport, |
| 32 | inet_ehash_secret + net_hash_mix(net)); | 36 | inet_ehash_secret + net_hash_mix(net)); |
| 33 | } | 37 | } |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b4437c7db6ce..89909dd730dd 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -411,8 +411,12 @@ static unsigned int udp_ehashfn(struct net *net, const __be32 laddr, | |||
| 411 | const __u16 lport, const __be32 faddr, | 411 | const __u16 lport, const __be32 faddr, |
| 412 | const __be16 fport) | 412 | const __be16 fport) |
| 413 | { | 413 | { |
| 414 | static u32 udp_ehash_secret __read_mostly; | ||
| 415 | |||
| 416 | net_get_random_once(&udp_ehash_secret, sizeof(udp_ehash_secret)); | ||
| 417 | |||
| 414 | return __inet_ehashfn(laddr, lport, faddr, fport, | 418 | return __inet_ehashfn(laddr, lport, faddr, fport, |
| 415 | inet_ehash_secret + net_hash_mix(net)); | 419 | udp_ehash_secret + net_hash_mix(net)); |
| 416 | } | 420 | } |
| 417 | 421 | ||
| 418 | 422 | ||
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index a2cb07cd3850..20af1fb81c83 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
| @@ -110,11 +110,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, | |||
| 110 | int try_loading_module = 0; | 110 | int try_loading_module = 0; |
| 111 | int err; | 111 | int err; |
| 112 | 112 | ||
| 113 | if (sock->type != SOCK_RAW && | ||
| 114 | sock->type != SOCK_DGRAM && | ||
| 115 | !inet_ehash_secret) | ||
| 116 | build_ehash_secret(); | ||
| 117 | |||
| 118 | /* Look for the requested type/protocol pair. */ | 113 | /* Look for the requested type/protocol pair. */ |
| 119 | lookup_protocol: | 114 | lookup_protocol: |
| 120 | err = -ESOCKTNOSUPPORT; | 115 | err = -ESOCKTNOSUPPORT; |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index fa7dd3856c55..262e13c02ec2 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c | |||
| @@ -29,10 +29,19 @@ static unsigned int inet6_ehashfn(struct net *net, | |||
| 29 | const struct in6_addr *faddr, | 29 | const struct in6_addr *faddr, |
| 30 | const __be16 fport) | 30 | const __be16 fport) |
| 31 | { | 31 | { |
| 32 | const u32 lhash = (__force u32)laddr->s6_addr32[3]; | 32 | static u32 inet6_ehash_secret __read_mostly; |
| 33 | const u32 fhash = __ipv6_addr_jhash(faddr, ipv6_hash_secret); | 33 | static u32 ipv6_hash_secret __read_mostly; |
| 34 | |||
| 35 | u32 lhash, fhash; | ||
| 36 | |||
| 37 | net_get_random_once(&inet6_ehash_secret, sizeof(inet6_ehash_secret)); | ||
| 38 | net_get_random_once(&ipv6_hash_secret, sizeof(ipv6_hash_secret)); | ||
| 39 | |||
| 40 | lhash = (__force u32)laddr->s6_addr32[3]; | ||
| 41 | fhash = __ipv6_addr_jhash(faddr, ipv6_hash_secret); | ||
| 42 | |||
| 34 | return __inet6_ehashfn(lhash, lport, fhash, fport, | 43 | return __inet6_ehashfn(lhash, lport, fhash, fport, |
| 35 | inet_ehash_secret + net_hash_mix(net)); | 44 | inet6_ehash_secret + net_hash_mix(net)); |
| 36 | } | 45 | } |
| 37 | 46 | ||
| 38 | static int inet6_sk_ehashfn(const struct sock *sk) | 47 | static int inet6_sk_ehashfn(const struct sock *sk) |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 324bd36c23bc..44fc4e3d661f 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -59,10 +59,21 @@ static unsigned int udp6_ehashfn(struct net *net, | |||
| 59 | const struct in6_addr *faddr, | 59 | const struct in6_addr *faddr, |
| 60 | const __be16 fport) | 60 | const __be16 fport) |
| 61 | { | 61 | { |
| 62 | const u32 lhash = (__force u32)laddr->s6_addr32[3]; | 62 | static u32 udp6_ehash_secret __read_mostly; |
| 63 | const u32 fhash = __ipv6_addr_jhash(faddr, ipv6_hash_secret); | 63 | static u32 udp_ipv6_hash_secret __read_mostly; |
| 64 | |||
| 65 | u32 lhash, fhash; | ||
| 66 | |||
| 67 | net_get_random_once(&udp6_ehash_secret, | ||
| 68 | sizeof(udp6_ehash_secret)); | ||
| 69 | net_get_random_once(&udp_ipv6_hash_secret, | ||
| 70 | sizeof(udp_ipv6_hash_secret)); | ||
| 71 | |||
| 72 | lhash = (__force u32)laddr->s6_addr32[3]; | ||
| 73 | fhash = __ipv6_addr_jhash(faddr, udp_ipv6_hash_secret); | ||
| 74 | |||
| 64 | return __inet6_ehashfn(lhash, lport, fhash, fport, | 75 | return __inet6_ehashfn(lhash, lport, fhash, fport, |
| 65 | inet_ehash_secret + net_hash_mix(net)); | 76 | udp_ipv6_hash_secret + net_hash_mix(net)); |
| 66 | } | 77 | } |
| 67 | 78 | ||
| 68 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | 79 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) |
diff --git a/net/rds/connection.c b/net/rds/connection.c index 45e23660437a..378c3a6acf84 100644 --- a/net/rds/connection.c +++ b/net/rds/connection.c | |||
| @@ -51,10 +51,16 @@ static struct kmem_cache *rds_conn_slab; | |||
| 51 | 51 | ||
| 52 | static struct hlist_head *rds_conn_bucket(__be32 laddr, __be32 faddr) | 52 | static struct hlist_head *rds_conn_bucket(__be32 laddr, __be32 faddr) |
| 53 | { | 53 | { |
| 54 | static u32 rds_hash_secret __read_mostly; | ||
| 55 | |||
| 56 | unsigned long hash; | ||
| 57 | |||
| 58 | net_get_random_once(&rds_hash_secret, sizeof(rds_hash_secret)); | ||
| 59 | |||
| 54 | /* Pass NULL, don't need struct net for hash */ | 60 | /* Pass NULL, don't need struct net for hash */ |
| 55 | unsigned long hash = __inet_ehashfn(be32_to_cpu(laddr), 0, | 61 | hash = __inet_ehashfn(be32_to_cpu(laddr), 0, |
| 56 | be32_to_cpu(faddr), 0, | 62 | be32_to_cpu(faddr), 0, |
| 57 | inet_ehash_secret); | 63 | rds_hash_secret); |
| 58 | return &rds_conn_hash[hash & RDS_CONNECTION_HASH_MASK]; | 64 | return &rds_conn_hash[hash & RDS_CONNECTION_HASH_MASK]; |
| 59 | } | 65 | } |
| 60 | 66 | ||
