Re: [RFC PATCH v2 net-next 03/16] net: dsa: inherit the actual bridge port flags at join time
From: Florian Fainelli <f.fainelli@gmail.com>
Date: 2021-03-19 22:10:05
Also in:
linux-omap, lkml
On 3/18/2021 4:18 PM, Vladimir Oltean wrote:
quoted hunk ↗ jump to hunk
From: Vladimir Oltean <vladimir.oltean@nxp.com> DSA currently assumes that the bridge port starts off with this constellation of bridge port flags: - learning on - unicast flooding on - multicast flooding on - broadcast flooding on just by virtue of code copy-pasta from the bridge layer (new_nbp). This was a simple enough strategy thus far, because the 'bridge join' moment always coincided with the 'bridge port creation' moment. But with sandwiched interfaces, such as: br0 | bond0 | swp0 it may happen that the user has had time to change the bridge port flags of bond0 before enslaving swp0 to it. In that case, swp0 will falsely assume that the bridge port flags are those determined by new_nbp, when in fact this can happen: ip link add br0 type bridge ip link add bond0 type bond ip link set bond0 master br0 ip link set bond0 type bridge_slave learning off ip link set swp0 master br0 Now swp0 has learning enabled, bond0 has learning disabled. Not nice. Fix this by "dumpster diving" through the actual bridge port flags with br_port_flag_is_set, at bridge join time. We use this opportunity to split dsa_port_change_brport_flags into two distinct functions called dsa_port_inherit_brport_flags and dsa_port_clear_brport_flags, now that the implementation for the two cases is no longer similar. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> --- net/dsa/port.c | 123 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 82 insertions(+), 41 deletions(-)diff --git a/net/dsa/port.c b/net/dsa/port.c index fcbe5b1545b8..346c50467810 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c@@ -122,26 +122,82 @@ void dsa_port_disable(struct dsa_port *dp) rtnl_unlock(); } -static void dsa_port_change_brport_flags(struct dsa_port *dp, - bool bridge_offload) +static void dsa_port_clear_brport_flags(struct dsa_port *dp, + struct netlink_ext_ack *extack) { struct switchdev_brport_flags flags; - int flag; - flags.mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD; - if (bridge_offload) - flags.val = flags.mask; - else - flags.val = flags.mask & ~BR_LEARNING; + flags.mask = BR_LEARNING; + flags.val = 0; + dsa_port_bridge_flags(dp, flags, extack);
Would not you want to use the same for_each_set_bit() loop that dsa_port_change_br_flags() uses, that would be a tad more compact. -- Florian