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

Commit 96a20d9d authored by Vlad Yasevich's avatar Vlad Yasevich Committed by David S. Miller
Browse files

bridge: Add a default_pvid sysfs attribute



This patch allows the user to set and retrieve default_pvid
value.  A new value can only be stored when vlan filtering
is disabled.

Signed-off-by: default avatarVladislav Yasevich <vyasevic@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e885439f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -299,6 +299,7 @@ struct net_bridge
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
	u8				vlan_enabled;
	__be16				vlan_proto;
	u16				default_pvid;
	struct net_port_vlans __rcu	*vlan_info;
#endif
};
@@ -605,6 +606,7 @@ void br_recalculate_fwd_mask(struct net_bridge *br);
int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
int br_vlan_set_proto(struct net_bridge *br, unsigned long val);
void br_vlan_init(struct net_bridge *br);
int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val);
int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags);
int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
void nbp_vlan_flush(struct net_bridge_port *port);
+17 −0
Original line number Diff line number Diff line
@@ -725,6 +725,22 @@ static ssize_t vlan_protocol_store(struct device *d,
	return store_bridge_parm(d, buf, len, br_vlan_set_proto);
}
static DEVICE_ATTR_RW(vlan_protocol);

static ssize_t default_pvid_show(struct device *d,
				 struct device_attribute *attr,
				 char *buf)
{
	struct net_bridge *br = to_bridge(d);
	return sprintf(buf, "%d\n", br->default_pvid);
}

static ssize_t default_pvid_store(struct device *d,
				  struct device_attribute *attr,
				  const char *buf, size_t len)
{
	return store_bridge_parm(d, buf, len, br_vlan_set_default_pvid);
}
static DEVICE_ATTR_RW(default_pvid);
#endif

static struct attribute *bridge_attrs[] = {
@@ -771,6 +787,7 @@ static struct attribute *bridge_attrs[] = {
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
	&dev_attr_vlan_filtering.attr,
	&dev_attr_vlan_protocol.attr,
	&dev_attr_default_pvid.attr,
#endif
	NULL
};
+29 −0
Original line number Diff line number Diff line
@@ -499,9 +499,38 @@ err_filt:
	goto unlock;
}

int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val)
{
	u16 pvid = val;
	int err = 0;

	if (!val || val >= VLAN_VID_MASK)
		return -EINVAL;

	if (!rtnl_trylock())
		return restart_syscall();

	if (pvid == br->default_pvid)
		goto unlock;

	/* Only allow default pvid change when filtering is disabled */
	if (br->vlan_enabled) {
		pr_info_once("Please disable vlan filtering to change default_pvid\n");
		err = -EPERM;
		goto unlock;
	}

	br->default_pvid = pvid;

unlock:
	rtnl_unlock();
	return err;
}

void br_vlan_init(struct net_bridge *br)
{
	br->vlan_proto = htons(ETH_P_8021Q);
	br->default_pvid = 1;
}

/* Must be protected by RTNL.