Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5bfddbd4 authored by Eric Dumazet's avatar Eric Dumazet Committed by Patrick McHardy
Browse files

netfilter: nf_conntrack: IPS_UNTRACKED bit



NOTRACK makes all cpus share a cache line on nf_conntrack_untracked
twice per packet. This is bad for performance.
__read_mostly annotation is also a bad choice.

This patch introduces IPS_UNTRACKED bit so that we can use later a
per_cpu untrack structure more easily.

A new helper, nf_ct_untracked_get() returns a pointer to
nf_conntrack_untracked.

Another one, nf_ct_untracked_status_or() is used by nf_nat_init() to add
IPS_NAT_DONE_MASK bits to untracked status.

nf_ct_is_untracked() prototype is changed to work on a nf_conn pointer.

Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent 339bb99e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -76,6 +76,10 @@ enum ip_conntrack_status {
	/* Conntrack is a template */
	IPS_TEMPLATE_BIT = 11,
	IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT),

	/* Conntrack is a fake untracked entry */
	IPS_UNTRACKED_BIT = 12,
	IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
};

/* Connection tracking event types */
+9 −3
Original line number Diff line number Diff line
@@ -261,8 +261,14 @@ extern s16 (*nf_ct_nat_offset)(const struct nf_conn *ct,
			       u32 seq);

/* Fake conntrack entry for untracked connections */
static inline struct nf_conn *nf_ct_untracked_get(void)
{
	extern struct nf_conn nf_conntrack_untracked;

	return &nf_conntrack_untracked;
}
extern void nf_ct_untracked_status_or(unsigned long bits);

/* Iterate over all conntracks: if iter returns true, it's deleted. */
extern void
nf_ct_iterate_cleanup(struct net *net, int (*iter)(struct nf_conn *i, void *data), void *data);
@@ -289,9 +295,9 @@ static inline int nf_ct_is_dying(struct nf_conn *ct)
	return test_bit(IPS_DYING_BIT, &ct->status);
}

static inline int nf_ct_is_untracked(const struct sk_buff *skb)
static inline int nf_ct_is_untracked(const struct nf_conn *ct)
{
	return (skb->nfct == &nf_conntrack_untracked.ct_general);
	return test_bit(IPS_UNTRACKED_BIT, &ct->status);
}

extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp);
+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ static inline int nf_conntrack_confirm(struct sk_buff *skb)
	struct nf_conn *ct = (struct nf_conn *)skb->nfct;
	int ret = NF_ACCEPT;

	if (ct && ct != &nf_conntrack_untracked) {
	if (ct && !nf_ct_is_untracked(ct)) {
		if (!nf_ct_is_confirmed(ct))
			ret = __nf_conntrack_confirm(skb);
		if (likely(ret == NF_ACCEPT))
+1 −1
Original line number Diff line number Diff line
@@ -742,7 +742,7 @@ static int __init nf_nat_init(void)
	spin_unlock_bh(&nf_nat_lock);

	/* Initialize fake conntrack so that NAT will skip it */
	nf_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
	nf_ct_untracked_status_or(IPS_NAT_DONE_MASK);

	l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET);

+1 −1
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ nf_nat_fn(unsigned int hooknum,
		return NF_ACCEPT;

	/* Don't try to NAT if this packet is not conntracked */
	if (ct == &nf_conntrack_untracked)
	if (nf_ct_is_untracked(ct))
		return NF_ACCEPT;

	nat = nfct_nat(ct);
Loading