inet: convert inet_ehash_secret and ipv6_hash_secret to net_get_random_once
authorHannes Frederic Sowa <hannes@stressinduktion.org>
Sat, 19 Oct 2013 19:48:57 +0000 (21:48 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sat, 19 Oct 2013 23:45:35 +0000 (19:45 -0400)
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>
include/net/inet_sock.h
net/ipv4/af_inet.c
net/ipv4/inet_hashtables.c
net/ipv4/udp.c
net/ipv6/af_inet6.c
net/ipv6/inet6_hashtables.c
net/ipv6/udp.c
net/rds/connection.c

index 7a6c7f80a8fd7f9c59b5299d10981613d09557e7..1833c3f389ee64a0c6b3862d4f2fbc6db0984b0a 100644 (file)
@@ -204,10 +204,6 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to,
 
 int inet_sk_rebuild_header(struct sock *sk);
 
-extern u32 inet_ehash_secret;
-extern u32 ipv6_hash_secret;
-void build_ehash_secret(void);
-
 static inline unsigned int __inet_ehashfn(const __be32 laddr,
                                          const __u16 lport,
                                          const __be32 faddr,
index 4049906010f715ce9a385e049b8c1b51be6d4e42..9433a6186f5415587cfb030c504225b2e5016e49 100644 (file)
@@ -245,29 +245,6 @@ out:
 }
 EXPORT_SYMBOL(inet_listen);
 
-u32 inet_ehash_secret __read_mostly;
-EXPORT_SYMBOL(inet_ehash_secret);
-
-u32 ipv6_hash_secret __read_mostly;
-EXPORT_SYMBOL(ipv6_hash_secret);
-
-/*
- * inet_ehash_secret must be set exactly once, and to a non nul value
- * ipv6_hash_secret must be set exactly once.
- */
-void build_ehash_secret(void)
-{
-       u32 rnd;
-
-       do {
-               get_random_bytes(&rnd, sizeof(rnd));
-       } while (rnd == 0);
-
-       if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0)
-               get_random_bytes(&ipv6_hash_secret, sizeof(ipv6_hash_secret));
-}
-EXPORT_SYMBOL(build_ehash_secret);
-
 /*
  *     Create an inet socket.
  */
@@ -284,10 +261,6 @@ static int inet_create(struct net *net, struct socket *sock, int protocol,
        int try_loading_module = 0;
        int err;
 
-       if (unlikely(!inet_ehash_secret))
-               if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
-                       build_ehash_secret();
-
        sock->state = SS_UNCONNECTED;
 
        /* Look for the requested type/protocol pair. */
index 18aa668d0cc96bb33911d3014727690377a8bc6d..8b9cf279450d6cf0c24e64a20fb0d05b9fb89a82 100644 (file)
@@ -28,6 +28,10 @@ static unsigned int inet_ehashfn(struct net *net, const __be32 laddr,
                                 const __u16 lport, const __be32 faddr,
                                 const __be16 fport)
 {
+       static u32 inet_ehash_secret __read_mostly;
+
+       net_get_random_once(&inet_ehash_secret, sizeof(inet_ehash_secret));
+
        return __inet_ehashfn(laddr, lport, faddr, fport,
                              inet_ehash_secret + net_hash_mix(net));
 }
index b4437c7db6cec846ef6b5055f9736f0bb236c896..89909dd730ddd65a4eac4f18e8a38925962b8534 100644 (file)
@@ -411,8 +411,12 @@ static unsigned int udp_ehashfn(struct net *net, const __be32 laddr,
                                 const __u16 lport, const __be32 faddr,
                                 const __be16 fport)
 {
+       static u32 udp_ehash_secret __read_mostly;
+
+       net_get_random_once(&udp_ehash_secret, sizeof(udp_ehash_secret));
+
        return __inet_ehashfn(laddr, lport, faddr, fport,
-                             inet_ehash_secret + net_hash_mix(net));
+                             udp_ehash_secret + net_hash_mix(net));
 }
 
 
