summaryrefslogtreecommitdiff
path: root/datapath/linux/compat/include/net/netfilter
diff options
context:
space:
mode:
authorJarno Rajahalme <jarno@ovn.org>2017-03-08 17:18:23 -0800
committerJarno Rajahalme <jarno@ovn.org>2017-03-08 17:23:33 -0800
commit6d9b6937c65d4b682ee41017b429b53db5898eda (patch)
tree6c911bcaf9fa21d3febd196f036e30aece5e224e /datapath/linux/compat/include/net/netfilter
parent2cd20955dc85dc611b5f24c8977d5a3f842ae380 (diff)
downloadopenvswitch-6d9b6937c65d4b682ee41017b429b53db5898eda.tar.gz
compat: nf_ct_delete compat.
Upstream commit: commit f330a7fdbe1611104622faff7e614a246a7d20f0 Author: Florian Westphal <fw@strlen.de> Date: Thu Aug 25 15:33:31 2016 +0200 netfilter: conntrack: get rid of conntrack timer With stats enabled this eats 80 bytes on x86_64 per nf_conn entry, as Eric Dumazet pointed out during netfilter workshop 2016. Eric also says: "Another reason was the fact that Thomas was about to change max timer range [..]" (500462a9de657f8, 'timers: Switch to a non-cascading wheel'). Remove the timer and use a 32bit jiffies value containing timestamp until entry is valid. During conntrack lookup, even before doing tuple comparision, check the timeout value and evict the entry in case it is too old. The dying bit is used as a synchronization point to avoid races where multiple cpus try to evict the same entry. Because lookup is always lockless, we need to bump the refcnt once when we evict, else we could try to evict already-dead entry that is being recycled. This is the standard/expected way when conntrack entries are destroyed. Followup patches will introduce garbage colliction via work queue and further places where we can reap obsoleted entries (e.g. during netlink dumps), this is needed to avoid expired conntracks from hanging around for too long when lookup rate is low after a busy period. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Upstream commit f330a7fdbe16 ("netfilter: conntrack: get rid of conntrack timer") changes the way nf_ct_delete() is called. Prior to commit the call pattern was like this: if (del_timer(&ct->timeout)) nf_ct_delete(ct, ...); After this change nf_ct_delete() is called directly: nf_ct_delete(ct, ...); This patch provides a replacement implementation for nf_ct_delete() that first calls the del_timer(). This replacement is only used if the struct nf_conn has member 'timeout' of type 'struct timer_list'. The following patch introduces the first caller to nf_ct_delete() in the OVS kernel module. Linux <3.12 does not have nf_ct_delete() at all, so we inline it if it does not exist. The inlined code is from 3.11 death_by_timeout(), which in later versions simply calls nf_ct_delete(). Upstream commit 02982c27ba1e1bd9f9d4747214e19ca83aa88d0e introduced nf_ct_delete() in Linux 3.12. This commit has the original code that is being inlined here. Signed-off-by: Jarno Rajahalme <jarno@ovn.org> Acked-by: Joe Stringer <joe@ovn.org>
Diffstat (limited to 'datapath/linux/compat/include/net/netfilter')
-rw-r--r--datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h37
1 files changed, 37 insertions, 0 deletions
diff --git a/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h b/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h
index 16b57a647..715e1d510 100644
--- a/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h
+++ b/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h
@@ -88,4 +88,41 @@ static unsigned int rpl_nf_conntrack_in(struct net *net, u_int8_t pf,
#define nf_conntrack_in rpl_nf_conntrack_in
#endif /* < 4.10 */
+#ifdef HAVE_NF_CONN_TIMER
+
+#ifndef HAVE_NF_CT_DELETE
+#include <net/netfilter/nf_conntrack_timestamp.h>
+#endif
+
+static inline bool rpl_nf_ct_delete(struct nf_conn *ct, u32 portid, int report)
+{
+ if (del_timer(&ct->timeout))
+#ifdef HAVE_NF_CT_DELETE
+ return nf_ct_delete(ct, portid, report);
+#else
+ {
+ struct nf_conn_tstamp *tstamp;
+
+ tstamp = nf_conn_tstamp_find(ct);
+ if (tstamp && tstamp->stop == 0)
+ tstamp->stop = ktime_to_ns(ktime_get_real());
+
+ if (!test_bit(IPS_DYING_BIT, &ct->status) &&
+ unlikely(nf_conntrack_event(IPCT_DESTROY, ct) < 0)) {
+ /* destroy event was not delivered */
+ nf_ct_delete_from_lists(ct);
+ nf_ct_dying_timeout(ct);
+ return false;
+ }
+ set_bit(IPS_DYING_BIT, &ct->status);
+ nf_ct_delete_from_lists(ct);
+ nf_ct_put(ct);
+ return true;
+ }
+#endif
+ return false;
+}
+#define nf_ct_delete rpl_nf_ct_delete
+#endif /* HAVE_NF_CONN_TIMER */
+
#endif /* _NF_CONNTRACK_CORE_WRAPPER_H */