netfilter: conntrack: small refactoring of conntrack seq_printf
The iteration process is lockless, so we test if the conntrack object is eligible for printing (e.g. is AF_INET) after obtaining the reference count. Once we put all conntracks into same hash table we might see more entries that need to be skipped. So add a helper and first perform the test in a lockless fashion for fast skip. Once we obtain the reference count, just repeat the check. Note that this refactoring also includes a missing check for unconfirmed conntrack entries due to slab rcu object re-usage, so they need to be skipped since they are not part of the listing. Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
868043485e
commit
245cfdcaba
|
@ -114,6 +114,19 @@ static inline void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool ct_seq_should_skip(const struct nf_conn *ct,
|
||||||
|
const struct nf_conntrack_tuple_hash *hash)
|
||||||
|
{
|
||||||
|
/* we only want to print DIR_ORIGINAL */
|
||||||
|
if (NF_CT_DIRECTION(hash))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (nf_ct_l3num(ct) != AF_INET)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int ct_seq_show(struct seq_file *s, void *v)
|
static int ct_seq_show(struct seq_file *s, void *v)
|
||||||
{
|
{
|
||||||
struct nf_conntrack_tuple_hash *hash = v;
|
struct nf_conntrack_tuple_hash *hash = v;
|
||||||
|
@ -123,14 +136,15 @@ static int ct_seq_show(struct seq_file *s, void *v)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
NF_CT_ASSERT(ct);
|
NF_CT_ASSERT(ct);
|
||||||
|
if (ct_seq_should_skip(ct, hash))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use)))
|
if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/* check if we raced w. object reuse */
|
||||||
/* we only want to print DIR_ORIGINAL */
|
if (!nf_ct_is_confirmed(ct) ||
|
||||||
if (NF_CT_DIRECTION(hash))
|
ct_seq_should_skip(ct, hash))
|
||||||
goto release;
|
|
||||||
if (nf_ct_l3num(ct) != AF_INET)
|
|
||||||
goto release;
|
goto release;
|
||||||
|
|
||||||
l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
|
l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
|
||||||
|
|
Loading…
Reference in New Issue