Commit dd6d2910 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

netfilter: conntrack: switch to siphash

Replace jhash in conntrack and nat core with siphash.

While at it, use the netns mix value as part of the input key
rather than abuse the seed value.
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent d532bcd0
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/jhash.h>
#include <linux/siphash.h> #include <linux/siphash.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/percpu.h> #include <linux/percpu.h>
...@@ -184,25 +183,31 @@ EXPORT_SYMBOL_GPL(nf_conntrack_htable_size); ...@@ -184,25 +183,31 @@ EXPORT_SYMBOL_GPL(nf_conntrack_htable_size);
unsigned int nf_conntrack_max __read_mostly; unsigned int nf_conntrack_max __read_mostly;
EXPORT_SYMBOL_GPL(nf_conntrack_max); EXPORT_SYMBOL_GPL(nf_conntrack_max);
seqcount_spinlock_t nf_conntrack_generation __read_mostly; seqcount_spinlock_t nf_conntrack_generation __read_mostly;
static unsigned int nf_conntrack_hash_rnd __read_mostly; static siphash_key_t nf_conntrack_hash_rnd __read_mostly;
static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple,
const struct net *net) const struct net *net)
{ {
unsigned int n; struct {
u32 seed; struct nf_conntrack_man src;
union nf_inet_addr dst_addr;
u32 net_mix;
u16 dport;
u16 proto;
} __aligned(SIPHASH_ALIGNMENT) combined;
get_random_once(&nf_conntrack_hash_rnd, sizeof(nf_conntrack_hash_rnd)); get_random_once(&nf_conntrack_hash_rnd, sizeof(nf_conntrack_hash_rnd));
/* The direction must be ignored, so we hash everything up to the memset(&combined, 0, sizeof(combined));
* destination ports (which is a multiple of 4) and treat the last
* three bytes manually. /* The direction must be ignored, so handle usable members manually. */
*/ combined.src = tuple->src;
seed = nf_conntrack_hash_rnd ^ net_hash_mix(net); combined.dst_addr = tuple->dst.u3;
n = (sizeof(tuple->src) + sizeof(tuple->dst.u3)) / sizeof(u32); combined.net_mix = net_hash_mix(net);
return jhash2((u32 *)tuple, n, seed ^ combined.dport = (__force __u16)tuple->dst.u.all;
(((__force __u16)tuple->dst.u.all << 16) | combined.proto = tuple->dst.protonum;
tuple->dst.protonum));
return (u32)siphash(&combined, sizeof(combined), &nf_conntrack_hash_rnd);
} }
static u32 scale_hash(u32 hash) static u32 scale_hash(u32 hash)
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/jhash.h> #include <linux/siphash.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/export.h> #include <linux/export.h>
#include <net/net_namespace.h> #include <net/net_namespace.h>
...@@ -41,7 +41,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_hash); ...@@ -41,7 +41,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_hash);
unsigned int nf_ct_expect_max __read_mostly; unsigned int nf_ct_expect_max __read_mostly;
static struct kmem_cache *nf_ct_expect_cachep __read_mostly; static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
static unsigned int nf_ct_expect_hashrnd __read_mostly; static siphash_key_t nf_ct_expect_hashrnd __read_mostly;
/* nf_conntrack_expect helper functions */ /* nf_conntrack_expect helper functions */
void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
...@@ -81,15 +81,26 @@ static void nf_ct_expectation_timed_out(struct timer_list *t) ...@@ -81,15 +81,26 @@ static void nf_ct_expectation_timed_out(struct timer_list *t)
static unsigned int nf_ct_expect_dst_hash(const struct net *n, const struct nf_conntrack_tuple *tuple) static unsigned int nf_ct_expect_dst_hash(const struct net *n, const struct nf_conntrack_tuple *tuple)
{ {
unsigned int hash, seed; struct {
union nf_inet_addr dst_addr;
u32 net_mix;
u16 dport;
u8 l3num;
u8 protonum;
} __aligned(SIPHASH_ALIGNMENT) combined;
u32 hash;
get_random_once(&nf_ct_expect_hashrnd, sizeof(nf_ct_expect_hashrnd)); get_random_once(&nf_ct_expect_hashrnd, sizeof(nf_ct_expect_hashrnd));
seed = nf_ct_expect_hashrnd ^ net_hash_mix(n); memset(&combined, 0, sizeof(combined));
hash = jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all), combined.dst_addr = tuple->dst.u3;
(((tuple->dst.protonum ^ tuple->src.l3num) << 16) | combined.net_mix = net_hash_mix(n);
(__force __u16)tuple->dst.u.all) ^ seed); combined.dport = (__force __u16)tuple->dst.u.all;
combined.l3num = tuple->src.l3num;
combined.protonum = tuple->dst.protonum;
hash = siphash(&combined, sizeof(combined), &nf_ct_expect_hashrnd);
return reciprocal_scale(hash, nf_ct_expect_hsize); return reciprocal_scale(hash, nf_ct_expect_hsize);
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <net/xfrm.h> #include <net/xfrm.h>
#include <linux/jhash.h> #include <linux/siphash.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
...@@ -34,7 +34,7 @@ static unsigned int nat_net_id __read_mostly; ...@@ -34,7 +34,7 @@ static unsigned int nat_net_id __read_mostly;
static struct hlist_head *nf_nat_bysource __read_mostly; static struct hlist_head *nf_nat_bysource __read_mostly;
static unsigned int nf_nat_htable_size __read_mostly; static unsigned int nf_nat_htable_size __read_mostly;
static unsigned int nf_nat_hash_rnd __read_mostly; static siphash_key_t nf_nat_hash_rnd __read_mostly;
struct nf_nat_lookup_hook_priv { struct nf_nat_lookup_hook_priv {
struct nf_hook_entries __rcu *entries; struct nf_hook_entries __rcu *entries;
...@@ -153,12 +153,22 @@ static unsigned int ...@@ -153,12 +153,22 @@ static unsigned int
hash_by_src(const struct net *n, const struct nf_conntrack_tuple *tuple) hash_by_src(const struct net *n, const struct nf_conntrack_tuple *tuple)
{ {
unsigned int hash; unsigned int hash;
struct {
struct nf_conntrack_man src;
u32 net_mix;
u32 protonum;
} __aligned(SIPHASH_ALIGNMENT) combined;
get_random_once(&nf_nat_hash_rnd, sizeof(nf_nat_hash_rnd)); get_random_once(&nf_nat_hash_rnd, sizeof(nf_nat_hash_rnd));
memset(&combined, 0, sizeof(combined));
/* Original src, to ensure we map it consistently if poss. */ /* Original src, to ensure we map it consistently if poss. */
hash = jhash2((u32 *)&tuple->src, sizeof(tuple->src) / sizeof(u32), combined.src = tuple->src;
tuple->dst.protonum ^ nf_nat_hash_rnd ^ net_hash_mix(n)); combined.net_mix = net_hash_mix(n);
combined.protonum = tuple->dst.protonum;
hash = siphash(&combined, sizeof(combined), &nf_nat_hash_rnd);
return reciprocal_scale(hash, nf_nat_htable_size); return reciprocal_scale(hash, nf_nat_htable_size);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment