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 <[email protected]>
---
 include/net/netfilter/nf_conntrack_count.h | 15 +++++++
 net/netfilter/nf_conncount.c               | 68 +++++++++++++++++++++---------
 2 files changed, 63 insertions(+), 20 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_count.h 
b/include/net/netfilter/nf_conntrack_count.h
index e61184fbfb71..4b4fc9f986a2 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(const char *cache_name);
+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..f1584d403950 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;
                }
 
@@ -141,6 +144,7 @@ static unsigned int check_hlist(struct net *net,
 
        return length;
 }
+EXPORT_SYMBOL_GPL(nf_conncount_lookup);
 
 static void tree_nodes_free(struct rb_root *root,
                            struct nf_conncount_rb *gc_nodes[],
@@ -187,13 +191,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 +211,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 +312,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 +332,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 +352,20 @@ void nf_conncount_destroy(struct net *net, unsigned int 
family,
 }
 EXPORT_SYMBOL_GPL(nf_conncount_destroy);
 
+struct kmem_cache *nf_conncount_cache_alloc(const char *cache_name)
+{
+       struct kmem_cache *conncount_cache;
+
+       conncount_cache = kmem_cache_create(cache_name,
+                                           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 +376,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("nf_conncount_tuple");
+       if (IS_ERR(conncount_conn_cachep))
                return -ENOMEM;
 
        conncount_rb_cachep = kmem_cache_create("nf_conncount_rb",
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to