config_parser: Reduce number of file reads

This changes focuses on reducing the number of Parser() constructions to
limit the number of duplicate file reads.

Change-Id: I05df943844c70dc6aa729ab744d2d405cbfe2c76
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/config_parser.cpp b/src/config_parser.cpp
index b684fa2..27a7b15 100644
--- a/src/config_parser.cpp
+++ b/src/config_parser.cpp
@@ -1,5 +1,8 @@
 #include "config_parser.hpp"
 
+#include <fmt/compile.h>
+#include <fmt/format.h>
+
 #include <functional>
 #include <iterator>
 #include <stdplus/exception.hpp>
@@ -37,6 +40,16 @@
     return std::nullopt;
 }
 
+fs::path pathForIntfConf(const fs::path& dir, std::string_view intf)
+{
+    return dir / fmt::format(FMT_COMPILE("00-bmc-{}.network"), intf);
+}
+
+fs::path pathForIntfDev(const fs::path& dir, std::string_view intf)
+{
+    return dir / fmt::format(FMT_COMPILE("{}.netdev"), intf);
+}
+
 Parser::Parser(const fs::path& filename)
 {
     setFile(filename);
@@ -209,6 +222,7 @@
             fmt::format("{}: Read error: {}", filename.native(), e.what()));
     }
 
+    this->filename = filename;
     this->sections = std::move(parse.sections);
     this->warnings = std::move(parse.warnings);
 }
diff --git a/src/config_parser.hpp b/src/config_parser.hpp
index 75ef4a7..7ff20ba 100644
--- a/src/config_parser.hpp
+++ b/src/config_parser.hpp
@@ -19,6 +19,11 @@
 /** @brief Turns a systemd bool string into a c++ bool */
 std::optional<bool> parseBool(std::string_view in) noexcept;
 
+namespace fs = std::filesystem;
+
+fs::path pathForIntfConf(const fs::path& dir, std::string_view intf);
+fs::path pathForIntfDev(const fs::path& dir, std::string_view intf);
+
 struct string_hash : public std::hash<std::string_view>
 {
     using is_transparent = void;
@@ -33,8 +38,6 @@
 using SectionMap =
     std::unordered_map<Section, KeyValuesMap, string_hash, std::equal_to<>>;
 
-namespace fs = std::filesystem;
-
 class Parser
 {
   public:
@@ -43,7 +46,6 @@
     /** @brief Constructor
      *  @param[in] filename - Absolute path of the file which will be parsed.
      */
-
     Parser(const fs::path& filename);
 
     /** @brief Get the values of the given key and section.
@@ -62,12 +64,21 @@
         return warnings;
     }
 
+    /** @brief Get the filename last parsed successfully
+     *  @return file path
+     */
+    inline const fs::path& getFilename() const noexcept
+    {
+        return filename;
+    }
+
     /** @brief Set the file name and parse it.
      *  @param[in] filename - Absolute path of the file.
      */
     void setFile(const fs::path& filename);
 
   private:
+    fs::path filename;
     SectionMap sections;
     std::vector<std::string> warnings;
 };
diff --git a/src/dhcp_configuration.cpp b/src/dhcp_configuration.cpp
index ec9e6d9..4308f96 100644
--- a/src/dhcp_configuration.cpp
+++ b/src/dhcp_configuration.cpp
@@ -79,17 +79,11 @@
 
 bool Configuration::getDHCPPropFromConf(const std::string& prop)
 {
-    fs::path confPath = manager.getConfDir();
     auto interfaceStrList = getInterfaces();
-    // get the first interface name, we need it to know config file name.
-    auto interface = *interfaceStrList.begin();
-    auto fileName = systemd::config::networkFilePrefix + interface +
-                    systemd::config::networkFileSuffix;
-
-    confPath /= fileName;
     // systemd default behaviour is all DHCP fields should be enabled by
     // default.
-    config::Parser parser(confPath);
+    config::Parser parser(config::pathForIntfConf(manager.getConfDir(),
+                                                  *interfaceStrList.begin()));
 
     const auto& values = parser.getValues("DHCP", prop);
     if (values.empty())
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index 06ccc93..db87e8a 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -10,6 +10,7 @@
 #include "vlan_interface.hpp"
 
 #include <arpa/inet.h>
+#include <fmt/compile.h>
 #include <fmt/format.h>
 #include <linux/ethtool.h>
 #include <linux/rtnetlink.h>
@@ -63,6 +64,7 @@
 
 EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus,
                                      const std::string& objPath,
+                                     const config::Parser& config,
                                      DHCPConf dhcpEnabled, Manager& parent,
                                      bool emitSignal,
                                      std::optional<bool> enabled) :
@@ -75,7 +77,7 @@
     std::replace(intfName.begin(), intfName.end(), '_', '.');
     interfaceName(intfName);
     EthernetInterfaceIntf::dhcpEnabled(dhcpEnabled);
-    EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRAFromConf());
+    EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
     EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
     const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
     const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
