diff mbox series

[nf-next,2/3] netfilter: nf_conncount: expose connection list interface

Message ID 20180531143439.9420-2-pablo@netfilter.org
State RFC
Delegated to: Pablo Neira
Headers show
Series [nf-next,1/3] netfilter: nf_tables: pass context to object destroy indirection | expand

Commit Message

Pablo Neira Ayuso May 31, 2018, 2:34 p.m. UTC
This patch provides an interface to maintain the list of connections and
the lookup function to obtain the number of connections in the list.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/net/netfilter/nf_conntrack_count.h | 15 +++++++
 net/netfilter/nf_conncount.c               | 67 +++++++++++++++++++++---------
 2 files changed, 62 insertions(+), 20 deletions(-)
diff mbox series

Patch

diff --git a/include/net/netfilter/nf_conntrack_count.h b/include/net/netfilter/nf_conntrack_count.h
index e61184fbfb71..2a356907ab80 100644
--- a/include/net/netfilter/nf_conntrack_count.h
+++ b/include/net/netfilter/nf_conntrack_count.h
@@ -13,4 +13,19 @@  unsigned int nf_conncount_count(struct net *net,
 				const u32 *key,
 				const struct nf_conntrack_tuple *tuple,
 				const struct nf_conntrack_zone *zone);
+
+struct kmem_cache;
+
+struct kmem_cache *nf_conncount_cache_alloc(void);
+void nf_conncount_cache_free(struct kmem_cache *cache, struct hlist_head *hhead);
+
+unsigned int nf_conncount_lookup(struct net *net, struct kmem_cache *cache,
+				 struct hlist_head *head,
+				 const struct nf_conntrack_tuple *tuple,
+				 const struct nf_conntrack_zone *zone,
+				 bool *addit);
+
+bool nf_conncount_add(struct kmem_cache *cache, struct hlist_head *head,
+		      const struct nf_conntrack_tuple *tuple);
+
 #endif
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index 153e690e2893..679c48feda14 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -79,24 +79,27 @@  static int key_diff(const u32 *a, const u32 *b, unsigned int klen)
 	return memcmp(a, b, klen * sizeof(u32));
 }
 
-static bool add_hlist(struct hlist_head *head,
+bool nf_conncount_add(struct kmem_cache *conncount_cache,
+		      struct hlist_head *head,
 		      const struct nf_conntrack_tuple *tuple)
 {
 	struct nf_conncount_tuple *conn;
 
-	conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC);
+	conn = kmem_cache_alloc(conncount_cache, GFP_ATOMIC);
 	if (conn == NULL)
 		return false;
 	conn->tuple = *tuple;
 	hlist_add_head(&conn->node, head);
 	return true;
 }
-
-static unsigned int check_hlist(struct net *net,
-				struct hlist_head *head,
-				const struct nf_conntrack_tuple *tuple,
-				const struct nf_conntrack_zone *zone,
-				bool *addit)
+EXPORT_SYMBOL_GPL(nf_conncount_add);
+
+unsigned int nf_conncount_lookup(struct net *net,
+				 struct kmem_cache *conncount_cache,
+				 struct hlist_head *head,
+				 const struct nf_conntrack_tuple *tuple,
+				 const struct nf_conntrack_zone *zone,
+				 bool *addit)
 {
 	const struct nf_conntrack_tuple_hash *found;
 	struct nf_conncount_tuple *conn;
@@ -131,7 +134,7 @@  static unsigned int check_hlist(struct net *net,
 			 */
 			nf_ct_put(found_ct);
 			hlist_del(&conn->node);
-			kmem_cache_free(conncount_conn_cachep, conn);
+			kmem_cache_free(conncount_cache, conn);
 			continue;
 		}
 
@@ -187,13 +190,17 @@  count_tree(struct net *net, struct rb_root *root,
 		} else {
 			/* same source network -> be counted! */
 			unsigned int count;
-			count = check_hlist(net, &rbconn->hhead, tuple, zone, &addit);
+
+			count = nf_conncount_lookup(net, conncount_conn_cachep,
+						    &rbconn->hhead, tuple,
+						    zone, &addit);
 
 			tree_nodes_free(root, gc_nodes, gc_count);
 			if (!addit)
 				return count;
 
-			if (!add_hlist(&rbconn->hhead, tuple))
+			if (!nf_conncount_add(conncount_conn_cachep,
+					      &rbconn->hhead, tuple))
 				return 0; /* hotdrop */
 
 			return count + 1;
@@ -203,7 +210,8 @@  count_tree(struct net *net, struct rb_root *root,
 			continue;
 
 		/* only used for GC on hhead, retval and 'addit' ignored */
-		check_hlist(net, &rbconn->hhead, tuple, zone, &addit);
+		nf_conncount_lookup(net, conncount_conn_cachep, &rbconn->hhead,
+				    tuple, zone, &addit);
 		if (hlist_empty(&rbconn->hhead))
 			gc_nodes[gc_count++] = rbconn;
 	}
@@ -303,11 +311,19 @@  struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family
 }
 EXPORT_SYMBOL_GPL(nf_conncount_init);
 
-static void destroy_tree(struct rb_root *r)
+void nf_conncount_cache_free(struct kmem_cache *cache, struct hlist_head *hhead)
 {
 	struct nf_conncount_tuple *conn;
-	struct nf_conncount_rb *rbconn;
 	struct hlist_node *n;
+
+	hlist_for_each_entry_safe(conn, n, hhead, node)
+		kmem_cache_free(conncount_conn_cachep, conn);
+}
+EXPORT_SYMBOL_GPL(nf_conncount_cache_free);
+
+static void destroy_tree(struct rb_root *r)
+{
+	struct nf_conncount_rb *rbconn;
 	struct rb_node *node;
 
 	while ((node = rb_first(r)) != NULL) {
@@ -315,8 +331,7 @@  static void destroy_tree(struct rb_root *r)
 
 		rb_erase(node, r);
 
-		hlist_for_each_entry_safe(conn, n, &rbconn->hhead, node)
-			kmem_cache_free(conncount_conn_cachep, conn);
+		nf_conncount_cache_free(conncount_conn_cachep, &rbconn->hhead);
 
 		kmem_cache_free(conncount_rb_cachep, rbconn);
 	}
@@ -336,6 +351,20 @@  void nf_conncount_destroy(struct net *net, unsigned int family,
 }
 EXPORT_SYMBOL_GPL(nf_conncount_destroy);
 
+struct kmem_cache *nf_conncount_cache_alloc(void)
+{
+	struct kmem_cache *conncount_cache;
+
+	conncount_cache = kmem_cache_create("nf_conncount_tuple",
+					    sizeof(struct nf_conncount_tuple),
+					    0, 0, NULL);
+	if (!conncount_cache)
+		return ERR_PTR(-ENOMEM);
+
+	return conncount_cache;
+}
+EXPORT_SYMBOL_GPL(nf_conncount_cache_alloc);
+
 static int __init nf_conncount_modinit(void)
 {
 	int i;
@@ -346,10 +375,8 @@  static int __init nf_conncount_modinit(void)
 	for (i = 0; i < CONNCOUNT_LOCK_SLOTS; ++i)
 		spin_lock_init(&nf_conncount_locks[i]);
 
-	conncount_conn_cachep = kmem_cache_create("nf_conncount_tuple",
-					   sizeof(struct nf_conncount_tuple),
-					   0, 0, NULL);
-	if (!conncount_conn_cachep)
+	conncount_conn_cachep = nf_conncount_cache_alloc();
+	if (IS_ERR(conncount_conn_cachep))
 		return -ENOMEM;
 
 	conncount_rb_cachep = kmem_cache_create("nf_conncount_rb",