diff options
author | Vladimir Oltean <vladimir.oltean@nxp.com> | 2022-02-15 18:02:12 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-02-16 12:21:04 +0100 |
commit | 8d23a54f5beea59b560855fb571e5d73d783e0b4 (patch) | |
tree | 146a1590d46062778c5dd7d2d4acc78916afd2bb | |
parent | net: bridge: vlan: notify switchdev only when something changed (diff) | |
download | linux-8d23a54f5beea59b560855fb571e5d73d783e0b4.tar.xz linux-8d23a54f5beea59b560855fb571e5d73d783e0b4.zip |
net: bridge: switchdev: differentiate new VLANs from changed ones
br_switchdev_port_vlan_add() currently emits a SWITCHDEV_PORT_OBJ_ADD
event with a SWITCHDEV_OBJ_ID_PORT_VLAN for 2 distinct cases:
- a struct net_bridge_vlan got created
- an existing struct net_bridge_vlan was modified
This makes it impossible for switchdev drivers to properly balance
PORT_OBJ_ADD with PORT_OBJ_DEL events, so if we want to allow that to
happen, we must provide a way for drivers to distinguish between a
VLAN with changed flags and a new one.
Annotate struct switchdev_obj_port_vlan with a "bool changed" that
distinguishes the 2 cases above.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/switchdev.h | 7 | ||||
-rw-r--r-- | net/bridge/br_private.h | 6 | ||||
-rw-r--r-- | net/bridge/br_switchdev.c | 3 | ||||
-rw-r--r-- | net/bridge/br_vlan.c | 10 |
4 files changed, 17 insertions, 9 deletions
diff --git a/include/net/switchdev.h b/include/net/switchdev.h index d353793dfeb5..92cc763991e9 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -81,6 +81,13 @@ struct switchdev_obj_port_vlan { struct switchdev_obj obj; u16 flags; u16 vid; + /* If set, the notifier signifies a change of one of the following + * flags for a VLAN that already exists: + * - BRIDGE_VLAN_INFO_PVID + * - BRIDGE_VLAN_INFO_UNTAGGED + * Entries with BRIDGE_VLAN_INFO_BRENTRY unset are not notified at all. + */ + bool changed; }; #define SWITCHDEV_OBJ_PORT_VLAN(OBJ) \ diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 2661dda1a92b..48bc61ebc211 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1985,7 +1985,7 @@ void br_switchdev_mdb_notify(struct net_device *dev, struct net_bridge_port_group *pg, int type); int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, - struct netlink_ext_ack *extack); + bool changed, struct netlink_ext_ack *extack); int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid); void br_switchdev_init(struct net_bridge *br); @@ -2052,8 +2052,8 @@ static inline int br_switchdev_set_port_flag(struct net_bridge_port *p, return 0; } -static inline int br_switchdev_port_vlan_add(struct net_device *dev, - u16 vid, u16 flags, +static inline int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, + u16 flags, bool changed, struct netlink_ext_ack *extack) { return -EOPNOTSUPP; diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c index f8fbaaa7c501..fb5115387d82 100644 --- a/net/bridge/br_switchdev.c +++ b/net/bridge/br_switchdev.c @@ -160,13 +160,14 @@ br_switchdev_fdb_notify(struct net_bridge *br, } int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, - struct netlink_ext_ack *extack) + bool changed, struct netlink_ext_ack *extack) { struct switchdev_obj_port_vlan v = { .obj.orig_dev = dev, .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, .flags = flags, .vid = vid, + .changed = changed, }; return switchdev_port_obj_add(dev, &v.obj, extack); diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 0ad55a1add0e..7557e90b60e1 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -109,7 +109,7 @@ static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br, /* Try switchdev op first. In case it is not supported, fallback to * 8021q add. */ - err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack); + err = br_switchdev_port_vlan_add(dev, v->vid, flags, false, extack); if (err == -EOPNOTSUPP) return vlan_vid_add(dev, br->vlan_proto, v->vid); v->priv_flags |= BR_VLFLAG_ADDED_BY_SWITCHDEV; @@ -303,7 +303,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags, } else { if (br_vlan_should_use(v)) { err = br_switchdev_port_vlan_add(dev, v->vid, flags, - extack); + false, extack); if (err && err != -EOPNOTSUPP) goto out; } @@ -714,7 +714,7 @@ static int br_vlan_add_existing(struct net_bridge *br, */ if (becomes_brentry || would_change) { err = br_switchdev_port_vlan_add(br->dev, vlan->vid, flags, - extack); + would_change, extack); if (err && err != -EOPNOTSUPP) return err; } @@ -1289,8 +1289,8 @@ int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags, if (would_change) { /* Pass the flags to the hardware bridge */ - ret = br_switchdev_port_vlan_add(port->dev, vid, - flags, extack); + ret = br_switchdev_port_vlan_add(port->dev, vid, flags, + true, extack); if (ret && ret != -EOPNOTSUPP) return ret; } |