@@ -108,7 +110,7 @@
     {
         MacAddressIntf::macAddress(getMACAddress(intfName));
     }
-    EthernetInterfaceIntf::ntpServers(getNTPServersFromConf());
+    EthernetInterfaceIntf::ntpServers(config.getValues("Network", "NTP"));
 
     EthernetInterfaceIntf::linkUp(linkUp());
     EthernetInterfaceIntf::mtu(mtu());
@@ -470,25 +472,14 @@
 
 void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
 {
-    auto confDir = manager.getConfDir();
-    fs::path networkFile = confDir;
-    networkFile /= systemd::config::networkFilePrefix + interface +
-                   systemd::config::networkFileSuffix;
-
-    fs::path deviceFile = confDir;
-    deviceFile /= interface + systemd::config::deviceFileSuffix;
+    const auto& confDir = manager.getConfDir();
+    auto networkFile = config::pathForIntfConf(confDir, interface);
+    auto deviceFile = config::pathForIntfDev(confDir, interface);
 
     // delete the vlan network file
-    if (fs::is_regular_file(networkFile))
-    {
-        fs::remove(networkFile);
-    }
-
-    // delete the vlan device file
-    if (fs::is_regular_file(deviceFile))
-    {
-        fs::remove(deviceFile);
-    }
+    std::error_code ec;
+    fs::remove(networkFile, ec);
+    fs::remove(deviceFile, ec);
 
     // TODO  systemd doesn't delete the virtual network interface
     // even after deleting all the related configuartion.
@@ -790,21 +781,11 @@
     return EthernetInterfaceIntf::staticNameServers();
 }
 
-void EthernetInterface::loadNameServers()
+void EthernetInterface::loadNameServers(const config::Parser& config)
 {
     EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
-    EthernetInterfaceIntf::staticNameServers(getstaticNameServerFromConf());
-}
-
-ServerList EthernetInterface::getstaticNameServerFromConf()
-{
-    fs::path confPath = manager.getConfDir();
-
-    std::string fileName = systemd::config::networkFilePrefix +
-                           interfaceName() + systemd::config::networkFileSuffix;
-    confPath /= fileName;
-    config::Parser parser(confPath.string());
-    return parser.getValues("Network", "DNS");
+    EthernetInterfaceIntf::staticNameServers(
+        config.getValues("Network", "DNS"));
 }
 
 ServerList EthernetInterface::getNameServerFromResolvd()
@@ -887,23 +868,33 @@
     return servers;
 }
 
+std::string EthernetInterface::vlanIntfName(VlanId id) const
+{
+    return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
+}
+
+std::string EthernetInterface::vlanObjPath(VlanId id) const
+{
+    return fmt::format(FMT_COMPILE("{}_{}"), objPath, id);
+}
+
 void EthernetInterface::loadVLAN(VlanId id)
 {
-    std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
-    std::string path = objPath;
-    path += "_" + std::to_string(id);
+    auto vlanInterfaceName = vlanIntfName(id);
+    auto path = vlanObjPath(id);
 
-    DHCPConf dhcpEnabled =
-        getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
+    config::Parser config(
+        config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));
+
     auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
-        bus, path.c_str(), dhcpEnabled, EthernetInterfaceIntf::nicEnabled(), id,
-        *this, manager);
+        bus, path.c_str(), config, getDHCPValue(config),
+        EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
 
     // Fetch the ip address from the system
     // and create the dbus object.
     vlanIntf->createIPAddressObjects();
     vlanIntf->createStaticNeighborObjects();
