From: Florian Westphal <[email protected]>

This patch does the following three tasks.

It applies the same early exit technique for nf_conncount_lookup().

Since now we keep the number of connections in 'struct nf_conncount_list',
we no longer need to return the count in nf_conncount_lookup().

Moreover, we expose the garbage collection function nf_conncount_gc_list()
for nft_connlimit.

Signed-off-by: Florian Westphal <[email protected]>
Signed-off-by: Yi-Hung Wei <[email protected]>
---
 include/net/netfilter/nf_conntrack_count.h | 11 ++++++----
 net/netfilter/nf_conncount.c               | 34 ++++++++++++++++++------------
 net/netfilter/nft_connlimit.c              |  9 ++++----
 3 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_count.h 
b/include/net/netfilter/nf_conntrack_count.h
index e4884e0e4f69..dbec17f674b7 100644
--- a/include/net/netfilter/nf_conntrack_count.h
+++ b/include/net/netfilter/nf_conntrack_count.h
@@ -21,10 +21,10 @@ unsigned int nf_conncount_count(struct net *net,
                                const struct nf_conntrack_tuple *tuple,
                                const struct nf_conntrack_zone *zone);
 
-unsigned int nf_conncount_lookup(struct net *net, struct nf_conncount_list 
*list,
-                                const struct nf_conntrack_tuple *tuple,
-                                const struct nf_conntrack_zone *zone,
-                                bool *addit);
+void nf_conncount_lookup(struct net *net, struct nf_conncount_list *list,
+                        const struct nf_conntrack_tuple *tuple,
+                        const struct nf_conntrack_zone *zone,
+                        bool *addit);
 
 void nf_conncount_list_init(struct nf_conncount_list *list);
 
@@ -32,6 +32,9 @@ bool nf_conncount_add(struct nf_conncount_list *list,
                      const struct nf_conntrack_tuple *tuple,
                      const struct nf_conntrack_zone *zone);
 
+void nf_conncount_gc_list(struct net *net,
+                         struct nf_conncount_list *list);
+
 void nf_conncount_cache_free(struct nf_conncount_list *list);
 
 #endif
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index 6eb52c2332bd..6e77b2a2f851 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -111,24 +111,29 @@ static void conn_free(struct nf_conncount_list *list,
        kmem_cache_free(conncount_conn_cachep, conn);
 }
 
-unsigned int nf_conncount_lookup(struct net *net,
-                                struct nf_conncount_list *list,
-                                const struct nf_conntrack_tuple *tuple,
-                                const struct nf_conntrack_zone *zone,
-                                bool *addit)
+void nf_conncount_lookup(struct net *net,
+                        struct nf_conncount_list *list,
+                        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, *conn_n;
        struct nf_conn *found_ct;
-       unsigned int length = 0;
+       unsigned int collect = 0;
 
+       /* best effort only */
        *addit = tuple ? true : false;
 
        /* check the saved connections */
        list_for_each_entry_safe(conn, conn_n, &list->head, node) {
+               if (collect > CONNCOUNT_GC_MAX_NODES)
+                       break;
+
                found = nf_conntrack_find_get(net, &conn->zone, &conn->tuple);
                if (found == NULL) {
                        conn_free(list, conn);
+                       collect++;
                        continue;
                }
 
@@ -137,9 +142,10 @@ unsigned int nf_conncount_lookup(struct net *net,
                if (tuple && nf_ct_tuple_equal(&conn->tuple, tuple) &&
                    nf_ct_zone_equal(found_ct, zone, zone->dir)) {
                        /*
-                        * Just to be sure we have it only once in the list.
                         * We should not see tuples twice unless someone hooks
                         * this into a table without "-p tcp --syn".
+                        *
+                        * Attempt to avoid a re-add in this case.
                         */
                        *addit = false;
                } else if (already_closed(found_ct)) {
@@ -149,14 +155,12 @@ unsigned int nf_conncount_lookup(struct net *net,
                         */
                        nf_ct_put(found_ct);
                        conn_free(list, conn);
+                       collect++;
                        continue;
                }
 
                nf_ct_put(found_ct);
-               length++;
        }
-
-       return length;
 }
 EXPORT_SYMBOL_GPL(nf_conncount_lookup);
 
@@ -167,8 +171,8 @@ void nf_conncount_list_init(struct nf_conncount_list *list)
 }
 EXPORT_SYMBOL_GPL(nf_conncount_list_init);
 
-static void nf_conncount_gc_list(struct net *net,
-                                struct nf_conncount_list *list)
+void nf_conncount_gc_list(struct net *net,
+                         struct nf_conncount_list *list)
 {
        const struct nf_conntrack_tuple_hash *found;
        struct nf_conncount_tuple *conn, *conn_n;
@@ -200,6 +204,7 @@ static void nf_conncount_gc_list(struct net *net,
                        return;
        }
 }
+EXPORT_SYMBOL_GPL(nf_conncount_gc_list);
 
 static void tree_nodes_free(struct rb_root *root,
                            struct nf_conncount_rb *gc_nodes[],
@@ -247,8 +252,9 @@ count_tree(struct net *net, struct rb_root *root,
                        /* same source network -> be counted! */
                        unsigned int count;
 
-                       count = nf_conncount_lookup(net, &rbconn->list, tuple,
-                                                   zone, &addit);
+                       nf_conncount_lookup(net, &rbconn->list, tuple, zone,
+                                           &addit);
+                       count = rbconn->list.count;
 
                        tree_nodes_free(root, gc_nodes, gc_count);
                        if (!addit)
diff --git a/net/netfilter/nft_connlimit.c b/net/netfilter/nft_connlimit.c
index 4f0491a36a1d..37c52ae06741 100644
--- a/net/netfilter/nft_connlimit.c
+++ b/net/netfilter/nft_connlimit.c
@@ -46,8 +46,9 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit 
*priv,
        }
 
        spin_lock_bh(&priv->lock);
-       count = nf_conncount_lookup(nft_net(pkt), &priv->list, tuple_ptr, zone,
-                                   &addit);
+       nf_conncount_lookup(nft_net(pkt), &priv->list, tuple_ptr, zone,
+                           &addit);
+       count = priv->list.count;
 
        if (!addit)
                goto out;
@@ -231,10 +232,10 @@ static void nft_connlimit_destroy_clone(const struct 
nft_ctx *ctx,
 static bool nft_connlimit_gc(struct net *net, const struct nft_expr *expr)
 {
        struct nft_connlimit *priv = nft_expr_priv(expr);
-       bool addit, ret;
+       bool ret;
 
        spin_lock_bh(&priv->lock);
-       nf_conncount_lookup(net, &priv->list, NULL, &nf_ct_zone_dflt, &addit);
+       nf_conncount_gc_list(net, &priv->list);
 
        ret = list_empty(&priv->list.head);
        spin_unlock_bh(&priv->lock);
-- 
2.7.4

--
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