[Bridge] RFC: Simple Private VLAN impl.
Joakim Tjernlund
joakim.tjernlund at transmode.se
Wed Jun 10 06:32:06 PDT 2009
Even though some folks on this list thinks ebtables should be used
to deploy Private VLAN I find using ebtables a bit clumsy.
So here a first simple(RFC only) Private VLAN impl. for only Promiscuous and Isolated
mode for the linux bridge. Not tested yet.
Jocke
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index d2c27c8..c10362c 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -18,11 +18,30 @@
#include <linux/netfilter_bridge.h>
#include "br_private.h"
-/* Don't forward packets to originating port or forwarding diasabled */
-static inline int should_deliver(const struct net_bridge_port *p,
+/* Don't forward packets to originating port or forwarding disabled.
+ * Don't froward packets between private VLAN's in ISOLATED mode.
+ */
+static inline int should_deliver(const struct net_bridge_port *to,
const struct sk_buff *skb)
{
- return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING);
+ struct net_bridge_port *from = rcu_dereference(skb->dev->br_port);
+
+ if (skb->dev == to->dev || to->state != BR_STATE_FORWARDING)
+ return 0;
+ if (to->priv_vlan == PVLAN_ISOLATED &&
+ from->priv_vlan == PVLAN_ISOLATED)
+ return 0;
+ return 1;
+}
+
+int br_set_private_vlan(struct net_bridge_port *p,
+ unsigned long v)
+{
+ if (!(v == PVLAN_ISOLATED ||
+ v == PVLAN_PROMISC))
+ return 1;
+ p->priv_vlan = v;
+ return 0;
}
static inline unsigned packet_length(const struct sk_buff *skb)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index b6c3b71..6f63b7f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -30,6 +30,10 @@
/* Path to usermode spanning tree program */
#define BR_STP_PROG "/sbin/bridge-stp"
+/* Private VLAN defs */
+#define PVLAN_PROMISC 0
+#define PVLAN_ISOLATED 1
+
typedef struct bridge_id bridge_id;
typedef struct mac_addr mac_addr;
typedef __u16 port_id;
@@ -67,6 +71,7 @@ struct net_bridge_port
/* STP */
u8 priority;
u8 state;
+ u8 priv_vlan;
u16 port_no;
unsigned char topology_change_ack;
unsigned char config_pending;
@@ -175,6 +180,7 @@ extern void br_forward(const struct net_bridge_port *to,
extern int br_forward_finish(struct sk_buff *skb);
extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb);
extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb);
+extern int br_set_private_vlan(struct net_bridge_port *p, unsigned long v);
/* br_if.c */
extern void br_port_carrier_check(struct net_bridge_port *p);
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 02b2d50..aaaa085 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -143,6 +143,18 @@ static ssize_t store_flush(struct net_bridge_port *p, unsigned long v)
}
static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush);
+static ssize_t show_private_vlan(struct net_bridge_port *p, char *buf)
+{
+ return sprintf(buf, "%d\n", p->priv_vlan);
+}
+static ssize_t store_private_vlan(struct net_bridge_port *p, unsigned long v)
+{
+ return br_set_private_vlan(p, v);
+}
+static BRPORT_ATTR(private_vlan, S_IRUGO | S_IWUSR,
+ show_private_vlan, store_private_vlan);
+
+
static struct brport_attribute *brport_attrs[] = {
&brport_attr_path_cost,
&brport_attr_priority,
@@ -159,6 +171,7 @@ static struct brport_attribute *brport_attrs[] = {
&brport_attr_forward_delay_timer,
&brport_attr_hold_timer,
&brport_attr_flush,
+ &brport_attr_private_vlan,
NULL
};
More information about the Bridge
mailing list