summaryrefslogtreecommitdiffstats
path: root/include/linux/netfilter.h
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2017-12-01 00:21:04 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2018-01-08 18:01:07 +0100
commit8c873e2199700c2de7dbd5eedb9d90d5f109462b (patch)
tree7c7a2d4d7853659a19a36a725767871351a7aedf /include/linux/netfilter.h
parent26888dfd7e7454686b8d3ea9ba5045d5f236e4d7 (diff)
downloadlinux-0-day-8c873e2199700c2de7dbd5eedb9d90d5f109462b.tar.gz
linux-0-day-8c873e2199700c2de7dbd5eedb9d90d5f109462b.tar.xz
netfilter: core: free hooks with call_rcu
Giuseppe Scrivano says: "SELinux, if enabled, registers for each new network namespace 6 netfilter hooks." Cost for this is high. With synchronize_net() removed: "The net benefit on an SMP machine with two cores is that creating a new network namespace takes -40% of the original time." This patch replaces synchronize_net+kvfree with call_rcu(). We store rcu_head at the tail of a structure that has no fixed layout, i.e. we cannot use offsetof() to compute the start of the original allocation. Thus store this information right after the rcu head. We could simplify this by just placing the rcu_head at the start of struct nf_hook_entries. However, this structure is used in packet processing hotpath, so only place what is needed for that at the beginning of the struct. Reported-by: Giuseppe Scrivano <gscrivan@redhat.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'include/linux/netfilter.h')
-rw-r--r--include/linux/netfilter.h19
1 files changed, 15 insertions, 4 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index b24e9b1016512..792f6d5357073 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -77,17 +77,28 @@ struct nf_hook_entry {
void *priv;
};
+struct nf_hook_entries_rcu_head {
+ struct rcu_head head;
+ void *allocation;
+};
+
struct nf_hook_entries {
u16 num_hook_entries;
/* padding */
struct nf_hook_entry hooks[];
- /* trailer: pointers to original orig_ops of each hook.
- *
- * This is not part of struct nf_hook_entry since its only
- * needed in slow path (hook register/unregister).
+ /* trailer: pointers to original orig_ops of each hook,
+ * followed by rcu_head and scratch space used for freeing
+ * the structure via call_rcu.
*
+ * This is not part of struct nf_hook_entry since its only
+ * needed in slow path (hook register/unregister):
* const struct nf_hook_ops *orig_ops[]
+ *
+ * For the same reason, we store this at end -- its
+ * only needed when a hook is deleted, not during
+ * packet path processing:
+ * struct nf_hook_entries_rcu_head head
*/
};