Commit d521bc0a authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'mlxsw-unified-bridge-conversion-part-4-6'

Ido Schimmel says:

====================
mlxsw: Unified bridge conversion - part 4/6

This is the fourth part of the conversion of mlxsw to the unified bridge
model.

Unlike previous parts that prepared mlxsw for the conversion, this part
actually starts the conversion. It focuses on flooding configuration and
converts mlxsw to the more "raw" APIs of the unified bridge model.

The patches configure the different stages of the flooding pipeline in
Spectrum that looks as follows (at a high-level):

         +------------+                +----------+           +-------+
  {FID,  |            | {Packet type,  |          |           |       |  MID
   DMAC} | FDB lookup |  Bridge type}  |   SFGC   | MID base  |       | Index
+-------->   (miss)   +----------------> register +-----------> Adder +------->
         |            |                |          |           |       |
         |            |                |          |           |       |
         +------------+                +----+-----+           +---^---+
                                            |                     |
                                    Table   |                     |
                                     type   |                     | Offset
                                            |      +-------+      |
                                            |      |       |      |
                                            |      |       |      |
                                            +----->+  Mux  +------+
                                                   |       |
                                                   |       |
                                                   +-^---^-+
                                                     |   |
                                                  FID|   |FID
                                                     |   |offset
                                                     +   +

The multicast identifier (MID) index is used as an index to the port
group table (PGT) that contains a bitmap of ports via which a packet
needs to be replicated.

From the PGT table, the packet continues to the multicast port egress
(MPE) table that determines the packet's egress VLAN. This is a
two-dimensional table that is indexed by port and switch multicast port
to egress (SMPE) index. The latter can be thought of as a FID. Without
it, all the packets replicated via a certain port would get the same
VLAN, regardless of the bridge domain (FID).

