blob: 73df65d7dd256afc38fb21e7cfd0adca325d0783 [file] [log] [blame]
Ratan Guptaa54d8f82017-09-08 17:05:46 +05301#include "config.h"
Gunnar Mills57d9c502018-09-14 14:42:34 -05002
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05303#include "network_manager.hpp"
4#include "rtnetlink_server.hpp"
William A. Kennington III3a70fa22018-09-20 18:48:20 -07005#include "types.hpp"
William A. Kennington III95530ec2022-08-19 01:44:39 -07006#ifdef SYNC_MAC_FROM_INVENTORY
7#include "util.hpp"
8#endif
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05309
William A. Kennington III4fd52ae2022-09-30 13:49:39 -070010#include <fmt/format.h>
Ratan Guptaf6657382017-11-10 17:58:17 +053011#include <linux/netlink.h>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053012
Manojkiran Edacc099a82020-05-11 14:25:16 +053013#include <filesystem>
14#include <fstream>
William A. Kennington III3a70fa22018-09-20 18:48:20 -070015#include <functional>
Ratan Guptaf6657382017-11-10 17:58:17 +053016#include <memory>
William A. Kennington IIIde433b72021-05-17 22:59:28 -070017#ifdef SYNC_MAC_FROM_INVENTORY
Manojkiran Edacc099a82020-05-11 14:25:16 +053018#include <nlohmann/json.hpp>
William A. Kennington IIIde433b72021-05-17 22:59:28 -070019#endif
Ratan Guptaf6657382017-11-10 17:58:17 +053020#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053021#include <phosphor-logging/log.hpp>
Ratan Guptacb7098d2017-04-14 17:46:05 +053022#include <sdbusplus/bus.hpp>
Manojkiran Edacc099a82020-05-11 14:25:16 +053023#include <sdbusplus/bus/match.hpp>
Ratan Guptacb7098d2017-04-14 17:46:05 +053024#include <sdbusplus/server/manager.hpp>
William A. Kennington III3a70fa22018-09-20 18:48:20 -070025#include <sdeventplus/event.hpp>
Ratan Guptaf6657382017-11-10 17:58:17 +053026#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053027
William A. Kennington III09095f82018-09-27 12:05:12 -070028using phosphor::logging::elog;
29using phosphor::logging::entry;
30using phosphor::logging::level;
31using phosphor::logging::log;
32using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Manojkiran Edacc099a82020-05-11 14:25:16 +053033using DbusObjectPath = std::string;
34using DbusInterface = std::string;
35using PropertyValue = std::string;
William A. Kennington III09095f82018-09-27 12:05:12 -070036
William A. Kennington III483e7772019-02-12 19:03:15 -080037constexpr char NETWORK_CONF_DIR[] = "/etc/systemd/network";
38
William A. Kennington III5f1eb462019-02-12 19:47:51 -080039constexpr char DEFAULT_OBJPATH[] = "/xyz/openbmc_project/network";
40
Manojkiran Edacc099a82020-05-11 14:25:16 +053041constexpr auto firstBootPath = "/var/lib/network/firstBoot_";
42constexpr auto configFile = "/usr/share/network/config.json";
43
44constexpr auto invNetworkIntf =
45 "xyz.openbmc_project.Inventory.Item.NetworkInterface";
46
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053047namespace phosphor
48{
49namespace network
50{
51
William A. Kennington III4fd52ae2022-09-30 13:49:39 -070052std::unique_ptr<Manager> manager = nullptr;
William A. Kennington III3a70fa22018-09-20 18:48:20 -070053std::unique_ptr<Timer> refreshObjectTimer = nullptr;
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -080054std::unique_ptr<Timer> reloadTimer = nullptr;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053055
William A. Kennington III6f39c5e2021-05-13 18:39:23 -070056#ifdef SYNC_MAC_FROM_INVENTORY
Patrick Williamsc38b0712022-07-22 19:26:54 -050057std::unique_ptr<sdbusplus::bus::match_t> EthInterfaceMatch = nullptr;
Manojkiran Edacc099a82020-05-11 14:25:16 +053058std::vector<std::string> first_boot_status;
59
Patrick Williamsc38b0712022-07-22 19:26:54 -050060bool setInventoryMACOnSystem(sdbusplus::bus_t& bus,
Manojkiran Edacc099a82020-05-11 14:25:16 +053061 const nlohmann::json& configJson,
62 const std::string& intfname)
63{
64 try
65 {
66 auto inventoryMAC = mac_address::getfromInventory(bus, intfname);
67 if (!mac_address::toString(inventoryMAC).empty())
68 {
69 log<level::INFO>("Mac Address in Inventory on "),
70 entry("Interface : ", intfname.c_str()),
71 entry("MAC Address :",
72 (mac_address::toString(inventoryMAC)).c_str());
73 manager->setFistBootMACOnInterface(std::make_pair(
74 intfname.c_str(), mac_address::toString(inventoryMAC)));
75 first_boot_status.push_back(intfname.c_str());
76 bool status = true;
77 for (const auto& keys : configJson.items())
78 {
79 if (!(std::find(first_boot_status.begin(),
80 first_boot_status.end(),
81 keys.key()) != first_boot_status.end()))
82 {
83 log<level::INFO>("Interface MAC is NOT set from VPD"),
84 entry("INTERFACE", keys.key().c_str());
85 status = false;
86 }
87 }
88 if (status)
89 {
90 log<level::INFO>("Removing the match for ethernet interfaces");
William A. Kennington III4fd52ae2022-09-30 13:49:39 -070091 EthInterfaceMatch = nullptr;
Manojkiran Edacc099a82020-05-11 14:25:16 +053092 }
93 }
94 else
95 {
96 log<level::INFO>("Nothing is present in Inventory");
97 return false;
98 }
99 }
100 catch (const std::exception& e)
101 {
102 log<level::ERR>("Exception occurred during getting of MAC "
103 "address from Inventory");
104 return false;
105 }
106 return true;
107}
108
109// register the macthes to be monitored from inventory manager
Patrick Williamsc38b0712022-07-22 19:26:54 -0500110void registerSignals(sdbusplus::bus_t& bus, const nlohmann::json& configJson)
Manojkiran Edacc099a82020-05-11 14:25:16 +0530111{
112 log<level::INFO>("Registering the Inventory Signals Matcher");
113
Patrick Williamsc38b0712022-07-22 19:26:54 -0500114 static std::unique_ptr<sdbusplus::bus::match_t> MacAddressMatch;
Manojkiran Edacc099a82020-05-11 14:25:16 +0530115
Patrick Williamsc38b0712022-07-22 19:26:54 -0500116 auto callback = [&](sdbusplus::message_t& m) {
Manojkiran Edacc099a82020-05-11 14:25:16 +0530117 std::map<DbusObjectPath,
118 std::map<DbusInterface, std::variant<PropertyValue>>>
119 interfacesProperties;
120
121 sdbusplus::message::object_path objPath;
122 std::pair<std::string, std::string> ethPair;
123 m.read(objPath, interfacesProperties);
124
125 for (const auto& pattern : configJson.items())
126 {
127 if (objPath.str.find(pattern.value()) != std::string::npos)
128 {
129 for (auto& interface : interfacesProperties)
130 {
131 if (interface.first == invNetworkIntf)
132 {
133 for (const auto& property : interface.second)
134 {
135 if (property.first == "MACAddress")
136 {
137 ethPair = std::make_pair(
138 pattern.key(),
139 std::get<std::string>(property.second));
140 break;
141 }
142 }
143 break;
144 }
145 }
146 if (!(ethPair.first.empty() || ethPair.second.empty()))
147 {
148 manager->setFistBootMACOnInterface(ethPair);
149 }
150 }
151 }
152 };
153
Patrick Williamsc38b0712022-07-22 19:26:54 -0500154 MacAddressMatch = std::make_unique<sdbusplus::bus::match_t>(
Manojkiran Edacc099a82020-05-11 14:25:16 +0530155 bus,
156 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
157 "member='InterfacesAdded',path='/xyz/openbmc_project/"
158 "inventory'",
159 callback);
160}
161
Patrick Williamsc38b0712022-07-22 19:26:54 -0500162void watchEthernetInterface(sdbusplus::bus_t& bus,
Manojkiran Edacc099a82020-05-11 14:25:16 +0530163 const nlohmann::json& configJson)
164{
Patrick Williamsc38b0712022-07-22 19:26:54 -0500165 auto mycallback = [&](sdbusplus::message_t& m) {
Manojkiran Edacc099a82020-05-11 14:25:16 +0530166 std::map<DbusObjectPath,
167 std::map<DbusInterface, std::variant<PropertyValue>>>
168 interfacesProperties;
169
170 sdbusplus::message::object_path objPath;
171 std::pair<std::string, std::string> ethPair;
172 m.read(objPath, interfacesProperties);
173 for (const auto& interfaces : interfacesProperties)
174 {
175 if (interfaces.first ==
176 "xyz.openbmc_project.Network.EthernetInterface")
177 {
178 for (const auto& property : interfaces.second)
179 {
180 if (property.first == "InterfaceName")
181 {
182 std::string infname =
183 std::get<std::string>(property.second);
184
185 if (configJson.find(infname) == configJson.end())
186 {
187 // ethernet interface not found in configJSON
188 // check if it is not sit0 interface, as it is
189 // expected.
190 if (infname != "sit0")
191 {
192 log<level::ERR>(
193 "Wrong Interface Name in Config Json");
194 }
195 }
196 else
197 {
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700198 if (!setInventoryMACOnSystem(bus, configJson,
199 infname))
Manojkiran Edacc099a82020-05-11 14:25:16 +0530200 {
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700201 registerSignals(bus, configJson);
202 EthInterfaceMatch = nullptr;
Manojkiran Edacc099a82020-05-11 14:25:16 +0530203 }
204 }
205 break;
206 }
207 }
208 break;
209 }
210 }
211 };
212 // Incase if phosphor-inventory-manager started early and the VPD is already
213 // collected by the time network service has come up, better to check the
214 // VPD directly and set the MAC Address on the respective Interface.
215
216 bool registeredSignals = false;
217 for (const auto& interfaceString : configJson.items())
218 {
219 if (!std::filesystem::exists(firstBootPath + interfaceString.key()) &&
220 !registeredSignals)
221 {
222
223 log<level::INFO>(
224 "First boot file is not present, check VPD for MAC");
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700225 EthInterfaceMatch = std::make_unique<sdbusplus::bus::match_t>(
Manojkiran Edacc099a82020-05-11 14:25:16 +0530226 bus,
227 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
228 "member='InterfacesAdded',path='/xyz/openbmc_project/network'",
229 mycallback);
230 registeredSignals = true;
231 }
232 }
233}
234
235#endif
236
Ratan Gupta16f12882017-09-22 18:26:11 +0530237/** @brief refresh the network objects. */
Ratan Guptaa54d8f82017-09-08 17:05:46 +0530238void refreshObjects()
239{
Ratan Gupta16f12882017-09-22 18:26:11 +0530240 if (manager)
241 {
Ratan Gupta310a0b12017-11-15 17:40:24 +0530242 log<level::INFO>("Refreshing the objects.");
Ratan Gupta16f12882017-09-22 18:26:11 +0530243 manager->createChildObjects();
Ratan Gupta310a0b12017-11-15 17:40:24 +0530244 log<level::INFO>("Refreshing complete.");
Ratan Gupta16f12882017-09-22 18:26:11 +0530245 }
246}
247
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -0800248void reloadNetworkd()
249{
250 if (manager)
251 {
252 log<level::INFO>("Sending networkd reload");
253 manager->doReloadConfigs();
254 log<level::INFO>("Done networkd reload");
255 }
256}
257
Ratan Gupta16f12882017-09-22 18:26:11 +0530258void initializeTimers()
259{
William A. Kennington III3a70fa22018-09-20 18:48:20 -0700260 auto event = sdeventplus::Event::get_default();
261 refreshObjectTimer =
262 std::make_unique<Timer>(event, std::bind(refreshObjects));
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -0800263 reloadTimer = std::make_unique<Timer>(event, std::bind(reloadNetworkd));
Ratan Gupta16f12882017-09-22 18:26:11 +0530264}
265
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700266int main()
Ratan Gupta8c834932017-04-14 16:30:24 +0530267{
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700268 initializeTimers();
Ratan Guptaa54d8f82017-09-08 17:05:46 +0530269
Ratan Guptacb7098d2017-04-14 17:46:05 +0530270 auto bus = sdbusplus::bus::new_default();
271
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530272 // Need sd_event to watch for OCC device errors
273 sd_event* event = nullptr;
274 auto r = sd_event_default(&event);
275 if (r < 0)
276 {
277 log<level::ERR>("Error creating a default sd_event handler");
278 return r;
279 }
280
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700281 EventPtr eventPtr{event};
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530282 event = nullptr;
283
284 // Attach the bus to sd_event to service user requests
285 bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL);
286
Ratan Guptacb7098d2017-04-14 17:46:05 +0530287 // Add sdbusplus Object Manager for the 'root' path of the network manager.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500288 sdbusplus::server::manager_t objManager(bus, DEFAULT_OBJPATH);
William A. Kennington III5f1eb462019-02-12 19:47:51 -0800289 bus.request_name(DEFAULT_BUSNAME);
Ratan Guptacb7098d2017-04-14 17:46:05 +0530290
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700291 manager = std::make_unique<Manager>(bus, DEFAULT_OBJPATH, NETWORK_CONF_DIR);
Ratan Guptacb7098d2017-04-14 17:46:05 +0530292
Ratan Guptab610caf2017-09-19 09:33:51 +0530293 // create the default network files if the network file
294 // is not there for any interface.
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700295 if (manager->createDefaultNetworkFiles())
Ratan Guptae9629412017-12-21 08:20:25 +0530296 {
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700297 manager->reloadConfigs();
Ratan Guptae9629412017-12-21 08:20:25 +0530298 }
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530299
300 // RTNETLINK event handler
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700301 rtnetlink::Server svr(eventPtr);
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530302
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700303#ifdef SYNC_MAC_FROM_INVENTORY
Manojkiran Edacc099a82020-05-11 14:25:16 +0530304 std::ifstream in(configFile);
305 nlohmann::json configJson;
306 in >> configJson;
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700307 watchEthernetInterface(bus, configJson);
Manojkiran Edacc099a82020-05-11 14:25:16 +0530308#endif
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700309
310 // Trigger the initial object scan
William A. Kennington III26c40a42021-11-03 18:27:52 -0700311 // This is intentionally deferred, to ensure that systemd-networkd is
312 // fully configured.
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700313 refreshObjectTimer->restartOnce(refreshTimeout);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700314
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700315 return sd_event_loop(eventPtr.get());
316}
317
318} // namespace network
319} // namespace phosphor
320
321int main(int /*argc*/, char** /*argv*/)
322{
323 try
324 {
325 return phosphor::network::main();
326 }
327 catch (const std::exception& e)
328 {
329 auto msg = fmt::format("FAILED: {}", e.what());
330 log<level::ERR>(msg.c_str(), entry("ERROR", e.what()));
331 return 1;
332 }
Ratan Gupta8c834932017-04-14 16:30:24 +0530333}