diff options
author | Patrick McHardy <kaber@trash.net> | 2007-12-18 01:45:52 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:59:11 -0500 |
commit | 34498825cb9062192b77fa02dae672a4fe6eec70 (patch) | |
tree | 7f856aff21ae3ab1328ab9bcf3549bca8e13df35 | |
parent | 7b21e09d1c17ef0296ec5a6df231a6c5c87b2fd7 (diff) |
[NETFILTER]: non-power-of-two jhash optimizations
Apply Eric Dumazet's jhash optimizations where applicable. Quoting Eric:
Thanks to jhash, hash value uses full 32 bits. Instead of returning
hash % size (implying a divide) we return the high 32 bits of the
(hash * size) that will give results between [0 and size-1] and same
hash distribution.
On most cpus, a multiply is less expensive than a divide, by an order
of magnitude.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/netfilter/ipt_CLUSTERIP.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_core.c | 10 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_expect.c | 8 |
4 files changed, 14 insertions, 8 deletions
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index a48e26449fd5..df39ca07fb12 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -273,7 +273,7 @@ clusterip_hashfn(const struct sk_buff *skb, | |||
273 | } | 273 | } |
274 | 274 | ||
275 | /* node numbers are 1..n, not 0..n */ | 275 | /* node numbers are 1..n, not 0..n */ |
276 | return (hashval % config->num_total_nodes) + 1; | 276 | return (((u64)hashval * config->num_total_nodes) >> 32) + 1; |
277 | } | 277 | } |
278 | 278 | ||
279 | static inline int | 279 | static inline int |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index aec157d0ad93..e53ae1ef8f5e 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -77,10 +77,13 @@ EXPORT_SYMBOL_GPL(nf_nat_proto_put); | |||
77 | static inline unsigned int | 77 | static inline unsigned int |
78 | hash_by_src(const struct nf_conntrack_tuple *tuple) | 78 | hash_by_src(const struct nf_conntrack_tuple *tuple) |
79 | { | 79 | { |
80 | unsigned int hash; | ||
81 | |||
80 | /* Original src, to ensure we map it consistently if poss. */ | 82 | /* Original src, to ensure we map it consistently if poss. */ |
81 | return jhash_3words((__force u32)tuple->src.u3.ip, | 83 | hash = jhash_3words((__force u32)tuple->src.u3.ip, |
82 | (__force u32)tuple->src.u.all, | 84 | (__force u32)tuple->src.u.all, |
83 | tuple->dst.protonum, 0) % nf_nat_htable_size; | 85 | tuple->dst.protonum, 0); |
86 | return ((u64)hash * nf_nat_htable_size) >> 32; | ||
84 | } | 87 | } |
85 | 88 | ||
86 | /* Is this tuple already taken? (not by us) */ | 89 | /* Is this tuple already taken? (not by us) */ |
@@ -211,7 +214,8 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple, | |||
211 | maxip = ntohl(range->max_ip); | 214 | maxip = ntohl(range->max_ip); |
212 | j = jhash_2words((__force u32)tuple->src.u3.ip, | 215 | j = jhash_2words((__force u32)tuple->src.u3.ip, |
213 | (__force u32)tuple->dst.u3.ip, 0); | 216 | (__force u32)tuple->dst.u3.ip, 0); |
214 | *var_ipp = htonl(minip + j % (maxip - minip + 1)); | 217 | j = ((u64)j * (maxip - minip + 1)) >> 32; |
218 | *var_ipp = htonl(minip + j); | ||
215 | } | 219 | } |
216 | 220 | ||
217 | /* Manipulate the tuple into the range given. For NF_INET_POST_ROUTING, | 221 | /* Manipulate the tuple into the range given. For NF_INET_POST_ROUTING, |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 5920f953f782..25564073ee23 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -81,7 +81,7 @@ static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple, | |||
81 | ((__force __u16)tuple->src.u.all << 16) | | 81 | ((__force __u16)tuple->src.u.all << 16) | |
82 | (__force __u16)tuple->dst.u.all); | 82 | (__force __u16)tuple->dst.u.all); |
83 | 83 | ||
84 | return jhash_2words(a, b, rnd) % size; | 84 | return ((u64)jhash_2words(a, b, rnd) * size) >> 32; |
85 | } | 85 | } |
86 | 86 | ||
87 | static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple) | 87 | static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple) |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 0efbf343eac8..e0cd9d00aa61 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
@@ -73,15 +73,17 @@ static void nf_ct_expectation_timed_out(unsigned long ul_expect) | |||
73 | 73 | ||
74 | static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple) | 74 | static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple) |
75 | { | 75 | { |
76 | unsigned int hash; | ||
77 | |||
76 | if (unlikely(!nf_ct_expect_hash_rnd_initted)) { | 78 | if (unlikely(!nf_ct_expect_hash_rnd_initted)) { |
77 | get_random_bytes(&nf_ct_expect_hash_rnd, 4); | 79 | get_random_bytes(&nf_ct_expect_hash_rnd, 4); |
78 | nf_ct_expect_hash_rnd_initted = 1; | 80 | nf_ct_expect_hash_rnd_initted = 1; |
79 | } | 81 | } |
80 | 82 | ||
81 | return jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all), | 83 | hash = jhash2(tuple->dst.u3.all, ARRAY_SIZE(tuple->dst.u3.all), |
82 | (((tuple->dst.protonum ^ tuple->src.l3num) << 16) | | 84 | (((tuple->dst.protonum ^ tuple->src.l3num) << 16) | |
83 | (__force __u16)tuple->dst.u.all) ^ nf_ct_expect_hash_rnd) % | 85 | (__force __u16)tuple->dst.u.all) ^ nf_ct_expect_hash_rnd); |
84 | nf_ct_expect_hsize; | 86 | return ((u64)hash * nf_ct_expect_hsize) >> 32; |
85 | } | 87 | } |
86 | 88 | ||
87 | struct nf_conntrack_expect * | 89 | struct nf_conntrack_expect * |