Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bb5355b2 authored by Nogah Frankel's avatar Nogah Frankel Committed by David S. Miller
Browse files

mlxsw: spectrum_switchdev: Flush the mdb when a port is being removed



When a port is being removed from a bridge, flush the bridge mdb to remove
the mids of that port.

Signed-off-by: default avatarNogah Frankel <nogahf@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9dad51bd
Loading
Loading
Loading
Loading
+29 −10
Original line number Diff line number Diff line
@@ -121,6 +121,10 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
			       struct mlxsw_sp_bridge_port *bridge_port,
			       u16 fid_index);

static void
mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
			       struct mlxsw_sp_bridge_port *bridge_port);

static void
mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp_port *mlxsw_sp_port,
				   struct mlxsw_sp_bridge_device
@@ -176,17 +180,11 @@ static void
mlxsw_sp_bridge_device_destroy(struct mlxsw_sp_bridge *bridge,
			       struct mlxsw_sp_bridge_device *bridge_device)
{
	struct mlxsw_sp_mid *mid, *tmp;

	list_del(&bridge_device->list);
	if (bridge_device->vlan_enabled)
		bridge->vlan_enabled_exists = false;
	WARN_ON(!list_empty(&bridge_device->ports_list));
	list_for_each_entry_safe(mid, tmp, &bridge_device->mids_list, list) {
		list_del(&mid->list);
		clear_bit(mid->mid, bridge->mids_bitmap);
		kfree(mid);
	}
	WARN_ON(!list_empty(&bridge_device->mids_list));
	kfree(bridge_device);
}

@@ -987,24 +985,28 @@ mlxsw_sp_port_vlan_bridge_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
	struct mlxsw_sp_bridge_vlan *bridge_vlan;
	struct mlxsw_sp_bridge_port *bridge_port;
	u16 vid = mlxsw_sp_port_vlan->vid;
	bool last;
	bool last_port, last_vlan;

	if (WARN_ON(mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_8021Q &&
		    mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_8021D))
		return;

	bridge_port = mlxsw_sp_port_vlan->bridge_port;
	last_vlan = list_is_singular(&bridge_port->vlans_list);
	bridge_vlan = mlxsw_sp_bridge_vlan_find(bridge_port, vid);
	last = list_is_singular(&bridge_vlan->port_vlan_list);
	last_port = list_is_singular(&bridge_vlan->port_vlan_list);

	list_del(&mlxsw_sp_port_vlan->bridge_vlan_node);
	mlxsw_sp_bridge_vlan_put(bridge_vlan);
	mlxsw_sp_port_vid_stp_set(mlxsw_sp_port, vid, BR_STATE_DISABLED);
	mlxsw_sp_port_vid_learning_set(mlxsw_sp_port, vid, false);
	if (last)
	if (last_port)
		mlxsw_sp_bridge_port_fdb_flush(mlxsw_sp_port->mlxsw_sp,
					       bridge_port,
					       mlxsw_sp_fid_index(fid));
	if (last_vlan)
		mlxsw_sp_bridge_port_mdb_flush(mlxsw_sp_port, bridge_port);

	mlxsw_sp_port_vlan_fid_leave(mlxsw_sp_port_vlan);

	mlxsw_sp_bridge_port_put(mlxsw_sp_port->mlxsw_sp->bridge, bridge_port);
@@ -1580,6 +1582,23 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
	return __mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port, mid);
}

static void
mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
			       struct mlxsw_sp_bridge_port *bridge_port)
{
	struct mlxsw_sp_bridge_device *bridge_device;
	struct mlxsw_sp_mid *mid, *tmp;

	bridge_device = bridge_port->bridge_device;

	list_for_each_entry_safe(mid, tmp, &bridge_device->mids_list, list) {
		if (test_bit(mlxsw_sp_port->local_port, mid->ports_in_mid)) {
			__mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port,
						mid);
		}
	}
}

static int mlxsw_sp_port_obj_del(struct net_device *dev,
				 const struct switchdev_obj *obj)
{