Re: [PATCH nf-next 2/6] netfilter: nat: convert nat bysrc hash to rhashtable

2016-07-11 Thread Pablo Neira Ayuso
On Tue, Jul 05, 2016 at 12:07:24PM +0200, Florian Westphal wrote:
> It did use a fixed-size bucket list plus single lock to protect add/del.
> 
> Unlike the main conntrack table we only need to add and remove keys.
> Convert it to rhashtable to get table autosizing and per-bucket locking.
> 
> The maximum number of entries is -- as before -- tied to the number of
> conntracks so we do not need another upperlimit.
> 
> The change does not handle rhashtable_remove_fast error, only possible
> "error" is -ENOENT, and that is something that can happen legitimetely,
> e.g. because nat module was inserted at a later time and no src manip
> took place yet.
> 
> Tested with http-client-benchmark + httpterm with DNAT and SNAT rules
> in place.

Applied, thanks.

I'm fixing this minor glitch here.

  CC [M]  net/netfilter/nf_nat_core.o
net/netfilter/nf_nat_core.c: In function ‘nf_nat_proto_clean’:
net/netfilter/nf_nat_core.c:555:6: warning: unused variable ‘err’
[-Wunused-variable]
  int err;
  ^

No need to resend.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next 2/6] netfilter: nat: convert nat bysrc hash to rhashtable

2016-07-05 Thread Florian Westphal
It did use a fixed-size bucket list plus single lock to protect add/del.

Unlike the main conntrack table we only need to add and remove keys.
Convert it to rhashtable to get table autosizing and per-bucket locking.

The maximum number of entries is -- as before -- tied to the number of
conntracks so we do not need another upperlimit.

The change does not handle rhashtable_remove_fast error, only possible
"error" is -ENOENT, and that is something that can happen legitimetely,
e.g. because nat module was inserted at a later time and no src manip
took place yet.

Tested with http-client-benchmark + httpterm with DNAT and SNAT rules
in place.

Signed-off-by: Florian Westphal 
---
 include/net/netfilter/nf_conntrack.h |   3 +-
 include/net/netfilter/nf_nat.h   |   1 +
 net/netfilter/nf_nat_core.c  | 127 +++
 3 files changed, 72 insertions(+), 59 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack.h 
b/include/net/netfilter/nf_conntrack.h
index 1d9e6c8..f8a8155 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -118,7 +119,7 @@ struct nf_conn {
struct nf_ct_ext *ext;
 
 #if IS_ENABLED(CONFIG_NF_NAT)
-   struct hlist_node   nat_bysource;
+   struct rhash_head   nat_bysource;
 #endif
/* Storage reserved for other modules, must be the last member */
union nf_conntrack_proto proto;
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index 02515f7..c327a43 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -1,5 +1,6 @@
 #ifndef _NF_NAT_H
 #define _NF_NAT_H
+#include 
 #include 
 #include 
 #include 
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 6e7a253..3d97fa3 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -30,17 +30,19 @@
 #include 
 #include 
 
-static DEFINE_SPINLOCK(nf_nat_lock);
-
 static DEFINE_MUTEX(nf_nat_proto_mutex);
 static const struct nf_nat_l3proto __rcu *nf_nat_l3protos[NFPROTO_NUMPROTO]
__read_mostly;
 static const struct nf_nat_l4proto __rcu **nf_nat_l4protos[NFPROTO_NUMPROTO]
__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_hash_rnd __read_mostly;
+struct nf_nat_conn_key {
+   const struct net *net;
+   const struct nf_conntrack_tuple *tuple;
+   const struct nf_conntrack_zone *zone;
+};
+
+static struct rhashtable nf_nat_bysource_table;
 
 inline const struct nf_nat_l3proto *
 __nf_nat_l3proto_find(u8 family)
@@ -119,19 +121,17 @@ int nf_xfrm_me_harder(struct net *net, struct sk_buff 
*skb, unsigned int family)
 EXPORT_SYMBOL(nf_xfrm_me_harder);
 #endif /* CONFIG_XFRM */
 
-/* We keep an extra hash for each conntrack, for fast searching. */
-static inline unsigned int
-hash_by_src(const struct net *n, const struct nf_conntrack_tuple *tuple)
+static u32 nf_nat_bysource_hash(const void *data, u32 len, u32 seed)
 {
-   unsigned int hash;
-
-   get_random_once(_nat_hash_rnd, sizeof(nf_nat_hash_rnd));
+   const struct nf_conntrack_tuple *t;
+   const struct nf_conn *ct = data;
 
+   t = >tuplehash[IP_CT_DIR_ORIGINAL].tuple;
/* Original src, to ensure we map it consistently if poss. */
-   hash = jhash2((u32 *)>src, sizeof(tuple->src) / sizeof(u32),
- tuple->dst.protonum ^ nf_nat_hash_rnd ^ net_hash_mix(n));
 
-   return reciprocal_scale(hash, nf_nat_htable_size);
+   seed ^= net_hash_mix(nf_ct_net(ct));
+   return jhash2((const u32 *)>src, sizeof(t->src) / sizeof(u32),
+ t->dst.protonum ^ seed);
 }
 
 /* Is this tuple already taken? (not by us) */
@@ -187,6 +187,26 @@ same_src(const struct nf_conn *ct,
t->src.u.all == tuple->src.u.all);
 }
 
+static int nf_nat_bysource_cmp(struct rhashtable_compare_arg *arg,
+  const void *obj)
+{
+   const struct nf_nat_conn_key *key = arg->key;
+   const struct nf_conn *ct = obj;
+
+   return same_src(ct, key->tuple) &&
+  net_eq(nf_ct_net(ct), key->net) &&
+  nf_ct_zone_equal(ct, key->zone, IP_CT_DIR_ORIGINAL);
+}
+
+static struct rhashtable_params nf_nat_bysource_params = {
+   .head_offset = offsetof(struct nf_conn, nat_bysource),
+   .obj_hashfn = nf_nat_bysource_hash,
+   .obj_cmpfn = nf_nat_bysource_cmp,
+   .nelem_hint = 256,
+   .min_size = 1024,
+   .nulls_base = (1U << RHT_BASE_SHIFT),
+};
+
 /* Only called for SRC manip */
 static int
 find_appropriate_src(struct net *net,
@@ -197,23 +217,23 @@ find_appropriate_src(struct net *net,
 struct nf_conntrack_tuple *result,