Skip to content

Commit

Permalink
net: bridge: add helper for retrieving the current bridge port STP state
Browse files Browse the repository at this point in the history
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>
Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Vladimir Oltean authored and David S. Miller committed Mar 23, 2021
1 parent 65d2dbb commit c0e715b
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 0 deletions.
6 changes: 6 additions & 0 deletions include/linux/if_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
14 changes: 14 additions & 0 deletions net/bridge/br_stp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down

0 comments on commit c0e715b

Please sign in to comment.