aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevich@gmail.com>2014-10-03 11:29:16 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-05 21:21:36 -0400
commit96a20d9d7fff7068a2233b00379f0778a150bf86 (patch)
tree21abf27f7f18b540f65770d2877c938735b02afe /net/bridge
parente885439f37b0dce404291350f7c0368c2bb97cdb (diff)
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: Vladislav Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_private.h2
-rw-r--r--net/bridge/br_sysfs_br.c17
-rw-r--r--net/bridge/br_vlan.c29
3 files changed, 48 insertions, 0 deletions
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index fe7463c2af9a..5a347eb1d139 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -299,6 +299,7 @@ struct net_bridge
299#ifdef CONFIG_BRIDGE_VLAN_FILTERING 299#ifdef CONFIG_BRIDGE_VLAN_FILTERING
300 u8 vlan_enabled; 300 u8 vlan_enabled;
301 __be16 vlan_proto; 301 __be16 vlan_proto;
302 u16 default_pvid;
302 struct net_port_vlans __rcu *vlan_info; 303 struct net_port_vlans __rcu *vlan_info;
303#endif 304#endif
304}; 305};
@@ -605,6 +606,7 @@ void br_recalculate_fwd_mask(struct net_bridge *br);
605int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); 606int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
606int br_vlan_set_proto(struct net_bridge *br, unsigned long val); 607int br_vlan_set_proto(struct net_bridge *br, unsigned long val);
607void br_vlan_init(struct net_bridge *br); 608void br_vlan_init(struct net_bridge *br);
609int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val);
608int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags); 610int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags);
609int nbp_vlan_delete(struct net_bridge_port *port, u16 vid); 611int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
610void nbp_vlan_flush(struct net_bridge_port *port); 612void nbp_vlan_flush(struct net_bridge_port *port);
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index cb431c6016ee..4c97fc50fb70 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -725,6 +725,22 @@ static ssize_t vlan_protocol_store(struct device *d,
725 return store_bridge_parm(d, buf, len, br_vlan_set_proto); 725 return store_bridge_parm(d, buf, len, br_vlan_set_proto);
726} 726}
727static DEVICE_ATTR_RW(vlan_protocol); 727static DEVICE_ATTR_RW(vlan_protocol);
728
729static ssize_t default_pvid_show(struct device *d,
730 struct device_attribute *attr,
731 char *buf)
732{
733 struct net_bridge *br = to_bridge(d);
734 return sprintf(buf, "%d\n", br->default_pvid);
735}
736
737static ssize_t default_pvid_store(struct device *d,
738 struct device_attribute *attr,
739 const char *buf, size_t len)
740{
741 return store_bridge_parm(d, buf, len, br_vlan_set_default_pvid);
742}
743static DEVICE_ATTR_RW(default_pvid);
728#endif 744#endif
729 745
730static struct attribute *bridge_attrs[] = { 746static struct attribute *bridge_attrs[] = {
@@ -771,6 +787,7 @@ static struct attribute *bridge_attrs[] = {
771#ifdef CONFIG_BRIDGE_VLAN_FILTERING 787#ifdef CONFIG_BRIDGE_VLAN_FILTERING
772 &dev_attr_vlan_filtering.attr, 788 &dev_attr_vlan_filtering.attr,
773 &dev_attr_vlan_protocol.attr, 789 &dev_attr_vlan_protocol.attr,
790 &dev_attr_default_pvid.attr,
774#endif 791#endif
775 NULL 792 NULL
776}; 793};
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 3ba57fcdcd13..dfa7c9a7e193 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -499,9 +499,38 @@ err_filt:
499 goto unlock; 499 goto unlock;
500} 500}
501 501
502int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val)
503{
504 u16 pvid = val;
505 int err = 0;
506
507 if (!val || val >= VLAN_VID_MASK)
508 return -EINVAL;
509
510 if (!rtnl_trylock())
511 return restart_syscall();
512
513 if (pvid == br->default_pvid)
514 goto unlock;
515
516 /* Only allow default pvid change when filtering is disabled */
517 if (br->vlan_enabled) {
518 pr_info_once("Please disable vlan filtering to change default_pvid\n");
519 err = -EPERM;
520 goto unlock;
521 }
522
523 br->default_pvid = pvid;
524
525unlock:
526 rtnl_unlock();
527 return err;
528}
529
502void br_vlan_init(struct net_bridge *br) 530void br_vlan_init(struct net_bridge *br)
503{ 531{
504 br->vlan_proto = htons(ETH_P_8021Q); 532 br->vlan_proto = htons(ETH_P_8021Q);
533 br->default_pvid = 1;
505} 534}
506 535
507/* Must be protected by RTNL. 536/* Must be protected by RTNL.