Commit 2a406e8a authored by Yi-Hung Wei's avatar Yi-Hung Wei Committed by Pablo Neira Ayuso

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: default avatarYi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 5d400a49
...@@ -189,6 +189,42 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, ...@@ -189,6 +189,42 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
} }
EXPORT_SYMBOL_GPL(nf_conncount_lookup); 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, static void tree_nodes_free(struct rb_root *root,
struct nf_conncount_rb *gc_nodes[], struct nf_conncount_rb *gc_nodes[],
unsigned int gc_count) unsigned int gc_count)
...@@ -251,8 +287,7 @@ count_tree(struct net *net, struct rb_root *root, ...@@ -251,8 +287,7 @@ count_tree(struct net *net, struct rb_root *root,
if (no_gc || gc_count >= ARRAY_SIZE(gc_nodes)) if (no_gc || gc_count >= ARRAY_SIZE(gc_nodes))
continue; continue;
/* only used for GC on hhead, retval and 'addit' ignored */ nf_conncount_gc_list(net, rbconn);
nf_conncount_lookup(net, &rbconn->hhead, tuple, zone, &addit);
if (hlist_empty(&rbconn->hhead)) if (hlist_empty(&rbconn->hhead))
gc_nodes[gc_count++] = rbconn; gc_nodes[gc_count++] = rbconn;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment