diff --git a/etc/conf.yaml b/etc/conf.yaml
index e92a1320de6465401891afa8cf706b03fa3b8c47..e2a07a1abb466108ef4b807e2f6fe47eeadb00ee 100755
--- a/etc/conf.yaml
+++ b/etc/conf.yaml
@@ -21,34 +21,43 @@
 
 ##### Base configuration #####
 
-# Name of the component, used towards NRF. Valid values: any string
+# Name of the component, used towards NRF. Valid values: any string, DEFAULT="PCF"
 name: "PCF"
-# Directories where policy configuration is stored
+# Directories where policy configuration is stored, absolute path
 pcc_rules_directory: "/openair-pcf/policies/pcc_rules"
 traffic_rules_directory: "/openair-pcf/policies/traffic_rules"
 policy_decisions_directory: "/openair-pcf/policies/policy_decisions"
 
 ##### Options to enable/disable #####
-# If "yes": Register to NRF
+# If "on": Register to NRF, DEFAULT= off
 register_nrf: on
-# If "yes": Send only HTTP/2 requests
+# If "on": Send only HTTP/2 requests, DEFAULT=off
 use_http2: off
 
 ##### Local interface #####
-# Local SBI interface, you can choose any key, but it must be unique
+# Local SBI interface
 ## name: Name of the NIC to read the IP address from
 ## Port: unsigned int between 0-65,535
+## http_version: Allowed values: "1", "2"
 ## api_version: Allowed values: "v1", "v2", used to create the 3GPP API version for the SBI URL
 local_sbi_interface:
   name: "eth0"
   port: 80
+  http_version: 1
+  api_version: "v1"
+
+# Local HTTP2 SBI interface, optional. When configured, HTTP2 server is used
+local_sbi_interface_http2:
+  name: "eth0"
+  port: 8080
+  http_version: 2
   api_version: "v1"
 
 ##### Next hop interfaces #####
 
-# Next hop SBI interfaces, you can choose any key, but it must be unique
-## url: has to follow this scheme: http://<name>:<port>/
+# Next hop SBI interfaces
+## url: has to follow this scheme: http://<name>:<port>
 ## api_version: Allowed values: "v1", "v2", used to create the 3GPP API version for the SBI URL
 nrf:
-  url: "http://oai-nrf:80/"
+  url: "http://oai-nrf:80"
   api_version: "v1"