-    vlanIntf->loadNameServers();
+    vlanIntf->loadNameServers(config);
 
     this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
                                  std::move(vlanIntf));
@@ -911,9 +902,9 @@
 
 ObjectPath EthernetInterface::createVLAN(VlanId id)
 {
-    std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
-
-    if (this->vlanInterfaces.count(vlanInterfaceName))
+    auto vlanInterfaceName = vlanIntfName(id);
+    if (this->vlanInterfaces.find(vlanInterfaceName) !=
+        this->vlanInterfaces.end())
     {
         log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
         elog<InvalidArgument>(
@@ -921,13 +912,12 @@
             Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
     }
 
-    std::string path = objPath;
-    path += "_" + std::to_string(id);
+    auto path = vlanObjPath(id);
 
     // Pass the parents nicEnabled property, so that the child
     // VLAN interface can inherit.
     auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
-        bus, path.c_str(), EthernetInterface::DHCPConf::none,
+        bus, path.c_str(), config::Parser(), EthernetInterface::DHCPConf::none,
         EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
 
     // write the device file for the vlan interface.
@@ -941,43 +931,6 @@
     return path;
 }
 
-bool EthernetInterface::getIPv6AcceptRAFromConf()
-{
-    fs::path confPath = manager.getConfDir();
-
-    std::string fileName = systemd::config::networkFilePrefix +
-                           interfaceName() + systemd::config::networkFileSuffix;
-    confPath /= fileName;
-    config::Parser parser(confPath);
-    const auto& values = parser.getValues("Network", "IPv6AcceptRA");
-    if (values.empty())
-    {
-        log<level::NOTICE>("Unable to get the value for Network[IPv6AcceptRA]");
-        return false;
-    }
-    auto ret = config::parseBool(values.back());
-    if (!ret.has_value())
-    {
-        auto msg =
-            fmt::format("Failed to parse section Network[IPv6AcceptRA]: `{}`",
-                        values.back());
-        log<level::NOTICE>(msg.c_str());
-    }
-    return ret.value_or(false);
-}
-
-ServerList EthernetInterface::getNTPServersFromConf()
-{
-    fs::path confPath = manager.getConfDir();
-
-    std::string fileName = systemd::config::networkFilePrefix +
-                           interfaceName() + systemd::config::networkFileSuffix;
-    confPath /= fileName;
-
-    config::Parser parser(confPath.string());
-    return parser.getValues("Network", "NTP");
-}
-
 ServerList EthernetInterface::ntpServers(ServerList servers)
 {
     auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
@@ -1006,18 +959,12 @@
         intf.second->writeConfigurationFile();
     }
 
-    fs::path confPath = manager.getConfDir();
-
-    std::string fileName = systemd::config::networkFilePrefix +
-                           interfaceName() + systemd::config::networkFileSuffix;
-    confPath /= fileName;
-    std::fstream stream;
-
-    stream.open(confPath.c_str(), std::fstream::out);
+    auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
+    std::fstream stream(path.c_str(), std::fstream::out);
     if (!stream.is_open())
     {
         log<level::ERR>("Unable to open the file",
-                        entry("FILE=%s", confPath.c_str()));
+                        entry("FILE=%s", path.c_str()));
         elog<InternalFailure>();
     }
 
@@ -1129,8 +1076,8 @@
     writeDHCPSection(stream);
 
     stream.close();
-    auto msg = fmt::format("Wrote networkd file: {}", confPath.native());
-    log<level::INFO>(msg.c_str(), entry("FILE=%s", confPath.c_str()));
+    auto msg = fmt::format("Wrote networkd file: {}", path.native());
+    log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
 }
 
 void EthernetInterface::writeDHCPSection(std::fstream& stream)
diff --git a/src/ethernet_interface.hpp b/src/ethernet_interface.hpp
index 751c74a..c519623 100644
--- a/src/ethernet_interface.hpp
+++ b/src/ethernet_interface.hpp
@@ -1,5 +1,6 @@
 #pragma once
 
+#include "config_parser.hpp"
 #include "types.hpp"
 #include "util.hpp"
 #include "xyz/openbmc_project/Network/IP/Create/server.hpp"
@@ -80,6 +81,7 @@
     /** @brief Constructor to put object onto bus at a dbus path.
      *  @param[in] bus - Bus to attach to.
      *  @param[in] objPath - Path to attach at.
+     *  @param[in] config - The parsed configuation file.
      *  @param[in] dhcpEnabled - is dhcp enabled(true/false).
      *  @param[in] parent - parent object.
      *  @param[in] emitSignal - true if the object added signal needs to be
@@ -87,13 +89,13 @@
      *  @param[in] enabled - Override the lookup of nicEnabled
      */
     EthernetInterface(sdbusplus::bus_t& bus, const std::string& objPath,
-                      DHCPConf dhcpEnabled, Manager& parent,
-                      bool emitSignal = true,
+                      const config::Parser& config, DHCPConf dhcpEnabled,
+                      Manager& parent, bool emitSignal = true,
                       std::optional<bool> enabled = std::nullopt);
 
     /** @brief Function used to load the nameservers.
      */
-    virtual void loadNameServers();
+    void loadNameServers(const config::Parser& config);
 
     /** @brief Function to create ipAddress dbus object.
      *  @param[in] addressType - Type of ip address.
@@ -184,11 +186,6 @@
      */
     std::string macAddress(std::string value) override;
 
-    /** @brief get the IPv6AcceptRA flag from the network configuration file
-     *
-     */
-    bool getIPv6AcceptRAFromConf();
-
     /** @brief check conf file for Router Advertisements
      *
      */
@@ -319,7 +316,6 @@
      *
      */
     virtual ServerList getNameServerFromResolvd();
-    ServerList getstaticNameServerFromConf();
 
     /** @brief Persistent sdbusplus DBus bus connection. */
     sdbusplus::bus_t& bus;
@@ -358,6 +354,9 @@
      *  @returns true/false value if the NIC is enabled
      */
     bool queryNicEnabled() const;
+
+    std::string vlanIntfName(VlanId id) const;
+    std::string vlanObjPath(VlanId id) const;
 };
 
 } // namespace network
diff --git a/src/network_manager.cpp b/src/network_manager.cpp
index c32c36e..86b8550 100644
--- a/src/network_manager.cpp
+++ b/src/network_manager.cpp
@@ -66,11 +66,7 @@
                 continue;
             }
 
-            auto fileName = systemd::config::networkFilePrefix + interface +
-                            systemd::config::networkFileSuffix;
-
-            fs::path filePath = confDir;
-            filePath /= fileName;
+            fs::path filePath = config::pathForIntfConf(confDir, interface);
 
             // create the interface specific network file
             // if not existing.
@@ -134,18 +130,16 @@
         }
         // normal ethernet interface
         objPath /= interface;
-
-        auto dhcp = getDHCPValue(confDir, interface);
+        config::Parser config(config::pathForIntfConf(confDir, interface));
 
         auto intf = std::make_shared<phosphor::network::EthernetInterface>(
-            bus, objPath.string(), dhcp, *this);
+            bus, objPath.string(), config, getDHCPValue(config), *this);
 
         intf->createIPAddressObjects();
         intf->createStaticNeighborObjects();
-        intf->loadNameServers();
+        intf->loadNameServers(config);
 
-        this->interfaces.emplace(
-            std::make_pair(std::move(interface), std::move(intf)));
+        this->interfaces.emplace(std::move(interface), std::move(intf));
     }
 }
 
diff --git a/src/network_manager.hpp b/src/network_manager.hpp
index 47a1e4d..2d5b255 100644
--- a/src/network_manager.hpp
+++ b/src/network_manager.hpp
@@ -80,7 +80,7 @@
 
     /** @brief gets the network conf directory.
      */
-    fs::path getConfDir()
+    const fs::path& getConfDir() const
     {
         return confDir;
     }
diff --git a/src/types.hpp b/src/types.hpp
index 2e27298..e0d768d 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -28,18 +28,6 @@
 // configuration takes 3-4 sec to reconfigure at most.
 constexpr auto refreshTimeout = 4s;
 
-namespace systemd
-{
-namespace config
-{
-
-constexpr auto networkFilePrefix = "00-bmc-";
-constexpr auto networkFileSuffix = ".network";
-constexpr auto deviceFileSuffix = ".netdev";
-
-} // namespace config
-} // namespace systemd
-
 using IntfName = std::string;
 
 using Addr_t = ifaddrs*;
diff --git a/src/util.cpp b/src/util.cpp
index 13be8d0..26d9b47 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -364,21 +364,41 @@
     return "eth" + std::to_string(idx) + "addr";
 }
 
-EthernetInterfaceIntf::DHCPConf getDHCPValue(const std::string& confDir,
-                                             const std::string& intf)
+bool getIPv6AcceptRA(const config::Parser& config)
 {
-    // Get the interface mode value from systemd conf
-    // using namespace std::string_literals;
-    fs::path confPath = confDir;
-    std::string fileName = systemd::config::networkFilePrefix + intf +
-                           systemd::config::networkFileSuffix;
-    confPath /= fileName;
-
-    config::Parser parser(confPath.string());
-    const auto& values = parser.getValues("Network", "DHCP");
+    const auto& values = config.getValues("Network", "IPv6AcceptRA");
     if (values.empty())
     {
-        log<level::NOTICE>("Unable to get the value for Network[DHCP]");
+        auto msg = fmt::format(
+            "Unable to get the value for Network[IPv6AcceptRA] from {}",
+            config.getFilename().native());
+        log<level::NOTICE>(msg.c_str(),
+                           entry("FILE=%s", config.getFilename().c_str()));
+        return false;
+    }
+    auto ret = config::parseBool(values.back());
+    if (!ret.has_value())
+    {
+        auto msg = fmt::format(
+            "Failed to parse section Network[IPv6AcceptRA] from {}: `{}`",
+            config.getFilename().native(), values.back());
+        log<level::NOTICE>(msg.c_str(),
+                           entry("FILE=%s", config.getFilename().c_str()),
+                           entry("VALUE=%s", values.back().c_str()));
+    }
+    return ret.value_or(false);
+}
+
+EthernetInterfaceIntf::DHCPConf getDHCPValue(const config::Parser& config)
+{
+    const auto& values = config.getValues("Network", "DHCP");
+    if (values.empty())
+    {
+        auto msg =
+            fmt::format("Unable to get the value for Network[DHCP] from {}",
+                        config.getFilename().native());
+        log<level::NOTICE>(msg.c_str(),
+                           entry("FILE=%s", config.getFilename().c_str()));
         return EthernetInterfaceIntf::DHCPConf::none;
     }
     if (config::icaseeq(values.back(), "ipv4"))
@@ -392,9 +412,11 @@
     auto ret = config::parseBool(values.back());
     if (!ret.has_value())
     {
-        auto str =
-            fmt::format("Unable to parse Network[DHCP]: `{}`", values.back());
-        log<level::NOTICE>(str.c_str());
+        auto str = fmt::format("Unable to parse Network[DHCP] from {}: `{}`",
+                               config.getFilename().native(), values.back());
+        log<level::NOTICE>(str.c_str(),
+                           entry("FILE=%s", config.getFilename().c_str()),
+                           entry("VALUE=%s", values.back().c_str()));
     }
     return ret.value_or(false) ? EthernetInterfaceIntf::DHCPConf::both
                                : EthernetInterfaceIntf::DHCPConf::none;
diff --git a/src/util.hpp b/src/util.hpp
index 43c231f..c4e1b60 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -9,6 +9,7 @@
 #include <unistd.h>
 
 #include <cstring>
+#include <filesystem>
 #include <optional>
 #include <sdbusplus/bus.hpp>
 #include <string>
@@ -123,12 +124,15 @@
  */
 std::optional<std::string> interfaceToUbootEthAddr(const char* intf);
 
-/** @brief read the DHCP value from the configuration file
- *  @param[in] confDir - Network configuration directory.
- *  @param[in] intf - Interface name.
+/** @brief read the IPv6AcceptRA value from the configuration file
+ *  @param[in] config - The parsed configuration.
  */
-EthernetInterfaceIntf::DHCPConf getDHCPValue(const std::string& confDir,
-                                             const std::string& intf);
+bool getIPv6AcceptRA(const config::Parser& config);
+
+/** @brief read the DHCP value from the configuration file
+ *  @param[in] config - The parsed configuration.
+ */
+EthernetInterfaceIntf::DHCPConf getDHCPValue(const config::Parser& config);
 
 namespace internal
 {
diff --git a/src/vlan_interface.cpp b/src/vlan_interface.cpp
index 6e37283..4f8583f 100644
--- a/src/vlan_interface.cpp
+++ b/src/vlan_interface.cpp
@@ -22,12 +22,13 @@
 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
 
 VlanInterface::VlanInterface(sdbusplus::bus_t& bus, const std::string& objPath,
-                             DHCPConf dhcpEnabled, bool nicEnabled,
-                             uint32_t vlanID, EthernetInterface& intf,
-                             Manager& parent) :
+                             const config::Parser& config, DHCPConf dhcpEnabled,
+                             bool nicEnabled, uint32_t vlanID,
+                             EthernetInterface& intf, Manager& parent) :
     VlanIface(bus, objPath.c_str()),
     DeleteIface(bus, objPath.c_str()),
-    EthernetInterface(bus, objPath, dhcpEnabled, parent, true, nicEnabled),
+    EthernetInterface(bus, objPath, config, dhcpEnabled, parent, true,
+                      nicEnabled),
     parentInterface(intf)
 {
     id(vlanID);
@@ -45,29 +46,24 @@
 
 void VlanInterface::writeDeviceFile()
 {
-    using namespace std::string_literals;
-    fs::path confPath = manager.getConfDir();
-    std::string fileName = EthernetInterface::interfaceName() + ".netdev"s;
-    confPath /= fileName;
-    std::fstream stream;
-    try
-    {
-        stream.open(confPath.c_str(), std::fstream::out);
-    }
-    catch (const std::ios_base::failure& e)
-    {
-        log<level::ERR>("Unable to open the VLAN device file",
-                        entry("FILE=%s", confPath.c_str()),
-                        entry("ERROR=%s", e.what()));
-        elog<InternalFailure>();
-    }
+    auto confPath = config::pathForIntfDev(manager.getConfDir(),
+                                           EthernetInterface::interfaceName());
+    std::fstream stream(confPath.c_str(), std::fstream::out);
 
     stream << "[NetDev]\n";
     stream << "Name=" << EthernetInterface::interfaceName() << "\n";
     stream << "Kind=vlan\n";
     stream << "[VLAN]\n";
     stream << "Id=" << id() << "\n";
+
     stream.close();
+
+    if (!stream.good())
+    {
+        log<level::ERR>("Unable to write the VLAN device file",
+                        entry("FILE=%s", confPath.c_str()));
+        elog<InternalFailure>();
+    }
 }
 
 void VlanInterface::delete_()
diff --git a/src/vlan_interface.hpp b/src/vlan_interface.hpp
index 953a01b..2d8baaa 100644
--- a/src/vlan_interface.hpp
+++ b/src/vlan_interface.hpp
@@ -1,5 +1,6 @@
 #pragma once
 
+#include "config_parser.hpp"
 #include "ethernet_interface.hpp"
 #include "types.hpp"
 #include "xyz/openbmc_project/Network/VLAN/server.hpp"
@@ -39,6 +40,7 @@
     /** @brief Constructor to put object onto bus at a dbus path.
      *  @param[in] bus - Bus to attach to.
      *  @param[in] objPath - Path to attach at.
+     *  @param[in] config - The parsed configuation file.
      *  @param[in] dhcpEnabled - DHCP enable value.
      *  @param[in] vlanID - vlan identifier.
      *  @param[in] intf - ethernet interface object.
@@ -47,8 +49,9 @@
      *  This constructor is called during loading the VLAN Interface
      */
     VlanInterface(sdbusplus::bus_t& bus, const std::string& objPath,
-                  DHCPConf dhcpEnabled, bool nicEnabled, uint32_t vlanID,
-                  EthernetInterface& intf, Manager& parent);
+                  const config::Parser& config, DHCPConf dhcpEnabled,
+                  bool nicEnabled, uint32_t vlanID, EthernetInterface& intf,
+                  Manager& parent);
 
     /** @brief Delete this d-bus object.
      */
diff --git a/test/mock_ethernet_interface.hpp b/test/mock_ethernet_interface.hpp
index b8c3335..a0358ed 100644
--- a/test/mock_ethernet_interface.hpp
+++ b/test/mock_ethernet_interface.hpp
@@ -13,9 +13,9 @@
 {
   public:
     MockEthernetInterface(sdbusplus::bus_t& bus, const std::string& objPath,
-                          DHCPConf dhcpEnabled, Manager& parent,
-                          bool emitSignal) :
-        EthernetInterface(bus, objPath, dhcpEnabled, parent, emitSignal,
+                          const config::Parser& config, DHCPConf dhcpEnabled,
+                          Manager& parent, bool emitSignal) :
+        EthernetInterface(bus, objPath, config, dhcpEnabled, parent, emitSignal,
                           /*nicEnabled=*/true)
     {
     }
diff --git a/test/mock_network_manager.hpp b/test/mock_network_manager.hpp
index 741cee9..46c7c4b 100644
--- a/test/mock_network_manager.hpp
+++ b/test/mock_network_manager.hpp
@@ -1,7 +1,4 @@
 #pragma once
-
-#include "config.h"
-
 #include "mock_ethernet_interface.hpp"
 #include "network_manager.hpp"
 
@@ -34,13 +31,14 @@
             fs::path objPath = objectPath;
             // normal ethernet interface
             objPath /= interface;
-            auto dhcp = getDHCPValue(confDir, interface);
+            config::Parser config(config::pathForIntfConf(confDir, interface));
             auto intf =
                 std::make_shared<phosphor::network::MockEthernetInterface>(
-                    bus, objPath.string(), dhcp, *this, true);
+                    bus, objPath.string(), config, getDHCPValue(config), *this,
+                    true);
             intf->createIPAddressObjects();
             intf->createStaticNeighborObjects();
-            intf->loadNameServers();
+            intf->loadNameServers(config);
             this->interfaces.emplace(
                 std::make_pair(std::move(interface), std::move(intf)));
         }
