11bbe3d1eSWilliam A. Kennington III #include "config.h"
21bbe3d1eSWilliam A. Kennington III 
31bbe3d1eSWilliam A. Kennington III #include "network_manager.hpp"
41bbe3d1eSWilliam A. Kennington III #include "rtnetlink_server.hpp"
51bbe3d1eSWilliam A. Kennington III #include "types.hpp"
61bbe3d1eSWilliam A. Kennington III 
71bbe3d1eSWilliam A. Kennington III #include <linux/netlink.h>
81bbe3d1eSWilliam A. Kennington III 
91bbe3d1eSWilliam A. Kennington III #include <filesystem>
101bbe3d1eSWilliam A. Kennington III #include <fstream>
111bbe3d1eSWilliam A. Kennington III #include <functional>
121bbe3d1eSWilliam A. Kennington III #include <memory>
131bbe3d1eSWilliam A. Kennington III #ifdef SYNC_MAC_FROM_INVENTORY
141bbe3d1eSWilliam A. Kennington III #include <nlohmann/json.hpp>
151bbe3d1eSWilliam A. Kennington III #endif
161bbe3d1eSWilliam A. Kennington III #include <phosphor-logging/elog-errors.hpp>
171bbe3d1eSWilliam A. Kennington III #include <phosphor-logging/log.hpp>
181bbe3d1eSWilliam A. Kennington III #include <sdbusplus/bus.hpp>
191bbe3d1eSWilliam A. Kennington III #include <sdbusplus/bus/match.hpp>
201bbe3d1eSWilliam A. Kennington III #include <sdbusplus/server/manager.hpp>
211bbe3d1eSWilliam A. Kennington III #include <sdeventplus/event.hpp>
221bbe3d1eSWilliam A. Kennington III #include <xyz/openbmc_project/Common/error.hpp>
231bbe3d1eSWilliam A. Kennington III 
241bbe3d1eSWilliam A. Kennington III using phosphor::logging::elog;
251bbe3d1eSWilliam A. Kennington III using phosphor::logging::entry;
261bbe3d1eSWilliam A. Kennington III using phosphor::logging::level;
271bbe3d1eSWilliam A. Kennington III using phosphor::logging::log;
281bbe3d1eSWilliam A. Kennington III using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
291bbe3d1eSWilliam A. Kennington III using DbusObjectPath = std::string;
301bbe3d1eSWilliam A. Kennington III using DbusInterface = std::string;
311bbe3d1eSWilliam A. Kennington III using PropertyValue = std::string;
321bbe3d1eSWilliam A. Kennington III 
331bbe3d1eSWilliam A. Kennington III constexpr char NETWORK_CONF_DIR[] = "/etc/systemd/network";
341bbe3d1eSWilliam A. Kennington III 
351bbe3d1eSWilliam A. Kennington III constexpr char DEFAULT_OBJPATH[] = "/xyz/openbmc_project/network";
361bbe3d1eSWilliam A. Kennington III 
371bbe3d1eSWilliam A. Kennington III constexpr auto firstBootPath = "/var/lib/network/firstBoot_";
381bbe3d1eSWilliam A. Kennington III constexpr auto configFile = "/usr/share/network/config.json";
391bbe3d1eSWilliam A. Kennington III 
401bbe3d1eSWilliam A. Kennington III constexpr auto invNetworkIntf =
411bbe3d1eSWilliam A. Kennington III     "xyz.openbmc_project.Inventory.Item.NetworkInterface";
421bbe3d1eSWilliam A. Kennington III 
431bbe3d1eSWilliam A. Kennington III namespace phosphor
441bbe3d1eSWilliam A. Kennington III {
451bbe3d1eSWilliam A. Kennington III namespace network
461bbe3d1eSWilliam A. Kennington III {
471bbe3d1eSWilliam A. Kennington III 
481bbe3d1eSWilliam A. Kennington III std::unique_ptr<phosphor::network::Manager> manager = nullptr;
491bbe3d1eSWilliam A. Kennington III std::unique_ptr<Timer> refreshObjectTimer = nullptr;
50c7cf25f7SWilliam A. Kennington III std::unique_ptr<Timer> reloadTimer = nullptr;
511bbe3d1eSWilliam A. Kennington III 
521bbe3d1eSWilliam A. Kennington III #ifdef SYNC_MAC_FROM_INVENTORY
53c38b0710SPatrick Williams std::unique_ptr<sdbusplus::bus::match_t> EthInterfaceMatch = nullptr;
541bbe3d1eSWilliam A. Kennington III std::vector<std::string> first_boot_status;
551bbe3d1eSWilliam A. Kennington III 
56c38b0710SPatrick Williams bool setInventoryMACOnSystem(sdbusplus::bus_t& bus,
571bbe3d1eSWilliam A. Kennington III                              const nlohmann::json& configJson,
581bbe3d1eSWilliam A. Kennington III                              const std::string& intfname)
591bbe3d1eSWilliam A. Kennington III {
601bbe3d1eSWilliam A. Kennington III     try
611bbe3d1eSWilliam A. Kennington III     {
621bbe3d1eSWilliam A. Kennington III         auto inventoryMAC = mac_address::getfromInventory(bus, intfname);
631bbe3d1eSWilliam A. Kennington III         if (!mac_address::toString(inventoryMAC).empty())
641bbe3d1eSWilliam A. Kennington III         {
651bbe3d1eSWilliam A. Kennington III             log<level::INFO>("Mac Address in Inventory on "),
661bbe3d1eSWilliam A. Kennington III                 entry("Interface : ", intfname.c_str()),
671bbe3d1eSWilliam A. Kennington III                 entry("MAC Address :",
681bbe3d1eSWilliam A. Kennington III                       (mac_address::toString(inventoryMAC)).c_str());
691bbe3d1eSWilliam A. Kennington III             manager->setFistBootMACOnInterface(std::make_pair(
701bbe3d1eSWilliam A. Kennington III                 intfname.c_str(), mac_address::toString(inventoryMAC)));
711bbe3d1eSWilliam A. Kennington III             first_boot_status.push_back(intfname.c_str());
721bbe3d1eSWilliam A. Kennington III             bool status = true;
731bbe3d1eSWilliam A. Kennington III             for (const auto& keys : configJson.items())
741bbe3d1eSWilliam A. Kennington III             {
751bbe3d1eSWilliam A. Kennington III                 if (!(std::find(first_boot_status.begin(),
761bbe3d1eSWilliam A. Kennington III                                 first_boot_status.end(),
771bbe3d1eSWilliam A. Kennington III                                 keys.key()) != first_boot_status.end()))
781bbe3d1eSWilliam A. Kennington III                 {
791bbe3d1eSWilliam A. Kennington III                     log<level::INFO>("Interface MAC is NOT set from VPD"),
801bbe3d1eSWilliam A. Kennington III                         entry("INTERFACE", keys.key().c_str());
811bbe3d1eSWilliam A. Kennington III                     status = false;
821bbe3d1eSWilliam A. Kennington III                 }
831bbe3d1eSWilliam A. Kennington III             }
841bbe3d1eSWilliam A. Kennington III             if (status)
851bbe3d1eSWilliam A. Kennington III             {
861bbe3d1eSWilliam A. Kennington III                 log<level::INFO>("Removing the match for ethernet interfaces");
871bbe3d1eSWilliam A. Kennington III                 phosphor::network::EthInterfaceMatch = nullptr;
881bbe3d1eSWilliam A. Kennington III             }
891bbe3d1eSWilliam A. Kennington III         }
901bbe3d1eSWilliam A. Kennington III         else
911bbe3d1eSWilliam A. Kennington III         {
921bbe3d1eSWilliam A. Kennington III             log<level::INFO>("Nothing is present in Inventory");
931bbe3d1eSWilliam A. Kennington III             return false;
941bbe3d1eSWilliam A. Kennington III         }
951bbe3d1eSWilliam A. Kennington III     }
961bbe3d1eSWilliam A. Kennington III     catch (const std::exception& e)
971bbe3d1eSWilliam A. Kennington III     {
981bbe3d1eSWilliam A. Kennington III         log<level::ERR>("Exception occurred during getting of MAC "
991bbe3d1eSWilliam A. Kennington III                         "address from Inventory");
1001bbe3d1eSWilliam A. Kennington III         return false;
1011bbe3d1eSWilliam A. Kennington III     }
1021bbe3d1eSWilliam A. Kennington III     return true;
1031bbe3d1eSWilliam A. Kennington III }
1041bbe3d1eSWilliam A. Kennington III 
1051bbe3d1eSWilliam A. Kennington III // register the macthes to be monitored from inventory manager
106c38b0710SPatrick Williams void registerSignals(sdbusplus::bus_t& bus, const nlohmann::json& configJson)
1071bbe3d1eSWilliam A. Kennington III {
1081bbe3d1eSWilliam A. Kennington III     log<level::INFO>("Registering the Inventory Signals Matcher");
1091bbe3d1eSWilliam A. Kennington III 
110c38b0710SPatrick Williams     static std::unique_ptr<sdbusplus::bus::match_t> MacAddressMatch;
1111bbe3d1eSWilliam A. Kennington III 
112c38b0710SPatrick Williams     auto callback = [&](sdbusplus::message_t& m) {
1131bbe3d1eSWilliam A. Kennington III         std::map<DbusObjectPath,
1141bbe3d1eSWilliam A. Kennington III                  std::map<DbusInterface, std::variant<PropertyValue>>>
1151bbe3d1eSWilliam A. Kennington III             interfacesProperties;
1161bbe3d1eSWilliam A. Kennington III 
1171bbe3d1eSWilliam A. Kennington III         sdbusplus::message::object_path objPath;
1181bbe3d1eSWilliam A. Kennington III         std::pair<std::string, std::string> ethPair;
1191bbe3d1eSWilliam A. Kennington III         m.read(objPath, interfacesProperties);
1201bbe3d1eSWilliam A. Kennington III 
1211bbe3d1eSWilliam A. Kennington III         for (const auto& pattern : configJson.items())
1221bbe3d1eSWilliam A. Kennington III         {
1231bbe3d1eSWilliam A. Kennington III             if (objPath.str.find(pattern.value()) != std::string::npos)
1241bbe3d1eSWilliam A. Kennington III             {
1251bbe3d1eSWilliam A. Kennington III                 for (auto& interface : interfacesProperties)
1261bbe3d1eSWilliam A. Kennington III                 {
1271bbe3d1eSWilliam A. Kennington III                     if (interface.first == invNetworkIntf)
1281bbe3d1eSWilliam A. Kennington III                     {
1291bbe3d1eSWilliam A. Kennington III                         for (const auto& property : interface.second)
1301bbe3d1eSWilliam A. Kennington III                         {
1311bbe3d1eSWilliam A. Kennington III                             if (property.first == "MACAddress")
1321bbe3d1eSWilliam A. Kennington III                             {
1331bbe3d1eSWilliam A. Kennington III                                 ethPair = std::make_pair(
1341bbe3d1eSWilliam A. Kennington III                                     pattern.key(),
1351bbe3d1eSWilliam A. Kennington III                                     std::get<std::string>(property.second));
1361bbe3d1eSWilliam A. Kennington III                                 break;
1371bbe3d1eSWilliam A. Kennington III                             }
1381bbe3d1eSWilliam A. Kennington III                         }
1391bbe3d1eSWilliam A. Kennington III                         break;
1401bbe3d1eSWilliam A. Kennington III                     }
1411bbe3d1eSWilliam A. Kennington III                 }
1421bbe3d1eSWilliam A. Kennington III                 if (!(ethPair.first.empty() || ethPair.second.empty()))
1431bbe3d1eSWilliam A. Kennington III                 {
1441bbe3d1eSWilliam A. Kennington III                     manager->setFistBootMACOnInterface(ethPair);
1451bbe3d1eSWilliam A. Kennington III                 }
1461bbe3d1eSWilliam A. Kennington III             }
1471bbe3d1eSWilliam A. Kennington III         }
1481bbe3d1eSWilliam A. Kennington III     };
1491bbe3d1eSWilliam A. Kennington III 
150c38b0710SPatrick Williams     MacAddressMatch = std::make_unique<sdbusplus::bus::match_t>(
1511bbe3d1eSWilliam A. Kennington III         bus,
1521bbe3d1eSWilliam A. Kennington III         "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
1531bbe3d1eSWilliam A. Kennington III         "member='InterfacesAdded',path='/xyz/openbmc_project/"
1541bbe3d1eSWilliam A. Kennington III         "inventory'",
1551bbe3d1eSWilliam A. Kennington III         callback);
1561bbe3d1eSWilliam A. Kennington III }
1571bbe3d1eSWilliam A. Kennington III 
158c38b0710SPatrick Williams void watchEthernetInterface(sdbusplus::bus_t& bus,
1591bbe3d1eSWilliam A. Kennington III                             const nlohmann::json& configJson)
1601bbe3d1eSWilliam A. Kennington III {
161c38b0710SPatrick Williams     auto mycallback = [&](sdbusplus::message_t& m) {
1621bbe3d1eSWilliam A. Kennington III         std::map<DbusObjectPath,
1631bbe3d1eSWilliam A. Kennington III                  std::map<DbusInterface, std::variant<PropertyValue>>>
1641bbe3d1eSWilliam A. Kennington III             interfacesProperties;
1651bbe3d1eSWilliam A. Kennington III 
1661bbe3d1eSWilliam A. Kennington III         sdbusplus::message::object_path objPath;
1671bbe3d1eSWilliam A. Kennington III         std::pair<std::string, std::string> ethPair;
1681bbe3d1eSWilliam A. Kennington III         m.read(objPath, interfacesProperties);
1691bbe3d1eSWilliam A. Kennington III         for (const auto& interfaces : interfacesProperties)
1701bbe3d1eSWilliam A. Kennington III         {
1711bbe3d1eSWilliam A. Kennington III             if (interfaces.first ==
1721bbe3d1eSWilliam A. Kennington III                 "xyz.openbmc_project.Network.EthernetInterface")
1731bbe3d1eSWilliam A. Kennington III             {
1741bbe3d1eSWilliam A. Kennington III                 for (const auto& property : interfaces.second)
1751bbe3d1eSWilliam A. Kennington III                 {
1761bbe3d1eSWilliam A. Kennington III                     if (property.first == "InterfaceName")
1771bbe3d1eSWilliam A. Kennington III                     {
1781bbe3d1eSWilliam A. Kennington III                         std::string infname =
1791bbe3d1eSWilliam A. Kennington III                             std::get<std::string>(property.second);
1801bbe3d1eSWilliam A. Kennington III 
1811bbe3d1eSWilliam A. Kennington III                         if (configJson.find(infname) == configJson.end())
1821bbe3d1eSWilliam A. Kennington III                         {
1831bbe3d1eSWilliam A. Kennington III                             // ethernet interface not found in configJSON
1841bbe3d1eSWilliam A. Kennington III                             // check if it is not sit0 interface, as it is
1851bbe3d1eSWilliam A. Kennington III                             // expected.
1861bbe3d1eSWilliam A. Kennington III                             if (infname != "sit0")
1871bbe3d1eSWilliam A. Kennington III                             {
1881bbe3d1eSWilliam A. Kennington III                                 log<level::ERR>(
1891bbe3d1eSWilliam A. Kennington III                                     "Wrong Interface Name in Config Json");
1901bbe3d1eSWilliam A. Kennington III                             }
1911bbe3d1eSWilliam A. Kennington III                         }
1921bbe3d1eSWilliam A. Kennington III                         else
1931bbe3d1eSWilliam A. Kennington III                         {
1941bbe3d1eSWilliam A. Kennington III                             if (!phosphor::network::setInventoryMACOnSystem(
1951bbe3d1eSWilliam A. Kennington III                                     bus, configJson, infname))
1961bbe3d1eSWilliam A. Kennington III                             {
1971bbe3d1eSWilliam A. Kennington III                                 phosphor::network::registerSignals(bus,
1981bbe3d1eSWilliam A. Kennington III                                                                    configJson);
1991bbe3d1eSWilliam A. Kennington III                                 phosphor::network::EthInterfaceMatch = nullptr;
2001bbe3d1eSWilliam A. Kennington III                             }
2011bbe3d1eSWilliam A. Kennington III                         }
2021bbe3d1eSWilliam A. Kennington III                         break;
2031bbe3d1eSWilliam A. Kennington III                     }
2041bbe3d1eSWilliam A. Kennington III                 }
2051bbe3d1eSWilliam A. Kennington III                 break;
2061bbe3d1eSWilliam A. Kennington III             }
2071bbe3d1eSWilliam A. Kennington III         }
2081bbe3d1eSWilliam A. Kennington III     };
2091bbe3d1eSWilliam A. Kennington III     // Incase if phosphor-inventory-manager started early and the VPD is already
2101bbe3d1eSWilliam A. Kennington III     // collected by the time network service has come up, better to check the
2111bbe3d1eSWilliam A. Kennington III     // VPD directly and set the MAC Address on the respective Interface.
2121bbe3d1eSWilliam A. Kennington III 
2131bbe3d1eSWilliam A. Kennington III     bool registeredSignals = false;
2141bbe3d1eSWilliam A. Kennington III     for (const auto& interfaceString : configJson.items())
2151bbe3d1eSWilliam A. Kennington III     {
2161bbe3d1eSWilliam A. Kennington III         if (!std::filesystem::exists(firstBootPath + interfaceString.key()) &&
2171bbe3d1eSWilliam A. Kennington III             !registeredSignals)
2181bbe3d1eSWilliam A. Kennington III         {
2191bbe3d1eSWilliam A. Kennington III 
2201bbe3d1eSWilliam A. Kennington III             log<level::INFO>(
2211bbe3d1eSWilliam A. Kennington III                 "First boot file is not present, check VPD for MAC");
2221bbe3d1eSWilliam A. Kennington III             phosphor::network::EthInterfaceMatch = std::make_unique<
223c38b0710SPatrick Williams                 sdbusplus::bus::match_t>(
2241bbe3d1eSWilliam A. Kennington III                 bus,
2251bbe3d1eSWilliam A. Kennington III                 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
2261bbe3d1eSWilliam A. Kennington III                 "member='InterfacesAdded',path='/xyz/openbmc_project/network'",
2271bbe3d1eSWilliam A. Kennington III                 mycallback);
2281bbe3d1eSWilliam A. Kennington III             registeredSignals = true;
2291bbe3d1eSWilliam A. Kennington III         }
2301bbe3d1eSWilliam A. Kennington III     }
2311bbe3d1eSWilliam A. Kennington III }
2321bbe3d1eSWilliam A. Kennington III 
2331bbe3d1eSWilliam A. Kennington III #endif
2341bbe3d1eSWilliam A. Kennington III 
2351bbe3d1eSWilliam A. Kennington III /** @brief refresh the network objects. */
2361bbe3d1eSWilliam A. Kennington III void refreshObjects()
2371bbe3d1eSWilliam A. Kennington III {
2381bbe3d1eSWilliam A. Kennington III     if (manager)
2391bbe3d1eSWilliam A. Kennington III     {
2401bbe3d1eSWilliam A. Kennington III         log<level::INFO>("Refreshing the objects.");
2411bbe3d1eSWilliam A. Kennington III         manager->createChildObjects();
2421bbe3d1eSWilliam A. Kennington III         log<level::INFO>("Refreshing complete.");
2431bbe3d1eSWilliam A. Kennington III     }
2441bbe3d1eSWilliam A. Kennington III }
2451bbe3d1eSWilliam A. Kennington III 
246c7cf25f7SWilliam A. Kennington III void reloadNetworkd()
247c7cf25f7SWilliam A. Kennington III {
248c7cf25f7SWilliam A. Kennington III     if (manager)
249c7cf25f7SWilliam A. Kennington III     {
250c7cf25f7SWilliam A. Kennington III         log<level::INFO>("Sending networkd reload");
251c7cf25f7SWilliam A. Kennington III         manager->doReloadConfigs();
252c7cf25f7SWilliam A. Kennington III         log<level::INFO>("Done networkd reload");
253c7cf25f7SWilliam A. Kennington III     }
254c7cf25f7SWilliam A. Kennington III }
255c7cf25f7SWilliam A. Kennington III 
2561bbe3d1eSWilliam A. Kennington III void initializeTimers()
2571bbe3d1eSWilliam A. Kennington III {
2581bbe3d1eSWilliam A. Kennington III     auto event = sdeventplus::Event::get_default();
2591bbe3d1eSWilliam A. Kennington III     refreshObjectTimer =
2601bbe3d1eSWilliam A. Kennington III         std::make_unique<Timer>(event, std::bind(refreshObjects));
261c7cf25f7SWilliam A. Kennington III     reloadTimer = std::make_unique<Timer>(event, std::bind(reloadNetworkd));
2621bbe3d1eSWilliam A. Kennington III }
2631bbe3d1eSWilliam A. Kennington III 
2641bbe3d1eSWilliam A. Kennington III } // namespace network
2651bbe3d1eSWilliam A. Kennington III } // namespace phosphor
2661bbe3d1eSWilliam A. Kennington III 
2671bbe3d1eSWilliam A. Kennington III int main(int /*argc*/, char** /*argv*/)
2681bbe3d1eSWilliam A. Kennington III {
2691bbe3d1eSWilliam A. Kennington III     phosphor::network::initializeTimers();
2701bbe3d1eSWilliam A. Kennington III 
2711bbe3d1eSWilliam A. Kennington III     auto bus = sdbusplus::bus::new_default();
2721bbe3d1eSWilliam A. Kennington III 
2731bbe3d1eSWilliam A. Kennington III     // Need sd_event to watch for OCC device errors
2741bbe3d1eSWilliam A. Kennington III     sd_event* event = nullptr;
2751bbe3d1eSWilliam A. Kennington III     auto r = sd_event_default(&event);
2761bbe3d1eSWilliam A. Kennington III     if (r < 0)
2771bbe3d1eSWilliam A. Kennington III     {
2781bbe3d1eSWilliam A. Kennington III         log<level::ERR>("Error creating a default sd_event handler");
2791bbe3d1eSWilliam A. Kennington III         return r;
2801bbe3d1eSWilliam A. Kennington III     }
2811bbe3d1eSWilliam A. Kennington III 
2821bbe3d1eSWilliam A. Kennington III     phosphor::network::EventPtr eventPtr{event};
2831bbe3d1eSWilliam A. Kennington III     event = nullptr;
2841bbe3d1eSWilliam A. Kennington III 
2851bbe3d1eSWilliam A. Kennington III     // Attach the bus to sd_event to service user requests
2861bbe3d1eSWilliam A. Kennington III     bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL);
2871bbe3d1eSWilliam A. Kennington III 
2881bbe3d1eSWilliam A. Kennington III     // Add sdbusplus Object Manager for the 'root' path of the network manager.
289c38b0710SPatrick Williams     sdbusplus::server::manager_t objManager(bus, DEFAULT_OBJPATH);
2901bbe3d1eSWilliam A. Kennington III     bus.request_name(DEFAULT_BUSNAME);
2911bbe3d1eSWilliam A. Kennington III 
2921bbe3d1eSWilliam A. Kennington III     phosphor::network::manager = std::make_unique<phosphor::network::Manager>(
2931bbe3d1eSWilliam A. Kennington III         bus, DEFAULT_OBJPATH, NETWORK_CONF_DIR);
2941bbe3d1eSWilliam A. Kennington III 
2951bbe3d1eSWilliam A. Kennington III     // create the default network files if the network file
2961bbe3d1eSWilliam A. Kennington III     // is not there for any interface.
297*9a1d9afaSWilliam A. Kennington III     if (phosphor::network::manager->createDefaultNetworkFiles())
2981bbe3d1eSWilliam A. Kennington III     {
299bd649af9SWilliam A. Kennington III         phosphor::network::manager->reloadConfigs();
3001bbe3d1eSWilliam A. Kennington III     }
3011bbe3d1eSWilliam A. Kennington III 
3021bbe3d1eSWilliam A. Kennington III     // RTNETLINK event handler
30332eef716SWilliam A. Kennington III     phosphor::network::rtnetlink::Server svr(eventPtr);
3041bbe3d1eSWilliam A. Kennington III 
3051bbe3d1eSWilliam A. Kennington III #ifdef SYNC_MAC_FROM_INVENTORY
3061bbe3d1eSWilliam A. Kennington III     std::ifstream in(configFile);
3071bbe3d1eSWilliam A. Kennington III     nlohmann::json configJson;
3081bbe3d1eSWilliam A. Kennington III     in >> configJson;
3091bbe3d1eSWilliam A. Kennington III     phosphor::network::watchEthernetInterface(bus, configJson);
3101bbe3d1eSWilliam A. Kennington III #endif
311bd649af9SWilliam A. Kennington III 
312bd649af9SWilliam A. Kennington III     // Trigger the initial object scan
31326c40a43SWilliam A. Kennington III     // This is intentionally deferred, to ensure that systemd-networkd is
31426c40a43SWilliam A. Kennington III     // fully configured.
31526c40a43SWilliam A. Kennington III     phosphor::network::refreshObjectTimer->restartOnce(
31626c40a43SWilliam A. Kennington III         phosphor::network::refreshTimeout);
317bd649af9SWilliam A. Kennington III 
3181bbe3d1eSWilliam A. Kennington III     sd_event_loop(eventPtr.get());
3191bbe3d1eSWilliam A. Kennington III }
320