1 #include "config.h" 2 3 #include "network_manager.hpp" 4 5 #include "config_parser.hpp" 6 #include "ipaddress.hpp" 7 #include "system_queries.hpp" 8 #include "types.hpp" 9 10 #include <filesystem> 11 #include <fstream> 12 #include <phosphor-logging/elog-errors.hpp> 13 #include <phosphor-logging/log.hpp> 14 #include <xyz/openbmc_project/Common/error.hpp> 15 16 constexpr char SYSTEMD_BUSNAME[] = "org.freedesktop.systemd1"; 17 constexpr char SYSTEMD_PATH[] = "/org/freedesktop/systemd1"; 18 constexpr char SYSTEMD_INTERFACE[] = "org.freedesktop.systemd1.Manager"; 19 constexpr auto FirstBootFile = "/var/lib/network/firstBoot_"; 20 21 constexpr char NETWORKD_BUSNAME[] = "org.freedesktop.network1"; 22 constexpr char NETWORKD_PATH[] = "/org/freedesktop/network1"; 23 constexpr char NETWORKD_INTERFACE[] = "org.freedesktop.network1.Manager"; 24 25 namespace phosphor 26 { 27 namespace network 28 { 29 30 extern std::unique_ptr<Timer> refreshObjectTimer; 31 extern std::unique_ptr<Timer> reloadTimer; 32 using namespace phosphor::logging; 33 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 34 using Argument = xyz::openbmc_project::Common::InvalidArgument; 35 36 Manager::Manager(sdbusplus::bus_t& bus, const char* objPath, 37 const fs::path& confDir) : 38 details::VLANCreateIface(bus, objPath, 39 details::VLANCreateIface::action::defer_emit), 40 bus(bus), objectPath(objPath) 41 { 42 setConfDir(confDir); 43 } 44 45 void Manager::setConfDir(const fs::path& dir) 46 { 47 confDir = dir; 48 49 if (!fs::exists(confDir)) 50 { 51 if (!fs::create_directories(confDir)) 52 { 53 log<level::ERR>("Unable to create the network conf dir", 54 entry("DIR=%s", confDir.c_str())); 55 elog<InternalFailure>(); 56 } 57 } 58 } 59 60 void Manager::createInterfaces() 61 { 62 // clear all the interfaces first 63 interfaces.clear(); 64 for (auto& interface : system::getInterfaces()) 65 { 66 config::Parser config( 67 config::pathForIntfConf(confDir, *interface.name)); 68 auto intf = std::make_unique<EthernetInterface>(bus, *this, interface, 69 objectPath, config); 70 intf->createIPAddressObjects(); 71 intf->createStaticNeighborObjects(); 72 intf->loadNameServers(config); 73 intf->loadNTPServers(config); 74 this->interfaces.emplace(std::move(*interface.name), std::move(intf)); 75 } 76 } 77 78 void Manager::createChildObjects() 79 { 80 routeTable.refresh(); 81 82 // creates the ethernet interface dbus object. 83 createInterfaces(); 84 85 systemConf.reset(nullptr); 86 dhcpConf.reset(nullptr); 87 88 fs::path objPath = objectPath; 89 objPath /= "config"; 90 91 // create the system conf object. 92 systemConf = std::make_unique<phosphor::network::SystemConfiguration>( 93 bus, objPath.string()); 94 // create the dhcp conf object. 95 objPath /= "dhcp"; 96 dhcpConf = std::make_unique<phosphor::network::dhcp::Configuration>( 97 bus, objPath.string(), *this); 98 } 99 100 ObjectPath Manager::vlan(std::string interfaceName, uint32_t id) 101 { 102 if (id == 0 || id >= 4095) 103 { 104 log<level::ERR>("VLAN ID is not valid", entry("VLANID=%u", id)); 105 elog<InvalidArgument>( 106 Argument::ARGUMENT_NAME("VLANId"), 107 Argument::ARGUMENT_VALUE(std::to_string(id).c_str())); 108 } 109 110 auto it = interfaces.find(interfaceName); 111 if (it == interfaces.end()) 112 { 113 using ResourceErr = 114 phosphor::logging::xyz::openbmc_project::Common::ResourceNotFound; 115 elog<ResourceNotFound>(ResourceErr::RESOURCE(interfaceName.c_str())); 116 } 117 return it->second->createVLAN(id); 118 } 119 120 void Manager::reset() 121 { 122 if (fs::is_directory(confDir)) 123 { 124 for (const auto& file : fs::directory_iterator(confDir)) 125 { 126 fs::remove(file.path()); 127 } 128 } 129 log<level::INFO>("Network Factory Reset queued."); 130 } 131 132 // Need to merge the below function with the code which writes the 133 // config file during factory reset. 134 // TODO openbmc/openbmc#1751 135 void Manager::writeToConfigurationFile() 136 { 137 // write all the static ip address in the systemd-network conf file 138 for (const auto& intf : interfaces) 139 { 140 intf.second->writeConfigurationFile(); 141 } 142 } 143 144 #ifdef SYNC_MAC_FROM_INVENTORY 145 void Manager::setFistBootMACOnInterface( 146 const std::pair<std::string, std::string>& inventoryEthPair) 147 { 148 for (const auto& interface : interfaces) 149 { 150 if (interface.first == inventoryEthPair.first) 151 { 152 auto returnMAC = 153 interface.second->macAddress(inventoryEthPair.second); 154 if (returnMAC == inventoryEthPair.second) 155 { 156 log<level::INFO>("Set the MAC on "), 157 entry("interface : ", interface.first.c_str()), 158 entry("MAC : ", inventoryEthPair.second.c_str()); 159 std::error_code ec; 160 if (std::filesystem::is_directory("/var/lib/network", ec)) 161 { 162 std::ofstream persistentFile(FirstBootFile + 163 interface.first); 164 } 165 break; 166 } 167 else 168 { 169 log<level::INFO>("MAC is Not Set on ethernet Interface"); 170 } 171 } 172 } 173 } 174 175 #endif 176 177 void Manager::reloadConfigs() 178 { 179 reloadTimer->restartOnce(reloadTimeout); 180 // Ensure that the next refresh happens after reconfiguration 181 refreshObjectTimer->setRemaining(reloadTimeout + refreshTimeout); 182 } 183 184 void Manager::doReloadConfigs() 185 { 186 for (auto& hook : reloadPreHooks) 187 { 188 try 189 { 190 hook(); 191 } 192 catch (const std::exception& ex) 193 { 194 log<level::ERR>("Failed executing reload hook, ignoring", 195 entry("ERR=%s", ex.what())); 196 } 197 } 198 reloadPreHooks.clear(); 199 try 200 { 201 auto method = bus.new_method_call(NETWORKD_BUSNAME, NETWORKD_PATH, 202 NETWORKD_INTERFACE, "Reload"); 203 bus.call_noreply(method); 204 } 205 catch (const sdbusplus::exception_t& ex) 206 { 207 log<level::ERR>("Failed to reload configuration", 208 entry("ERR=%s", ex.what())); 209 elog<InternalFailure>(); 210 } 211 // Ensure reconfiguration has enough time 212 refreshObjectTimer->setRemaining(refreshTimeout); 213 } 214 215 } // namespace network 216 } // namespace phosphor 217