public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC] net/bridge: port based vlan filtering for bridges
@ 2012-04-11 15:10 Benjamin LaHaise
  2012-04-11 15:30 ` Stephen Hemminger
  0 siblings, 1 reply; 4+ messages in thread
From: Benjamin LaHaise @ 2012-04-11 15:10 UTC (permalink / raw)
  To: netdev

Hello folks,

Attached is the first stab at a patch to make it possible to filter packets 
received from other bridge ports based on the port number.  This can be used 
to emulate port based VLANs that some switches support.

The justification for this is a bit interesting.  Initially, I had been 
filtering packets using firewall rules.  Unfortunately, the number of 
filter rules becomes impossible to manage when trying to filter traffic 
between 100 different ports.  CPU overhead of the filters is also a major 
problem.

The particular use-case I'm dealing with is simulating wireless networks 
on a system using LXC containers.  Each guest has a veth device that is a 
member of the bridge, but the topology of which nodes can "hear" each other 
changes at runtime.

Comments/thoughts?

		-ben
---
 br_forward.c  |    3 +++
 br_if.c       |    3 +--
 br_private.h  |    4 ++++
 br_sysfs_if.c |   20 ++++++++++++++++++++
 4 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index ee64287..9b106f8 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -30,6 +30,9 @@ static int deliver_clone(const struct net_bridge_port *prev,
 static inline int should_deliver(const struct net_bridge_port *p,
 				 const struct sk_buff *skb)
 {
+	struct net_bridge_port *from = br_port_get_rcu(skb->dev);
+	if (from && test_bit(from->port_no, p->filter_ports))
+		return 0;
 	return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
 		p->state == BR_STATE_FORWARDING);
 }
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index f603e5b..2f2e595 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -183,8 +183,7 @@ static int find_portno(struct net_bridge *br)
 	struct net_bridge_port *p;
 	unsigned long *inuse;
 
-	inuse = kcalloc(BITS_TO_LONGS(BR_MAX_PORTS), sizeof(unsigned long),
-			GFP_KERNEL);
+	inuse = kcalloc(BR_PORT_LONGS, sizeof(unsigned long), GFP_KERNEL);
 	if (!inuse)
 		return -ENOMEM;
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d7d6fb0..c6fbab0 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -17,6 +17,7 @@
 #include <linux/if_bridge.h>
 #include <linux/netpoll.h>
 #include <linux/u64_stats_sync.h>
+#include <linux/bitops.h>
 #include <net/route.h>
 
 #define BR_HASH_BITS 8
@@ -26,6 +27,7 @@
 
 #define BR_PORT_BITS	10
 #define BR_MAX_PORTS	(1<<BR_PORT_BITS)
+#define BR_PORT_LONGS	BITS_TO_LONGS(BR_MAX_PORTS)
 
 #define BR_VERSION	"2.3"
 
@@ -156,6 +158,8 @@ struct net_bridge_port
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	struct netpoll			*np;
 #endif
+
+	unsigned long			filter_ports[BR_PORT_LONGS];
 };
 
 #define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 6229b62..9d95f6a 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -164,6 +164,24 @@ static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,
 		   store_multicast_router);
 #endif
 
+static int store_add_filter_port(struct net_bridge_port *p, unsigned long v)
+{
+	if (v >= BR_MAX_PORTS)
+		return -EINVAL;
+	set_bit(v, p->filter_ports);
+	return 0;
+}
+static BRPORT_ATTR(add_filter_port, S_IWUSR, NULL, store_add_filter_port);
+
+static int store_remove_filter_port(struct net_bridge_port *p, unsigned long v)
+{
+	if (v >= BR_MAX_PORTS)
+		return -EINVAL;
+	clear_bit(v, p->filter_ports);
+	return 0;
+}
+static BRPORT_ATTR(remove_filter_port, S_IWUSR, NULL, store_remove_filter_port);
+
 static struct brport_attribute *brport_attrs[] = {
 	&brport_attr_path_cost,
 	&brport_attr_priority,
@@ -184,6 +202,8 @@ static struct brport_attribute *brport_attrs[] = {
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 	&brport_attr_multicast_router,
 #endif
+	&brport_attr_add_filter_port,
+	&brport_attr_remove_filter_port,
 	NULL
 };
 
-- 
"Thought is the essence of where you are now."

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-04-11 15:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-11 15:10 [RFC] net/bridge: port based vlan filtering for bridges Benjamin LaHaise
2012-04-11 15:30 ` Stephen Hemminger
2012-04-11 15:36   ` Benjamin LaHaise
2012-04-11 15:38     ` Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox