mirror of https://gitee.com/openkylin/linux.git
netfilter: nf_conncount: Early exit in nf_conncount_lookup() and cleanup
This patch is originally from Florian Westphal. 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: Yi-Hung Wei <yihung.wei@gmail.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
cb2b36f5a9
commit
976afca1ce
|
@ -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
|
||||
|
|
|
@ -144,26 +144,29 @@ find_or_evict(struct net *net, struct nf_conncount_list *list,
|
|||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
|
||||
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 = find_or_evict(net, list, conn);
|
||||
if (IS_ERR(found)) {
|
||||
/* Not found, but might be about to be confirmed */
|
||||
if (PTR_ERR(found) == -EAGAIN) {
|
||||
length++;
|
||||
if (!tuple)
|
||||
continue;
|
||||
|
||||
|
@ -171,8 +174,8 @@ unsigned int nf_conncount_lookup(struct net *net,
|
|||
nf_ct_zone_id(&conn->zone, conn->zone.dir) ==
|
||||
nf_ct_zone_id(zone, zone->dir))
|
||||
*addit = false;
|
||||
}
|
||||
|
||||
} else if (PTR_ERR(found) == -ENOENT)
|
||||
collect++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -181,9 +184,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)) {
|
||||
|
@ -193,14 +197,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);
|
||||
|
||||
|
@ -211,8 +213,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;
|
||||
|
@ -244,6 +246,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[],
|
||||
|
@ -291,8 +294,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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue