static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
                                    unsigned long event, void *ptr);
 
+#define MLXSW_SP_DEFAULT_PARSING_DEPTH 96
+#define MLXSW_SP_INCREASED_PARSING_DEPTH 128
+#define MLXSW_SP_DEFAULT_VXLAN_UDP_DPORT 4789
+
+static void mlxsw_sp_parsing_init(struct mlxsw_sp *mlxsw_sp)
+{
+       mlxsw_sp->parsing.parsing_depth = MLXSW_SP_DEFAULT_PARSING_DEPTH;
+       mlxsw_sp->parsing.vxlan_udp_dport = MLXSW_SP_DEFAULT_VXLAN_UDP_DPORT;
+       mutex_init(&mlxsw_sp->parsing.lock);
+}
+
+static void mlxsw_sp_parsing_fini(struct mlxsw_sp *mlxsw_sp)
+{
+       mutex_destroy(&mlxsw_sp->parsing.lock);
+}
+
 static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
                         const struct mlxsw_bus_info *mlxsw_bus_info,
                         struct netlink_ext_ack *extack)
        mlxsw_sp->core = mlxsw_core;
        mlxsw_sp->bus_info = mlxsw_bus_info;
 
+       mlxsw_sp_parsing_init(mlxsw_sp);
        mlxsw_core_emad_string_tlv_enable(mlxsw_core);
 
        err = mlxsw_sp_base_mac_get(mlxsw_sp);
        mlxsw_sp_fids_fini(mlxsw_sp);
 err_fids_init:
        mlxsw_sp_kvdl_fini(mlxsw_sp);
+       mlxsw_sp_parsing_fini(mlxsw_sp);
        return err;
 }
 
        mlxsw_sp_policers_fini(mlxsw_sp);
        mlxsw_sp_fids_fini(mlxsw_sp);
        mlxsw_sp_kvdl_fini(mlxsw_sp);
+       mlxsw_sp_parsing_fini(mlxsw_sp);
 }
 
 /* Per-FID flood tables are used for both "true" 802.1D FIDs and emulated
        dev_put(mlxsw_sp_port->dev);
 }
 
+int mlxsw_sp_parsing_depth_inc(struct mlxsw_sp *mlxsw_sp)
+{
+       char mprs_pl[MLXSW_REG_MPRS_LEN];
+       int err = 0;
+
+       mutex_lock(&mlxsw_sp->parsing.lock);
+
+       if (refcount_inc_not_zero(&mlxsw_sp->parsing.parsing_depth_ref))
+               goto out_unlock;
+
+       mlxsw_reg_mprs_pack(mprs_pl, MLXSW_SP_INCREASED_PARSING_DEPTH,
+                           mlxsw_sp->parsing.vxlan_udp_dport);
+       err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
+       if (err)
+               goto out_unlock;
+
+       mlxsw_sp->parsing.parsing_depth = MLXSW_SP_INCREASED_PARSING_DEPTH;
+       refcount_set(&mlxsw_sp->parsing.parsing_depth_ref, 1);
+
+out_unlock:
+       mutex_unlock(&mlxsw_sp->parsing.lock);
+       return err;
+}
+
+void mlxsw_sp_parsing_depth_dec(struct mlxsw_sp *mlxsw_sp)
+{
+       char mprs_pl[MLXSW_REG_MPRS_LEN];
+
+       mutex_lock(&mlxsw_sp->parsing.lock);
+
+       if (!refcount_dec_and_test(&mlxsw_sp->parsing.parsing_depth_ref))
+               goto out_unlock;
+
+       mlxsw_reg_mprs_pack(mprs_pl, MLXSW_SP_DEFAULT_PARSING_DEPTH,
+                           mlxsw_sp->parsing.vxlan_udp_dport);
+       mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
+       mlxsw_sp->parsing.parsing_depth = MLXSW_SP_DEFAULT_PARSING_DEPTH;
+
+out_unlock:
+       mutex_unlock(&mlxsw_sp->parsing.lock);
+}
+
+int mlxsw_sp_parsing_vxlan_udp_dport_set(struct mlxsw_sp *mlxsw_sp,
+                                        __be16 udp_dport)
+{
+       char mprs_pl[MLXSW_REG_MPRS_LEN];
+       int err;
+
+       mutex_lock(&mlxsw_sp->parsing.lock);
+
+       mlxsw_reg_mprs_pack(mprs_pl, mlxsw_sp->parsing.parsing_depth,
+                           be16_to_cpu(udp_dport));
+       err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
+       if (err)
+               goto out_unlock;
+
+       mlxsw_sp->parsing.vxlan_udp_dport = be16_to_cpu(udp_dport);
+
+out_unlock:
+       mutex_unlock(&mlxsw_sp->parsing.lock);
+       return err;
+}
+
 static void
 mlxsw_sp_port_lag_uppers_cleanup(struct mlxsw_sp_port *mlxsw_sp_port,
                                 struct net_device *lag_dev)
 
        u8 lane;
 };
 
+struct mlxsw_sp_parsing {
+       refcount_t parsing_depth_ref;
+       u16 parsing_depth;
+       u16 vxlan_udp_dport;
+       struct mutex lock; /* Protects parsing configuration */
+};
+
 struct mlxsw_sp {
        struct mlxsw_sp_port **ports;
        struct mlxsw_core *core;
        struct mlxsw_sp_counter_pool *counter_pool;
        struct mlxsw_sp_span *span;
        struct mlxsw_sp_trap *trap;
+       struct mlxsw_sp_parsing parsing;
        const struct mlxsw_sp_switchdev_ops *switchdev_ops;
        const struct mlxsw_sp_kvdl_ops *kvdl_ops;
        const struct mlxsw_afa_ops *afa_ops;
 struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev);
 void mlxsw_sp_port_dev_put(struct mlxsw_sp_port *mlxsw_sp_port);
 struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev);
+int mlxsw_sp_parsing_depth_inc(struct mlxsw_sp *mlxsw_sp);
+void mlxsw_sp_parsing_depth_dec(struct mlxsw_sp *mlxsw_sp);
+int mlxsw_sp_parsing_vxlan_udp_dport_set(struct mlxsw_sp *mlxsw_sp,
+                                        __be16 udp_dport);
 
 /* spectrum_dcb.c */
 #ifdef CONFIG_MLXSW_SPECTRUM_DCB