index a2cb07cd385032a0e4212d351c32950729eb1e8b..20af1fb81c837ad0a4b328642e958210c6d01f3d 100644 (file)
@@ -110,11 +110,6 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
        int try_loading_module = 0;
        int err;
 
-       if (sock->type != SOCK_RAW &&
-           sock->type != SOCK_DGRAM &&
-           !inet_ehash_secret)
-               build_ehash_secret();
-
        /* Look for the requested type/protocol pair. */
 lookup_protocol:
        err = -ESOCKTNOSUPPORT;
index fa7dd3856c555d0c6dcd4c04062c7983b1aeb61b..262e13c02ec27dea15154d9b4af5fd413dd1c504 100644 (file)
@@ -29,10 +29,19 @@ static unsigned int inet6_ehashfn(struct net *net,
                                  const struct in6_addr *faddr,
                                  const __be16 fport)
 {
-       const u32 lhash = (__force u32)laddr->s6_addr32[3];
-       const u32 fhash = __ipv6_addr_jhash(faddr, ipv6_hash_secret);
+       static u32 inet6_ehash_secret __read_mostly;
+       static u32 ipv6_hash_secret __read_mostly;
+
+       u32 lhash, fhash;
+
+       net_get_random_once(&inet6_ehash_secret, sizeof(inet6_ehash_secret));
+       net_get_random_once(&ipv6_hash_secret, sizeof(ipv6_hash_secret));
+
+       lhash = (__force u32)laddr->s6_addr32[3];
+       fhash = __ipv6_addr_jhash(faddr, ipv6_hash_secret);
+
        return __inet6_ehashfn(lhash, lport, fhash, fport,
-                              inet_ehash_secret + net_hash_mix(net));
+                              inet6_ehash_secret + net_hash_mix(net));
 }
 
 static int inet6_sk_ehashfn(const struct sock *sk)
index 324bd36c23bce8601968710b142a08e905019ddf..44fc4e3d661fc342cc4cea555823c69694039d5c 100644 (file)
@@ -59,10 +59,21 @@ static unsigned int udp6_ehashfn(struct net *net,
                                  const struct in6_addr *faddr,
                                  const __be16 fport)
 {
-       const u32 lhash = (__force u32)laddr->s6_addr32[3];
-       const u32 fhash = __ipv6_addr_jhash(faddr, ipv6_hash_secret);
+       static u32 udp6_ehash_secret __read_mostly;
+       static u32 udp_ipv6_hash_secret __read_mostly;
+
+       u32 lhash, fhash;
+
+       net_get_random_once(&udp6_ehash_secret,
+                           sizeof(udp6_ehash_secret));
+       net_get_random_once(&udp_ipv6_hash_secret,
+                           sizeof(udp_ipv6_hash_secret));
+
+       lhash = (__force u32)laddr->s6_addr32[3];
+       fhash = __ipv6_addr_jhash(faddr, udp_ipv6_hash_secret);
+
        return __inet6_ehashfn(lhash, lport, fhash, fport,
-                              inet_ehash_secret + net_hash_mix(net));
+                              udp_ipv6_hash_secret + net_hash_mix(net));
 }
 
 int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2)
index 45e23660437a6ed15006e7a125cea99183c86c04..378c3a6acf84cab59346ab832d2fffba33e6e543 100644 (file)
@@ -51,10 +51,16 @@ static struct kmem_cache *rds_conn_slab;
 
 static struct hlist_head *rds_conn_bucket(__be32 laddr, __be32 faddr)
 {
+       static u32 rds_hash_secret __read_mostly;
+
+       unsigned long hash;
+
+       net_get_random_once(&rds_hash_secret, sizeof(rds_hash_secret));
+
        /* Pass NULL, don't need struct net for hash */
-       unsigned long hash = __inet_ehashfn(be32_to_cpu(laddr), 0,
-                                           be32_to_cpu(faddr), 0,
-                                           inet_ehash_secret);
+       hash = __inet_ehashfn(be32_to_cpu(laddr), 0,
+                             be32_to_cpu(faddr), 0,
+                             rds_hash_secret);
        return &rds_conn_hash[hash & RDS_CONNECTION_HASH_MASK];
 }