summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYi-Hung Wei <yihung.wei@gmail.com>2018-07-02 17:33:39 -0700
committerPablo Neira Ayuso <pablo@netfilter.org>2018-07-18 11:26:31 +0200
commit2a406e8ac7c3e7e96b94d6c0765d5a4641970446 (patch)
tree13e54c7f9a824946c9082f510393a12c330141c3
parent5d400a4933e867dbc3706023c8ed55d364c233ed (diff)
downloadlinux-2a406e8ac7c3e7e96b94d6c0765d5a4641970446.tar.bz2
netfilter: nf_conncount: Early exit for garbage collection
This patch is originally from Florian Westphal. We use an extra function with early exit for garbage collection. It is not necessary to traverse the full list for every node since it is enough to zap a couple of entries for garbage collection. Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/netfilter/nf_conncount.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index 510039862aa9..81c02185b2e8 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -189,6 +189,42 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
}
EXPORT_SYMBOL_GPL(nf_conncount_lookup);
+static void nf_conncount_gc_list(struct net *net,
+ struct nf_conncount_rb *rbconn)
+{
+ const struct nf_conntrack_tuple_hash *found;
+ struct nf_conncount_tuple *conn;
+ struct hlist_node *n;
+ struct nf_conn *found_ct;
+ unsigned int collected = 0;
+
+ hlist_for_each_entry_safe(conn, n, &rbconn->hhead, node) {
+ found = find_or_evict(net, conn);
+ if (IS_ERR(found)) {
+ if (PTR_ERR(found) == -ENOENT)
+ collected++;
+ continue;
+ }
+
+ found_ct = nf_ct_tuplehash_to_ctrack(found);
+ if (already_closed(found_ct)) {
+ /*
+ * we do not care about connections which are
+ * closed already -> ditch it
+ */
+ nf_ct_put(found_ct);
+ hlist_del(&conn->node);
+ kmem_cache_free(conncount_conn_cachep, conn);
+ collected++;
+ continue;
+ }
+
+ nf_ct_put(found_ct);
+ if (collected > CONNCOUNT_GC_MAX_NODES)
+ return;
+ }
+}
+
static void tree_nodes_free(struct rb_root *root,
struct nf_conncount_rb *gc_nodes[],
unsigned int gc_count)
@@ -251,8 +287,7 @@ count_tree(struct net *net, struct rb_root *root,
if (no_gc || gc_count >= ARRAY_SIZE(gc_nodes))
continue;
- /* only used for GC on hhead, retval and 'addit' ignored */
- nf_conncount_lookup(net, &rbconn->hhead, tuple, zone, &addit);
+ nf_conncount_gc_list(net, rbconn);
if (hlist_empty(&rbconn->hhead))
gc_nodes[gc_count++] = rbconn;
}