Logically, these two steps look as follows:

                     PGT table                           MPE table
             +-----------------------+               +---------------+
             |                       | {Local port,  |               | Egress
  MID index  | Local ports bitmap #1 |  SMPE index}  |               |  VID
+------------>        ...            +--------------->               +-------->
             | Local ports bitmap #N |               |               |
             |                       |          SMPE |               |
             +-----------------------+               +---------------+
                                                        Local port

Patchset overview:

Patch #1 adds a variable to guard against mixed model configuration.
Will be removed in part 6 when mlxsw is fully converted to the unified
model.

Patches #2-#5 introduce two new FID attributes required for flooding
configuration in the new model:

1. 'flood_rsp': Instructs the firmware to handle flooding configuration
for this FID. Only set for router FIDs (rFIDs) which are used to connect
a {Port, VLAN} to the router block.

2. 'bridge_type': Allows the device to determine the flood table (i.e.,
base index to the PGT table) for the FID. The first type will be used
for FIDs in a VLAN-aware bridge and the second for FIDs representing
VLAN-unaware bridges.

Patch #6 configures the MPE table that determines the egress VLAN of a
packet that is forwarded according to L2 multicast / flood.

Patches #7-#11 add the PGT table and related APIs to allocate entries
and set / clear ports in them.

Patches #12-#13 convert the flooding configuration to use the new PGT
APIs.
====================

Link: https://lore.kernel.org/r/20220627070621.648499-1-idosch@nvidia.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 778964f2 fe94df6d
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -28,7 +28,8 @@ mlxsw_spectrum-objs := spectrum.o spectrum_buffers.o \
				   spectrum_qdisc.o spectrum_span.o \
				   spectrum_nve.o spectrum_nve_vxlan.o \
				   spectrum_dpipe.o spectrum_trap.o \
				   spectrum_ethtool.o spectrum_policer.o
				   spectrum_ethtool.o spectrum_policer.o \
				   spectrum_pgt.o
mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB)	+= spectrum_dcb.o
mlxsw_spectrum-$(CONFIG_PTP_1588_CLOCK)		+= spectrum_ptp.o
obj-$(CONFIG_MLXSW_MINIMAL)	+= mlxsw_minimal.o
+11 −6
Original line number Diff line number Diff line
@@ -1054,9 +1054,10 @@ enum mlxsw_reg_sfgc_type {
 */
MLXSW_ITEM32(reg, sfgc, type, 0x00, 0, 4);

enum mlxsw_reg_sfgc_bridge_type {
	MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID = 0,
	MLXSW_REG_SFGC_BRIDGE_TYPE_VFID = 1,
/* bridge_type is used in SFGC and SFMR. */
enum mlxsw_reg_bridge_type {
	MLXSW_REG_BRIDGE_TYPE_0 = 0, /* Used for .1q FIDs. */
	MLXSW_REG_BRIDGE_TYPE_1 = 1, /* Used for .1d FIDs. */
};

/* reg_sfgc_bridge_type
@@ -1111,15 +1112,16 @@ MLXSW_ITEM32(reg, sfgc, mid_base, 0x10, 0, 16);

static inline void
mlxsw_reg_sfgc_pack(char *payload, enum mlxsw_reg_sfgc_type type,
		    enum mlxsw_reg_sfgc_bridge_type bridge_type,
		    enum mlxsw_reg_bridge_type bridge_type,
		    enum mlxsw_flood_table_type table_type,
		    unsigned int flood_table)
		    unsigned int flood_table, u16 mid_base)
{
	MLXSW_REG_ZERO(sfgc, payload);
	mlxsw_reg_sfgc_type_set(payload, type);
	mlxsw_reg_sfgc_bridge_type_set(payload, bridge_type);
	mlxsw_reg_sfgc_table_type_set(payload, table_type);
	mlxsw_reg_sfgc_flood_table_set(payload, flood_table);
	mlxsw_reg_sfgc_mid_base_set(payload, mid_base);
}

/* SFDF - Switch Filtering DB Flush
@@ -1960,7 +1962,8 @@ MLXSW_ITEM32(reg, sfmr, smpe, 0x28, 0, 16);

static inline void mlxsw_reg_sfmr_pack(char *payload,
				       enum mlxsw_reg_sfmr_op op, u16 fid,
				       u16 fid_offset)
				       u16 fid_offset, bool flood_rsp,
				       enum mlxsw_reg_bridge_type bridge_type)
{
	MLXSW_REG_ZERO(sfmr, payload);
	mlxsw_reg_sfmr_op_set(payload, op);
@@ -1968,6 +1971,8 @@ static inline void mlxsw_reg_sfmr_pack(char *payload,
	mlxsw_reg_sfmr_fid_offset_set(payload, fid_offset);
	mlxsw_reg_sfmr_vtfp_set(payload, false);
	mlxsw_reg_sfmr_vv_set(payload, false);
	mlxsw_reg_sfmr_flood_rsp_set(payload, flood_rsp);
	mlxsw_reg_sfmr_flood_bridge_type_set(payload, bridge_type);
}

/* SPVMLR - Switch Port VLAN MAC Learning Register
+2 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ enum mlxsw_res_id {
	MLXSW_RES_ID_KVD_SIZE,
	MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE,
	MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE,
	MLXSW_RES_ID_PGT_SIZE,
	MLXSW_RES_ID_MAX_KVD_LINEAR_RANGE,
	MLXSW_RES_ID_MAX_KVD_ACTION_SETS,
	MLXSW_RES_ID_MAX_TRAP_GROUPS,
@@ -69,6 +70,7 @@ static u16 mlxsw_res_ids[] = {
	[MLXSW_RES_ID_KVD_SIZE] = 0x1001,
	[MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE] = 0x1002,
	[MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE] = 0x1003,
	[MLXSW_RES_ID_PGT_SIZE] = 0x1004,
	[MLXSW_RES_ID_MAX_KVD_LINEAR_RANGE] = 0x1005,
	[MLXSW_RES_ID_MAX_KVD_ACTION_SETS] = 0x1007,
	[MLXSW_RES_ID_MAX_TRAP_GROUPS] = 0x2201,
+14 −0
Original line number Diff line number Diff line
@@ -3010,6 +3010,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
		return err;
	}

	err = mlxsw_sp_pgt_init(mlxsw_sp);
	if (err) {
		dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize PGT\n");
		goto err_pgt_init;
	}

	err = mlxsw_sp_fids_init(mlxsw_sp);
	if (err) {
		dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize FIDs\n");
@@ -3155,6 +3161,7 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
		goto err_ports_create;
	}

	mlxsw_sp->ubridge = false;
	return 0;

err_ports_create:
@@ -3201,6 +3208,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
err_policers_init:
	mlxsw_sp_fids_fini(mlxsw_sp);
err_fids_init:
	mlxsw_sp_pgt_fini(mlxsw_sp);
err_pgt_init:
	mlxsw_sp_kvdl_fini(mlxsw_sp);
	mlxsw_sp_parsing_fini(mlxsw_sp);
	return err;
@@ -3234,6 +3243,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
	mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener);
	mlxsw_sp->fid_family_arr = mlxsw_sp1_fid_family_arr;
	mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP1;
	mlxsw_sp->pgt_smpe_index_valid = true;

	return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
}
@@ -3267,6 +3277,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
	mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener);
	mlxsw_sp->fid_family_arr = mlxsw_sp2_fid_family_arr;
	mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2;
	mlxsw_sp->pgt_smpe_index_valid = false;

	return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
}
@@ -3300,6 +3311,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
	mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener);
	mlxsw_sp->fid_family_arr = mlxsw_sp2_fid_family_arr;
	mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3;
	mlxsw_sp->pgt_smpe_index_valid = false;

	return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
}
@@ -3333,6 +3345,7 @@ static int mlxsw_sp4_init(struct mlxsw_core *mlxsw_core,
	mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener);
	mlxsw_sp->fid_family_arr = mlxsw_sp2_fid_family_arr;
	mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP4;
	mlxsw_sp->pgt_smpe_index_valid = false;

	return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
}
@@ -3365,6 +3378,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
	mlxsw_sp_traps_fini(mlxsw_sp);
	mlxsw_sp_policers_fini(mlxsw_sp);
	mlxsw_sp_fids_fini(mlxsw_sp);
	mlxsw_sp_pgt_fini(mlxsw_sp);
	mlxsw_sp_kvdl_fini(mlxsw_sp);
	mlxsw_sp_parsing_fini(mlxsw_sp);
}
+41 −0
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ struct mlxsw_sp_ptp_ops;
struct mlxsw_sp_span_ops;
struct mlxsw_sp_qdisc_state;
struct mlxsw_sp_mall_entry;
struct mlxsw_sp_pgt;

struct mlxsw_sp_port_mapping {
	u8 module;
@@ -216,6 +217,9 @@ struct mlxsw_sp {
	u32 lowest_shaper_bs;
	struct rhashtable ipv6_addr_ht;
	struct mutex ipv6_addr_ht_lock; /* Protects ipv6_addr_ht */
	bool ubridge;
	struct mlxsw_sp_pgt *pgt;
	bool pgt_smpe_index_valid;
};

struct mlxsw_sp_ptp_ops {
@@ -391,6 +395,31 @@ struct mlxsw_sp_port_type_speed_ops {
	u32 (*ptys_proto_cap_masked_get)(u32 eth_proto_cap);
};

struct mlxsw_sp_ports_bitmap {
	unsigned long *bitmap;
	unsigned int nbits;
};

static inline int
mlxsw_sp_port_bitmap_init(struct mlxsw_sp *mlxsw_sp,
			  struct mlxsw_sp_ports_bitmap *ports_bm)
{
	unsigned int nbits = mlxsw_core_max_ports(mlxsw_sp->core);

	ports_bm->nbits = nbits;
	ports_bm->bitmap = bitmap_zalloc(nbits, GFP_KERNEL);
	if (!ports_bm->bitmap)
		return -ENOMEM;

	return 0;
}

static inline void
mlxsw_sp_port_bitmap_fini(struct mlxsw_sp_ports_bitmap *ports_bm)
{
	bitmap_free(ports_bm->bitmap);
}

static inline u8 mlxsw_sp_tunnel_ecn_decap(u8 outer_ecn, u8 inner_ecn,
					   bool *trap_en)
{
@@ -1447,4 +1476,16 @@ int mlxsw_sp_policers_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_policers_fini(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_policer_resources_register(struct mlxsw_core *mlxsw_core);

/* spectrum_pgt.c */
int mlxsw_sp_pgt_mid_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_mid);
void mlxsw_sp_pgt_mid_free(struct mlxsw_sp *mlxsw_sp, u16 mid_base);
int mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base,
				 u16 count);
void mlxsw_sp_pgt_mid_free_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base,
				 u16 count);
int mlxsw_sp_pgt_entry_port_set(struct mlxsw_sp *mlxsw_sp, u16 mid,
				u16 smpe, u16 local_port, bool member);
int mlxsw_sp_pgt_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_pgt_fini(struct mlxsw_sp *mlxsw_sp);

#endif
Loading