Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 243a2e63 authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller
Browse files

bridge: Add vlan filtering infrastructure



Adds an optional infrustructure component to bridge that would allow
native vlan filtering in the bridge.  Each bridge port (as well
as the bridge device) now get a VLAN bitmap.  Each bit in the bitmap
is associated with a vlan id.  This way if the bit corresponding to
the vid is set in the bitmap that the packet with vid is allowed to
enter and exit the port.

Write access the bitmap is protected by RTNL and read access
protected by RCU.

Vlan functionality is disabled by default.

Signed-off-by: default avatarVlad Yasevich <vyasevic@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 22222997
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -46,3 +46,17 @@ config BRIDGE_IGMP_SNOOPING
	  Say N to exclude this support and reduce the binary size.

	  If unsure, say Y.

config BRIDGE_VLAN_FILTERING
	bool "VLAN filtering"
	depends on BRIDGE
	depends on VLAN_8021Q
	default n
	---help---
	  If you say Y here, then the Ethernet bridge will be able selectively
	  receive and forward traffic based on VLAN information in the packet
	  any VLAN information configured on the bridge port or bridge device.

	  Say N to exclude this support and reduce the binary size.

	  If unsure, say Y.
+2 −0
Original line number Diff line number Diff line
@@ -14,4 +14,6 @@ bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o

bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o

bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) += br_vlan.o

obj-$(CONFIG_BRIDGE_NF_EBTABLES) += netfilter/
+1 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ static void del_nbp(struct net_bridge_port *p)

	br_ifinfo_notify(RTM_DELLINK, p);

	nbp_vlan_flush(p);
	br_fdb_delete_by_port(br, p, 1);

	list_del_rcu(&p->list);
+59 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/netpoll.h>
#include <linux/u64_stats_sync.h>
#include <net/route.h>
#include <linux/if_vlan.h>

#define BR_HASH_BITS 8
#define BR_HASH_SIZE (1 << BR_HASH_BITS)
@@ -26,6 +27,7 @@

#define BR_PORT_BITS	10
#define BR_MAX_PORTS	(1<<BR_PORT_BITS)
#define BR_VLAN_BITMAP_LEN	BITS_TO_LONGS(VLAN_N_VID)

#define BR_VERSION	"2.3"

@@ -63,6 +65,16 @@ struct br_ip
	__be16		proto;
};

struct net_port_vlans {
	u16				port_idx;
	union {
		struct net_bridge_port		*port;
		struct net_bridge		*br;
	}				parent;
	struct rcu_head			rcu;
	unsigned long			vlan_bitmap[BR_VLAN_BITMAP_LEN];
};

struct net_bridge_fdb_entry
{
	struct hlist_node		hlist;
@@ -156,6 +168,9 @@ struct net_bridge_port
#ifdef CONFIG_NET_POLL_CONTROLLER
	struct netpoll			*np;
#endif
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
	struct net_port_vlans __rcu	*vlan_info;
#endif
};

#define br_port_exists(dev) (dev->priv_flags & IFF_BRIDGE_PORT)
@@ -257,6 +272,10 @@ struct net_bridge
	struct timer_list		topology_change_timer;
	struct timer_list		gc_timer;
	struct kobject			*ifobj;
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
	u8				vlan_enabled;
	struct net_port_vlans __rcu	*vlan_info;
#endif
};

struct br_input_skb_cb {
@@ -531,6 +550,46 @@ static inline void br_mdb_uninit(void)
}
#endif

/* br_vlan.c */
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
extern int br_vlan_add(struct net_bridge *br, u16 vid);
extern int br_vlan_delete(struct net_bridge *br, u16 vid);
extern void br_vlan_flush(struct net_bridge *br);
extern int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
extern int nbp_vlan_add(struct net_bridge_port *port, u16 vid);
extern int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
extern void nbp_vlan_flush(struct net_bridge_port *port);
#else
static inline int br_vlan_add(struct net_bridge *br, u16 vid)
{
	return -EOPNOTSUPP;
}

static inline int br_vlan_delete(struct net_bridge *br, u16 vid)
{
	return -EOPNOTSUPP;
}

static inline void br_vlan_flush(struct net_bridge *br)
{
}

static inline int nbp_vlan_add(struct net_bridge_port *port, u16 vid)
{
	return -EOPNOTSUPP;
}

static inline int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
{
	return -EOPNOTSUPP;
}

static inline void nbp_vlan_flush(struct net_bridge_port *port)
{
}

#endif

/* br_netfilter.c */
#ifdef CONFIG_BRIDGE_NETFILTER
extern int br_netfilter_init(void);
+21 −0
Original line number Diff line number Diff line
@@ -691,6 +691,24 @@ static ssize_t store_nf_call_arptables(
static DEVICE_ATTR(nf_call_arptables, S_IRUGO | S_IWUSR,
		   show_nf_call_arptables, store_nf_call_arptables);
#endif
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
static ssize_t show_vlan_filtering(struct device *d,
				   struct device_attribute *attr,
				   char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", br->vlan_enabled);
}

static ssize_t store_vlan_filtering(struct device *d,
				    struct device_attribute *attr,
				    const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_vlan_filter_toggle);
}
static DEVICE_ATTR(vlan_filtering, S_IRUGO | S_IWUSR,
		   show_vlan_filtering, store_vlan_filtering);
#endif

static struct attribute *bridge_attrs[] = {
	&dev_attr_forward_delay.attr,
@@ -731,6 +749,9 @@ static struct attribute *bridge_attrs[] = {
	&dev_attr_nf_call_iptables.attr,
	&dev_attr_nf_call_ip6tables.attr,
	&dev_attr_nf_call_arptables.attr,
#endif
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
	&dev_attr_vlan_filtering.attr,
#endif
	NULL
};
Loading