aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorNikolay Aleksandrov <nikolay@cumulusnetworks.com>2015-08-07 12:40:45 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-10 16:36:43 -0400
commita7854037da006a7472c48773e3190db55217ec9b (patch)
treee8a4d43fe4dc2d7c0e32f6022d293c9814edf257 /net/bridge
parente72ee3ed51542092d83001be6803468e4b91e7be (diff)
bridge: netlink: add support for vlan_filtering attribute
This patch adds the ability to toggle the vlan filtering support via netlink. Since we're already running with rtnl in .changelink() we don't need to take any additional locks. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_netlink.c14
-rw-r--r--net/bridge/br_private.h7
-rw-r--r--net/bridge/br_vlan.c18
3 files changed, 32 insertions, 7 deletions
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 91a2e08c2bb8..6eb683d8e0c5 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -724,6 +724,7 @@ static const struct nla_policy br_policy[IFLA_BR_MAX + 1] = {
724 [IFLA_BR_AGEING_TIME] = { .type = NLA_U32 }, 724 [IFLA_BR_AGEING_TIME] = { .type = NLA_U32 },
725 [IFLA_BR_STP_STATE] = { .type = NLA_U32 }, 725 [IFLA_BR_STP_STATE] = { .type = NLA_U32 },
726 [IFLA_BR_PRIORITY] = { .type = NLA_U16 }, 726 [IFLA_BR_PRIORITY] = { .type = NLA_U16 },
727 [IFLA_BR_VLAN_FILTERING] = { .type = NLA_U8 },
727}; 728};
728 729
729static int br_changelink(struct net_device *brdev, struct nlattr *tb[], 730static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
@@ -771,6 +772,14 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
771 br_stp_set_bridge_priority(br, priority); 772 br_stp_set_bridge_priority(br, priority);
772 } 773 }
773 774
775 if (data[IFLA_BR_VLAN_FILTERING]) {
776 u8 vlan_filter = nla_get_u8(data[IFLA_BR_VLAN_FILTERING]);
777
778 err = __br_vlan_filter_toggle(br, vlan_filter);
779 if (err)
780 return err;
781 }
782
774 return 0; 783 return 0;
775} 784}
776 785
@@ -782,6 +791,7 @@ static size_t br_get_size(const struct net_device *brdev)
782 nla_total_size(sizeof(u32)) + /* IFLA_BR_AGEING_TIME */ 791 nla_total_size(sizeof(u32)) + /* IFLA_BR_AGEING_TIME */
783 nla_total_size(sizeof(u32)) + /* IFLA_BR_STP_STATE */ 792 nla_total_size(sizeof(u32)) + /* IFLA_BR_STP_STATE */
784 nla_total_size(sizeof(u16)) + /* IFLA_BR_PRIORITY */ 793 nla_total_size(sizeof(u16)) + /* IFLA_BR_PRIORITY */
794 nla_total_size(sizeof(u8)) + /* IFLA_BR_VLAN_FILTERING */
785 0; 795 0;
786} 796}
787 797
@@ -794,13 +804,15 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev)
794 u32 ageing_time = jiffies_to_clock_t(br->ageing_time); 804 u32 ageing_time = jiffies_to_clock_t(br->ageing_time);
795 u32 stp_enabled = br->stp_enabled; 805 u32 stp_enabled = br->stp_enabled;
796 u16 priority = (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]; 806 u16 priority = (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1];
807 u8 vlan_enabled = br_vlan_enabled(br);
797 808
798 if (nla_put_u32(skb, IFLA_BR_FORWARD_DELAY, forward_delay) || 809 if (nla_put_u32(skb, IFLA_BR_FORWARD_DELAY, forward_delay) ||
799 nla_put_u32(skb, IFLA_BR_HELLO_TIME, hello_time) || 810 nla_put_u32(skb, IFLA_BR_HELLO_TIME, hello_time) ||
800 nla_put_u32(skb, IFLA_BR_MAX_AGE, age_time) || 811 nla_put_u32(skb, IFLA_BR_MAX_AGE, age_time) ||
801 nla_put_u32(skb, IFLA_BR_AGEING_TIME, ageing_time) || 812 nla_put_u32(skb, IFLA_BR_AGEING_TIME, ageing_time) ||
802 nla_put_u32(skb, IFLA_BR_STP_STATE, stp_enabled) || 813 nla_put_u32(skb, IFLA_BR_STP_STATE, stp_enabled) ||
803 nla_put_u16(skb, IFLA_BR_PRIORITY, priority)) 814 nla_put_u16(skb, IFLA_BR_PRIORITY, priority) ||
815 nla_put_u8(skb, IFLA_BR_VLAN_FILTERING, vlan_enabled))
804 return -EMSGSIZE; 816 return -EMSGSIZE;
805 817
806 return 0; 818 return 0;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index e2cb359f9dd3..3d95647039d0 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -614,6 +614,7 @@ int br_vlan_delete(struct net_bridge *br, u16 vid);
614void br_vlan_flush(struct net_bridge *br); 614void br_vlan_flush(struct net_bridge *br);
615bool br_vlan_find(struct net_bridge *br, u16 vid); 615bool br_vlan_find(struct net_bridge *br, u16 vid);
616void br_recalculate_fwd_mask(struct net_bridge *br); 616void br_recalculate_fwd_mask(struct net_bridge *br);
617int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
617int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val); 618int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
618int br_vlan_set_proto(struct net_bridge *br, unsigned long val); 619int br_vlan_set_proto(struct net_bridge *br, unsigned long val);
619int br_vlan_init(struct net_bridge *br); 620int br_vlan_init(struct net_bridge *br);
@@ -771,6 +772,12 @@ static inline int br_vlan_enabled(struct net_bridge *br)
771{ 772{
772 return 0; 773 return 0;
773} 774}
775
776static inline int __br_vlan_filter_toggle(struct net_bridge *br,
777 unsigned long val)
778{
779 return -EOPNOTSUPP;
780}
774#endif 781#endif
775 782
776struct nf_br_ops { 783struct nf_br_ops {
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 0d41f81838ff..3cef6892c0bb 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -468,21 +468,27 @@ void br_recalculate_fwd_mask(struct net_bridge *br)
468 ~(1u << br->group_addr[5]); 468 ~(1u << br->group_addr[5]);
469} 469}
470 470
471int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) 471int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
472{ 472{
473 if (!rtnl_trylock())
474 return restart_syscall();
475
476 if (br->vlan_enabled == val) 473 if (br->vlan_enabled == val)
477 goto unlock; 474 return 0;
478 475
479 br->vlan_enabled = val; 476 br->vlan_enabled = val;
480 br_manage_promisc(br); 477 br_manage_promisc(br);
481 recalculate_group_addr(br); 478 recalculate_group_addr(br);
482 br_recalculate_fwd_mask(br); 479 br_recalculate_fwd_mask(br);
483 480
484unlock: 481 return 0;
482}
483
484int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
485{
486 if (!rtnl_trylock())
487 return restart_syscall();
488
489 __br_vlan_filter_toggle(br, val);
485 rtnl_unlock(); 490 rtnl_unlock();
491
486 return 0; 492 return 0;
487} 493}
488 494