Message ID | 20210322235152.268695-2-olteanv@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Better support for sandwiched LAGs with bridge and DSA | expand |
On 23/03/2021 01:51, Vladimir Oltean wrote: > From: Vladimir Oltean <vladimir.oltean@nxp.com> > > It may happen that we have the following topology with DSA or any other > switchdev driver with LAG offload: > > 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. > > We need a function in the bridge driver 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> > Reviewed-by: Tobias Waldekranz <tobias@waldekranz.com> > --- > include/linux/if_bridge.h | 6 ++++++ > net/bridge/br_stp.c | 14 ++++++++++++++ > 2 files changed, 20 insertions(+) > Acked-by: Nikolay Aleksandrov <nikolay@nvidia.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) {