Skip to contentSkip to conversation

per-netns sysctl for br_netfilter

RFC PATCH Superseded Vasily Averin 2 participants 19 messages May 9, 2014 – May 11, 2014 2 messages not in the archive

Subsystems (3)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

cover per-netns sysctl for br_netfilter

This patch set implements per-netns sysctl for br_netfilter.

I would be very grateful for any feedback and improvement recommendations.

I'm not sure is it safe to use dev_net(skb->dev) to get reference to net namespace (see patches 11-15 for details), however I expect that skb inside bridge should have correct reference to device.

Vasily Averin (15):
1 br_netfilter: brnf_net structure definition
2 br_netfilter: default settings in init_brnf_net
3 br_netfilter: switch sysctl nf_call_arptables to init_brnf_net 4 br_netfilter: switch sysctl nf_call_iptables to init_brnf_net 5 br_netfilter: switch sysctl nf_call_ip6tables to init_brnf_net 6 br_netfilter: switch sysctl filter_vlan_tagged to init_brnf_net 7 br_netfilter: switch sysctl filter_pppoe_tagged to init_brnf_net 8 br_netfilter: switch sysctl pass_vlan_indev to init_brnf_net 9 br_netfilter: pernet_operations brnf_net_ops without per-netns sysctl
registration
10 br_netfilter: added per-netns sysctl registration
11 br_netfilter: switch sysctl nf_call_arptables to per-netns processing 12 br_netfilter: switch sysctls nf_call_iptables and nf_call_ip6tables
to per-netns processing
13 br_netfilter: switch sysctl filter_vlan_tagged to per-netns
processing
14 br_netfilter: switch sysctl filter_pppoe_tagged to per-netns
processing
15 br_netfilter: switch sysctl pass_vlan_indev to per-netns processing

 net/bridge/br_netfilter.c |  168 ++++++++++++++++++++++++++++++++-------------
 net/bridge/br_private.h   |   15 ++++
 2 files changed, 136 insertions(+), 47 deletions(-)
Signature · 1 line
1.7.5.4

A message that is not in the archive (sent off-list or not yet received): [email protected]

#3 lore raw

PATCH 1/15 br_netfilter: brnf_net structure

struct brnf_net for per-netns settings in br_netfilters

---
 net/bridge/br_private.h |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)
