Commit 6ae7989c authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: conntrack: avoid useless indirection during conntrack destruction



nf_ct_put() results in a usesless indirection:

nf_ct_put -> nf_conntrack_put -> nf_conntrack_destroy -> rcu readlock +
indirect call of ct_hooks->destroy().

There are two _put helpers:
nf_ct_put and nf_conntrack_put.  The latter is what should be used in
code that MUST NOT cause a linker dependency on the conntrack module
(e.g. calls from core network stack).

Everyone else should call nf_ct_put() instead.

A followup patch will convert a few nf_conntrack_put() calls to
nf_ct_put(), in particular from modules that already have a conntrack
dependency such as act_ct or even nf_conntrack itself.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 285c8a7a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ struct nf_conntrack {
};

void nf_conntrack_destroy(struct nf_conntrack *nfct);

/* like nf_ct_put, but without module dependency on nf_conntrack */
static inline void nf_conntrack_put(struct nf_conntrack *nfct)
{
	if (nfct && refcount_dec_and_test(&nfct->use))
+6 −2
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ struct nf_conn {
	 * Hint, SKB address this struct and refcnt via skb->_nfct and
	 * helpers nf_conntrack_get() and nf_conntrack_put().
	 * Helper nf_ct_put() equals nf_conntrack_put() by dec refcnt,
	 * except that the latter uses internal indirection and does not
	 * result in a conntrack module dependency.
	 * beware nf_ct_get() is different and don't inc refcnt.
	 */
	struct nf_conntrack ct_general;
@@ -170,11 +172,13 @@ nf_ct_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
	return (struct nf_conn *)(nfct & NFCT_PTRMASK);
}

void nf_ct_destroy(struct nf_conntrack *nfct);

/* decrement reference count on a conntrack */
static inline void nf_ct_put(struct nf_conn *ct)
{
	WARN_ON(!ct);
	nf_conntrack_put(&ct->ct_general);
	if (ct && refcount_dec_and_test(&ct->ct_general.use))
		nf_ct_destroy(&ct->ct_general);
}

/* Protocol module loading */
+6 −6
Original line number Diff line number Diff line
@@ -558,7 +558,7 @@ static void nf_ct_del_from_dying_or_unconfirmed_list(struct nf_conn *ct)

#define NFCT_ALIGN(len)	(((len) + NFCT_INFOMASK) & ~NFCT_INFOMASK)

/* Released via destroy_conntrack() */
/* Released via nf_ct_destroy() */
struct nf_conn *nf_ct_tmpl_alloc(struct net *net,
				 const struct nf_conntrack_zone *zone,
				 gfp_t flags)
@@ -612,12 +612,11 @@ static void destroy_gre_conntrack(struct nf_conn *ct)
#endif
}

static void
destroy_conntrack(struct nf_conntrack *nfct)
void nf_ct_destroy(struct nf_conntrack *nfct)
{
	struct nf_conn *ct = (struct nf_conn *)nfct;

	pr_debug("destroy_conntrack(%p)\n", ct);
	pr_debug("%s(%p)\n", __func__, ct);
	WARN_ON(refcount_read(&nfct->use) != 0);

	if (unlikely(nf_ct_is_template(ct))) {
@@ -643,9 +642,10 @@ destroy_conntrack(struct nf_conntrack *nfct)
	if (ct->master)
		nf_ct_put(ct->master);

	pr_debug("destroy_conntrack: returning ct=%p to slab\n", ct);
	pr_debug("%s: returning ct=%p to slab\n", __func__, ct);
	nf_conntrack_free(ct);
}
EXPORT_SYMBOL(nf_ct_destroy);

static void nf_ct_delete_from_lists(struct nf_conn *ct)
{
@@ -2771,7 +2771,7 @@ int nf_conntrack_init_start(void)

static const struct nf_ct_hook nf_conntrack_hook = {
	.update		= nf_conntrack_update,
	.destroy	= destroy_conntrack,
	.destroy	= nf_ct_destroy,
	.get_tuple_skb  = nf_conntrack_get_tuple_skb,
	.attach		= nf_conntrack_attach,
};