From 6ff64f6f9242d7e50f3e99cb280f69d1927a5fa6 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Tue, 15 Dec 2015 16:03:35 +0100 Subject: switchdev: Pass original device to port netdev driver switchdev drivers need to know the netdev on which the switchdev op was invoked. For example, the STP state of a VLAN interface configured on top of a port can change while being member in a bridge. In this case, the underlying driver should only change the STP state of that particular VLAN and not of all the VLANs configured on the port. However, current switchdev infrastructure only passes the port netdev down to the driver. Solve that by passing the original device down to the driver as part of the required switchdev object / attribute. This doesn't entail any change in current switchdev drivers. It simply enables those supporting stacked devices to know the originating device and act accordingly. Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/bridge/br_vlan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net/bridge/br_vlan.c') diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 1394da6..66c4549 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -73,6 +73,7 @@ static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br, u16 vid, u16 flags) { struct switchdev_obj_port_vlan v = { + .obj.orig_dev = dev, .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, .flags = flags, .vid_begin = vid, @@ -120,6 +121,7 @@ static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br, u16 vid) { struct switchdev_obj_port_vlan v = { + .obj.orig_dev = dev, .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, .vid_begin = vid, .vid_end = vid, -- cgit v1.1 From 6b72a770202a0ad843312436dd50ed4690d7cc65 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Wed, 6 Jan 2016 13:01:06 +0100 Subject: bridge: add vlan filtering change notification Notifying hardware about bridge vlan-aware changes. Signed-off-by: Elad Raz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/bridge/br_vlan.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'net/bridge/br_vlan.c') diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 66c4549..190fb33 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -626,9 +626,21 @@ void br_recalculate_fwd_mask(struct net_bridge *br) int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) { + struct switchdev_attr attr = { + .orig_dev = br->dev, + .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, + .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, + .u.vlan_filtering = val, + }; + int err; + if (br->vlan_enabled == val) return 0; + err = switchdev_port_attr_set(br->dev, &attr); + if (err && err != -EOPNOTSUPP) + return err; + br->vlan_enabled = val; br_manage_promisc(br); recalculate_group_addr(br); @@ -639,13 +651,15 @@ int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) { + int err; + if (!rtnl_trylock()) return restart_syscall(); - __br_vlan_filter_toggle(br, val); + err = __br_vlan_filter_toggle(br, val); rtnl_unlock(); - return 0; + return err; } int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) -- cgit v1.1 From 404cdbf0894a0707dd19179d2e21a3ab37f33f54 Mon Sep 17 00:00:00 2001 From: Elad Raz Date: Wed, 6 Jan 2016 13:01:07 +0100 Subject: bridge: add vlan filtering change for new bridged device Notifying hardware about newly bridged port vlan-aware changes. Signed-off-by: Elad Raz Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/bridge/br_vlan.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'net/bridge/br_vlan.c') diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 190fb33..85e43af 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -907,6 +907,12 @@ err_rhtbl: int nbp_vlan_init(struct net_bridge_port *p) { + struct switchdev_attr attr = { + .orig_dev = p->br->dev, + .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, + .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, + .u.vlan_filtering = p->br->vlan_enabled, + }; struct net_bridge_vlan_group *vg; int ret = -ENOMEM; @@ -914,6 +920,10 @@ int nbp_vlan_init(struct net_bridge_port *p) if (!vg) goto out; + ret = switchdev_port_attr_set(p->dev, &attr); + if (ret && ret != -EOPNOTSUPP) + goto err_vlan_enabled; + ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params); if (ret) goto err_rhtbl; @@ -933,6 +943,7 @@ err_vlan_add: RCU_INIT_POINTER(p->vlgrp, NULL); synchronize_rcu(); rhashtable_destroy(&vg->vlan_hash); +err_vlan_enabled: err_rhtbl: kfree(vg); -- cgit v1.1