diff --git a/src/common/config/config.cmake b/src/common/config/config.cmake
index 6a8558d84b53e3b49e2c51906dcfa63158d9b282..453a0f9a7488e4d98d77167390e0ca249dd3accc 100644
--- a/src/common/config/config.cmake
+++ b/src/common/config/config.cmake
@@ -44,7 +44,7 @@ target_sources(${NF_TARGET_LIB} PRIVATE
 endif()
 
 ## CONFIG used in NF_TARGET_API (API library)
-#target_include_directories(${NF_TARGET_API_LIB} PUBLIC ${CONFIG_DIR})
-#target_sources(${NF_TARGET_API_LIB} PRIVATE
-#        ${CONFIG_SRC_FILES}
-#        )
+target_include_directories(${NF_TARGET_API_LIB} PUBLIC ${CONFIG_DIR})
+target_sources(${NF_TARGET_API_LIB} PRIVATE
+        ${CONFIG_SRC_FILES}
+        )
diff --git a/src/common/config/config.cpp b/src/common/config/config.cpp
index 69f367ddf7530f2d57b4633e177b5debde9c8668..7ea5fb6a966a58eed747bc844c5aa8fac27c97a7 100644
--- a/src/common/config/config.cpp
+++ b/src/common/config/config.cpp
@@ -52,16 +52,18 @@ bool config::validate() const {
   for (const auto& key : m_mandatory_keys) {
     const auto it = m_config.find(key);
     if (it == m_config.end()) {
-      logger::logger_registry::get_logger(LOGGER_NAME).error(
-          "Mandatory configuration %s does not exist in configuration", key);
+      logger::logger_registry::get_logger(LOGGER_NAME)
+          .error(
+              "Mandatory configuration %s does not exist in configuration",
+              key);
       success = false;
     }
   }
 
   for (const auto& conf : m_config) {
     if (!conf.second->validate()) {
-      logger::logger_registry::get_logger(LOGGER_NAME).error(
-          "Validation of %s not successful", conf.first);
+      logger::logger_registry::get_logger(LOGGER_NAME)
+          .error("Validation of %s not successful", conf.first);
       success = false;
     }
   }
@@ -79,7 +81,6 @@ std::string config::to_string() const {
   std::string others_out;
 
   for (const auto& conf : m_config) {
-
     std::string val = fmt::format(
         BASE_FORMATTER, "-", conf.first, COLUMN_WIDTH,
         conf.second->to_string("  "));
@@ -98,8 +99,10 @@ std::string config::to_string() const {
         sbi_out.append(val);
         break;
       case config_type_e::INVALID:
-        logger::logger_registry::get_logger(LOGGER_NAME).error(
-            "General error in configuration. Invalid type of: %s", conf.first);
+        logger::logger_registry::get_logger(LOGGER_NAME)
+            .error(
+                "General error in configuration. Invalid type of: %s",
+                conf.first);
         others_out.append(val);
         break;
     }
@@ -133,9 +136,18 @@ bool config::get_support_feature(const std::string& name) const {
   return get<option_config_value>(name).value;
 }
 
-const network_interface& config::get_network_interface(
+const sbi_interface& config::get_sbi_interface(const std::string& name) const {
+  return get<sbi_interface>(name);
+}
+
+const local_interface& config::get_local_interface(
+    const std::string& name) const {
+  return get<local_interface>(name);
+}
+
+const local_sbi_interface& config::get_local_sbi_interface(
     const std::string& name) const {
-  return get<network_interface>(name);
+  return get<local_sbi_interface>(name);
 }
 
 template<typename T>
diff --git a/src/common/config/config.hpp b/src/common/config/config.hpp
index 89c94590d60bc804aa85454475531c2fb2a7dee7..f3b7a35f1234d9c04d44975efe42ec84cd1c00f7 100644
--- a/src/common/config/config.hpp
+++ b/src/common/config/config.hpp
@@ -39,9 +39,9 @@
 
 namespace oai::config {
 
-const int COLUMN_WIDTH = 20;
+const int COLUMN_WIDTH           = 20;
 const std::string BASE_FORMATTER = " {} {:.<{}}: {}\n";
-const std::string LOGGER_NAME = "config ";
+const std::string LOGGER_NAME    = "config ";
 
 class config_iface {
  public:
@@ -51,10 +51,12 @@ class config_iface {
    * @param name name of the configuration
    * @param val value of the configuration
    */
-  virtual void set_configuration(const std::string& name, std::unique_ptr<config_type> val) = 0;
+  virtual void set_configuration(
+      const std::string& name, std::unique_ptr<config_type> val) = 0;
 
   /**
-   * Set a configuration of any type with name to be mandatory, used for validation
+   * Set a configuration of any type with name to be mandatory, used for
+   * validation
    * @param name name of the configuration
    */
   virtual void set_configuration_mandatory(const std::string& name) = 0;
@@ -73,45 +75,72 @@ class config_iface {
    */
   [[nodiscard]] virtual std::string to_string() const = 0;
 
-  // The get method is not defined here, as we cannot have virtual template members
-  // Annoying that I cannot have a virtual template method just called "get"
+  // The get method is not defined here, as we cannot have virtual template
+  // members Annoying that I cannot have a virtual template method just called
+  // "get"
   /**
    * Get a string base configuration
    * @throws std::invalid_argument when name does not exist in configuration
    * @param name of the configuration
+   * @return value
    */
-  [[nodiscard]] virtual const std::string& get_base_conf_val(const std::string& name) const = 0;
+  [[nodiscard]] virtual const std::string& get_base_conf_val(
+      const std::string& name) const = 0;
 
   /**
    * Get a boolean configuration
    * @throws std::invalid_argument when name does not exist in configuration
    * @param name of the configuration
+   * @return value
    */
-  [[nodiscard]] virtual bool get_support_feature(const std::string& name) const = 0;
+  [[nodiscard]] virtual bool get_support_feature(
+      const std::string& name) const = 0;
 
   /**
-   * Get a network interface configuration
+   * Get a SBI interface configuration
    * @throws std::invalid_argument when name does not exist in configuration
    * @param name of the configuration
+   * @return value
    */
-  [[nodiscard]] virtual const network_interface& get_network_interface(const std::string& name) const = 0 ;
+  [[nodiscard]] virtual const sbi_interface& get_sbi_interface(
+      const std::string& name) const = 0;
+
+  /**
+   * Get a local SBI interface configuration
+   * @throws std::invalid_argument when name does not exist in configuration
+   * @param name of the configuration
+   * @return value
+   */
+  [[nodiscard]] virtual const local_sbi_interface& get_local_sbi_interface(
+      const std::string& name) const = 0;
+
+  /**
+   * Get a local interface configuration
+   * @throws std::invalid_argument when name does not exist in configuration
+   * @param name of the configuration
+   * @return value
+   */
+  [[nodiscard]] virtual const local_interface& get_local_interface(
+      const std::string& name) const = 0;
 
   /**
    * Display the to_string method to the config logger
    */
   virtual void display() const = 0;
 
+  virtual ~config_iface() = default;
 };
 
-class config : public config_iface{
-
+class config : public config_iface {
  public:
-
-  explicit config(bool log_stdout, bool log_rot_file) {
-    logger::logger_registry::register_logger(PACKAGE_NAME, LOGGER_NAME, log_stdout, log_rot_file);
+  explicit config(
+      const std::string& nf_name, bool log_stdout, bool log_rot_file) {
+    logger::logger_registry::register_logger(
+        nf_name, LOGGER_NAME, log_stdout, log_rot_file);
   }
 
-  void set_configuration(const std::string& name, std::unique_ptr<config_type> val) override;
+  void set_configuration(
+      const std::string& name, std::unique_ptr<config_type> val) override;
 
   void set_configuration_mandatory(const std::string& name) override;
 
@@ -129,16 +158,24 @@ class config : public config_iface{
   template<typename T>
   [[nodiscard]] const T& get(const std::string& name) const;
 
-  [[nodiscard]] const std::string& get_base_conf_val(const std::string& name) const override;
+  [[nodiscard]] const std::string& get_base_conf_val(
+      const std::string& name) const override;
 
-  [[nodiscard]] bool get_support_feature(const std::string& name) const override;
+  [[nodiscard]] bool get_support_feature(
+      const std::string& name) const override;
 
-  [[nodiscard]] const network_interface& get_network_interface(const std::string& name) const override;
+  [[nodiscard]] const sbi_interface& get_sbi_interface(
+      const std::string& name) const override;
+
+  [[nodiscard]] const local_interface& get_local_interface(
+      const std::string& name) const override;
+
+  [[nodiscard]] const local_sbi_interface& get_local_sbi_interface(
+      const std::string& name) const override;
 
   void display() const override;
 
  private:
-
   std::map<std::string, std::unique_ptr<config_type>> m_config;
 
   std::vector<std::string> m_mandatory_keys;
@@ -146,5 +183,4 @@ class config : public config_iface{
   mutable std::shared_mutex m_config_mutex;
 };
 
-
-}
\ No newline at end of file
+}  // namespace oai::config
\ No newline at end of file
diff --git a/src/common/config/config_types.cpp b/src/common/config/config_types.cpp
index 692ad1f3017d86fa37522fbeca062be29623ce2c..59997c689bf2ecec335f258b03d100218cbaae82 100644
--- a/src/common/config/config_types.cpp
+++ b/src/common/config/config_types.cpp
@@ -28,18 +28,38 @@
 */
 
 #include "config_types.hpp"
-#include "fmt/format.h"
 #include "config.hpp"
 #include "conversions.hpp"
-#include "algorithm"
 #include "logger_base.hpp"
+#include "if.hpp"
+#include "common_defs.h"
+
+#include <fmt/format.h>
+#include <algorithm>
+#include <regex>
+#include <string>
 
 using namespace oai::config;
 
 const std::string INNER_LIST_ELEM = "+";
 
-bool sbi_interface::validate() const {
-  // TODO validation
+bool config_type::matches_regex(
+    const std::string& value, const std::string& regex) {
+  std::regex re(regex);
+
+  if (!std::regex_match(value, re)) {
+    logger::logger_registry::get_logger(LOGGER_NAME)
+        .error("%s does not follow regex specification: %s", value, regex);
+    return false;
+  }
+  return true;
+}
+
+bool sbi_interface::validate() {
+  if (!matches_regex(url, URL_REGEX)) {
+    return false;
+  }
+  set = true;
   return true;
 }
 
@@ -59,8 +79,26 @@ config_type_e sbi_interface::get_config_type() const {
   return type;
 }
 
-bool local_interface::validate() const {
-  // TODO validation
+bool sbi_interface::is_set() const {
+  return set;
+}
+
+bool local_interface::validate() {
+  unsigned int _mtu{};
+  in_addr _addr4{};
+  in_addr _netmask{};
+  if (get_inet_addr_infos_from_iface(if_name, _addr4, _netmask, _mtu) ==
+      RETURNerror) {
+    logger::logger_registry::get_logger(LOGGER_NAME)
+        .error(
+            "Error in reading configuration from network interface %s",
+            if_name);
+    return false;
+  }
+  mtu   = _mtu;
+  addr4 = _addr4;
+
+  set = true;
   return true;
 }
 
@@ -73,15 +111,15 @@ std::string local_interface::to_string(const std::string& indent) const {
 
   out.append(indent).append(fmt::format(
       BASE_FORMATTER, INNER_LIST_ELEM, "IPv4 Address ", inner_width, ip4));
-  if (!ip6.empty()) {
+  if (ip6 != "::") {
     out.append(indent).append(fmt::format(
-        BASE_FORMATTER, INNER_LIST_ELEM, "IPv6 Address", inner_width, ip4));
+        BASE_FORMATTER, INNER_LIST_ELEM, "IPv6 Address", inner_width, ip6));
   }
   out.append(indent).append(
       fmt::format(BASE_FORMATTER, INNER_LIST_ELEM, "MTU", inner_width, mtu));
   out.append(indent).append(fmt::format(
       BASE_FORMATTER, INNER_LIST_ELEM, "Interface name: ", inner_width,
-      iface_name));
+      if_name));
   out.append(indent).append(
       fmt::format(BASE_FORMATTER, INNER_LIST_ELEM, "Port", inner_width, port));
 
@@ -92,11 +130,16 @@ config_type_e local_interface::get_config_type() const {
   return type;
 }
 
-bool local_sbi_interface::validate() const {
+bool local_interface::is_set() const {
+  return set;
+}
+
+bool local_sbi_interface::validate() {
   bool sbi_validate = validate_sbi_api_version(api_version);
   if (!sbi_validate) {
     return false;
   }
+  set = true;
   return local_interface::validate();
 }
 
@@ -106,9 +149,20 @@ std::string local_sbi_interface::to_string(const std::string& indent) const {
   out.append(indent).append(fmt::format(
       BASE_FORMATTER, INNER_LIST_ELEM, "API Version", inner_width,
       api_version));
+
+  std::string http_version = use_http2 ? "2" : "1";
+
+  out.append(indent).append(fmt::format(
+      BASE_FORMATTER, INNER_LIST_ELEM, "HTTP Version", inner_width,
+      http_version));
+
   return out;
 }
 
+bool local_sbi_interface::is_set() const {
+  return set;
+}
+
 bool network_interface::validate_sbi_api_version(const std::string& v) {
   auto it =
       std::find(allowed_api_versions.begin(), allowed_api_versions.end(), v);
@@ -125,23 +179,45 @@ std::string string_config_value::to_string(const std::string&) const {
   return out.append(value);
 }
 
-bool string_config_value::validate() const {
-  return false;
+bool string_config_value::validate() {
+  set = true;
+  return true;
 }
 
 config_type_e string_config_value::get_config_type() const {
   return type;
 }
 
+bool string_config_value::is_set() const {
+  return set;
+}
+
 std::string option_config_value::to_string(const std::string&) const {
   std::string val = value ? "Yes" : "No";
   return val;
 }
 
-bool option_config_value::validate() const {
+bool option_config_value::validate() {
+  set = true;
   return true;
 }
 
 config_type_e option_config_value::get_config_type() const {
   return type;
 }
+
+bool option_config_value::is_set() const {
+  return set;
+}
+
+option_config_value factory::get_option_config(bool val) {
+  option_config_value v;
+  v.value = val;
+  return v;
+}
+
+string_config_value factory::get_string_config(const std::string& val) {
+  string_config_value v;
+  v.value = val;
+  return v;
+}
diff --git a/src/common/config/config_types.hpp b/src/common/config/config_types.hpp
index 65e36e565945b4fe7d73f5445a36437dac902c7d..ec4f07b39da8efcfae09ff33f762fcc01b8b2e12 100644
--- a/src/common/config/config_types.hpp
+++ b/src/common/config/config_types.hpp
@@ -38,16 +38,24 @@ namespace oai::config {
 
 const std::vector<std::string> allowed_api_versions{"v1", "v2"};
 
+const std::string URL_REGEX = "http://.*:[0-9]*";
+
 // Only used for pretty-printing
 enum class config_type_e { STRING, OPTION, SBI, LOCAL, INVALID };
 
 class config_type {
  public:
   [[nodiscard]] virtual std::string to_string(
-      const std::string& indent) const                        = 0;
-  [[nodiscard]] virtual bool validate() const                 = 0;
+      const std::string& indent) const = 0;
+
+  [[nodiscard]] virtual bool validate() = 0;
+
   [[nodiscard]] virtual config_type_e get_config_type() const = 0;
 
+  [[nodiscard]] virtual bool is_set() const = 0;
+
+  static bool matches_regex(const std::string& value, const std::string& regex);
+
   virtual ~config_type() = default;
 };
 
@@ -57,11 +65,13 @@ class string_config_value : public config_type {
   std::string regex;
 
   [[nodiscard]] std::string to_string(const std::string& indent) const override;
-  [[nodiscard]] bool validate() const override;
+  [[nodiscard]] bool validate() override;
   [[nodiscard]] config_type_e get_config_type() const override;
+  [[nodiscard]] bool is_set() const override;
 
  private:
   config_type_e type = config_type_e::STRING;
+  bool set           = false;
 };
 
 class option_config_value : public config_type {
@@ -69,11 +79,13 @@ class option_config_value : public config_type {
   bool value = false;
 
   [[nodiscard]] std::string to_string(const std::string& indent) const override;
-  [[nodiscard]] bool validate() const override;
+  [[nodiscard]] bool validate() override;
   [[nodiscard]] config_type_e get_config_type() const override;
+  [[nodiscard]] bool is_set() const override;
 
  private:
   config_type_e type = config_type_e::OPTION;
+  bool set           = false;
 };
 
 class network_interface : public config_type {
@@ -86,39 +98,53 @@ class sbi_interface : public network_interface {
   std::string api_version;
   std::string url;
 
-  [[nodiscard]] bool validate() const override;
+  [[nodiscard]] bool validate() override;
   [[nodiscard]] std::string to_string(const std::string& indent) const override;
   [[nodiscard]] config_type_e get_config_type() const override;
+  [[nodiscard]] bool is_set() const override;
 
  private:
   config_type_e type = config_type_e::SBI;
+  bool set           = false;
 };
 
 class local_interface : public network_interface {
  public:
-  std::string iface_name;
-  in_addr addr4;
-  in6_addr addr6;
-  unsigned int mtu;
-  uint16_t port;
+  std::string if_name{};
+  in_addr addr4{};
+  in6_addr addr6{};
+  unsigned int mtu{};
+  uint16_t port{};
 
-  [[nodiscard]] bool validate() const override;
+  [[nodiscard]] bool validate() override;
   [[nodiscard]] std::string to_string(const std::string& indent) const override;
   [[nodiscard]] config_type_e get_config_type() const override;
+  [[nodiscard]] bool is_set() const override;
 
  private:
   config_type_e type = config_type_e::LOCAL;
+  bool set           = false;
 };
 
 class local_sbi_interface : public local_interface {
  public:
   std::string api_version;
+  bool use_http2 = false;
 
-  [[nodiscard]] bool validate() const override;
+  [[nodiscard]] bool validate() override;
   [[nodiscard]] std::string to_string(const std::string& indent) const override;
+  [[nodiscard]] bool is_set() const override;
 
  private:
   config_type_e type = config_type_e::LOCAL;
+  bool set           = false;
+};
+
+class factory {
+ public:
+  static option_config_value get_option_config(bool val);
+
+  static string_config_value get_string_config(const std::string& val);
 };
 
 }  // namespace oai::config
\ No newline at end of file
diff --git a/src/common/config/config_yaml_file.hpp b/src/common/config/config_yaml_file.hpp
index 6cd11d3513c1a487a152bb020f1f2190cb590b90..c468c4a65921dd4ae2e11590324afab88dae2b5f 100644
--- a/src/common/config/config_yaml_file.hpp
+++ b/src/common/config/config_yaml_file.hpp
@@ -99,8 +99,8 @@ struct convert<oai::config::local_interface> {
     if (!node["name"] || !node["port"]) {
       return false;
     }
-    val.port       = node["port"].as<uint16_t>();
-    val.iface_name = node["name"].as<std::string>();
+    val.port    = node["port"].as<uint16_t>();
+    val.if_name = node["name"].as<std::string>();
     return true;
   }
 };
@@ -109,14 +109,18 @@ template<>
 struct convert<oai::config::local_sbi_interface> {
   static bool decode(const Node& node, oai::config::local_sbi_interface& val) {
     auto iface = node.as<oai::config::local_interface>();
-    if (!node["api_version"]) {
+    if (!node["api_version"] || !node["http_version"]) {
       return false;
     }
 
-    val.port        = iface.port;
-    val.iface_name  = iface.iface_name;
-    val.api_version = node["api_version"].as<std::string>();
+    val.port          = iface.port;
+    val.if_name       = iface.if_name;
+    val.api_version   = node["api_version"].as<std::string>();
+    auto http_version = node["http_version"].as<std::string>();
 
+    if (http_version == "2") {
+      val.use_http2 = true;
+    }
     return true;
   }
 };
diff --git a/src/oai_pcf/main.cpp b/src/oai_pcf/main.cpp
index 3a7c45d776b8bb4a92557bfd013334f6cfff1c9a..e7607aa174601853687f5df031eaf52f4ded1b1d 100644
--- a/src/oai_pcf/main.cpp
+++ b/src/oai_pcf/main.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include "common_defs.h"
 #include "logger.hpp"
 #include "pcf-api-server.hpp"
 #include "pcf-http2-server.hpp"
@@ -24,7 +23,6 @@
 #include "pistache/http.h"
 #include "nf_launch.hpp"
 
-#include <algorithm>
 #include <iostream>
 #include <csignal>
 #include <thread>
@@ -35,11 +33,13 @@ using namespace oai::pcf::app;
 using namespace oai::pcf::config;
 using namespace oai::utils;
 
+using namespace oai::config;
+
 std::unique_ptr<pcf_app> pcf_app_inst;
 // TODO Stefan: I am not happy with these global variables
 // We could make a singleton getInstance in config
 // or we handle everything in smf_app init and have a reference to config there
-std::unique_ptr<pcf_config> pcf_cfg = std::make_unique<pcf_config>();
+std::unique_ptr<pcf_config> pcf_cfg;
 std::unique_ptr<PCFApiServer> pcf_api_server_1;
 std::unique_ptr<pcf_http2_server> pcf_api_server_2;
 
@@ -86,36 +86,42 @@ int main(int argc, char** argv) {
 
   std::signal(SIGINT, signal_handler_sigint);
 
-  // Event subsystem
-  pcf_event ev;
-
-  // Config
-  if (pcf_cfg->load(oai::utils::options::getlibconfigConfig()) == RETURNerror) {
-    exit(-1);
+  pcf_cfg = std::make_unique<pcf_config>(
+      oai::utils::options::getlibconfigConfig(),
+      oai::utils::options::getlogStdout(),
+      oai::utils::options::getlogRotFilelog());
+  if (!pcf_cfg->init()) {
+    pcf_cfg->display();
+    return 1;
   }
   pcf_cfg->display();
 
+  // Event subsystem
+  pcf_event ev;
+
   // PCF application layer
   pcf_app_inst = std::make_unique<pcf_app>(ev);
 
   std::string v4_address = conv::toString(pcf_cfg->sbi.addr4);
 
   // PCF Pistache API server (HTTP1)
-  Pistache::Address addr(v4_address, Pistache::Port(pcf_cfg->sbi.http1_port));
+  Pistache::Address addr(v4_address, Pistache::Port(pcf_cfg->sbi.port));
   PCFApiServer test(addr, pcf_app_inst);
 
   pcf_api_server_1 = std::make_unique<PCFApiServer>(addr, pcf_app_inst);
   pcf_api_server_1->init(2);
   std::thread pcf_http1_manager(&PCFApiServer::start, pcf_api_server_1.get());
 
-  // PCF NGHTTP API server (HTTP2)
-  pcf_api_server_2 = std::make_unique<pcf_http2_server>(
-      v4_address, pcf_cfg->sbi.http2_port, pcf_app_inst);
-  std::thread pcf_http2_manager(
-      &pcf_http2_server::start, pcf_api_server_2.get());
+  if (pcf_cfg->sbi_http2.is_set()) {
+    // PCF NGHTTP API server (HTTP2)
+    pcf_api_server_2 = std::make_unique<pcf_http2_server>(
+        v4_address, pcf_cfg->sbi_http2.port, pcf_app_inst);
+    std::thread pcf_http2_manager(
+        &pcf_http2_server::start, pcf_api_server_2.get());
+    pcf_http2_manager.join();
+  }
 
   pcf_http1_manager.join();
-  pcf_http2_manager.join();
 
   Logger::pcf_app().info("HTTP servers successfully stopped. Exiting");
 
diff --git a/src/pcf_app/pcf_config.cpp b/src/pcf_app/pcf_config.cpp
index 5446940f8c387149090c5c0fe77d04d646552bc7..d4a3c1f2efe8610e5d216cb76efae55cc6342ec9 100644
--- a/src/pcf_app/pcf_config.cpp
+++ b/src/pcf_app/pcf_config.cpp
@@ -21,339 +21,81 @@
 
 /*! \file pcf_config.cpp
  \brief
- \author  Rohan Kharade
- \company Openairinterface Software Allianse
+ \author  Rohan Kharade, Stefan Spettel
+ \company OpenAirInterface Software Alliance
  \date 2022
  \email: rohan.kharade@openairinterface.org
 */
 
+#include <config_yaml_file.hpp>
 #include "pcf_config.hpp"
-#include "common_defs.h"
-#include "conversions.hpp"
-#include "if.hpp"
-#include "string.hpp"
-#include "fqdn.hpp"
-#include <fstream>
-#include <nlohmann/json.hpp>
 
-#include <boost/algorithm/string.hpp>
-#include <boost/algorithm/string/classification.hpp>
-#include <boost/algorithm/string/split.hpp>
+using namespace oai::config;
 
-#include <cstdlib>
-#include <iomanip>
-#include <iostream>
+bool oai::pcf::config::pcf_config::init() {
+  // Default configuration
+  std::unique_ptr<config_type> use_http2 =
+      std::make_unique<option_config_value>(
+          factory::get_option_config(USE_HTTP2_DEFAULT_VALUE));
+  std::unique_ptr<config_type> register_nrf =
+      std::make_unique<option_config_value>(
+          factory::get_option_config(REGISTER_NRF_DEFAULT_VALUE));
+  std::unique_ptr<config_type> pcf_name = std::make_unique<string_config_value>(
+      factory::get_string_config(NAME_DEFAULT_VALUE));
 
-using namespace std;
-using namespace libconfig;
+  m_cfg->set_configuration(PCF_CONFIG_STRING_USE_HTTP2, std::move(use_http2));
+  m_cfg->set_configuration(
+      PCF_CONFIG_STRING_REGISTER_NRF, std::move(register_nrf));
+  m_cfg->set_configuration(PCF_CONFIG_STRING_NAME, std::move(pcf_name));
 
-namespace oai::pcf::config {
-// C includes
-#include <arpa/inet.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/stat.h>
+  m_cfg->set_configuration_mandatory(PCF_CONFIG_STRING_TRAFFIC_RULES_DIR);
+  m_cfg->set_configuration_mandatory(PCF_CONFIG_STRING_POLICY_DECISIONS_DIR);
+  m_cfg->set_configuration_mandatory(PCF_CONFIG_STRING_PCC_RULES_DIR);
 
-//------------------------------------------------------------------------------
-// int pcf_config::execute() { return RETURNok; }
+  m_cfg->set_configuration_mandatory(PCF_CONFIG_STRING_SBI_IFACE);
 
-//------------------------------------------------------------------------------
-int pcf_config::load_interface(const Setting& if_cfg, interface_cfg_t& cfg) {
-  if_cfg.lookupValue(PCF_CONFIG_STRING_INTERFACE_NAME, cfg.if_name);
-  util::trim(cfg.if_name);
-  if (not boost::iequals(cfg.if_name, "none")) {
-    std::string address = {};
-    if_cfg.lookupValue(PCF_CONFIG_STRING_IPV4_ADDRESS, address);
-    util::trim(address);
-    if (boost::iequals(address, "read")) {
-      if (get_inet_addr_infos_from_iface(
-              cfg.if_name, cfg.addr4, cfg.network4, cfg.mtu)) {
-        Logger::pcf_app().error(
-            "Could not read %s network interface configuration", cfg.if_name);
-        return RETURNerror;
-      }
-    } else {
-      std::vector<std::string> words;
-      boost::split(
-          words, address, boost::is_any_of("/"), boost::token_compress_on);
-      if (words.size() != 2) {
-        Logger::pcf_app().error(
-            "Bad value " PCF_CONFIG_STRING_IPV4_ADDRESS " = %s in config file",
-            address.c_str());
-        return RETURNerror;
-      }
-      unsigned char buf_in_addr[sizeof(struct in6_addr)];  // you never know...
-      if (inet_pton(AF_INET, util::trim(words.at(0)).c_str(), buf_in_addr) ==
-          1) {
-        memcpy(&cfg.addr4, buf_in_addr, sizeof(struct in_addr));
-      } else {
-        Logger::pcf_app().error(
-            "In conversion: Bad value " PCF_CONFIG_STRING_IPV4_ADDRESS
-            " = %s in config file",
-            util::trim(words.at(0)).c_str());
-        return RETURNerror;
-      }
-      cfg.network4.s_addr = htons(
-          ntohs(cfg.addr4.s_addr) &
-          0xFFFFFFFF << (32 - std::stoi(util::trim(words.at(1)))));
-    }
-    if_cfg.lookupValue(PCF_CONFIG_STRING_SBI_PORT_HTTP1, cfg.http1_port);
-    if_cfg.lookupValue(PCF_CONFIG_STRING_SBI_PORT_HTTP2, cfg.http2_port);
-  }
-  return RETURNok;
-}
-//------------------------------------------------------------------------------
-int pcf_config::check_directory(
-    const Setting& pcf_cfg, const std::string& path_config, std::string& path) {
-  try {
-    pcf_cfg.lookupValue(path_config, path);
-
-    struct stat info;
-    if (stat(path.c_str(), &info) != 0) {
-      Logger::pcf_app().info("Path %s cannot be accessed.", path.c_str());
-      return RETURNerror;
-    } else if (!(info.st_mode & S_IFDIR)) {
-      Logger::pcf_app().info("Path %s is not a directory.", path.c_str());
-      return RETURNerror;
-    }
-  } catch (const SettingNotFoundException& nfex) {
-    Logger::pcf_app().info("Configuration %s is not set.", path_config.c_str());
-    return RETURNerror;
-  }
-  return RETURNok;
-}
-//------------------------------------------------------------------------------
-int pcf_config::load(const string& config_file) {
-  Config cfg;
-
-  // Read the file. If there is an error, report it and exit.
+  yaml_file file;
   try {
-    cfg.readFile(config_file.c_str());
-  } catch (const FileIOException& fioex) {
-    Logger::pcf_app().error(
-        "I/O error while reading file %s - %s", config_file.c_str(),
-        fioex.what());
-    throw;
-  } catch (const ParseException& pex) {
-    Logger::pcf_app().error(
-        "Parse error at %s:%d - %s", pex.getFile(), pex.getLine(),
-        pex.getError());
-    throw;
-  }
-
-  const Setting& root = cfg.getRoot();
-
-  if (root.exists(PCF_CONFIG_STRING_PCF_CONFIG) == false) {
-    Logger::pcf_app().error(
-        "Setting does not exist: " + std::string{PCF_CONFIG_STRING_PCF_CONFIG});
-    return RETURNerror;
+    file.read_from_file(m_config_path, *m_cfg);
+  } catch (std::runtime_error& err) {
+    return false;
   }
-
-  const Setting& pcf_cfg = root[PCF_CONFIG_STRING_PCF_CONFIG];
-
-  try {
-    pcf_cfg.lookupValue(PCF_CONFIG_STRING_FQDN, fqdn);
-    util::trim(fqdn);
-  } catch (const SettingNotFoundException& nfex) {
-    Logger::pcf_app().info(
-        "%s : %s, No FQDN configured", nfex.what(), nfex.getPath());
+  // this is only mandatory when REGISTER_NRF is set
+  if (m_cfg->get_support_feature(PCF_CONFIG_STRING_REGISTER_NRF)) {
+    m_cfg->set_configuration_mandatory(PCF_CONFIG_STRING_NRF);
   }
 
-  if (check_directory(
-          pcf_cfg, PCF_CONFIG_STRING_PCC_RULES_DIRECTORY, pcc_rules_path) !=
-      RETURNok) {
-    Logger::pcf_app().error(
-        "PCC Rules Path is not set or not a valid directory. Exiting");
-    return RETURNerror;
-  }
-  if (check_directory(
-          pcf_cfg, PCF_CONFIG_STRING_POLICY_DECISIONS_DIRECTORY,
-          policy_decisions_path) != RETURNok) {
-    Logger::pcf_app().error(
-        "Policy Decisions Path is not set or not a valid directory. Exiting");
-    return RETURNerror;
+  bool validated = m_cfg->validate();
+  if (!validated) {
+    logger::logger_registry::get_logger(LOGGER_NAME)
+        .error("Configuration validation not successful!");
+    return false;
   }
-  if (check_directory(
-          pcf_cfg, PCF_CONFIG_STRING_TRAFFIC_RULES_DIRECTORY,
-          traffic_rules_path) != RETURNok) {
-    Logger::pcf_app().warn(
-        "Traffic Rules Path is not set or not a valid directory. This feature "
-        "is disabled.");
-  }
-
-  try {
-    const Setting& nw_if_cfg = pcf_cfg[PCF_CONFIG_STRING_INTERFACES];
-
-    const Setting& sbi_cfg = nw_if_cfg[PCF_CONFIG_STRING_SBI_INTERFACE];
-    load_interface(sbi_cfg, sbi);
+  set_direct_variables();
+  return true;
+}
 
-    sbi_cfg.lookupValue(PCF_CONFIG_STRING_API_VERSION, sbi_api_version);
-  } catch (const SettingNotFoundException& nfex) {
-    Logger::pcf_app().error("%s : %s", nfex.what(), nfex.getPath());
-    return RETURNerror;
-  }
-  // Support features
+void oai::pcf::config::pcf_config::set_direct_variables() {
+  sbi = m_cfg->get_local_sbi_interface(PCF_CONFIG_STRING_SBI_IFACE);
   try {
-    const Setting& support_features =
-        pcf_cfg[PCF_CONFIG_STRING_SUPPORT_FEATURES];
-    string opt;
-    support_features.lookupValue(
-        PCF_CONFIG_STRING_SUPPORT_FEATURES_REGISTER_NRF, opt);
-    if (boost::iequals(opt, "yes")) {
-      pcf_features.register_nrf = true;
-    } else {
-      pcf_features.register_nrf = false;
-    }
-
-    support_features.lookupValue(
-        PCF_CONFIG_STRING_SUPPORT_FEATURES_USE_FQDN_DNS, opt);
-    if (boost::iequals(opt, "yes")) {
-      pcf_features.use_fqdn = true;
-    } else {
-      pcf_features.use_fqdn = false;
-    }
-
-    support_features.lookupValue(
-        PCF_CONFIG_STRING_SUPPORT_FEATURES_USE_HTTP2, opt);
-    if (boost::iequals(opt, "yes")) {
-      pcf_features.use_http2 = true;
-    } else {
-      pcf_features.use_http2 = false;
-    }
-
-  } catch (const SettingNotFoundException& nfex) {
-    Logger::pcf_app().error(
-        "%s : %s, using defaults", nfex.what(), nfex.getPath());
-    return -1;
+    sbi_http2 =
+        m_cfg->get_local_sbi_interface(PCF_CONFIG_STRING_SBI_IFACE_HTTP2);
+  } catch (std::invalid_argument&) {
   }
-  try {
-    string astring = {};
 
-    // NRF
-    if (pcf_features.register_nrf) {
-      const Setting& nrf_cfg       = pcf_cfg[PCF_CONFIG_STRING_NRF];
-      struct in_addr nrf_ipv4_addr = {};
-      unsigned int nrf_port        = {0};
-      std::string nrf_api_version  = {};
-
-      if (!pcf_features.use_fqdn) {
-        nrf_cfg.lookupValue(PCF_CONFIG_STRING_NRF_IPV4_ADDRESS, astring);
-        IPV4_STR_ADDR_TO_INADDR(
-            util::trim(astring).c_str(), nrf_ipv4_addr,
-            "BAD IPv4 ADDRESS FORMAT FOR NRF !");
-        nrf_addr.ipv4_addr = nrf_ipv4_addr;
-        if (!(nrf_cfg.lookupValue(PCF_CONFIG_STRING_NRF_PORT, nrf_port))) {
-          Logger::pcf_app().error(PCF_CONFIG_STRING_NRF_PORT "failed");
-          throw(PCF_CONFIG_STRING_NRF_PORT "failed");
-        }
-        nrf_addr.port = nrf_port;
-
-        if (!(nrf_cfg.lookupValue(
-                PCF_CONFIG_STRING_API_VERSION, nrf_api_version))) {
-          Logger::pcf_app().error(PCF_CONFIG_STRING_API_VERSION "failed");
-          throw(PCF_CONFIG_STRING_API_VERSION "failed");
-        }
-        nrf_addr.api_version = nrf_api_version;
-      } else {
-        nrf_cfg.lookupValue(PCF_CONFIG_STRING_FQDN, astring);
-        uint8_t addr_type   = {0};
-        std::string address = {};
-        fqdn::resolve(astring, address, nrf_port, addr_type);
-        if (addr_type != 0) {  // IPv6
-          // TODO:
-          throw("DO NOT SUPPORT IPV6 ADDR FOR NRF!");
-        } else {  // IPv4
-          IPV4_STR_ADDR_TO_INADDR(
-              util::trim(address).c_str(), nrf_ipv4_addr,
-              "BAD IPv4 ADDRESS FORMAT FOR NRF !");
-          nrf_addr.ipv4_addr = nrf_ipv4_addr;
-          // nrf_addr.port        = nrf_port;
-          // We hardcode nrf port from config for the moment
-          if (!(nrf_cfg.lookupValue(PCF_CONFIG_STRING_NRF_PORT, nrf_port))) {
-            Logger::pcf_app().error(PCF_CONFIG_STRING_NRF_PORT "failed");
-            throw(PCF_CONFIG_STRING_NRF_PORT "failed");
-          }
-          nrf_addr.port        = nrf_port;
-          nrf_addr.api_version = "v1";  // TODO: to get API version from DNS
-          nrf_addr.fqdn        = astring;
-        }
-      }
-    }
-  } catch (const SettingNotFoundException& nfex) {
-    Logger::pcf_app().error("%s : %s", nfex.what(), nfex.getPath());
-    return RETURNerror;
-  }
-  return RETURNok;
+  nrf_addr       = m_cfg->get_sbi_interface(PCF_CONFIG_STRING_NRF);
+  pcc_rules_path = m_cfg->get_base_conf_val(PCF_CONFIG_STRING_PCC_RULES_DIR);
+  policy_decisions_path =
+      m_cfg->get_base_conf_val(PCF_CONFIG_STRING_POLICY_DECISIONS_DIR);
+  traffic_rules_path =
+      m_cfg->get_base_conf_val(PCF_CONFIG_STRING_TRAFFIC_RULES_DIR);
+
+  pcf_features.register_nrf =
+      m_cfg->get_support_feature(PCF_CONFIG_STRING_REGISTER_NRF);
+  pcf_features.use_http2 =
+      m_cfg->get_support_feature(PCF_CONFIG_STRING_USE_HTTP2);
 }
 
-//------------------------------------------------------------------------------
-void pcf_config::display() {
-  Logger::pcf_app().info(
-      "==== OPENAIRINTERFACE %s v%s ====", PACKAGE_NAME, PACKAGE_VERSION);
-  Logger::pcf_app().info("Configuration:");
-  Logger::pcf_app().info("- FQDN ..................: %s", fqdn.c_str());
-  Logger::pcf_app().info(
-      "- Policies Path..........: %s", policy_decisions_path.c_str());
-  Logger::pcf_app().info(
-      "- PCC Rules Path.........: %s", pcc_rules_path.c_str());
-  Logger::pcf_app().info(
-      "- Traffic Rules Path.....: %s", traffic_rules_path.c_str());
-
-  Logger::pcf_app().info("- SBI:");
-  Logger::pcf_app().info("    iface ............: %s", sbi.if_name.c_str());
-  Logger::pcf_app().info("    ipv4.addr ........: %s", inet_ntoa(sbi.addr4));
-  Logger::pcf_app().info("    ipv4.mask ........: %s", inet_ntoa(sbi.network4));
-  Logger::pcf_app().info("    mtu ..............: %d", sbi.mtu);
-  Logger::pcf_app().info("    http1_port .......: %u", sbi.http1_port);
-  Logger::pcf_app().info("    http2_port .......: %u", sbi.http2_port);
-  Logger::pcf_app().info("    api_version ......: %s", sbi_api_version.c_str());
-  if (pcf_features.register_nrf) {
-    Logger::pcf_app().info("- NRF:");
-    Logger::pcf_app().info(
-        "    IPv4 Addr ...........: %s",
-        inet_ntoa(*((struct in_addr*) &nrf_addr.ipv4_addr)));
-    Logger::pcf_app().info("    Port ................: %lu  ", nrf_addr.port);
-    Logger::pcf_app().info(
-        "    API version .........: %s", nrf_addr.api_version.c_str());
-    if (pcf_features.use_fqdn)
-      Logger::pcf_app().info(
-          "    FQDN ................: %s", nrf_addr.fqdn.c_str());
-  }
-  Logger::pcf_app().info("- Supported Features:");
-  Logger::pcf_app().info(
-      "    Register to NRF........: %s",
-      pcf_features.register_nrf ? "Yes" : "No");
-  Logger::pcf_app().info(
-      "    Use FQDN ..............: %s", pcf_features.use_fqdn ? "Yes" : "No");
-  Logger::pcf_app().info(
-      "    Use HTTP2..............: %s", pcf_features.use_http2 ? "Yes" : "No");
+void oai::pcf::config::pcf_config::display() {
+  m_cfg->display();
 }
-
-//------------------------------------------------------------------------------
-// bool pcf_config::get_slice_config(nlohmann::json& slice_config) {
-//   slice_config = pcf_slice_config;
-//   return true;
-// }
-
-//------------------------------------------------------------------------------
-// bool pcf_config::get_api_list(nlohmann::json &api_list) {
-//   api_list["OAI-PCF"] = {
-//       {"Organisation", "Openairinterface Software Aliance"},
-//       {"Description", "OAI-PCF initial Release"},
-//       {"Version", "1.0.0"},
-//       {"Supported APIs",
-//        {{"API", "Network Slice Information (Document)"},
-//         {"Method", "GET"},
-//         {"URI Path",
-//          "/npcf-nsselection/<api_version>/network-slice-information"},
-//         {"Details",
-//          "Retrieve the Network Slice Selection Information (PDU
-//          Session)"}}}};
-//   return true;
-// }
-//------------------------------------------------------------------------------
-
-}  // namespace oai::pcf::config
diff --git a/src/pcf_app/pcf_config.hpp b/src/pcf_app/pcf_config.hpp
index 4519d26698397301d2928fe315a5e5166a90c7e0..e64ef3b9fc0ddecf702ea999b2ce505c5b557ddd 100644
--- a/src/pcf_app/pcf_config.hpp
+++ b/src/pcf_app/pcf_config.hpp
@@ -21,138 +21,74 @@
 
 /*! \file pcf_config.hpp
  \brief
- \author  Rohan Kharade
- \company Openairinterface Software Allianse
+ \author  Rohan Kharade, Stefan Spettel
+ \company OpenAirInterface Software Alliance
  \date 2022
  \email: rohan.kharade@openairinterface.org
 */
 
-#ifndef FILE_PCF_CONFIG_HPP_SEEN
-#define FILE_PCF_CONFIG_HPP_SEEN
+#pragma once
 
-#include "3gpp_29.510.h"
-#include "logger.hpp"
-#include <libconfig.h++>
-#include <mutex>
-#include <netinet/in.h>
-#include <nlohmann/json.hpp>
-#include <stdbool.h>
-#include <stdint.h>
-#include <string>
-#include <unistd.h>
-
-// using namespace oai::pcf::model;
-
-#define PCF_CONFIG_STRING_PCF_CONFIG "PCF"
-#define PCF_CONFIG_STRING_FQDN "FQDN"
-#define PCF_CONFIG_STRING_PCF_SLICE_CONFIG "PCF_SLICE_CONFIG"
-#define PCF_CONFIG_STRING_INTERFACES "INTERFACES"
-#define PCF_CONFIG_STRING_INTERFACE_NAME "INTERFACE_NAME"
-#define PCF_CONFIG_STRING_IPV4_ADDRESS "IPV4_ADDRESS"
-#define PCF_CONFIG_STRING_SBI_PORT_HTTP1 "HTTP1_PORT"
-#define PCF_CONFIG_STRING_SBI_PORT_HTTP2 "HTTP2_PORT"
-#define PCF_CONFIG_STRING_SBI_INTERFACE "SBI"
-#define PCF_CONFIG_STRING_API_VERSION "API_VERSION"
-
-#define PCF_CONFIG_STRING_NETWORK_IPV4 "NETWORK_IPV4"
-#define PCF_CONFIG_STRING_NETWORK_IPV6 "NETWORK_IPV6"
-#define PCF_CONFIG_STRING_ADDRESS_PREFIX_DELIMITER "/"
-#define PCF_CONFIG_STRING_ITTI_TASKS "ITTI_TASKS"
-#define PCF_CONFIG_STRING_ITTI_TIMER_SCHED_PARAMS "ITTI_TIMER_SCHED_PARAMS"
-#define PCF_CONFIG_STRING_SBI_SCHED_PARAMS "SBI_SCHED_PARAMS"
-
-#define PCF_CONFIG_STRING_SUPPORT_FEATURES "SUPPORT_FEATURES"
-#define PCF_CONFIG_STRING_SUPPORT_FEATURES_REGISTER_NRF "REGISTER_NRF"
-#define PCF_CONFIG_STRING_NRF "NRF"
-#define PCF_CONFIG_STRING_NRF_IPV4_ADDRESS "IPV4_ADDRESS"
-#define PCF_CONFIG_STRING_NRF_PORT "PORT"
-#define PCF_CONFIG_STRING_NRF_HTTP_VERSION "HTTP_VERSION"
-#define PCF_CONFIG_STRING_SUPPORT_FEATURES_USE_HTTP2 "USE_HTTP2"
-#define PCF_CONFIG_STRING_SUPPORT_FEATURES_USE_FQDN_DNS "USE_FQDN"
-
-#define PCF_CONFIG_STRING_PCC_RULES_DIRECTORY "PCC_RULES_DIRECTORY"
-#define PCF_CONFIG_STRING_POLICY_DECISIONS_DIRECTORY                           \
-  "POLICY_DECISIONS_DIRECTORY"
-#define PCF_CONFIG_STRING_TRAFFIC_RULES_DIRECTORY "TRAFFIC_RULES_DIRECTORY"
+#include "config.hpp"
 
 namespace oai::pcf::config {
 
-typedef struct interface_cfg_s {
-  std::string if_name;
-  struct in_addr addr4;
-  struct in_addr network4;
-  struct in6_addr addr6;
-  unsigned int mtu;
-  unsigned int http1_port;
-  unsigned int http2_port;
-} interface_cfg_t;
+const std::string NAME_DEFAULT_VALUE  = "PCF";
+const bool REGISTER_NRF_DEFAULT_VALUE = false;
+const bool USE_HTTP2_DEFAULT_VALUE    = false;
+
+const std::string PCF_CONFIG_STRING_REGISTER_NRF  = "register_nrf";
+const std::string PCF_CONFIG_STRING_USE_HTTP2     = "use_http2";
+const std::string PCF_CONFIG_STRING_NAME          = "name";
+const std::string PCF_CONFIG_STRING_PCC_RULES_DIR = "pcc_rules_directory";
+const std::string PCF_CONFIG_STRING_POLICY_DECISIONS_DIR =
+    "policy_decisions_directory";
+const std::string PCF_CONFIG_STRING_TRAFFIC_RULES_DIR =
+    "traffic_rules_directory";
+const std::string PCF_CONFIG_STRING_SBI_IFACE = "local_sbi_interface";
+const std::string PCF_CONFIG_STRING_SBI_IFACE_HTTP2 =
+    "local_sbi_interface_http2";
+const std::string PCF_CONFIG_STRING_NRF = "nrf";
+
+struct support_features {
+  bool register_nrf;
+  bool use_http2;
+};
 
 class pcf_config {
- protected:
- private:
-  int load_interface(const libconfig::Setting& if_cfg, interface_cfg_t& cfg);
-  int check_directory(
-      const libconfig::Setting& pcf_cfg, const std::string& path_config,
-      std::string& path);
-
  public:
-  /* Reader/writer lock for this configuration */
-  std::mutex m_rw_lock;
-  std::string pid_dir;
-  unsigned int instance;
-  std::string fqdn;
-  interface_cfg_t sbi;
-  std::string sbi_api_version;
-
-  std::string gateway;
-
+  oai::config::local_sbi_interface sbi;
+  oai::config::local_sbi_interface sbi_http2;
   std::string pcc_rules_path;
   std::string policy_decisions_path;
   std::string traffic_rules_path;
 
-  struct {
-    bool register_nrf;
-    bool use_fqdn;
-    bool use_http2;
-
-    struct {
-      struct in_addr ipv4_addr;
-      unsigned int port;
-      unsigned int http_version;
-      std::string api_version;
-      std::string fqdn;
-    } nrf_addr;
-  } pcf_features;
-
-  struct {
-    struct in_addr ipv4_addr;
-    unsigned int port;
-    unsigned int http_version;
-    std::string api_version;
-    std::string fqdn;
-  } nrf_addr;
+  oai::config::sbi_interface nrf_addr;
 
-  // struct {
-  //   struct in_addr ipv4_addr;
-  //   unsigned int port;
-  //   unsigned int http_version;
-  //   std::string api_version;
-  //   std::string fqdn;
-  // } smf_addr;
+  support_features pcf_features;
 
-  pcf_config() : m_rw_lock(), pid_dir(), instance(0) {
-    sbi.http1_port = 8080;
-    sbi.http2_port = 80;
+  explicit pcf_config(
+      const std::string& config_path, bool log_stdout, bool log_rot_file)
+      : pcf_features() {
+    m_cfg =
+        std::make_unique<oai::config::config>("pcf", log_stdout, log_rot_file);
+    m_config_path = config_path;
   };
 
-  void lock() { m_rw_lock.lock(); };
-  void unlock() { m_rw_lock.unlock(); };
-  int load(const std::string& config_file);
-  int execute();
+  /**
+   * Initialize the configuration, sets mandatory values for validation, sets
+   * default values, reads YAML configuration file and validates the
+   * configuration
+   * @return True on success
+   */
+  bool init();
+
   void display();
 
-  static bool parse_config();
+ private:
+  std::unique_ptr<oai::config::config_iface> m_cfg;
+  std::string m_config_path;
+
+  void set_direct_variables();
 };
 }  // namespace oai::pcf::config
-
-#endif /* FILE_PCF_CONFIG_HPP_SEEN */
diff --git a/src/pcf_app/pcf_nrf.cpp b/src/pcf_app/pcf_nrf.cpp
index 141837bceb3012a469ef1ffb8f5f888dcb814cdd..b000b728d997ac785f9a6a2a03ee9c182fdd296f 100644
--- a/src/pcf_app/pcf_nrf.cpp
+++ b/src/pcf_app/pcf_nrf.cpp
@@ -58,11 +58,8 @@ pcf_nrf::pcf_nrf(pcf_event& ev) : m_event_sub(ev) {
 
 //------------------------------------------------------------------------------
 void pcf_nrf::generate_nrf_api_url() {
-  m_nrf_url = "";
-  m_nrf_url.append(conv::toString(pcf_cfg->nrf_addr.ipv4_addr))
-      .append(":")
-      .append(to_string(pcf_cfg->nrf_addr.port))
-      .append(NNRF_NFM_BASE)
+  m_nrf_url = pcf_cfg->nrf_addr.url;
+  m_nrf_url.append(NNRF_NFM_BASE)
       .append(pcf_cfg->nrf_addr.api_version)
       .append(NNRF_DISC_INSTANCES)
       .append(m_pcf_instance_id);
@@ -86,7 +83,7 @@ void pcf_nrf::generate_pcf_profile() {
   nf_service.service_instance_id = SM_POLICY_API_NAME;
   nf_service.service_name        = SM_POLICY_API_NAME;
   nf_service_version_t version   = {};
-  version.api_version_in_uri     = pcf_cfg->sbi_api_version;
+  version.api_version_in_uri     = pcf_cfg->sbi.api_version;
   version.api_full_version       = "1.0.0";  // TODO: to be updated
   nf_service.versions.push_back(version);
   nf_service.scheme            = "http";
@@ -96,8 +93,7 @@ void pcf_nrf::generate_pcf_profile() {
   // TODO: use only one IP address from cfg for now
   endpoint.ipv4_address = pcf_cfg->sbi.addr4;
   endpoint.transport    = "TCP";
-  endpoint.port         = pcf_cfg->sbi.http1_port;
-  if (pcf_cfg->pcf_features.use_http2) endpoint.port = pcf_cfg->sbi.http2_port;
+  endpoint.port         = pcf_cfg->sbi.port;
   nf_service.ip_endpoints.push_back(endpoint);
 
   m_nf_instance_profile.add_nf_service(nf_service);