Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Vlad Yasevich and committed by
David S. Miller
96a20d9d e885439f

+48
+2
net/bridge/br_private.h
··· 299 299 #ifdef CONFIG_BRIDGE_VLAN_FILTERING 300 300 u8 vlan_enabled; 301 301 __be16 vlan_proto; 302 + u16 default_pvid; 302 303 struct net_port_vlans __rcu *vlan_info; 303 304 #endif 304 305 }; ··· 606 605 int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); 607 606 int br_vlan_set_proto(struct net_bridge *br, unsigned long val); 608 607 void br_vlan_init(struct net_bridge *br); 608 + int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val); 609 609 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags); 610 610 int nbp_vlan_delete(struct net_bridge_port *port, u16 vid); 611 611 void nbp_vlan_flush(struct net_bridge_port *port);
+17
net/bridge/br_sysfs_br.c
··· 725 725 return store_bridge_parm(d, buf, len, br_vlan_set_proto); 726 726 } 727 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 744 #endif 729 745 730 746 static struct attribute *bridge_attrs[] = { ··· 787 771 #ifdef CONFIG_BRIDGE_VLAN_FILTERING 788 772 &dev_attr_vlan_filtering.attr, 789 773 &dev_attr_vlan_protocol.attr, 774 + &dev_attr_default_pvid.attr, 790 775 #endif 791 776 NULL 792 777 };
+29
net/bridge/br_vlan.c
··· 499 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 530 void br_vlan_init(struct net_bridge *br) 503 531 { 504 532 br->vlan_proto = htons(ETH_P_8021Q); 533 + br->default_pvid = 1; 505 534 } 506 535 507 536 /* Must be protected by RTNL.