net/bridge/br_private.h +15 -0
index 06811d7..e29ae83 100644
@@ -312,6 +312,21 @@ struct br_input_skb_cb {
 # define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb)	(0)
 #endif
 
+#ifdef CONFIG_BRIDGE_NETFILTER
+struct brnf_net {
+	struct net *net;
+#ifdef CONFIG_SYSCTL
+	struct ctl_table_header	*hdr;
+#endif
+	int nf_call_arptables;
+	int nf_call_iptables;
+	int nf_call_ip6tables;
+	int filter_vlan_tagged;
+	int filter_pppoe_tagged;
+	int pass_vlan_indev;
+};
+#endif
+
 #define br_printk(level, br, format, args...)	\
 	printk(level "%s: " format, (br)->dev->name, ##args)
 
Signature · 1 line
1.7.5.4
#4 lore raw

Re: [PATCH 01/15] br_netfilter: brnf_net structure

Vasily Averin schreef op 9/05/2014 23:26:

Quoted 12 lines

struct brnf_net for per-netns settings in br_netfilters

---
  net/bridge/br_private.h |   15 +++++++++++++++
  1 files changed, 15 insertions(+), 0 deletions(-)
net/bridge/br_private.h +0 -0
index 06811d7..e29ae83 100644

net/bridge/br_private.h struct br_input_skb_cb { · line 317

Quoted 6 lines
net/bridge/br_private.h +3 -0
@@ -312,6 +312,21 @@ struct br_input_skb_cb {
  # define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb)	(0)
  #endif
 
+#ifdef CONFIG_BRIDGE_NETFILTER
+struct brnf_net {
+	struct net *net;

Unless I missed something, the net member is only really needed for CONFIG_SYSCTL.

cheers,
Bart

#5 lore raw

PATCH 2/15 br_netfilter: default settings in init_brnf_net

In reply to a message not in the archive

init_brnf_net with default per-netns settings

---
 net/bridge/br_netfilter.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)
net/bridge/br_netfilter.c +12 -0
index 2acf7fa..871f481 100644
@@ -47,6 +47,18 @@
 #define store_orig_dstaddr(skb)	 (skb_origaddr(skb) = ip_hdr(skb)->daddr)
 #define dnat_took_place(skb)	 (skb_origaddr(skb) != ip_hdr(skb)->daddr)
 
+static struct brnf_net init_brnf_net = {
+#ifdef CONFIG_SYSCTL
+	.hdr			= NULL,
+#endif
+	.nf_call_arptables	= 1,
+	.nf_call_iptables	= 1,
+	.nf_call_ip6tables	= 1,
+	.filter_vlan_tagged	= 0,
+	.filter_pppoe_tagged	= 0,
+	.pass_vlan_indev	= 0,
+};
+
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
 static int brnf_call_iptables __read_mostly = 1;
Signature · 1 line
1.7.5.4
#6 lore raw

PATCH 3/15 br_netfilter: switch sysctl nf_call_arptables to init_brnf_net

In reply to a message not in the archive
---
 net/bridge/br_netfilter.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)
net/bridge/br_netfilter.c +2 -4
index 871f481..2b0dda80 100644
@@ -63,14 +63,12 @@ static struct brnf_net init_brnf_net = {
 static struct ctl_table_header *brnf_sysctl_header;
 static int brnf_call_iptables __read_mostly = 1;
 static int brnf_call_ip6tables __read_mostly = 1;
-static int brnf_call_arptables __read_mostly = 1;
 static int brnf_filter_vlan_tagged __read_mostly = 0;
 static int brnf_filter_pppoe_tagged __read_mostly = 0;
 static int brnf_pass_vlan_indev __read_mostly = 0;
 #else
 #define brnf_call_iptables 1
 #define brnf_call_ip6tables 1
-#define brnf_call_arptables 1
 #define brnf_filter_vlan_tagged 0
 #define brnf_filter_pppoe_tagged 0
 #define brnf_pass_vlan_indev 0
@@ -850,7 +848,7 @@ static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops,
 		return NF_ACCEPT;
 	br = p->br;
 
-	if (!brnf_call_arptables && !br->nf_call_arptables)
+	if (!init_brnf_net.nf_call_arptables && !br->nf_call_arptables)
 		return NF_ACCEPT;
 
 	if (!IS_ARP(skb)) {
@@ -1027,7 +1025,7 @@ int brnf_sysctl_call_tables(struct ctl_table *ctl, int write,
 static struct ctl_table brnf_table[] = {
 	{
 		.procname	= "bridge-nf-call-arptables",
-		.data		= &brnf_call_arptables,
+		.data		= &init_brnf_net.nf_call_arptables,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= brnf_sysctl_call_tables,
Signature · 1 line
1.7.5.4
#7 lore raw

PATCH 4/15 br_netfilter: switch sysctl nf_call_iptables to init_brnf_net

In reply to a message not in the archive
---
 net/bridge/br_netfilter.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)
net/bridge/br_netfilter.c +2 -4
index 2b0dda80..cb75e80 100644
@@ -61,13 +61,11 @@ static struct brnf_net init_brnf_net = {
 
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
-static int brnf_call_iptables __read_mostly = 1;
 static int brnf_call_ip6tables __read_mostly = 1;
 static int brnf_filter_vlan_tagged __read_mostly = 0;
 static int brnf_filter_pppoe_tagged __read_mostly = 0;
 static int brnf_pass_vlan_indev __read_mostly = 0;
 #else
-#define brnf_call_iptables 1
 #define brnf_call_ip6tables 1
 #define brnf_filter_vlan_tagged 0
 #define brnf_filter_pppoe_tagged 0
@@ -707,7 +705,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
 		return br_nf_pre_routing_ipv6(ops, skb, in, out, okfn);
 	}
 
-	if (!brnf_call_iptables && !br->nf_call_iptables)
+	if (!init_brnf_net.nf_call_iptables && !br->nf_call_iptables)
 		return NF_ACCEPT;
 
 	if (!IS_IP(skb) && !IS_VLAN_IP(skb) && !IS_PPPOE_IP(skb))
@@ -1032,7 +1030,7 @@ static struct ctl_table brnf_table[] = {
 	},
 	{
 		.procname	= "bridge-nf-call-iptables",
-		.data		= &brnf_call_iptables,
+		.data		= &init_brnf_net.nf_call_iptables,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= brnf_sysctl_call_tables,
Signature · 1 line
1.7.5.4
#8 lore raw

Re: [PATCH 04/15] br_netfilter: switch sysctl nf_call_iptables to init_brnf_net

Vasily Averin schreef op 9/05/2014 23:27:

Quoted 11 lines
---
  net/bridge/br_netfilter.c |    6 ++----
  1 files changed, 2 insertions(+), 4 deletions(-)
net/bridge/br_netfilter.c +0 -0
index 2b0dda80..cb75e80 100644

net/bridge/br_netfilter.c static struct brnf_net init_brnf_net = { · line 70

Quoted 10 lines
net/bridge/br_netfilter.c +0 -2
@@ -61,13 +61,11 @@ static struct brnf_net init_brnf_net = {
 
  #ifdef CONFIG_SYSCTL
  static struct ctl_table_header *brnf_sysctl_header;
-static int brnf_call_iptables __read_mostly = 1;
  static int brnf_call_ip6tables __read_mostly = 1;
  static int brnf_filter_vlan_tagged __read_mostly = 0;
  static int brnf_filter_pppoe_tagged __read_mostly = 0;
  static int brnf_pass_vlan_indev __read_mostly = 0;
  #else
-#define brnf_call_iptables 1

Your patch creates extra unneeded overhead in case CONFIG_SYSCTL isn't defined (a compile-time check of brnf_call_iptables is replaced by a runtime check of brnf_net(dev_net(skb->dev))->brnf_call_iptables). Please refactor to remove this extra overhead (for all flags).

cheers,
Bart

#9 lore raw

PATCH 5/15 br_netfilter: switch sysctl nf_call_ip6tables to init_brnf_net

In reply to a message not in the archive
---
 net/bridge/br_netfilter.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)
net/bridge/br_netfilter.c +2 -4
index cb75e80..94c0dcb 100644
@@ -61,12 +61,10 @@ static struct brnf_net init_brnf_net = {
 
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
-static int brnf_call_ip6tables __read_mostly = 1;
 static int brnf_filter_vlan_tagged __read_mostly = 0;
 static int brnf_filter_pppoe_tagged __read_mostly = 0;
 static int brnf_pass_vlan_indev __read_mostly = 0;
 #else
-#define brnf_call_ip6tables 1
 #define brnf_filter_vlan_tagged 0
 #define brnf_filter_pppoe_tagged 0
 #define brnf_pass_vlan_indev 0
@@ -698,7 +696,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
 	br = p->br;
 
 	if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb)) {
-		if (!brnf_call_ip6tables && !br->nf_call_ip6tables)
+		if (!init_brnf_net.nf_call_ip6tables && !br->nf_call_ip6tables)
 			return NF_ACCEPT;
 
 		nf_bridge_pull_encap_header_rcsum(skb);
@@ -1037,7 +1035,7 @@ static struct ctl_table brnf_table[] = {
 	},
 	{
 		.procname	= "bridge-nf-call-ip6tables",
-		.data		= &brnf_call_ip6tables,
+		.data		= &init_brnf_net.nf_call_ip6tables,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= brnf_sysctl_call_tables,
Signature · 1 line
1.7.5.4
#10 lore raw

PATCH 6/15 br_netfilter: switch sysctl filter_vlan_tagged to init_brnf_net

In reply to a message not in the archive
---
 net/bridge/br_netfilter.c |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)
net/bridge/br_netfilter.c +4 -6
index 94c0dcb..16a69cf 100644
@@ -61,11 +61,9 @@ static struct brnf_net init_brnf_net = {
 
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
-static int brnf_filter_vlan_tagged __read_mostly = 0;
 static int brnf_filter_pppoe_tagged __read_mostly = 0;
 static int brnf_pass_vlan_indev __read_mostly = 0;
 #else
-#define brnf_filter_vlan_tagged 0
 #define brnf_filter_pppoe_tagged 0
 #define brnf_pass_vlan_indev 0
 #endif
@@ -91,15 +89,15 @@ static inline __be16 vlan_proto(const struct sk_buff *skb)
 
 #define IS_VLAN_IP(skb) \
 	(vlan_proto(skb) == htons(ETH_P_IP) && \
-	 brnf_filter_vlan_tagged)
+	 init_brnf_net.filter_vlan_tagged)
 
 #define IS_VLAN_IPV6(skb) \
 	(vlan_proto(skb) == htons(ETH_P_IPV6) && \
-	 brnf_filter_vlan_tagged)
+	 init_brnf_net.filter_vlan_tagged)
 
 #define IS_VLAN_ARP(skb) \
 	(vlan_proto(skb) == htons(ETH_P_ARP) &&	\
-	 brnf_filter_vlan_tagged)
+	 init_brnf_net.filter_vlan_tagged)
 
 static inline __be16 pppoe_proto(const struct sk_buff *skb)
 {
@@ -1042,7 +1040,7 @@ static struct ctl_table brnf_table[] = {
 	},
 	{
 		.procname	= "bridge-nf-filter-vlan-tagged",
-		.data		= &brnf_filter_vlan_tagged,
+		.data		= &init_brnf_net.filter_vlan_tagged,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= brnf_sysctl_call_tables,
Signature · 1 line
1.7.5.4
#11 lore raw

PATCH 7/15 br_netfilter: switch sysctl filter_pppoe_tagged to init_brnf_net

In reply to a message not in the archive
---
 net/bridge/br_netfilter.c |    8 +++-----
 1 files changed, 3 insertions(+), 5 deletions(-)
net/bridge/br_netfilter.c +3 -5
index 16a69cf..3650f21 100644
@@ -61,10 +61,8 @@ static struct brnf_net init_brnf_net = {
 
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
-static int brnf_filter_pppoe_tagged __read_mostly = 0;
 static int brnf_pass_vlan_indev __read_mostly = 0;
 #else
-#define brnf_filter_pppoe_tagged 0
 #define brnf_pass_vlan_indev 0
 #endif
 
@@ -108,12 +106,12 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
 #define IS_PPPOE_IP(skb) \
 	(skb->protocol == htons(ETH_P_PPP_SES) && \
 	 pppoe_proto(skb) == htons(PPP_IP) && \
-	 brnf_filter_pppoe_tagged)
+	 init_brnf_net.filter_pppoe_tagged)
 
 #define IS_PPPOE_IPV6(skb) \
 	(skb->protocol == htons(ETH_P_PPP_SES) && \
 	 pppoe_proto(skb) == htons(PPP_IPV6) && \
-	 brnf_filter_pppoe_tagged)
+	 init_brnf_net.filter_pppoe_tagged)
 
 static void fake_update_pmtu(struct dst_entry *dst, struct sock *sk,
 			     struct sk_buff *skb, u32 mtu)
@@ -1047,7 +1045,7 @@ static struct ctl_table brnf_table[] = {
 	},
 	{
 		.procname	= "bridge-nf-filter-pppoe-tagged",
-		.data		= &brnf_filter_pppoe_tagged,
+		.data		= &init_brnf_net.filter_pppoe_tagged,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= brnf_sysctl_call_tables,
Signature · 1 line
1.7.5.4
#12 lore raw

PATCH 8/15 br_netfilter: switch sysctl pass_vlan_indev to init_brnf_net

In reply to a message not in the archive
---
 net/bridge/br_netfilter.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)
net/bridge/br_netfilter.c +2 -5
index 3650f21..e3ab72f8 100644
@@ -61,9 +61,6 @@ static struct brnf_net init_brnf_net = {
 
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
-static int brnf_pass_vlan_indev __read_mostly = 0;
-#else
-#define brnf_pass_vlan_indev 0
 #endif
 
 #define IS_IP(skb) \
@@ -534,7 +531,7 @@ static struct net_device *brnf_get_logical_dev(struct sk_buff *skb, const struct
 	struct net_device *vlan, *br;
 
 	br = bridge_parent(dev);
-	if (brnf_pass_vlan_indev == 0 || !vlan_tx_tag_present(skb))
+	if (init_brnf_net.pass_vlan_indev == 0 || !vlan_tx_tag_present(skb))
 		return br;
 
 	vlan = __vlan_find_dev_deep(br, skb->vlan_proto,
@@ -1052,7 +1049,7 @@ static struct ctl_table brnf_table[] = {
 	},
 	{
 		.procname	= "bridge-nf-pass-vlan-input-dev",
-		.data		= &brnf_pass_vlan_indev,
+		.data		= &init_brnf_net.pass_vlan_indev,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= brnf_sysctl_call_tables,
Signature · 1 line
1.7.5.4
#13 lore raw

PATCH 9/15 br_netfilter: pernet_operations brnf_net_ops without per-netns sysctl registration

In reply to a message not in the archive

pernet_operations was added,
rollback in br_netfilter_init was reworked

---
 net/bridge/br_netfilter.c |   60 ++++++++++++++++++++++++++++++++++++++------
 1 files changed, 51 insertions(+), 9 deletions(-)
net/bridge/br_netfilter.c +51 -9
index e3ab72f8..460917c 100644
@@ -35,6 +35,7 @@
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/route.h>
+#include <net/netns/generic.h>
 
 #include <asm/uaccess.h>
 #include "br_private.h"
@@ -47,6 +48,7 @@
 #define store_orig_dstaddr(skb)	 (skb_origaddr(skb) = ip_hdr(skb)->daddr)
 #define dnat_took_place(skb)	 (skb_origaddr(skb) != ip_hdr(skb)->daddr)
 
+int brnf_net_id __read_mostly;
 static struct brnf_net init_brnf_net = {
 #ifdef CONFIG_SYSCTL
 	.hdr			= NULL,
@@ -59,6 +61,11 @@ static struct brnf_net init_brnf_net = {
 	.pass_vlan_indev	= 0,
 };
 
+static inline struct brnf_net *brnf_net(const struct net *net)
+{
+	return net_generic(net, brnf_net_id);
+}
+
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *brnf_sysctl_header;
 #endif
@@ -1058,38 +1065,73 @@ static struct ctl_table brnf_table[] = {
 };
 #endif
 
+#define brnf_sysctl_net_register(x)	(0)
+#define brnf_sysctl_net_unregister(x)
+
+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 brnf_sysctl_net_register(bn);
+}
+
+static void __net_exit brnf_net_exit(struct net *net)
+{
+	brnf_sysctl_net_unregister(brnf_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),
+};
+
 int __init br_netfilter_init(void)
 {
 	int ret;
 
 	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;
+
+	ret = register_pernet_subsys(&brnf_net_ops);
+	if (ret < 0)
+		goto err_pernet;
 #ifdef CONFIG_SYSCTL
 	brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table);
 	if (brnf_sysctl_header == NULL) {
 		printk(KERN_WARNING
 		       "br_netfilter: can't register to sysctl.\n");
-		nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
-		dst_entries_destroy(&fake_dst_ops);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		unregister_pernet_subsys(&brnf_net_ops);
+		goto err_pernet;
 	}
 #endif
 	printk(KERN_NOTICE "Bridge firewalling registered\n");
 	return 0;
+
+err_pernet:
+	nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
+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_net_sysctl_table(brnf_sysctl_header);
 #endif
+	unregister_pernet_subsys(&brnf_net_ops);
+	nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
 	dst_entries_destroy(&fake_dst_ops);
 }
Signature · 1 line
1.7.5.4
#14 lore raw

Re: [PATCH 09/15] br_netfilter: pernet_operations brnf_net_ops without per-netns sysctl registration

Vasily Averin schreef op 9/05/2014 23:28:

Quoted 21 lines

pernet_operations was added,
rollback in br_netfilter_init was reworked

---
  net/bridge/br_netfilter.c |   60 ++++++++++++++++++++++++++++++++++++++------
  1 files changed, 51 insertions(+), 9 deletions(-)
net/bridge/br_netfilter.c +1 -0
index e3ab72f8..460917c 100644
@@ -35,6 +35,7 @@
  #include <net/ip.h>
  #include <net/ipv6.h>
  #include <net/route.h>
+#include <net/netns/generic.h>
 
  #include <asm/uaccess.h>
  #include "br_private.h"

net/bridge/br_netfilter.c line 51

Quoted 4 lines
net/bridge/br_netfilter.c +1 -0
@@ -47,6 +48,7 @@
  #define store_orig_dstaddr(skb)	 (skb_origaddr(skb) = ip_hdr(skb)->daddr)
  #define dnat_took_place(skb)	 (skb_origaddr(skb) != ip_hdr(skb)->daddr)
 
+int brnf_net_id __read_mostly;

Should be static.

cheers,
Bart

#15 lore raw

PATCH 10/15 br_netfilter: added per-netns sysctl registration

In reply to a message not in the archive

added separate per-netns sysctl tables,
however systcl variables from init_brnf_net are still used

---
 net/bridge/br_netfilter.c |   59 +++++++++++++++++++++++++++++++-------------
 1 files changed, 41 insertions(+), 18 deletions(-)
net/bridge/br_netfilter.c +41 -18
index 460917c..16b68da 100644
@@ -66,10 +66,6 @@ static inline struct brnf_net *brnf_net(const struct net *net)
 	return net_generic(net, brnf_net_id);
 }
 
-#ifdef CONFIG_SYSCTL
-static struct ctl_table_header *brnf_sysctl_header;
-#endif
-
 #define IS_IP(skb) \
 	(!vlan_tx_tag_present(skb) && skb->protocol == htons(ETH_P_IP))
 
@@ -1063,10 +1059,49 @@ static struct ctl_table brnf_table[] = {
 	},
 	{ }
 };
-#endif
 
+static int brnf_sysctl_net_register(struct brnf_net *bn)
+{
+	struct ctl_table *table;
+	struct ctl_table_header *hdr;
+
+	table = brnf_table;
+	if (!net_eq(bn->net, &init_net)) {
+
+		table = kmemdup(table, sizeof(brnf_table), GFP_KERNEL);
+		if (!table)
+			goto err_alloc;
+	}
+	hdr = register_net_sysctl(bn->net, "net/bridge", table);
+	if (!hdr)
+		goto err_reg;
+
+	bn->hdr = hdr;
+	return 0;
+
+err_reg:
+	if (!net_eq(bn->net, &init_net))
+		kfree(table);
+err_alloc:
+	return -ENOMEM;
+}
+
+static void brnf_sysctl_net_unregister(struct brnf_net *bn)
+{
+	struct ctl_table *table;
+
+	if (bn->hdr == NULL)
+		return;
+
+	table = bn->hdr->ctl_table_arg;
+	unregister_net_sysctl_table(bn->hdr);
+	if (!net_eq(bn->net, &init_net))
+		kfree(table);
+}
+#else
 #define brnf_sysctl_net_register(x)	(0)
 #define brnf_sysctl_net_unregister(x)
+#endif
 
 static int __net_init brnf_net_init(struct net *net)
 {
@@ -1105,16 +1140,7 @@ int __init br_netfilter_init(void)
 	ret = register_pernet_subsys(&brnf_net_ops);
 	if (ret < 0)
 		goto err_pernet;
-#ifdef CONFIG_SYSCTL
-	brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table);
-	if (brnf_sysctl_header == NULL) {
-		printk(KERN_WARNING
-		       "br_netfilter: can't register to sysctl.\n");
-		ret = -ENOMEM;
-		unregister_pernet_subsys(&brnf_net_ops);
-		goto err_pernet;
-	}
-#endif
+
 	printk(KERN_NOTICE "Bridge firewalling registered\n");
 	return 0;
 
@@ -1128,9 +1154,6 @@ err_dst:
 
 void br_netfilter_fini(void)
 {
-#ifdef CONFIG_SYSCTL
-	unregister_net_sysctl_table(brnf_sysctl_header);
-#endif
 	unregister_pernet_subsys(&brnf_net_ops);
 	nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
 	dst_entries_destroy(&fake_dst_ops);
Signature · 1 line
1.7.5.4
#16 lore raw

PATCH 11/15 br_netfilter: switch sysctl nf_call_arptables to per-netns processing

In reply to a message not in the archive

now sysctl nf_call_arptables uses per-netns setting .data in sysctl tables now points to per-netns struct brnf_net

---
 net/bridge/br_netfilter.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)
net/bridge/br_netfilter.c +7 -1
index 16b68da..dbf73cb 100644
@@ -834,13 +834,15 @@ static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops,
 	struct net_bridge_port *p;
 	struct net_bridge *br;
 	struct net_device **d = (struct net_device **)(skb->cb);
+	struct brnf_net *bn;
 
 	p = br_port_get_rcu(out);
 	if (p == NULL)
 		return NF_ACCEPT;
 	br = p->br;
+	bn = brnf_net(dev_net(skb->dev));
 
-	if (!init_brnf_net.nf_call_arptables && !br->nf_call_arptables)
+	if (!bn->nf_call_arptables && !br->nf_call_arptables)
 		return NF_ACCEPT;
 
 	if (!IS_ARP(skb)) {
@@ -1064,6 +1066,7 @@ static int brnf_sysctl_net_register(struct brnf_net *bn)
 {
 	struct ctl_table *table;
 	struct ctl_table_header *hdr;
+	int i;
 
 	table = brnf_table;
 	if (!net_eq(bn->net, &init_net)) {
@@ -1072,6 +1075,9 @@ static int brnf_sysctl_net_register(struct brnf_net *bn)
 		if (!table)
 			goto err_alloc;
 	}
+	for (i = 0; i < 1; i++)
+		table[i].data += (char *)bn - (char *)&init_brnf_net;
+
 	hdr = register_net_sysctl(bn->net, "net/bridge", table);
 	if (!hdr)
 		goto err_reg;
Signature · 1 line
1.7.5.4
#17 lore raw

PATCH 12/15 br_netfilter: switch sysctls nf_call_iptables and nf_call_ip6tables to per-netns processing

In reply to a message not in the archive
---
 net/bridge/br_netfilter.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)
net/bridge/br_netfilter.c +5 -3
index dbf73cb..5043b1e 100644
@@ -681,6 +681,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
 {
 	struct net_bridge_port *p;
 	struct net_bridge *br;
+	struct brnf_net *bn;
 	__u32 len = nf_bridge_encap_header_len(skb);
 
 	if (unlikely(!pskb_may_pull(skb, len)))
@@ -691,15 +692,16 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
 		return NF_DROP;
 	br = p->br;
 
+	bn = brnf_net(dev_net(skb->dev));
 	if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb)) {
-		if (!init_brnf_net.nf_call_ip6tables && !br->nf_call_ip6tables)
+		if (!bn->nf_call_ip6tables && !br->nf_call_ip6tables)
 			return NF_ACCEPT;
 
 		nf_bridge_pull_encap_header_rcsum(skb);
 		return br_nf_pre_routing_ipv6(ops, skb, in, out, okfn);
 	}
 
-	if (!init_brnf_net.nf_call_iptables && !br->nf_call_iptables)
+	if (!bn->nf_call_iptables && !br->nf_call_iptables)
 		return NF_ACCEPT;
 
 	if (!IS_IP(skb) && !IS_VLAN_IP(skb) && !IS_PPPOE_IP(skb))
@@ -1075,7 +1077,7 @@ static int brnf_sysctl_net_register(struct brnf_net *bn)
 		if (!table)
 			goto err_alloc;
 	}
-	for (i = 0; i < 1; i++)
+	for (i = 0; i < 3; i++)
 		table[i].data += (char *)bn - (char *)&init_brnf_net;
 
 	hdr = register_net_sysctl(bn->net, "net/bridge", table);
Signature · 1 line
1.7.5.4
#18 lore raw

PATCH 13/15 br_netfilter: switch sysctl filter_vlan_tagged to per-netns processing

In reply to a message not in the archive
---
 net/bridge/br_netfilter.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
net/bridge/br_netfilter.c +4 -4
index 5043b1e..680d60d 100644
@@ -87,15 +87,15 @@ static inline __be16 vlan_proto(const struct sk_buff *skb)
 
 #define IS_VLAN_IP(skb) \
 	(vlan_proto(skb) == htons(ETH_P_IP) && \
-	 init_brnf_net.filter_vlan_tagged)
+	 brnf_net(dev_net(skb->dev))->filter_vlan_tagged)
 
 #define IS_VLAN_IPV6(skb) \
 	(vlan_proto(skb) == htons(ETH_P_IPV6) && \
-	 init_brnf_net.filter_vlan_tagged)
+	 brnf_net(dev_net(skb->dev))->filter_vlan_tagged)
 
 #define IS_VLAN_ARP(skb) \
 	(vlan_proto(skb) == htons(ETH_P_ARP) &&	\
-	 init_brnf_net.filter_vlan_tagged)
+	 brnf_net(dev_net(skb->dev))->filter_vlan_tagged)
 
 static inline __be16 pppoe_proto(const struct sk_buff *skb)
 {
@@ -1077,7 +1077,7 @@ static int brnf_sysctl_net_register(struct brnf_net *bn)
 		if (!table)
 			goto err_alloc;
 	}
-	for (i = 0; i < 3; i++)
+	for (i = 0; i < 4; i++)
 		table[i].data += (char *)bn - (char *)&init_brnf_net;
 
 	hdr = register_net_sysctl(bn->net, "net/bridge", table);
Signature · 1 line
1.7.5.4
#19 lore raw

PATCH 14/15 br_netfilter: switch sysctl filter_pppoe_tagged to per-netns processing

In reply to a message not in the archive
---
 net/bridge/br_netfilter.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
net/bridge/br_netfilter.c +3 -3
index 680d60d..44bae8e 100644
@@ -106,12 +106,12 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
 #define IS_PPPOE_IP(skb) \
 	(skb->protocol == htons(ETH_P_PPP_SES) && \
 	 pppoe_proto(skb) == htons(PPP_IP) && \
-	 init_brnf_net.filter_pppoe_tagged)
+	 brnf_net(dev_net(skb->dev))->filter_pppoe_tagged)
 
 #define IS_PPPOE_IPV6(skb) \
 	(skb->protocol == htons(ETH_P_PPP_SES) && \
 	 pppoe_proto(skb) == htons(PPP_IPV6) && \
-	 init_brnf_net.filter_pppoe_tagged)
+	 brnf_net(dev_net(skb->dev))->filter_pppoe_tagged)
 
 static void fake_update_pmtu(struct dst_entry *dst, struct sock *sk,
 			     struct sk_buff *skb, u32 mtu)
@@ -1077,7 +1077,7 @@ static int brnf_sysctl_net_register(struct brnf_net *bn)
 		if (!table)
 			goto err_alloc;
 	}
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < 5; i++)
 		table[i].data += (char *)bn - (char *)&init_brnf_net;
 
 	hdr = register_net_sysctl(bn->net, "net/bridge", table);
Signature · 1 line
1.7.5.4
#20 lore raw

PATCH 15/15 br_netfilter: switch sysctl pass_vlan_indev to per-netns processing

In reply to a message not in the archive
---
 net/bridge/br_netfilter.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)
net/bridge/br_netfilter.c +4 -2
index 44bae8e..5ca6010 100644
@@ -532,9 +532,11 @@ bridged_dnat:
 static struct net_device *brnf_get_logical_dev(struct sk_buff *skb, const struct net_device *dev)
 {
 	struct net_device *vlan, *br;
+	struct brnf_net *bn;
 
 	br = bridge_parent(dev);
-	if (init_brnf_net.pass_vlan_indev == 0 || !vlan_tx_tag_present(skb))
+	bn = brnf_net(dev_net(dev));
+	if (bn->pass_vlan_indev == 0 || !vlan_tx_tag_present(skb))
 		return br;
 
 	vlan = __vlan_find_dev_deep(br, skb->vlan_proto,
@@ -1077,7 +1079,7 @@ static int brnf_sysctl_net_register(struct brnf_net *bn)
 		if (!table)
 			goto err_alloc;
 	}
-	for (i = 0; i < 5; i++)
+	for (i = 0; table[i].data; i++)
 		table[i].data += (char *)bn - (char *)&init_brnf_net;
 
 	hdr = register_net_sysctl(bn->net, "net/bridge", table);
Signature · 1 line
1.7.5.4