xref: /openbmc/phosphor-networkd/src/network_manager.cpp (revision 09f3a4ade17b076ce611320725e0871c3fa40031)
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