mlxsw: spectrum_ptp: Increase parsing depth when PTP is enabled
authorPetr Machata <petrm@mellanox.com>
Mon, 29 Jul 2019 18:26:14 +0000 (18:26 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 29 Jul 2019 20:55:05 +0000 (13:55 -0700)
Spectrum systems have a configurable limit on how far into the packet they
parse. By default, the limit is 96 bytes.

An IPv6 PTP packet is layered as Ethernet/IPv6/UDP (14+40+8 bytes), and
sequence ID of a PTP event is only available 32 bytes into payload, for a
total of 94 bytes. When an additional 802.1q header is present as
well (such as when ptp4l is running on a VLAN port), the parsing limit is
exceeded. Such packets are not recognized as PTP, and are not timestamped.

Therefore generalize the current VXLAN-specific parsing depth setting to
allow reference-counted requests from other modules as well. Keep it in the
VXLAN module, because the MPRS register also configures UDP destination
port number used for VXLAN, and is thus closely tied to the VXLAN code
anyway.

Then invoke the new interfaces from both VXLAN (in obvious places), as well
as from PTP code, when the (global) timestamping configuration changes from
disabled to enabled or vice versa.

Fixes: 8748642751ed ("mlxsw: spectrum: PTP: Support SIOCGHWTSTAMP, SIOCSHWTSTAMP ioctls")
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c

index 131f62ce9297a05e0ba5406995beb1a16c14bdfa..6664119fb0c8cfc39ffd24c8963657de2e47c98b 100644 (file)
@@ -951,4 +951,8 @@ void mlxsw_sp_port_nve_fini(struct mlxsw_sp_port *mlxsw_sp_port);
 int mlxsw_sp_nve_init(struct mlxsw_sp *mlxsw_sp);
 void mlxsw_sp_nve_fini(struct mlxsw_sp *mlxsw_sp);
 
+/* spectrum_nve_vxlan.c */
+int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp);
+void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp);
+
 #endif
index 1df164a4b06d3516b45dd034b8dbd71cb7988ab1..17f334b46c4056c6689d41d8288d3812a263a406 100644 (file)
@@ -775,6 +775,7 @@ static void mlxsw_sp_nve_tunnel_fini(struct mlxsw_sp *mlxsw_sp)
                ops->fini(nve);
                mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ADJ, 1,
                                   nve->tunnel_index);
+               memset(&nve->config, 0, sizeof(nve->config));
        }
        nve->num_nve_tunnels--;
 }
index 0035640156a16ebbee0391f8c105b4bbd455dfb0..12f664f42f2108abfc85b381959905713d8971cf 100644 (file)
@@ -29,6 +29,7 @@ struct mlxsw_sp_nve {
        unsigned int num_max_mc_entries[MLXSW_SP_L3_PROTO_MAX];
        u32 tunnel_index;
        u16 ul_rif_index;       /* Reserved for Spectrum */
+       unsigned int inc_parsing_depth_refs;
 };
 
 struct mlxsw_sp_nve_ops {
index 93ccd9fc22662d78ea91f12de0d9a2ea01ab4d30..05517c7feaa563fe0b8d1a365ce26980ea93b4a4 100644 (file)
@@ -103,9 +103,9 @@ static void mlxsw_sp_nve_vxlan_config(const struct mlxsw_sp_nve *nve,
        config->udp_dport = cfg->dst_port;
 }
 
-static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
-                                   unsigned int parsing_depth,
-                                   __be16 udp_dport)
+static int __mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
+                                     unsigned int parsing_depth,
+                                     __be16 udp_dport)
 {
        char mprs_pl[MLXSW_REG_MPRS_LEN];
 
@@ -113,6 +113,56 @@ static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
 }
 
