Commit 26f0e7fb authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

mlxsw: spectrum: Add support for VLAN devices bridging

All the member VLAN devices in a bridge need to share the same vFID.

To achieve that, expand the vFID struct to include the associated bridge
device (or lack of) and allow one to lookup a vFID based on a bridge
device.

When joining a bridge, lookup the relevant vFID or create one if none
exists. Next, make the VLAN device use the vFID.

Leaving a bridge can either occur because a user removed the VLAN device
from a bridge or because the VLAN device was deleted by the user. In the
latter case the bridge's teardown sequence is invoked after the hardware
vPort is already gone. Therefore, when unlinking the VLAN device from
the real device, check if the associated vPort is bridged and act
accordingly. The bridge's notification will be ignored in this case.

Note that bridging a VLAN interface with an ordinary port netdev is
currently not supported, but not forbidden. This will be addressed in a
follow-up patchset.
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9589a7b5
......@@ -65,6 +65,7 @@ struct mlxsw_sp_vfid {
struct list_head list;
u16 nr_vports;
u16 vfid; /* Starting at 0 */
struct net_device *br_dev;
u16 vid;
};
......@@ -88,6 +89,10 @@ struct mlxsw_sp {
struct list_head list;
unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_VFID_PORT_MAX)];
} port_vfids;
struct {
struct list_head list;
unsigned long mapped[BITS_TO_LONGS(MLXSW_SP_VFID_BR_MAX)];
} br_vfids;
unsigned long active_fids[BITS_TO_LONGS(VLAN_N_VID)];
struct mlxsw_sp_port **ports;
struct mlxsw_core *core;
......@@ -161,6 +166,12 @@ mlxsw_sp_port_is_vport(const struct mlxsw_sp_port *mlxsw_sp_port)
return mlxsw_sp_port->vport.vfid;
}
static inline struct net_device *
mlxsw_sp_vport_br_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
{
return mlxsw_sp_vport->vport.vfid->br_dev;
}
static inline u16
mlxsw_sp_vport_vid_get(const struct mlxsw_sp_port *mlxsw_sp_vport)
{
......
......@@ -151,6 +151,11 @@ static int mlxsw_sp_port_attr_stp_state_set(struct mlxsw_sp_port *mlxsw_sp_port,
return mlxsw_sp_port_stp_state_set(mlxsw_sp_port, state);
}
static bool mlxsw_sp_vfid_is_vport_br(u16 vfid)
{
return vfid >= MLXSW_SP_VFID_PORT_MAX;
}
static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
u16 idx_begin, u16 idx_end, bool set,
bool only_uc)
......@@ -164,6 +169,9 @@ static int __mlxsw_sp_port_flood_set(struct mlxsw_sp_port *mlxsw_sp_port,
if (mlxsw_sp_port_is_vport(mlxsw_sp_port)) {
table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID;
if (mlxsw_sp_vfid_is_vport_br(idx_begin))
local_port = mlxsw_sp_port->local_port;
else
local_port = MLXSW_PORT_CPU_PORT;
} else {
table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFEST;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment