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

Commit 35e03f3a authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller
Browse files

bridge: Separate egress policy bitmap



Add an ability to configure a separate "untagged" egress
policy to the VLAN information of the bridge.  This superseeds PVID
policy and makes PVID ingress-only.  The policy is configured with a
new flag and is represented as a port bitmap per vlan.  Egress frames
with a VLAN id in "untagged" policy bitmap would egress
the port without VLAN header.

Signed-off-by: default avatarVlad Yasevich <vyasevic@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bc9a25d2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ enum {

#define BRIDGE_VLAN_INFO_MASTER	(1<<0)	/* Operate on Bridge device as well */
#define BRIDGE_VLAN_INFO_PVID	(1<<1)	/* VLAN is PVID, ingress untagged */
#define BRIDGE_VLAN_INFO_UNTAGGED	(1<<2)	/* VLAN egresses untagged */

struct bridge_vlan_info {
	u16 flags;
+4 −0
Original line number Diff line number Diff line
@@ -143,6 +143,10 @@ static int br_fill_ifinfo(struct sk_buff *skb,
			vinfo.flags = 0;
			if (vid == pvid)
				vinfo.flags |= BRIDGE_VLAN_INFO_PVID;

			if (test_bit(vid, pv->untagged_bitmap))
				vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;

			if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
				    sizeof(vinfo), &vinfo))
				goto nla_put_failure;
+1 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ struct net_port_vlans {
	}				parent;
	struct rcu_head			rcu;
	unsigned long			vlan_bitmap[BR_VLAN_BITMAP_LEN];
	unsigned long			untagged_bitmap[BR_VLAN_BITMAP_LEN];
	u16				num_vlans;
};

+14 −6
Original line number Diff line number Diff line
@@ -23,6 +23,15 @@ static void __vlan_delete_pvid(struct net_port_vlans *v, u16 vid)
	v->pvid = 0;
}

static void __vlan_add_flags(struct net_port_vlans *v, u16 vid, u16 flags)
{
	if (flags & BRIDGE_VLAN_INFO_PVID)
		__vlan_add_pvid(v, vid);

	if (flags & BRIDGE_VLAN_INFO_UNTAGGED)
		set_bit(vid, v->untagged_bitmap);
}

static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
{
	struct net_bridge_port *p = NULL;
@@ -31,8 +40,7 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
	int err;

	if (test_bit(vid, v->vlan_bitmap)) {
		if (flags & BRIDGE_VLAN_INFO_PVID)
			__vlan_add_pvid(v, vid);
		__vlan_add_flags(v, vid, flags);
		return 0;
	}

@@ -69,8 +77,7 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)

	set_bit(vid, v->vlan_bitmap);
	v->num_vlans++;
	if (flags & BRIDGE_VLAN_INFO_PVID)
		__vlan_add_pvid(v, vid);
	__vlan_add_flags(v, vid, flags);

	return 0;

@@ -86,6 +93,7 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
		return -EINVAL;

	__vlan_delete_pvid(v, vid);
	clear_bit(vid, v->untagged_bitmap);

	if (v->port_idx && vid) {
		struct net_device *dev = v->parent.port->dev;
@@ -144,11 +152,11 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
		goto out;

	/* At this point, we know that the frame was filtered and contains
	 * a valid vlan id.  If the vlan id matches the pvid of current port
	 * a valid vlan id.  If the vlan id is set in the untagged bitmap,
	 * send untagged; otherwise, send taged.
	 */
	br_vlan_get_tag(skb, &vid);
	if (vid == br_get_pvid(pv))
	if (test_bit(vid, pv->untagged_bitmap))
		skb = br_vlan_untag(skb);
	else {
		/* Egress policy says "send tagged".  If output device