+static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
+                                   __be16 udp_dport)
+{
+       int parsing_depth = mlxsw_sp->nve->inc_parsing_depth_refs ?
+                               MLXSW_SP_NVE_VXLAN_PARSING_DEPTH :
+                               MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH;
+
+       return __mlxsw_sp_nve_parsing_set(mlxsw_sp, parsing_depth, udp_dport);
+}
+
+static int
+__mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp,
+                                    __be16 udp_dport)
+{
+       int err;
+
+       mlxsw_sp->nve->inc_parsing_depth_refs++;
+
+       err = mlxsw_sp_nve_parsing_set(mlxsw_sp, udp_dport);
+       if (err)
+               goto err_nve_parsing_set;
+       return 0;
+
+err_nve_parsing_set:
+       mlxsw_sp->nve->inc_parsing_depth_refs--;
+       return err;
+}
+
+static void
+__mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp,
+                                    __be16 udp_dport)
+{
+       mlxsw_sp->nve->inc_parsing_depth_refs--;
+       mlxsw_sp_nve_parsing_set(mlxsw_sp, udp_dport);
+}
+
+int mlxsw_sp_nve_inc_parsing_depth_get(struct mlxsw_sp *mlxsw_sp)
+{
+       __be16 udp_dport = mlxsw_sp->nve->config.udp_dport;
+
+       return __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, udp_dport);
+}
+
+void mlxsw_sp_nve_inc_parsing_depth_put(struct mlxsw_sp *mlxsw_sp)
+{
+       __be16 udp_dport = mlxsw_sp->nve->config.udp_dport;
+
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, udp_dport);
+}
+
 static void
 mlxsw_sp_nve_vxlan_config_prepare(char *tngcr_pl,
                                  const struct mlxsw_sp_nve_config *config)
@@ -176,9 +226,7 @@ static int mlxsw_sp1_nve_vxlan_init(struct mlxsw_sp_nve *nve,
        struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
        int err;
 
-       err = mlxsw_sp_nve_parsing_set(mlxsw_sp,
-                                      MLXSW_SP_NVE_VXLAN_PARSING_DEPTH,
-                                      config->udp_dport);
+       err = __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, config->udp_dport);
        if (err)
                return err;
 
@@ -203,8 +251,7 @@ err_promote_decap:
 err_rtdp_set:
        mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp);
 err_config_set:
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
        return err;
 }
 
@@ -216,8 +263,7 @@ static void mlxsw_sp1_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
        mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
                                         config->ul_proto, &config->ul_sip);
        mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp);
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
 }
 
 static int
@@ -320,9 +366,7 @@ static int mlxsw_sp2_nve_vxlan_init(struct mlxsw_sp_nve *nve,
        struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp;
        int err;
 
-       err = mlxsw_sp_nve_parsing_set(mlxsw_sp,
-                                      MLXSW_SP_NVE_VXLAN_PARSING_DEPTH,
-                                      config->udp_dport);
+       err = __mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp, config->udp_dport);
        if (err)
                return err;
 
@@ -348,8 +392,7 @@ err_promote_decap:
 err_rtdp_set:
        mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
 err_config_set:
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
        return err;
 }
 
@@ -361,8 +404,7 @@ static void mlxsw_sp2_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
        mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id,
                                         config->ul_proto, &config->ul_sip);
        mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp);
-       mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH,
-                                config->udp_dport);
+       __mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp, 0);
 }
 
 const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = {
index bd9c2bc2d5d6e0569935ad77aedf56f1db198594..98c5ba3200bca23a8ef0b2b1c66d7e63b4eac649 100644 (file)
@@ -979,6 +979,9 @@ static int mlxsw_sp1_ptp_mtpppc_update(struct mlxsw_sp_port *mlxsw_sp_port,
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
        struct mlxsw_sp_port *tmp;
+       u16 orig_ing_types = 0;
+       u16 orig_egr_types = 0;
+       int err;
        int i;
 
        /* MTPPPC configures timestamping globally, not per port. Find the
@@ -986,12 +989,26 @@ static int mlxsw_sp1_ptp_mtpppc_update(struct mlxsw_sp_port *mlxsw_sp_port,
         */
        for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++) {
                tmp = mlxsw_sp->ports[i];
+               if (tmp) {
+                       orig_ing_types |= tmp->ptp.ing_types;
+                       orig_egr_types |= tmp->ptp.egr_types;
+               }
                if (tmp && tmp != mlxsw_sp_port) {
                        ing_types |= tmp->ptp.ing_types;
                        egr_types |= tmp->ptp.egr_types;
                }
        }
 
+       if ((ing_types || egr_types) && !(orig_egr_types || orig_egr_types)) {
+               err = mlxsw_sp_nve_inc_parsing_depth_get(mlxsw_sp);
+               if (err) {
+                       netdev_err(mlxsw_sp_port->dev, "Failed to increase parsing depth");
+                       return err;
+               }
+       }
+       if (!(ing_types || egr_types) && (orig_egr_types || orig_egr_types))
+               mlxsw_sp_nve_inc_parsing_depth_put(mlxsw_sp);
+
        return mlxsw_sp1_ptp_mtpppc_set(mlxsw_sp_port->mlxsw_sp,
                                       ing_types, egr_types);
 }