inventory_mac: Migrate code out of other places

Change-Id: I5a84c07eebad1b9b0dc535a47edbf6bf0f72b6cb
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/inventory_mac.cpp b/src/inventory_mac.cpp
new file mode 100644
index 0000000..6a60990
--- /dev/null
+++ b/src/inventory_mac.cpp
@@ -0,0 +1,350 @@
+#include "config.h"
+
+#include "inventory_mac.hpp"
+
+#include "network_manager.hpp"
+#include "types.hpp"
+
+#include <filesystem>
+#include <fstream>
+#include <memory>
+#include <nlohmann/json.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
+#include <string>
+#include <vector>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+namespace phosphor::network::inventory
+{
+
+using phosphor::logging::elog;
+using phosphor::logging::entry;
+using phosphor::logging::level;
+using phosphor::logging::log;
+using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+
+using DbusObjectPath = std::string;
+using DbusInterface = std::string;
+using PropertyValue = std::string;
+using DbusService = std::string;
+using ObjectTree = string_umap<string_umap<std::vector<std::string>>>;
+
+constexpr auto firstBootPath = "/var/lib/network/firstBoot_";
+constexpr auto configFile = "/usr/share/network/config.json";
+
+constexpr auto invNetworkIntf =
+    "xyz.openbmc_project.Inventory.Item.NetworkInterface";
+constexpr auto invRoot = "/xyz/openbmc_project/inventory";
+constexpr auto mapperBus = "xyz.openbmc_project.ObjectMapper";
+constexpr auto mapperObj = "/xyz/openbmc_project/object_mapper";
+constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
+constexpr auto propIntf = "org.freedesktop.DBus.Properties";
+constexpr auto methodGet = "Get";
+
+Manager* manager = nullptr;
+std::unique_ptr<sdbusplus::bus::match_t> EthInterfaceMatch = nullptr;
+std::vector<std::string> first_boot_status;
+
+void setFirstBootMACOnInterface(const std::string& intf, const std::string& mac)
+{
+    for (const auto& interface : manager->interfaces)
+    {
+        if (interface.first == intf)
+        {
+            auto returnMAC = interface.second->macAddress(mac);
+            if (returnMAC == mac)
+            {
+                log<level::INFO>(fmt::format("Setting MAC on {}", intf).c_str(),
+                                 entry("INTF=%s", intf.c_str()),
+                                 entry("MAC=%s", mac.c_str()));
+                std::error_code ec;
+                if (std::filesystem::is_directory("/var/lib/network", ec))
+                {
+                    std::ofstream persistentFile(firstBootPath + intf);
+                }
+                break;
+            }
+            else
+            {
+                log<level::INFO>("MAC is Not Set on ethernet Interface");
+            }
+        }
+    }
+}
+
+ether_addr getfromInventory(sdbusplus::bus_t& bus, const std::string& intfName)
+{
+    std::string interfaceName = intfName;
+
+    // load the config JSON from the Read Only Path
+    std::ifstream in(configFile);
+    nlohmann::json configJson;
+    in >> configJson;
+    interfaceName = configJson[intfName];
+
+    std::vector<DbusInterface> interfaces;
+    interfaces.emplace_back(invNetworkIntf);
+
+    auto depth = 0;
+
+    auto mapperCall =
+        bus.new_method_call(mapperBus, mapperObj, mapperIntf, "GetSubTree");
+
+    mapperCall.append(invRoot, depth, interfaces);
+
+    auto mapperReply = bus.call(mapperCall);
+    if (mapperReply.is_method_error())
+    {
+        log<level::ERR>("Error in mapper call");
+        elog<InternalFailure>();
+    }
+
+    ObjectTree objectTree;
+    mapperReply.read(objectTree);
+
+    if (objectTree.empty())
+    {
+        log<level::ERR>("No Object has implemented the interface",
+                        entry("INTERFACE=%s", invNetworkIntf));
+        elog<InternalFailure>();
+    }
+
+    DbusObjectPath objPath;
+    DbusService service;
+
+    if (1 == objectTree.size())
+    {
+        objPath = objectTree.begin()->first;
+        service = objectTree.begin()->second.begin()->first;
+    }
+    else
+    {
+        // If there are more than 2 objects, object path must contain the
+        // interface name
+        for (auto const& object : objectTree)
+        {
+            log<level::INFO>("interface",
+                             entry("INT=%s", interfaceName.c_str()));
+            log<level::INFO>("object", entry("OBJ=%s", object.first.c_str()));
+
+            if (std::string::npos != object.first.find(interfaceName.c_str()))
+            {
+                objPath = object.first;
+                service = object.second.begin()->first;
+                break;
+            }
+        }
+
+        if (objPath.empty())
+        {
+            log<level::ERR>("Can't find the object for the interface",
+                            entry("intfName=%s", interfaceName.c_str()));
+            elog<InternalFailure>();
+        }
+    }
+
+    auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
+                                      propIntf, methodGet);
+
+    method.append(invNetworkIntf, "MACAddress");
+
+    auto reply = bus.call(method);
+    if (reply.is_method_error())
+    {
+        log<level::ERR>("Failed to get MACAddress",
+                        entry("PATH=%s", objPath.c_str()),
+                        entry("INTERFACE=%s", invNetworkIntf));
+        elog<InternalFailure>();
+    }
+
+    std::variant<std::string> value;
+    reply.read(value);
+    return ToAddr<ether_addr>{}(std::get<std::string>(value));
+}
+
+bool setInventoryMACOnSystem(sdbusplus::bus_t& bus,
+                             const nlohmann::json& configJson,
+                             const std::string& intfname)
+{
+    try
+    {
+        auto inventoryMAC = getfromInventory(bus, intfname);
+        if (inventoryMAC != ether_addr{})
+        {
+            auto macStr = std::to_string(inventoryMAC);
+            log<level::INFO>("Mac Address in Inventory on ",
+                             entry("Interface : ", intfname.c_str()),
+                             entry("MAC Address :", macStr.c_str()));
+            setFirstBootMACOnInterface(intfname, macStr);
+            first_boot_status.push_back(intfname);
+            bool status = true;
+            for (const auto& keys : configJson.items())
+            {
+                if (!(std::find(first_boot_status.begin(),
+                                first_boot_status.end(),
+                                keys.key()) != first_boot_status.end()))
+                {
+                    log<level::INFO>("Interface MAC is NOT set from VPD"),
+                        entry("INTERFACE", keys.key().c_str());
+                    status = false;
+                }
+            }
+            if (status)
+            {
+                log<level::INFO>("Removing the match for ethernet interfaces");
+                EthInterfaceMatch = nullptr;
+            }
+        }
+        else
+        {
+            log<level::INFO>("Nothing is present in Inventory");
+            return false;
+        }
+    }
+    catch (const std::exception& e)
+    {
+        log<level::ERR>("Exception occurred during getting of MAC "
+                        "address from Inventory");
+        return false;
+    }
+    return true;
+}
+
+// register the macthes to be monitored from inventory manager
+void registerSignals(sdbusplus::bus_t& bus, const nlohmann::json& configJson)
+{
+    log<level::INFO>("Registering the Inventory Signals Matcher");
+
+    static std::unique_ptr<sdbusplus::bus::match_t> MacAddressMatch;
+
+    auto callback = [&](sdbusplus::message_t& m) {
+        std::map<DbusObjectPath,
+                 std::map<DbusInterface, std::variant<PropertyValue>>>
+            interfacesProperties;
+
+        sdbusplus::message::object_path objPath;
+        m.read(objPath, interfacesProperties);
+
+        for (const auto& pattern : configJson.items())
+        {
+            if (objPath.str.find(pattern.value()) != std::string::npos)
+            {
+                for (auto& interface : interfacesProperties)
+                {
+                    if (interface.first == invNetworkIntf)
+                    {
+                        for (const auto& property : interface.second)
+                        {
+                            if (property.first == "MACAddress")
+                            {
+                                setFirstBootMACOnInterface(
+                                    pattern.key(),
+                                    std::get<std::string>(property.second));
+                                break;
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+    };
+
+    MacAddressMatch = std::make_unique<sdbusplus::bus::match_t>(
+        bus,
+        "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
+        "member='InterfacesAdded',path='/xyz/openbmc_project/"
+        "inventory'",
+        callback);
+}
+
+void watchEthernetInterface(sdbusplus::bus_t& bus,
+                            const nlohmann::json& configJson)
+{
+    auto mycallback = [&](sdbusplus::message_t& m) {
+        std::map<DbusObjectPath,
+                 std::map<DbusInterface, std::variant<PropertyValue>>>
+            interfacesProperties;
+
+        sdbusplus::message::object_path objPath;
+        std::pair<std::string, std::string> ethPair;
+        m.read(objPath, interfacesProperties);
+        for (const auto& interfaces : interfacesProperties)
+        {
+            if (interfaces.first ==
+                "xyz.openbmc_project.Network.EthernetInterface")
+            {
+                for (const auto& property : interfaces.second)
+                {
+                    if (property.first == "InterfaceName")
+                    {
+                        std::string infname =
+                            std::get<std::string>(property.second);
+
+                        if (configJson.find(infname) == configJson.end())
+                        {
+                            // ethernet interface not found in configJSON
+                            // check if it is not sit0 interface, as it is
+                            // expected.
+                            if (infname != "sit0")
+                            {
+                                log<level::ERR>(
+                                    "Wrong Interface Name in Config Json");
+                            }
+                        }
+                        else
+                        {
+                            if (!setInventoryMACOnSystem(bus, configJson,
+                                                         infname))
+                            {
+                                registerSignals(bus, configJson);
+                                EthInterfaceMatch = nullptr;
+                            }
+                        }
+                        break;
+                    }
+                }
+                break;
+            }
+        }
+    };
+    // Incase if phosphor-inventory-manager started early and the VPD is already
+    // collected by the time network service has come up, better to check the
+    // VPD directly and set the MAC Address on the respective Interface.
+
+    bool registeredSignals = false;
+    for (const auto& interfaceString : configJson.items())
+    {
+        if ((FORCE_SYNC_MAC_FROM_INVENTORY ||
+             !std::filesystem::exists(firstBootPath + interfaceString.key())) &&
+            !registeredSignals)
+        {
+            auto msg = fmt::format("{}, check VPD for MAC",
+                                   (FORCE_SYNC_MAC_FROM_INVENTORY)
+                                       ? "Force sync enabled"
+                                       : "First boot file is not present");
+            log<level::INFO>(msg.c_str());
+            EthInterfaceMatch = std::make_unique<sdbusplus::bus::match_t>(
+                bus,
+                "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
+                "member='InterfacesAdded',path='/xyz/openbmc_project/network'",
+                mycallback);
+            registeredSignals = true;
+        }
+    }
+}
+
+std::unique_ptr<Runtime> watch(sdbusplus::bus::bus& bus, Manager& m)
+{
+    manager = &m;
+    std::ifstream in(configFile);
+    nlohmann::json configJson;
+    in >> configJson;
+    watchEthernetInterface(bus, configJson);
+    return nullptr;
+}
+
+} // namespace phosphor::network::inventory
diff --git a/src/inventory_mac.hpp b/src/inventory_mac.hpp
new file mode 100644
index 0000000..f7aec32
--- /dev/null
+++ b/src/inventory_mac.hpp
@@ -0,0 +1,24 @@
+#pragma once
+#include <memory>
+
+namespace sdbusplus::bus
+{
+class bus;
+}
+
+namespace phosphor::network
+{
+
+class Manager;
+
+namespace inventory
+{
+
+struct Runtime
+{
+    virtual ~Runtime() = default;
+};
+std::unique_ptr<Runtime> watch(sdbusplus::bus::bus& bus, Manager& m);
+
+} // namespace inventory
+} // namespace phosphor::network
diff --git a/src/meson.build b/src/meson.build
index 3119a88..93cf1f2 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -17,21 +17,20 @@
   install: true,
   install_dir: get_option('bindir'))
 
-json_dep = declare_dependency()
+main_deps = []
+main_srcs = []
 if get_option('sync-mac')
+  main_srcs += [
+    'inventory_mac.cpp',
+  ]
   # nlohmann_json might not have a pkg-config. It is header only so just make
   # sure we can access the needed symbols from the header.
-  has_json = meson.get_compiler('cpp').has_header_symbol(
-    'nlohmann/json.hpp',
-    'nlohmann::json::string_t',
-    required: false)
-  if not has_json
-    json_dep = dependency('nlohmann_json')
-  endif
+  main_deps += [
+    dependency('nlohmann_json', allow_fallback: true, required: false),
+  ]
 endif
 
 networkd_deps = [
-  json_dep,
   phosphor_dbus_interfaces_dep,
   dependency('phosphor-logging'),
   networkd_dbus_dep,
@@ -74,8 +73,9 @@
 executable(
   'phosphor-network-manager',
   'network_manager_main.cpp',
+  main_srcs,
   implicit_include_directories: false,
-  dependencies: networkd_dep,
+  dependencies: [networkd_dep] + main_deps,
   install: true,
   install_dir: get_option('bindir'))
 
diff --git a/src/network_manager.cpp b/src/network_manager.cpp
index 30af9a6..51863a7 100644
--- a/src/network_manager.cpp
+++ b/src/network_manager.cpp
@@ -1,5 +1,3 @@
-#include "config.h"
-
 #include "network_manager.hpp"
 
 #include "config_parser.hpp"
@@ -13,7 +11,6 @@
 #include <net/if.h>
 
 #include <filesystem>
-#include <fstream>
 #include <phosphor-logging/elog-errors.hpp>
 #include <phosphor-logging/log.hpp>
 #include <sdbusplus/message.hpp>
@@ -22,7 +19,6 @@
 constexpr char SYSTEMD_BUSNAME[] = "org.freedesktop.systemd1";
 constexpr char SYSTEMD_PATH[] = "/org/freedesktop/systemd1";
 constexpr char SYSTEMD_INTERFACE[] = "org.freedesktop.systemd1.Manager";
-constexpr auto FirstBootFile = "/var/lib/network/firstBoot_";
 
 constexpr char NETWORKD_BUSNAME[] = "org.freedesktop.network1";
 constexpr char NETWORKD_PATH[] = "/org/freedesktop/network1";
@@ -467,39 +463,6 @@
     }
 }
 
-#ifdef SYNC_MAC_FROM_INVENTORY
-void Manager::setFistBootMACOnInterface(
-    const std::pair<std::string, std::string>& inventoryEthPair)
-{
-    for (const auto& interface : interfaces)
-    {
-        if (interface.first == inventoryEthPair.first)
-        {
-            auto returnMAC =
-                interface.second->macAddress(inventoryEthPair.second);
-            if (returnMAC == inventoryEthPair.second)
-            {
-                log<level::INFO>("Set the MAC on "),
-                    entry("interface : ", interface.first.c_str()),
-                    entry("MAC : ", inventoryEthPair.second.c_str());
-                std::error_code ec;
-                if (std::filesystem::is_directory("/var/lib/network", ec))
-                {
-                    std::ofstream persistentFile(FirstBootFile +
-                                                 interface.first);
-                }
-                break;
-            }
-            else
-            {
-                log<level::INFO>("MAC is Not Set on ethernet Interface");
-            }
-        }
-    }
-}
-
-#endif
-
 void Manager::reloadConfigs()
 {
     reloadTimer->restartOnce(reloadTimeout);
diff --git a/src/network_manager.hpp b/src/network_manager.hpp
index 27ac8ae..5166f7a 100644
--- a/src/network_manager.hpp
+++ b/src/network_manager.hpp
@@ -90,20 +90,6 @@
         return *dhcpConf;
     }
 
-    /** @brief This function gets the MAC address from the VPD and
-     *  sets it on the corresponding ethernet interface during first
-     *  Boot, once it sets the MAC from VPD, it creates a file named
-     *  firstBoot under /var/lib to make sure we dont run this function
-     *  again.
-     *
-     *  @param[in] ethPair - Its a pair of ethernet interface name & the
-     * corresponding MAC Address from the VPD
-     *
-     *  return - NULL
-     */
-    void setFistBootMACOnInterface(
-        const std::pair<std::string, std::string>& ethPair);
-
     /** @brief Arms a timer to tell systemd-network to reload all of the network
      * configurations
      */
diff --git a/src/network_manager_main.cpp b/src/network_manager_main.cpp
index 15bc59f..dc51915 100644
--- a/src/network_manager_main.cpp
+++ b/src/network_manager_main.cpp
@@ -1,51 +1,29 @@
 #include "config.h"
 
+#ifdef SYNC_MAC_FROM_INVENTORY
+#include "inventory_mac.hpp"
+#endif
 #include "network_manager.hpp"
 #include "rtnetlink_server.hpp"
 #include "types.hpp"
-#ifdef SYNC_MAC_FROM_INVENTORY
-#include "util.hpp"
-#endif
 
 #include <fmt/format.h>
-#include <linux/netlink.h>
 
-#include <filesystem>
-#include <fstream>
 #include <functional>
 #include <memory>
-#ifdef SYNC_MAC_FROM_INVENTORY
-#include <nlohmann/json.hpp>
-#endif
-#include <phosphor-logging/elog-errors.hpp>
 #include <phosphor-logging/log.hpp>
 #include <sdbusplus/bus.hpp>
-#include <sdbusplus/bus/match.hpp>
 #include <sdbusplus/server/manager.hpp>
 #include <sdeventplus/event.hpp>
 #include <sdeventplus/source/signal.hpp>
 #include <stdplus/signal.hpp>
-#include <xyz/openbmc_project/Common/error.hpp>
 
-using phosphor::logging::elog;
-using phosphor::logging::entry;
 using phosphor::logging::level;
 using phosphor::logging::log;
-using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
-using DbusObjectPath = std::string;
-using DbusInterface = std::string;
-using PropertyValue = std::string;
 
 constexpr char NETWORK_CONF_DIR[] = "/etc/systemd/network";
-
 constexpr char DEFAULT_OBJPATH[] = "/xyz/openbmc_project/network";
 
-constexpr auto firstBootPath = "/var/lib/network/firstBoot_";
-constexpr auto configFile = "/usr/share/network/config.json";
-
-constexpr auto invNetworkIntf =
-    "xyz.openbmc_project.Inventory.Item.NetworkInterface";
-
 namespace phosphor
 {
 namespace network
@@ -54,190 +32,6 @@
 std::unique_ptr<Manager> manager = nullptr;
 std::unique_ptr<Timer> reloadTimer = nullptr;
 
-#ifdef SYNC_MAC_FROM_INVENTORY
-std::unique_ptr<sdbusplus::bus::match_t> EthInterfaceMatch = nullptr;
-std::vector<std::string> first_boot_status;
-
-bool setInventoryMACOnSystem(sdbusplus::bus_t& bus,
-                             const nlohmann::json& configJson,
-                             const std::string& intfname)
-{
-    try
-    {
-        auto inventoryMAC = mac_address::getfromInventory(bus, intfname);
-        if (inventoryMAC != ether_addr{})
-        {
-            auto macStr = std::to_string(inventoryMAC);
-            log<level::INFO>("Mac Address in Inventory on ",
-                             entry("Interface : ", intfname.c_str()),
-                             entry("MAC Address :", macStr.c_str()));
-            manager->setFistBootMACOnInterface(
-                std::make_pair(intfname.c_str(), std::move(macStr)));
-            first_boot_status.push_back(intfname.c_str());
-            bool status = true;
-            for (const auto& keys : configJson.items())
-            {
-                if (!(std::find(first_boot_status.begin(),
-                                first_boot_status.end(),
-                                keys.key()) != first_boot_status.end()))
-                {
-                    log<level::INFO>("Interface MAC is NOT set from VPD"),
-                        entry("INTERFACE", keys.key().c_str());
-                    status = false;
-                }
-            }
-            if (status)
-            {
-                log<level::INFO>("Removing the match for ethernet interfaces");
-                EthInterfaceMatch = nullptr;
-            }
-        }
-        else
-        {
-            log<level::INFO>("Nothing is present in Inventory");
-            return false;
-        }
-    }
-    catch (const std::exception& e)
-    {
-        log<level::ERR>("Exception occurred during getting of MAC "
-                        "address from Inventory");
-        return false;
-    }
-    return true;
-}
-
-// register the macthes to be monitored from inventory manager
-void registerSignals(sdbusplus::bus_t& bus, const nlohmann::json& configJson)
-{
-    log<level::INFO>("Registering the Inventory Signals Matcher");
-
-    static std::unique_ptr<sdbusplus::bus::match_t> MacAddressMatch;
-
-    auto callback = [&](sdbusplus::message_t& m) {
-        std::map<DbusObjectPath,
-                 std::map<DbusInterface, std::variant<PropertyValue>>>
-            interfacesProperties;
-
-        sdbusplus::message::object_path objPath;
-        std::pair<std::string, std::string> ethPair;
-        m.read(objPath, interfacesProperties);
-
-        for (const auto& pattern : configJson.items())
-        {
-            if (objPath.str.find(pattern.value()) != std::string::npos)
-            {
-                for (auto& interface : interfacesProperties)
-                {
-                    if (interface.first == invNetworkIntf)
-                    {
-                        for (const auto& property : interface.second)
-                        {
-                            if (property.first == "MACAddress")
-                            {
-                                ethPair = std::make_pair(
-                                    pattern.key(),
-                                    std::get<std::string>(property.second));
-                                break;
-                            }
-                        }
-                        break;
-                    }
-                }
-                if (!(ethPair.first.empty() || ethPair.second.empty()))
-                {
-                    manager->setFistBootMACOnInterface(ethPair);
-                }
-            }
-        }
-    };
-
-    MacAddressMatch = std::make_unique<sdbusplus::bus::match_t>(
-        bus,
-        "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
-        "member='InterfacesAdded',path='/xyz/openbmc_project/"
-        "inventory'",
-        callback);
-}
-
-void watchEthernetInterface(sdbusplus::bus_t& bus,
-                            const nlohmann::json& configJson)
-{
-    auto mycallback = [&](sdbusplus::message_t& m) {
-        std::map<DbusObjectPath,
-                 std::map<DbusInterface, std::variant<PropertyValue>>>
-            interfacesProperties;
-
-        sdbusplus::message::object_path objPath;
-        std::pair<std::string, std::string> ethPair;
-        m.read(objPath, interfacesProperties);
-        for (const auto& interfaces : interfacesProperties)
-        {
-            if (interfaces.first ==
-                "xyz.openbmc_project.Network.EthernetInterface")
-            {
-                for (const auto& property : interfaces.second)
-                {
-                    if (property.first == "InterfaceName")
-                    {
-                        std::string infname =
-                            std::get<std::string>(property.second);
-
-                        if (configJson.find(infname) == configJson.end())
-                        {
-                            // ethernet interface not found in configJSON
-                            // check if it is not sit0 interface, as it is
-                            // expected.
-                            if (infname != "sit0")
-                            {
-                                log<level::ERR>(
-                                    "Wrong Interface Name in Config Json");
-                            }
-                        }
-                        else
-                        {
-                            if (!setInventoryMACOnSystem(bus, configJson,
-                                                         infname))
-                            {
-                                registerSignals(bus, configJson);
-                                EthInterfaceMatch = nullptr;
-                            }
-                        }
-                        break;
-                    }
-                }
-                break;
-            }
-        }
-    };
-    // Incase if phosphor-inventory-manager started early and the VPD is already
-    // collected by the time network service has come up, better to check the
-    // VPD directly and set the MAC Address on the respective Interface.
-
-    bool registeredSignals = false;
-    for (const auto& interfaceString : configJson.items())
-    {
-        if ((FORCE_SYNC_MAC_FROM_INVENTORY ||
-             !std::filesystem::exists(firstBootPath + interfaceString.key())) &&
-            !registeredSignals)
-        {
-            auto msg = fmt::format("{}, check VPD for MAC",
-                                   (FORCE_SYNC_MAC_FROM_INVENTORY)
-                                       ? "Force sync enabled"
-                                       : "First boot file is not present");
-            log<level::INFO>(msg.c_str());
-            EthInterfaceMatch = std::make_unique<sdbusplus::bus::match_t>(
-                bus,
-                "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
-                "member='InterfacesAdded',path='/xyz/openbmc_project/network'",
-                mycallback);
-            registeredSignals = true;
-        }
-    }
-}
-
-#endif
-
 void reloadNetworkd()
 {
     if (manager)
@@ -281,10 +75,7 @@
     netlink::Server svr(event, *manager);
 
 #ifdef SYNC_MAC_FROM_INVENTORY
-    std::ifstream in(configFile);
-    nlohmann::json configJson;
-    in >> configJson;
-    watchEthernetInterface(bus, configJson);
+    auto runtime = inventory::watch(bus, *manager);
 #endif
 
     return event.loop();
diff --git a/src/util.cpp b/src/util.cpp
index 938e4d4..23c642f 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -11,10 +11,6 @@
 
 #include <cctype>
 #include <charconv>
-#include <fstream>
-#ifdef SYNC_MAC_FROM_INVENTORY
-#include <nlohmann/json.hpp>
-#endif
 #include <phosphor-logging/elog-errors.hpp>
 #include <phosphor-logging/log.hpp>
 #include <string>
@@ -224,117 +220,6 @@
 namespace mac_address
 {
 
-constexpr auto mapperBus = "xyz.openbmc_project.ObjectMapper";
-constexpr auto mapperObj = "/xyz/openbmc_project/object_mapper";
-constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
-constexpr auto propIntf = "org.freedesktop.DBus.Properties";
-constexpr auto methodGet = "Get";
-constexpr auto configFile = "/usr/share/network/config.json";
-
-using DbusObjectPath = std::string;
-using DbusService = std::string;
-using DbusInterface = std::string;
-using ObjectTree =
-    std::map<DbusObjectPath, std::map<DbusService, std::vector<DbusInterface>>>;
-
-constexpr auto invBus = "xyz.openbmc_project.Inventory.Manager";
-constexpr auto invNetworkIntf =
-    "xyz.openbmc_project.Inventory.Item.NetworkInterface";
-constexpr auto invRoot = "/xyz/openbmc_project/inventory";
-
-ether_addr getfromInventory(sdbusplus::bus_t& bus, const std::string& intfName)
-{
-
-    std::string interfaceName = intfName;
-
-#ifdef SYNC_MAC_FROM_INVENTORY
-    // load the config JSON from the Read Only Path
-    std::ifstream in(configFile);
-    nlohmann::json configJson;
-    in >> configJson;
-    interfaceName = configJson[intfName];
-#endif
-
-    std::vector<DbusInterface> interfaces;
-    interfaces.emplace_back(invNetworkIntf);
-
-    auto depth = 0;
-
-    auto mapperCall =
-        bus.new_method_call(mapperBus, mapperObj, mapperIntf, "GetSubTree");
-
-    mapperCall.append(invRoot, depth, interfaces);
-
-    auto mapperReply = bus.call(mapperCall);
-    if (mapperReply.is_method_error())
-    {
-        log<level::ERR>("Error in mapper call");
-        elog<InternalFailure>();
-    }
-
-    ObjectTree objectTree;
-    mapperReply.read(objectTree);
-
-    if (objectTree.empty())
-    {
-        log<level::ERR>("No Object has implemented the interface",
-                        entry("INTERFACE=%s", invNetworkIntf));
-        elog<InternalFailure>();
-    }
-
-    DbusObjectPath objPath;
-    DbusService service;
-
-    if (1 == objectTree.size())
-    {
-        objPath = objectTree.begin()->first;
-        service = objectTree.begin()->second.begin()->first;
-    }
-    else
-    {
-        // If there are more than 2 objects, object path must contain the
-        // interface name
-        for (auto const& object : objectTree)
-        {
-            log<level::INFO>("interface",
-                             entry("INT=%s", interfaceName.c_str()));
-            log<level::INFO>("object", entry("OBJ=%s", object.first.c_str()));
-
-            if (std::string::npos != object.first.find(interfaceName.c_str()))
-            {
-                objPath = object.first;
-                service = object.second.begin()->first;
-                break;
-            }
-        }
-
-        if (objPath.empty())
-        {
-            log<level::ERR>("Can't find the object for the interface",
-                            entry("intfName=%s", interfaceName.c_str()));
-            elog<InternalFailure>();
-        }
-    }
-
-    auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
-                                      propIntf, methodGet);
-
-    method.append(invNetworkIntf, "MACAddress");
-
-    auto reply = bus.call(method);
-    if (reply.is_method_error())
-    {
-        log<level::ERR>("Failed to get MACAddress",
-                        entry("PATH=%s", objPath.c_str()),
-                        entry("INTERFACE=%s", invNetworkIntf));
-        elog<InternalFailure>();
-    }
-
-    std::variant<std::string> value;
-    reply.read(value);
-    return ToAddr<ether_addr>{}(std::get<std::string>(value));
-}
-
 bool isEmpty(const ether_addr& mac)
 {
     return mac == ether_addr{};
diff --git a/src/util.hpp b/src/util.hpp
index 4cf27a0..90beca2 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -1,20 +1,12 @@
 #pragma once
 #include "types.hpp"
 
-#include <net/ethernet.h>
-#include <netinet/in.h>
-#include <unistd.h>
-
-#include <cstring>
-#include <filesystem>
 #include <optional>
-#include <sdbusplus/bus.hpp>
 #include <stdplus/raw.hpp>
 #include <stdplus/zstring.hpp>
 #include <string>
 #include <string_view>
 #include <unordered_set>
-#include <xyz/openbmc_project/Network/EthernetInterface/server.hpp>
 
 namespace phosphor
 {
@@ -25,18 +17,9 @@
 class Parser;
 }
 
-using EthernetInterfaceIntf =
-    sdbusplus::xyz::openbmc_project::Network::server::EthernetInterface;
-
 namespace mac_address
 {
 
-/** @brief gets the MAC address from the Inventory.
- *  @param[in] bus - DBUS Bus Object.
- *  @param[in] intfName - Interface name
- */
-ether_addr getfromInventory(sdbusplus::bus_t& bus, const std::string& intfName);
-
 /** @brief Determines if the mac address is empty
  *  @param[in] mac - The mac address
  *  @return True if 00:00:00:00:00:00