diff options
author | Vlad Yasevich <vyasevich@gmail.com> | 2014-10-03 11:29:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-10-05 21:21:36 -0400 |
commit | 96a20d9d7fff7068a2233b00379f0778a150bf86 (patch) | |
tree | 21abf27f7f18b540f65770d2877c938735b02afe /net/bridge | |
parent | e885439f37b0dce404291350f7c0368c2bb97cdb (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.h | 2 | ||||
-rw-r--r-- | net/bridge/br_sysfs_br.c | 17 | ||||
-rw-r--r-- | net/bridge/br_vlan.c | 29 |
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); | |||
605 | int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); | 606 | int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); |
606 | int br_vlan_set_proto(struct net_bridge *br, unsigned long val); | 607 | int br_vlan_set_proto(struct net_bridge *br, unsigned long val); |
607 | void br_vlan_init(struct net_bridge *br); | 608 | void br_vlan_init(struct net_bridge *br); |
609 | int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val); | ||
608 | int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags); | 610 | int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags); |
609 | int nbp_vlan_delete(struct net_bridge_port *port, u16 vid); | 611 | int nbp_vlan_delete(struct net_bridge_port *port, u16 vid); |
610 | void nbp_vlan_flush(struct net_bridge_port *port); | 612 | void 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 | } |
727 | static DEVICE_ATTR_RW(vlan_protocol); | 727 | static DEVICE_ATTR_RW(vlan_protocol); |
728 | |||
729 | static 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 | |||
737 | static 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 | } | ||
743 | static DEVICE_ATTR_RW(default_pvid); | ||
728 | #endif | 744 | #endif |
729 | 745 | ||
730 | static struct attribute *bridge_attrs[] = { | 746 | static 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 | ||
502 | int 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 | |||
525 | unlock: | ||
526 | rtnl_unlock(); | ||
527 | return err; | ||
528 | } | ||
529 | |||
502 | void br_vlan_init(struct net_bridge *br) | 530 | void 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. |