From 22ec19f3aee327806c37c9fa1188741574bc6445 Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Sun, 29 Nov 2020 14:54:05 +0200 Subject: [PATCH] bridge: switchdev: Notify about VLAN protocol changes Drivers that support bridge offload need to be notified about changes to the bridge's VLAN protocol so that they could react accordingly and potentially veto the change. Add a new switchdev attribute to communicate the change to drivers. Signed-off-by: Danielle Ratson Reviewed-by: Petr Machata Acked-by: Nikolay Aleksandrov Signed-off-by: Ido Schimmel Reviewed-by: Ivan Vecera Signed-off-by: Jakub Kicinski --- include/net/switchdev.h | 2 ++ net/bridge/br_vlan.c | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 53e8b4994296..99cd538d6519 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -38,6 +38,7 @@ enum switchdev_attr_id { SWITCHDEV_ATTR_ID_PORT_MROUTER, SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, + SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL, SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED, SWITCHDEV_ATTR_ID_BRIDGE_MROUTER, #if IS_ENABLED(CONFIG_BRIDGE_MRP) @@ -58,6 +59,7 @@ struct switchdev_attr { bool mrouter; /* PORT_MROUTER */ clock_t ageing_time; /* BRIDGE_AGEING_TIME */ bool vlan_filtering; /* BRIDGE_VLAN_FILTERING */ + u16 vlan_protocol; /* BRIDGE_VLAN_PROTOCOL */ bool mc_disabled; /* MC_DISABLED */ #if IS_ENABLED(CONFIG_BRIDGE_MRP) u8 mrp_port_state; /* MRP_PORT_STATE */ diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 11f54a7c0d1d..d07008678d32 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -854,15 +854,25 @@ EXPORT_SYMBOL_GPL(br_vlan_get_proto); int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) { + struct switchdev_attr attr = { + .orig_dev = br->dev, + .id = SWITCHDEV_ATTR_ID_BRIDGE_VLAN_PROTOCOL, + .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP, + .u.vlan_protocol = ntohs(proto), + }; int err = 0; struct net_bridge_port *p; struct net_bridge_vlan *vlan; struct net_bridge_vlan_group *vg; - __be16 oldproto; + __be16 oldproto = br->vlan_proto; if (br->vlan_proto == proto) return 0; + err = switchdev_port_attr_set(br->dev, &attr); + if (err && err != -EOPNOTSUPP) + return err; + /* Add VLANs for the new proto to the device filter. */ list_for_each_entry(p, &br->port_list, list) { vg = nbp_vlan_group(p); @@ -873,7 +883,6 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) } } - oldproto = br->vlan_proto; br->vlan_proto = proto; recalculate_group_addr(br); @@ -889,6 +898,9 @@ int __br_vlan_set_proto(struct net_bridge *br, __be16 proto) return 0; err_filt: + attr.u.vlan_protocol = ntohs(oldproto); + switchdev_port_attr_set(br->dev, &attr); + list_for_each_entry_continue_reverse(vlan, &vg->vlan_list, vlist) vlan_vid_del(p->dev, proto, vlan->vid);