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"
695530ec9SWilliam A. Kennington III #ifdef SYNC_MAC_FROM_INVENTORY
795530ec9SWilliam A. Kennington III #include "util.hpp"
895530ec9SWilliam A. Kennington III #endif
91bbe3d1eSWilliam A. Kennington III 
104fd52ae4SWilliam A. Kennington III #include <fmt/format.h>
111bbe3d1eSWilliam A. Kennington III #include <linux/netlink.h>
121bbe3d1eSWilliam A. Kennington III 
131bbe3d1eSWilliam A. Kennington III #include <filesystem>
141bbe3d1eSWilliam A. Kennington III #include <fstream>
151bbe3d1eSWilliam A. Kennington III #include <functional>
161bbe3d1eSWilliam A. Kennington III #include <memory>
171bbe3d1eSWilliam A. Kennington III #ifdef SYNC_MAC_FROM_INVENTORY
181bbe3d1eSWilliam A. Kennington III #include <nlohmann/json.hpp>
191bbe3d1eSWilliam A. Kennington III #endif
201bbe3d1eSWilliam A. Kennington III #include <phosphor-logging/elog-errors.hpp>
211bbe3d1eSWilliam A. Kennington III #include <phosphor-logging/log.hpp>
221bbe3d1eSWilliam A. Kennington III #include <sdbusplus/bus.hpp>
231bbe3d1eSWilliam A. Kennington III #include <sdbusplus/bus/match.hpp>
241bbe3d1eSWilliam A. Kennington III #include <sdbusplus/server/manager.hpp>
251bbe3d1eSWilliam A. Kennington III #include <sdeventplus/event.hpp>
26*217bb3fdSWilliam A. Kennington III #include <sdeventplus/source/signal.hpp>
27*217bb3fdSWilliam A. Kennington III #include <stdplus/signal.hpp>
281bbe3d1eSWilliam A. Kennington III #include <xyz/openbmc_project/Common/error.hpp>
291bbe3d1eSWilliam A. Kennington III 
301bbe3d1eSWilliam A. Kennington III using phosphor::logging::elog;
311bbe3d1eSWilliam A. Kennington III using phosphor::logging::entry;
321bbe3d1eSWilliam A. Kennington III using phosphor::logging::level;
331bbe3d1eSWilliam A. Kennington III using phosphor::logging::log;
341bbe3d1eSWilliam A. Kennington III using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
351bbe3d1eSWilliam A. Kennington III using DbusObjectPath = std::string;
361bbe3d1eSWilliam A. Kennington III using DbusInterface = std::string;
371bbe3d1eSWilliam A. Kennington III using PropertyValue = std::string;
381bbe3d1eSWilliam A. Kennington III 
391bbe3d1eSWilliam A. Kennington III constexpr char NETWORK_CONF_DIR[] = "/etc/systemd/network";
401bbe3d1eSWilliam A. Kennington III 
411bbe3d1eSWilliam A. Kennington III constexpr char DEFAULT_OBJPATH[] = "/xyz/openbmc_project/network";
421bbe3d1eSWilliam A. Kennington III 
431bbe3d1eSWilliam A. Kennington III constexpr auto firstBootPath = "/var/lib/network/firstBoot_";
441bbe3d1eSWilliam A. Kennington III constexpr auto configFile = "/usr/share/network/config.json";
451bbe3d1eSWilliam A. Kennington III 
461bbe3d1eSWilliam A. Kennington III constexpr auto invNetworkIntf =
471bbe3d1eSWilliam A. Kennington III     "xyz.openbmc_project.Inventory.Item.NetworkInterface";
481bbe3d1eSWilliam A. Kennington III 
491bbe3d1eSWilliam A. Kennington III namespace phosphor
501bbe3d1eSWilliam A. Kennington III {
511bbe3d1eSWilliam A. Kennington III namespace network
521bbe3d1eSWilliam A. Kennington III {
531bbe3d1eSWilliam A. Kennington III 
544fd52ae4SWilliam A. Kennington III std::unique_ptr<Manager> manager = nullptr;
551bbe3d1eSWilliam A. Kennington III std::unique_ptr<Timer> refreshObjectTimer = nullptr;
56c7cf25f7SWilliam A. Kennington III std::unique_ptr<Timer> reloadTimer = nullptr;
571bbe3d1eSWilliam A. Kennington III 
581bbe3d1eSWilliam A. Kennington III #ifdef SYNC_MAC_FROM_INVENTORY
59c38b0710SPatrick Williams std::unique_ptr<sdbusplus::bus::match_t> EthInterfaceMatch = nullptr;
601bbe3d1eSWilliam A. Kennington III std::vector<std::string> first_boot_status;
611bbe3d1eSWilliam A. Kennington III 
62c38b0710SPatrick Williams bool setInventoryMACOnSystem(sdbusplus::bus_t& bus,
631bbe3d1eSWilliam A. Kennington III                              const nlohmann::json& configJson,
641bbe3d1eSWilliam A. Kennington III                              const std::string& intfname)
651bbe3d1eSWilliam A. Kennington III {
661bbe3d1eSWilliam A. Kennington III     try
671bbe3d1eSWilliam A. Kennington III     {
681bbe3d1eSWilliam A. Kennington III         auto inventoryMAC = mac_address::getfromInventory(bus, intfname);
69bb0eaccbSWilliam A. Kennington III         if (inventoryMAC != ether_addr{})
701bbe3d1eSWilliam A. Kennington III         {
71bb0eaccbSWilliam A. Kennington III             auto macStr = std::to_string(inventoryMAC);
72bb0eaccbSWilliam A. Kennington III             log<level::INFO>("Mac Address in Inventory on ",
731bbe3d1eSWilliam A. Kennington III                              entry("Interface : ", intfname.c_str()),
74bb0eaccbSWilliam A. Kennington III                              entry("MAC Address :", macStr.c_str()));
75bb0eaccbSWilliam A. Kennington III             manager->setFistBootMACOnInterface(
76bb0eaccbSWilliam A. Kennington III                 std::make_pair(intfname.c_str(), std::move(macStr)));
771bbe3d1eSWilliam A. Kennington III             first_boot_status.push_back(intfname.c_str());
781bbe3d1eSWilliam A. Kennington III             bool status = true;
791bbe3d1eSWilliam A. Kennington III             for (const auto& keys : configJson.items())
801bbe3d1eSWilliam A. Kennington III             {
811bbe3d1eSWilliam A. Kennington III                 if (!(std::find(first_boot_status.begin(),
821bbe3d1eSWilliam A. Kennington III                                 first_boot_status.end(),
831bbe3d1eSWilliam A. Kennington III                                 keys.key()) != first_boot_status.end()))
841bbe3d1eSWilliam A. Kennington III                 {
851bbe3d1eSWilliam A. Kennington III                     log<level::INFO>("Interface MAC is NOT set from VPD"),
861bbe3d1eSWilliam A. Kennington III                         entry("INTERFACE", keys.key().c_str());
871bbe3d1eSWilliam A. Kennington III                     status = false;
881bbe3d1eSWilliam A. Kennington III                 }
891bbe3d1eSWilliam A. Kennington III             }
901bbe3d1eSWilliam A. Kennington III             if (status)
911bbe3d1eSWilliam A. Kennington III             {
921bbe3d1eSWilliam A. Kennington III                 log<level::INFO>("Removing the match for ethernet interfaces");
934fd52ae4SWilliam A. Kennington III                 EthInterfaceMatch = nullptr;
941bbe3d1eSWilliam A. Kennington III             }
951bbe3d1eSWilliam A. Kennington III         }
961bbe3d1eSWilliam A. Kennington III         else
971bbe3d1eSWilliam A. Kennington III         {
981bbe3d1eSWilliam A. Kennington III             log<level::INFO>("Nothing is present in Inventory");
991bbe3d1eSWilliam A. Kennington III             return false;
1001bbe3d1eSWilliam A. Kennington III         }
1011bbe3d1eSWilliam A. Kennington III     }
1021bbe3d1eSWilliam A. Kennington III     catch (const std::exception& e)
1031bbe3d1eSWilliam A. Kennington III     {
1041bbe3d1eSWilliam A. Kennington III         log<level::ERR>("Exception occurred during getting of MAC "
1051bbe3d1eSWilliam A. Kennington III                         "address from Inventory");
1061bbe3d1eSWilliam A. Kennington III         return false;
1071bbe3d1eSWilliam A. Kennington III     }
1081bbe3d1eSWilliam A. Kennington III     return true;
1091bbe3d1eSWilliam A. Kennington III }
1101bbe3d1eSWilliam A. Kennington III 
1111bbe3d1eSWilliam A. Kennington III // register the macthes to be monitored from inventory manager
112c38b0710SPatrick Williams void registerSignals(sdbusplus::bus_t& bus, const nlohmann::json& configJson)
1131bbe3d1eSWilliam A. Kennington III {
1141bbe3d1eSWilliam A. Kennington III     log<level::INFO>("Registering the Inventory Signals Matcher");
1151bbe3d1eSWilliam A. Kennington III 
116c38b0710SPatrick Williams     static std::unique_ptr<sdbusplus::bus::match_t> MacAddressMatch;
1171bbe3d1eSWilliam A. Kennington III 
118c38b0710SPatrick Williams     auto callback = [&](sdbusplus::message_t& m) {
1191bbe3d1eSWilliam A. Kennington III         std::map<DbusObjectPath,
1201bbe3d1eSWilliam A. Kennington III                  std::map<DbusInterface, std::variant<PropertyValue>>>
1211bbe3d1eSWilliam A. Kennington III             interfacesProperties;
1221bbe3d1eSWilliam A. Kennington III 
1231bbe3d1eSWilliam A. Kennington III         sdbusplus::message::object_path objPath;
1241bbe3d1eSWilliam A. Kennington III         std::pair<std::string, std::string> ethPair;
1251bbe3d1eSWilliam A. Kennington III         m.read(objPath, interfacesProperties);
1261bbe3d1eSWilliam A. Kennington III 
1271bbe3d1eSWilliam A. Kennington III         for (const auto& pattern : configJson.items())
1281bbe3d1eSWilliam A. Kennington III         {
1291bbe3d1eSWilliam A. Kennington III             if (objPath.str.find(pattern.value()) != std::string::npos)
1301bbe3d1eSWilliam A. Kennington III             {
1311bbe3d1eSWilliam A. Kennington III                 for (auto& interface : interfacesProperties)
1321bbe3d1eSWilliam A. Kennington III                 {
1331bbe3d1eSWilliam A. Kennington III                     if (interface.first == invNetworkIntf)
1341bbe3d1eSWilliam A. Kennington III                     {
1351bbe3d1eSWilliam A. Kennington III                         for (const auto& property : interface.second)
1361bbe3d1eSWilliam A. Kennington III                         {
1371bbe3d1eSWilliam A. Kennington III                             if (property.first == "MACAddress")
1381bbe3d1eSWilliam A. Kennington III                             {
1391bbe3d1eSWilliam A. Kennington III                                 ethPair = std::make_pair(
1401bbe3d1eSWilliam A. Kennington III                                     pattern.key(),
1411bbe3d1eSWilliam A. Kennington III                                     std::get<std::string>(property.second));
1421bbe3d1eSWilliam A. Kennington III                                 break;
1431bbe3d1eSWilliam A. Kennington III                             }
1441bbe3d1eSWilliam A. Kennington III                         }
1451bbe3d1eSWilliam A. Kennington III                         break;
1461bbe3d1eSWilliam A. Kennington III                     }
1471bbe3d1eSWilliam A. Kennington III                 }
1481bbe3d1eSWilliam A. Kennington III                 if (!(ethPair.first.empty() || ethPair.second.empty()))
1491bbe3d1eSWilliam A. Kennington III                 {
1501bbe3d1eSWilliam A. Kennington III                     manager->setFistBootMACOnInterface(ethPair);
1511bbe3d1eSWilliam A. Kennington III                 }
1521bbe3d1eSWilliam A. Kennington III             }
1531bbe3d1eSWilliam A. Kennington III         }
1541bbe3d1eSWilliam A. Kennington III     };
1551bbe3d1eSWilliam A. Kennington III 
156c38b0710SPatrick Williams     MacAddressMatch = std::make_unique<sdbusplus::bus::match_t>(
1571bbe3d1eSWilliam A. Kennington III         bus,
1581bbe3d1eSWilliam A. Kennington III         "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
1591bbe3d1eSWilliam A. Kennington III         "member='InterfacesAdded',path='/xyz/openbmc_project/"
1601bbe3d1eSWilliam A. Kennington III         "inventory'",
1611bbe3d1eSWilliam A. Kennington III         callback);
1621bbe3d1eSWilliam A. Kennington III }
1631bbe3d1eSWilliam A. Kennington III 
164c38b0710SPatrick Williams void watchEthernetInterface(sdbusplus::bus_t& bus,
1651bbe3d1eSWilliam A. Kennington III                             const nlohmann::json& configJson)
1661bbe3d1eSWilliam A. Kennington III {
167c38b0710SPatrick Williams     auto mycallback = [&](sdbusplus::message_t& m) {
1681bbe3d1eSWilliam A. Kennington III         std::map<DbusObjectPath,
1691bbe3d1eSWilliam A. Kennington III                  std::map<DbusInterface, std::variant<PropertyValue>>>
1701bbe3d1eSWilliam A. Kennington III             interfacesProperties;
1711bbe3d1eSWilliam A. Kennington III 
1721bbe3d1eSWilliam A. Kennington III         sdbusplus::message::object_path objPath;
1731bbe3d1eSWilliam A. Kennington III         std::pair<std::string, std::string> ethPair;
1741bbe3d1eSWilliam A. Kennington III         m.read(objPath, interfacesProperties);
1751bbe3d1eSWilliam A. Kennington III         for (const auto& interfaces : interfacesProperties)
1761bbe3d1eSWilliam A. Kennington III         {
1771bbe3d1eSWilliam A. Kennington III             if (interfaces.first ==
1781bbe3d1eSWilliam A. Kennington III                 "xyz.openbmc_project.Network.EthernetInterface")
1791bbe3d1eSWilliam A. Kennington III             {
1801bbe3d1eSWilliam A. Kennington III                 for (const auto& property : interfaces.second)
1811bbe3d1eSWilliam A. Kennington III                 {
1821bbe3d1eSWilliam A. Kennington III                     if (property.first == "InterfaceName")
1831bbe3d1eSWilliam A. Kennington III                     {
1841bbe3d1eSWilliam A. Kennington III                         std::string infname =
1851bbe3d1eSWilliam A. Kennington III                             std::get<std::string>(property.second);
1861bbe3d1eSWilliam A. Kennington III 
1871bbe3d1eSWilliam A. Kennington III                         if (configJson.find(infname) == configJson.end())
1881bbe3d1eSWilliam A. Kennington III                         {
1891bbe3d1eSWilliam A. Kennington III                             // ethernet interface not found in configJSON
1901bbe3d1eSWilliam A. Kennington III                             // check if it is not sit0 interface, as it is
1911bbe3d1eSWilliam A. Kennington III                             // expected.
1921bbe3d1eSWilliam A. Kennington III                             if (infname != "sit0")
1931bbe3d1eSWilliam A. Kennington III                             {
1941bbe3d1eSWilliam A. Kennington III                                 log<level::ERR>(
1951bbe3d1eSWilliam A. Kennington III                                     "Wrong Interface Name in Config Json");
1961bbe3d1eSWilliam A. Kennington III                             }
1971bbe3d1eSWilliam A. Kennington III                         }
1981bbe3d1eSWilliam A. Kennington III                         else
1991bbe3d1eSWilliam A. Kennington III                         {
2004fd52ae4SWilliam A. Kennington III                             if (!setInventoryMACOnSystem(bus, configJson,
2014fd52ae4SWilliam A. Kennington III                                                          infname))
2021bbe3d1eSWilliam A. Kennington III                             {
2034fd52ae4SWilliam A. Kennington III                                 registerSignals(bus, configJson);
2044fd52ae4SWilliam A. Kennington III                                 EthInterfaceMatch = nullptr;
2051bbe3d1eSWilliam A. Kennington III                             }
2061bbe3d1eSWilliam A. Kennington III                         }
2071bbe3d1eSWilliam A. Kennington III                         break;
2081bbe3d1eSWilliam A. Kennington III                     }
2091bbe3d1eSWilliam A. Kennington III                 }
2101bbe3d1eSWilliam A. Kennington III                 break;
2111bbe3d1eSWilliam A. Kennington III             }
2121bbe3d1eSWilliam A. Kennington III         }
2131bbe3d1eSWilliam A. Kennington III     };
2141bbe3d1eSWilliam A. Kennington III     // Incase if phosphor-inventory-manager started early and the VPD is already
2151bbe3d1eSWilliam A. Kennington III     // collected by the time network service has come up, better to check the
2161bbe3d1eSWilliam A. Kennington III     // VPD directly and set the MAC Address on the respective Interface.
2171bbe3d1eSWilliam A. Kennington III 
2181bbe3d1eSWilliam A. Kennington III     bool registeredSignals = false;
2191bbe3d1eSWilliam A. Kennington III     for (const auto& interfaceString : configJson.items())
2201bbe3d1eSWilliam A. Kennington III     {
2211bbe3d1eSWilliam A. Kennington III         if (!std::filesystem::exists(firstBootPath + interfaceString.key()) &&
2221bbe3d1eSWilliam A. Kennington III             !registeredSignals)
2231bbe3d1eSWilliam A. Kennington III         {
2241bbe3d1eSWilliam A. Kennington III 
2251bbe3d1eSWilliam A. Kennington III             log<level::INFO>(
2261bbe3d1eSWilliam A. Kennington III                 "First boot file is not present, check VPD for MAC");
2274fd52ae4SWilliam A. Kennington III             EthInterfaceMatch = std::make_unique<sdbusplus::bus::match_t>(
2281bbe3d1eSWilliam A. Kennington III                 bus,
2291bbe3d1eSWilliam A. Kennington III                 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
2301bbe3d1eSWilliam A. Kennington III                 "member='InterfacesAdded',path='/xyz/openbmc_project/network'",
2311bbe3d1eSWilliam A. Kennington III                 mycallback);
2321bbe3d1eSWilliam A. Kennington III             registeredSignals = true;
2331bbe3d1eSWilliam A. Kennington III         }
2341bbe3d1eSWilliam A. Kennington III     }
2351bbe3d1eSWilliam A. Kennington III }
2361bbe3d1eSWilliam A. Kennington III 
2371bbe3d1eSWilliam A. Kennington III #endif
2381bbe3d1eSWilliam A. Kennington III 
2391bbe3d1eSWilliam A. Kennington III /** @brief refresh the network objects. */
2401bbe3d1eSWilliam A. Kennington III void refreshObjects()
2411bbe3d1eSWilliam A. Kennington III {
2421bbe3d1eSWilliam A. Kennington III     if (manager)
2431bbe3d1eSWilliam A. Kennington III     {
2441bbe3d1eSWilliam A. Kennington III         log<level::INFO>("Refreshing the objects.");
2451bbe3d1eSWilliam A. Kennington III         manager->createChildObjects();
2461bbe3d1eSWilliam A. Kennington III         log<level::INFO>("Refreshing complete.");
2471bbe3d1eSWilliam A. Kennington III     }
2481bbe3d1eSWilliam A. Kennington III }
2491bbe3d1eSWilliam A. Kennington III 
250c7cf25f7SWilliam A. Kennington III void reloadNetworkd()
251c7cf25f7SWilliam A. Kennington III {
252c7cf25f7SWilliam A. Kennington III     if (manager)
253c7cf25f7SWilliam A. Kennington III     {
254c7cf25f7SWilliam A. Kennington III         log<level::INFO>("Sending networkd reload");
255c7cf25f7SWilliam A. Kennington III         manager->doReloadConfigs();
256c7cf25f7SWilliam A. Kennington III         log<level::INFO>("Done networkd reload");
257c7cf25f7SWilliam A. Kennington III     }
258c7cf25f7SWilliam A. Kennington III }
259c7cf25f7SWilliam A. Kennington III 
260*217bb3fdSWilliam A. Kennington III void initializeTimers(sdeventplus::Event& event)
2611bbe3d1eSWilliam A. Kennington III {
2621bbe3d1eSWilliam A. Kennington III     refreshObjectTimer =
2631bbe3d1eSWilliam A. Kennington III         std::make_unique<Timer>(event, std::bind(refreshObjects));
264c7cf25f7SWilliam A. Kennington III     reloadTimer = std::make_unique<Timer>(event, std::bind(reloadNetworkd));
2651bbe3d1eSWilliam A. Kennington III }
2661bbe3d1eSWilliam A. Kennington III 
267*217bb3fdSWilliam A. Kennington III void termCb(sdeventplus::source::Signal& signal, const struct signalfd_siginfo*)
2681bbe3d1eSWilliam A. Kennington III {
269*217bb3fdSWilliam A. Kennington III     log<level::NOTICE>("Got TERM, exiting");
270*217bb3fdSWilliam A. Kennington III     signal.get_event().exit(0);
2711bbe3d1eSWilliam A. Kennington III }
2721bbe3d1eSWilliam A. Kennington III 
273*217bb3fdSWilliam A. Kennington III int main()
274*217bb3fdSWilliam A. Kennington III {
275*217bb3fdSWilliam A. Kennington III     auto event = sdeventplus::Event::get_default();
276*217bb3fdSWilliam A. Kennington III     stdplus::signal::block(SIGTERM);
277*217bb3fdSWilliam A. Kennington III     sdeventplus::source::Signal(event, SIGTERM, termCb).set_floating(true);
2781bbe3d1eSWilliam A. Kennington III 
279*217bb3fdSWilliam A. Kennington III     initializeTimers(event);
280*217bb3fdSWilliam A. Kennington III 
281*217bb3fdSWilliam A. Kennington III     auto bus = sdbusplus::bus::new_default();
2821bbe3d1eSWilliam A. Kennington III     // Attach the bus to sd_event to service user requests
283*217bb3fdSWilliam A. Kennington III     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
2841bbe3d1eSWilliam A. Kennington III 
2851bbe3d1eSWilliam A. Kennington III     // Add sdbusplus Object Manager for the 'root' path of the network manager.
286c38b0710SPatrick Williams     sdbusplus::server::manager_t objManager(bus, DEFAULT_OBJPATH);
2871bbe3d1eSWilliam A. Kennington III     bus.request_name(DEFAULT_BUSNAME);
2881bbe3d1eSWilliam A. Kennington III 
2894fd52ae4SWilliam A. Kennington III     manager = std::make_unique<Manager>(bus, DEFAULT_OBJPATH, NETWORK_CONF_DIR);
2901bbe3d1eSWilliam A. Kennington III 
2911bbe3d1eSWilliam A. Kennington III     // create the default network files if the network file
2921bbe3d1eSWilliam A. Kennington III     // is not there for any interface.
2934fd52ae4SWilliam A. Kennington III     if (manager->createDefaultNetworkFiles())
2941bbe3d1eSWilliam A. Kennington III     {
2954fd52ae4SWilliam A. Kennington III         manager->reloadConfigs();
2961bbe3d1eSWilliam A. Kennington III     }
2971bbe3d1eSWilliam A. Kennington III 
2981bbe3d1eSWilliam A. Kennington III     // RTNETLINK event handler
299*217bb3fdSWilliam A. Kennington III     rtnetlink::Server svr(event);
3001bbe3d1eSWilliam A. Kennington III 
3011bbe3d1eSWilliam A. Kennington III #ifdef SYNC_MAC_FROM_INVENTORY
3021bbe3d1eSWilliam A. Kennington III     std::ifstream in(configFile);
3031bbe3d1eSWilliam A. Kennington III     nlohmann::json configJson;
3041bbe3d1eSWilliam A. Kennington III     in >> configJson;
3054fd52ae4SWilliam A. Kennington III     watchEthernetInterface(bus, configJson);
3061bbe3d1eSWilliam A. Kennington III #endif
307bd649af9SWilliam A. Kennington III 
308bd649af9SWilliam A. Kennington III     // Trigger the initial object scan
30926c40a43SWilliam A. Kennington III     // This is intentionally deferred, to ensure that systemd-networkd is
31026c40a43SWilliam A. Kennington III     // fully configured.
3114fd52ae4SWilliam A. Kennington III     refreshObjectTimer->restartOnce(refreshTimeout);
312bd649af9SWilliam A. Kennington III 
313*217bb3fdSWilliam A. Kennington III     return event.loop();
3144fd52ae4SWilliam A. Kennington III }
3154fd52ae4SWilliam A. Kennington III 
3164fd52ae4SWilliam A. Kennington III } // namespace network
3174fd52ae4SWilliam A. Kennington III } // namespace phosphor
3184fd52ae4SWilliam A. Kennington III 
3194fd52ae4SWilliam A. Kennington III int main(int /*argc*/, char** /*argv*/)
3204fd52ae4SWilliam A. Kennington III {
3214fd52ae4SWilliam A. Kennington III     try
3224fd52ae4SWilliam A. Kennington III     {
3234fd52ae4SWilliam A. Kennington III         return phosphor::network::main();
3244fd52ae4SWilliam A. Kennington III     }
3254fd52ae4SWilliam A. Kennington III     catch (const std::exception& e)
3264fd52ae4SWilliam A. Kennington III     {
3274fd52ae4SWilliam A. Kennington III         auto msg = fmt::format("FAILED: {}", e.what());
3284fd52ae4SWilliam A. Kennington III         log<level::ERR>(msg.c_str(), entry("ERROR", e.what()));
3294fd52ae4SWilliam A. Kennington III         return 1;
3304fd52ae4SWilliam A. Kennington III     }
3311bbe3d1eSWilliam A. Kennington III }
332