diff --git a/test/test_config_parser.cpp b/test/test_config_parser.cpp
index cd2fa4f..896d61e 100644
--- a/test/test_config_parser.cpp
+++ b/test/test_config_parser.cpp
@@ -69,18 +69,21 @@
 
 TEST_F(TestConfigParser, EmptyObject)
 {
+    EXPECT_TRUE(parser.getFilename().empty());
     EXPECT_EQ(0, parser.getWarnings().size());
 }
 
 TEST_F(TestConfigParser, ReadDirectory)
 {
     parser.setFile("/");
+    EXPECT_EQ("/", parser.getFilename());
     EXPECT_EQ(1, parser.getWarnings().size());
 }
 
 TEST_F(TestConfigParser, ReadConfigDataMissingFile)
 {
     parser.setFile("/no-such-path");
+    EXPECT_EQ("/no-such-path", parser.getFilename());
     EXPECT_EQ(1, parser.getWarnings().size());
 }
 
@@ -88,6 +91,7 @@
 {
     WriteSampleFile();
     parser.setFile(filename);
+    EXPECT_EQ(filename, parser.getFilename());
     EXPECT_EQ(4, parser.getWarnings().size());
 
     EXPECT_THAT(parser.getValues("Match", "Name"), ElementsAre("eth0"));
diff --git a/test/test_ethernet_interface.cpp b/test/test_ethernet_interface.cpp
index 96f00d1..e9ed3fd 100644
--- a/test/test_ethernet_interface.cpp
+++ b/test/test_ethernet_interface.cpp
@@ -43,8 +43,12 @@
     {
         mock_clear();
         mock_addIF("test0", 1, mac);
-        return {bus, "/xyz/openbmc_test/network/test0",
-                EthernetInterface::DHCPConf::none, manager, true};
+        return {bus,
+                "/xyz/openbmc_test/network/test0",
+                config::Parser(),
+                EthernetInterface::DHCPConf::none,
+                manager,
+                true};
     }
 
     int countIPObjects()
diff --git a/test/test_vlan_interface.cpp b/test/test_vlan_interface.cpp
index 126d2d0..5ee1cf9 100644
--- a/test/test_vlan_interface.cpp
+++ b/test/test_vlan_interface.cpp
@@ -43,6 +43,7 @@
         mock_addIF("test0", 1);
         return {bus,
                 "/xyz/openbmc_test/network/test0",
+                config::Parser(),
                 EthernetInterface::DHCPConf::none,
                 manager,
                 false,