Message ID | 20210318231829.3892920-5-olteanv@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Better support for sandwiched LAGs with bridge and DSA | expand |
On 3/18/2021 4:18 PM, Vladimir Oltean wrote: > From: Vladimir Oltean <vladimir.oltean@nxp.com> > > It may happen that we have the following topology: > > ip link add br0 type bridge stp_state 1 > ip link add bond0 type bond > ip link set bond0 master br0 > ip link set swp0 master bond0 > ip link set swp1 master bond0 > > STP decides that it should put bond0 into the BLOCKING state, and > that's that. The ports that are actively listening for the switchdev > port attributes emitted for the bond0 bridge port (because they are > offloading it) and have the honor of seeing that switchdev port > attribute can react to it, so we can program swp0 and swp1 into the > BLOCKING state. > > But if then we do: > > ip link set swp2 master bond0 > > then as far as the bridge is concerned, nothing has changed: it still > has one bridge port. But this new bridge port will not see any STP state > change notification and will remain FORWARDING, which is how the > standalone code leaves it in. > > Add a function to the bridge which retrieves the current STP state, such > that drivers can synchronize to it when they may have missed switchdev > events. > > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
On Fri, Mar 19, 2021 at 01:18, Vladimir Oltean <olteanv@gmail.com> wrote: > From: Vladimir Oltean <vladimir.oltean@nxp.com> > > It may happen that we have the following topology: > > ip link add br0 type bridge stp_state 1 > ip link add bond0 type bond > ip link set bond0 master br0 > ip link set swp0 master bond0 > ip link set swp1 master bond0 > > STP decides that it should put bond0 into the BLOCKING state, and > that's that. The ports that are actively listening for the switchdev > port attributes emitted for the bond0 bridge port (because they are > offloading it) and have the honor of seeing that switchdev port > attribute can react to it, so we can program swp0 and swp1 into the > BLOCKING state. > > But if then we do: > > ip link set swp2 master bond0 > > then as far as the bridge is concerned, nothing has changed: it still > has one bridge port. But this new bridge port will not see any STP state > change notification and will remain FORWARDING, which is how the > standalone code leaves it in. > > Add a function to the bridge which retrieves the current STP state, such > that drivers can synchronize to it when they may have missed switchdev > events. > > Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> > --- Reviewed-by: Tobias Waldekranz <tobias@waldekranz.com>
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index b979005ea39c..920d3a02cc68 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -136,6 +136,7 @@ struct net_device *br_fdb_find_port(const struct net_device *br_dev, __u16 vid); void br_fdb_clear_offload(const struct net_device *dev, u16 vid); bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag); +u8 br_port_get_stp_state(const struct net_device *dev); #else static inline struct net_device * br_fdb_find_port(const struct net_device *br_dev, @@ -154,6 +155,11 @@ br_port_flag_is_set(const struct net_device *dev, unsigned long flag) { return false; } + +static inline u8 br_port_get_stp_state(const struct net_device *dev) +{ + return BR_STATE_DISABLED; +} #endif #endif diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 21c6781906aa..86b5e05d3f21 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -64,6 +64,20 @@ void br_set_state(struct net_bridge_port *p, unsigned int state) } } +u8 br_port_get_stp_state(const struct net_device *dev) +{ + struct net_bridge_port *p; + + ASSERT_RTNL(); + + p = br_port_get_rtnl(dev); + if (!p) + return BR_STATE_DISABLED; + + return p->state; +} +EXPORT_SYMBOL_GPL(br_port_get_stp_state); + /* called under bridge lock */ struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no) { diff --git a/net/dsa/port.c b/net/dsa/port.c index 346c50467810..785374744462 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -171,12 +171,19 @@ static int dsa_port_inherit_brport_flags(struct dsa_port *dp, static int dsa_port_switchdev_sync(struct dsa_port *dp, struct netlink_ext_ack *extack) { + struct net_device *brport_dev = dsa_port_to_bridge_port(dp); + u8 stp_state; int err; err = dsa_port_inherit_brport_flags(dp, extack); if (err) return err; + stp_state = br_port_get_stp_state(brport_dev); + err = dsa_port_set_state(dp, stp_state); + if (err && err != -EOPNOTSUPP) + return err; + return 0; }