mlxsw: Add support for egress FID classification after decapsulation
authorAmit Cohen <amcohen@nvidia.com>
Sun, 19 Jun 2022 10:29:20 +0000 (13:29 +0300)
committerDavid S. Miller <davem@davemloft.net>
Mon, 20 Jun 2022 09:03:33 +0000 (10:03 +0100)
As preparation for unified bridge model, add support for VNI->FID mapping
via SVFA register.

When performing VXLAN encapsulation, the VXLAN header needs to contain a
VNI. This VNI is derived from the FID classification performed on
ingress, through which the ingress RIF is also determined.

Similarly, when performing VXLAN decapsulation, the FID of the packet
needs to be determined. This FID is derived from VNI classification
performed during decapsulation.

In the old model, both entries (i.e., FID->VNI and VNI->FID) were
configured via SFMR.vni.

In the new model, where ingress is separated from egress, ingress
configuration (VNI->FID) is performed via SVFA, while SFMR only
configures egress (FID->VNI).

Add 'vni' field to SVFA, add new mapping table - VNI to FID, add new
pack() function for VNI mapping and edit the comment in SFMR.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Danielle Ratson <danieller@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c

index 9992b64..33d460a 100644 (file)
@@ -1573,6 +1573,7 @@ MLXSW_ITEM32_LP(reg, svfa, 0x00, 16, 0x00, 12);
 enum mlxsw_reg_svfa_mt {
        MLXSW_REG_SVFA_MT_VID_TO_FID,
        MLXSW_REG_SVFA_MT_PORT_VID_TO_FID,
+       MLXSW_REG_SVFA_MT_VNI_TO_FID,
 };
 
 /* reg_svfa_mapping_table
@@ -1622,6 +1623,14 @@ MLXSW_ITEM32(reg, svfa, counter_set_type, 0x08, 24, 8);
  */
 MLXSW_ITEM32(reg, svfa, counter_index, 0x08, 0, 24);
 
+/* reg_svfa_vni
+ * Virtual Network Identifier.
+ * Access: Index
+ *
+ * Note: Reserved when mapping_table is not 2 (VNI mapping table).
+ */
+MLXSW_ITEM32(reg, svfa, vni, 0x10, 0, 24);
+
 /* reg_svfa_irif_v
  * Ingress RIF valid.
  * 0 - Ingress RIF is not valid, no ingress RIF assigned.
@@ -1642,20 +1651,45 @@ MLXSW_ITEM32(reg, svfa, irif_v, 0x14, 24, 1);
  */
 MLXSW_ITEM32(reg, svfa, irif, 0x14, 0, 16);
 
-static inline void mlxsw_reg_svfa_pack(char *payload, u16 local_port,
-                                      enum mlxsw_reg_svfa_mt mt, bool valid,
-                                      u16 fid, u16 vid)
+static inline void __mlxsw_reg_svfa_pack(char *payload,
+                                        enum mlxsw_reg_svfa_mt mt, bool valid,
+                                        u16 fid)
 {
        MLXSW_REG_ZERO(svfa, payload);
-       local_port = mt == MLXSW_REG_SVFA_MT_VID_TO_FID ? 0 : local_port;
        mlxsw_reg_svfa_swid_set(payload, 0);
-       mlxsw_reg_svfa_local_port_set(payload, local_port);
        mlxsw_reg_svfa_mapping_table_set(payload, mt);
        mlxsw_reg_svfa_v_set(payload, valid);
        mlxsw_reg_svfa_fid_set(payload, fid);
+}
+
+static inline void mlxsw_reg_svfa_port_vid_pack(char *payload, u16 local_port,
+                                               bool valid, u16 fid, u16 vid)
+{
+       enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
+
+       __mlxsw_reg_svfa_pack(payload, mt, valid, fid);
+       mlxsw_reg_svfa_local_port_set(payload, local_port);
        mlxsw_reg_svfa_vid_set(payload, vid);
 }
 
+static inline void mlxsw_reg_svfa_vid_pack(char *payload, bool valid, u16 fid,
+                                          u16 vid)
+{
+       enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VID_TO_FID;
+
+       __mlxsw_reg_svfa_pack(payload, mt, valid, fid);
+       mlxsw_reg_svfa_vid_set(payload, vid);
+}
+
+static inline void mlxsw_reg_svfa_vni_pack(char *payload, bool valid, u16 fid,
+                                          u32 vni)
+{
+       enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VNI_TO_FID;
+
+       __mlxsw_reg_svfa_pack(payload, mt, valid, fid);
+       mlxsw_reg_svfa_vni_set(payload, vni);
+}
+
 /*  SPVTR - Switch Port VLAN Stacking Register
  *  ------------------------------------------
  *  The Switch Port VLAN Stacking register configures the VLAN mode of the port
@@ -1878,9 +1912,10 @@ MLXSW_ITEM32(reg, sfmr, vv, 0x10, 31, 1);
 
 /* reg_sfmr_vni
  * Virtual Network Identifier.
+ * When legacy bridge model is used, a given VNI can only be assigned to one
+ * FID. When unified bridge model is used, it configures only the FID->VNI,
+ * the VNI->FID is done by SVFA.
  * Access: RW
- *
- * Note: A given VNI can only be assigned to one FID.
  */
 MLXSW_ITEM32(reg, sfmr, vni, 0x10, 0, 24);
 
index ce80931..86b88e6 100644 (file)
@@ -441,10 +441,10 @@ static int mlxsw_sp_fid_vni_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
 static int __mlxsw_sp_fid_port_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index,
                                       u16 local_port, u16 vid, bool valid)
 {
-       enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_PORT_VID_TO_FID;
        char svfa_pl[MLXSW_REG_SVFA_LEN];
 
-       mlxsw_reg_svfa_pack(svfa_pl, local_port, mt, valid, fid_index, vid);
+       mlxsw_reg_svfa_port_vid_pack(svfa_pl, local_port, valid, fid_index,
+                                    vid);
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl);
 }