diff mbox

[RFC,v2,09/11] br_netfilter: added pernet_operations without sysctl registration

Message ID 5370C556.9020206@parallels.com
State Superseded
Headers show

Commit Message

Vasily Averin May 12, 2014, 12:57 p.m. UTC
added registration of per-netns operation without sysctl registration
also reworked rollback in br_netfilter_init()

Signed-off-by: Vasily Averin <vvs@openvz.org>
---
 net/bridge/br_netfilter.c |   50 +++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 44 insertions(+), 6 deletions(-)
diff mbox

Patch

diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 55794c4..a079c06 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -40,6 +40,7 @@ 
 #include "br_private.h"
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
+#include <net/netns/generic.h>
 #endif
 
 #define skb_origaddr(skb)	 (((struct bridge_skb_cb *) \
@@ -58,6 +59,7 @@  static struct ctl_table_header *brnf_sysctl_header;
 #define brnf_pass_vlan_indev 0
 
 #ifdef CONFIG_SYSCTL
+static int brnf_net_id __read_mostly;
 static struct brnf_net init_brnf_net = {
 	.hdr			= NULL,
 	.call_arptables		= brnf_call_arptables,
@@ -67,6 +69,11 @@  static struct brnf_net init_brnf_net = {
 	.filter_pppoe_tagged	= brnf_filter_pppoe_tagged,
 	.pass_vlan_indev	= brnf_pass_vlan_indev,
 };
+
+static inline struct brnf_net *brnf_net(const struct net *net)
+{
+	return net_generic(net, brnf_net_id);
+}
 #endif
 
 #ifdef CONFIG_SYSCTL
@@ -1068,6 +1075,26 @@  static struct ctl_table brnf_table[] = {
 	},
 	{ }
 };
+
+static int __net_init brnf_net_init(struct net *net)
+{
+	struct brnf_net *bn = brnf_net(net);
+
+	memcpy(bn, &init_brnf_net, sizeof(struct brnf_net));
+	bn->net = net;
+	return 0;
+}
+
+static void __net_exit brnf_net_exit(struct net *net)
+{
+}
+
+static struct pernet_operations __net_initdata brnf_net_ops = {
+	.init	= brnf_net_init,
+	.exit	= brnf_net_exit,
+	.id	= &brnf_net_id,
+	.size	= sizeof(struct brnf_net),
+};
 #endif
 
 int __init br_netfilter_init(void)
@@ -1076,13 +1103,12 @@  int __init br_netfilter_init(void)
 
 	ret = dst_entries_init(&fake_dst_ops);
 	if (ret < 0)
-		return ret;
+		goto err_dst;
 
 	ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
-	if (ret < 0) {
-		dst_entries_destroy(&fake_dst_ops);
-		return ret;
-	}
+	if (ret < 0)
+		goto err_nf;
+
 #ifdef CONFIG_SYSCTL
 	brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table);
 	if (brnf_sysctl_header == NULL) {
@@ -1092,16 +1118,28 @@  int __init br_netfilter_init(void)
 		dst_entries_destroy(&fake_dst_ops);
 		return -ENOMEM;
 	}
+	ret = register_pernet_subsys(&brnf_net_ops);
+	if (ret < 0) {
+		unregister_net_sysctl_table(brnf_sysctl_header);
+		nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
+		goto err_nf;
+	}
 #endif
 	printk(KERN_NOTICE "Bridge firewalling registered\n");
 	return 0;
+
+err_nf:
+	dst_entries_destroy(&fake_dst_ops);
+err_dst:
+	return ret;
 }
 
 void br_netfilter_fini(void)
 {
-	nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
 #ifdef CONFIG_SYSCTL
+	unregister_pernet_subsys(&brnf_net_ops);
 	unregister_net_sysctl_table(brnf_sysctl_header);
 #endif
+	nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
 	dst_entries_destroy(&fake_dst_ops);
 }