blob: 1c2e38e2c11a5f7a7fb53305f07c116d02e407ac [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>
William A. Kennington III217bb3f2022-09-29 13:43:13 -070026#include <sdeventplus/source/signal.hpp>
27#include <stdplus/signal.hpp>
Ratan Guptaf6657382017-11-10 17:58:17 +053028#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053029
William A. Kennington III09095f82018-09-27 12:05:12 -070030using phosphor::logging::elog;
31using phosphor::logging::entry;
32using phosphor::logging::level;
33using phosphor::logging::log;
34using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Manojkiran Edacc099a82020-05-11 14:25:16 +053035using DbusObjectPath = std::string;
36using DbusInterface = std::string;
37using PropertyValue = std::string;
William A. Kennington III09095f82018-09-27 12:05:12 -070038
William A. Kennington III483e7772019-02-12 19:03:15 -080039constexpr char NETWORK_CONF_DIR[] = "/etc/systemd/network";
40
William A. Kennington III5f1eb462019-02-12 19:47:51 -080041constexpr char DEFAULT_OBJPATH[] = "/xyz/openbmc_project/network";
42
Manojkiran Edacc099a82020-05-11 14:25:16 +053043constexpr auto firstBootPath = "/var/lib/network/firstBoot_";
44constexpr auto configFile = "/usr/share/network/config.json";
45
46constexpr auto invNetworkIntf =
47 "xyz.openbmc_project.Inventory.Item.NetworkInterface";
48
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053049namespace phosphor
50{
51namespace network
52{
53
William A. Kennington III4fd52ae2022-09-30 13:49:39 -070054std::unique_ptr<Manager> manager = nullptr;
William A. Kennington III3a70fa22018-09-20 18:48:20 -070055std::unique_ptr<Timer> refreshObjectTimer = nullptr;
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -080056std::unique_ptr<Timer> reloadTimer = nullptr;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053057
William A. Kennington III6f39c5e2021-05-13 18:39:23 -070058#ifdef SYNC_MAC_FROM_INVENTORY
Patrick Williamsc38b0712022-07-22 19:26:54 -050059std::unique_ptr<sdbusplus::bus::match_t> EthInterfaceMatch = nullptr;
Manojkiran Edacc099a82020-05-11 14:25:16 +053060std::vector<std::string> first_boot_status;
61
Patrick Williamsc38b0712022-07-22 19:26:54 -050062bool setInventoryMACOnSystem(sdbusplus::bus_t& bus,
Manojkiran Edacc099a82020-05-11 14:25:16 +053063 const nlohmann::json& configJson,
64 const std::string& intfname)
65{
66 try
67 {
68 auto inventoryMAC = mac_address::getfromInventory(bus, intfname);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070069 if (inventoryMAC != ether_addr{})
Manojkiran Edacc099a82020-05-11 14:25:16 +053070 {
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -070071 auto macStr = std::to_string(inventoryMAC);
72 log<level::INFO>("Mac Address in Inventory on ",
73 entry("Interface : ", intfname.c_str()),
74 entry("MAC Address :", macStr.c_str()));
75 manager->setFistBootMACOnInterface(
76 std::make_pair(intfname.c_str(), std::move(macStr)));
Manojkiran Edacc099a82020-05-11 14:25:16 +053077 first_boot_status.push_back(intfname.c_str());
78 bool status = true;
79 for (const auto& keys : configJson.items())
80 {
81 if (!(std::find(first_boot_status.begin(),
82 first_boot_status.end(),
83 keys.key()) != first_boot_status.end()))
84 {
85 log<level::INFO>("Interface MAC is NOT set from VPD"),
86 entry("INTERFACE", keys.key().c_str());
87 status = false;
88 }
89 }
90 if (status)
91 {
92 log<level::INFO>("Removing the match for ethernet interfaces");
William A. Kennington III4fd52ae2022-09-30 13:49:39 -070093 EthInterfaceMatch = nullptr;
Manojkiran Edacc099a82020-05-11 14:25:16 +053094 }
95 }
96 else
97 {
98 log<level::INFO>("Nothing is present in Inventory");
99 return false;
100 }
101 }
102 catch (const std::exception& e)
103 {
104 log<level::ERR>("Exception occurred during getting of MAC "
105 "address from Inventory");
106 return false;
107 }
108 return true;
109}
110
111// register the macthes to be monitored from inventory manager
Patrick Williamsc38b0712022-07-22 19:26:54 -0500112void registerSignals(sdbusplus::bus_t& bus, const nlohmann::json& configJson)
Manojkiran Edacc099a82020-05-11 14:25:16 +0530113{
114 log<level::INFO>("Registering the Inventory Signals Matcher");
115
Patrick Williamsc38b0712022-07-22 19:26:54 -0500116 static std::unique_ptr<sdbusplus::bus::match_t> MacAddressMatch;
Manojkiran Edacc099a82020-05-11 14:25:16 +0530117
Patrick Williamsc38b0712022-07-22 19:26:54 -0500118 auto callback = [&](sdbusplus::message_t& m) {
Manojkiran Edacc099a82020-05-11 14:25:16 +0530119 std::map<DbusObjectPath,
120 std::map<DbusInterface, std::variant<PropertyValue>>>
121 interfacesProperties;
122
123 sdbusplus::message::object_path objPath;
124 std::pair<std::string, std::string> ethPair;
125 m.read(objPath, interfacesProperties);
126
127 for (const auto& pattern : configJson.items())
128 {
129 if (objPath.str.find(pattern.value()) != std::string::npos)
130 {
131 for (auto& interface : interfacesProperties)
132 {
133 if (interface.first == invNetworkIntf)
134 {
135 for (const auto& property : interface.second)
136 {
137 if (property.first == "MACAddress")
138 {
139 ethPair = std::make_pair(
140 pattern.key(),
141 std::get<std::string>(property.second));
142 break;
143 }
144 }
145 break;
146 }
147 }
148 if (!(ethPair.first.empty() || ethPair.second.empty()))
149 {
150 manager->setFistBootMACOnInterface(ethPair);
151 }
152 }
153 }
154 };
155
Patrick Williamsc38b0712022-07-22 19:26:54 -0500156 MacAddressMatch = std::make_unique<sdbusplus::bus::match_t>(
Manojkiran Edacc099a82020-05-11 14:25:16 +0530157 bus,
158 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
159 "member='InterfacesAdded',path='/xyz/openbmc_project/"
160 "inventory'",
161 callback);
162}
163
Patrick Williamsc38b0712022-07-22 19:26:54 -0500164void watchEthernetInterface(sdbusplus::bus_t& bus,
Manojkiran Edacc099a82020-05-11 14:25:16 +0530165 const nlohmann::json& configJson)
166{
Patrick Williamsc38b0712022-07-22 19:26:54 -0500167 auto mycallback = [&](sdbusplus::message_t& m) {
Manojkiran Edacc099a82020-05-11 14:25:16 +0530168 std::map<DbusObjectPath,
169 std::map<DbusInterface, std::variant<PropertyValue>>>
170 interfacesProperties;
171
172 sdbusplus::message::object_path objPath;
173 std::pair<std::string, std::string> ethPair;
174 m.read(objPath, interfacesProperties);
175 for (const auto& interfaces : interfacesProperties)
176 {
177 if (interfaces.first ==
178 "xyz.openbmc_project.Network.EthernetInterface")
179 {
180 for (const auto& property : interfaces.second)
181 {
182 if (property.first == "InterfaceName")
183 {
184 std::string infname =
185 std::get<std::string>(property.second);
186
187 if (configJson.find(infname) == configJson.end())
188 {
189 // ethernet interface not found in configJSON
190 // check if it is not sit0 interface, as it is
191 // expected.
192 if (infname != "sit0")
193 {
194 log<level::ERR>(
195 "Wrong Interface Name in Config Json");
196 }
197 }
198 else
199 {
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700200 if (!setInventoryMACOnSystem(bus, configJson,
201 infname))
Manojkiran Edacc099a82020-05-11 14:25:16 +0530202 {
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700203 registerSignals(bus, configJson);
204 EthInterfaceMatch = nullptr;
Manojkiran Edacc099a82020-05-11 14:25:16 +0530205 }
206 }
207 break;
208 }
209 }
210 break;
211 }
212 }
213 };
214 // Incase if phosphor-inventory-manager started early and the VPD is already
215 // collected by the time network service has come up, better to check the
216 // VPD directly and set the MAC Address on the respective Interface.
217
218 bool registeredSignals = false;
219 for (const auto& interfaceString : configJson.items())
220 {
Potin Lai9f621f32022-11-18 12:03:09 +0800221 if ((FORCE_SYNC_MAC_FROM_INVENTORY ||
222 !std::filesystem::exists(firstBootPath + interfaceString.key())) &&
Manojkiran Edacc099a82020-05-11 14:25:16 +0530223 !registeredSignals)
224 {
Potin Lai9f621f32022-11-18 12:03:09 +0800225 auto msg = fmt::format("{}, check VPD for MAC",
226 (FORCE_SYNC_MAC_FROM_INVENTORY)
227 ? "Force sync enabled"
228 : "First boot file is not present");
229 log<level::INFO>(msg.c_str());
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700230 EthInterfaceMatch = std::make_unique<sdbusplus::bus::match_t>(
Manojkiran Edacc099a82020-05-11 14:25:16 +0530231 bus,
232 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
233 "member='InterfacesAdded',path='/xyz/openbmc_project/network'",
234 mycallback);
235 registeredSignals = true;
236 }
237 }
238}
239
240#endif
241
Ratan Gupta16f12882017-09-22 18:26:11 +0530242/** @brief refresh the network objects. */
Ratan Guptaa54d8f82017-09-08 17:05:46 +0530243void refreshObjects()
244{
Ratan Gupta16f12882017-09-22 18:26:11 +0530245 if (manager)
246 {
Ratan Gupta310a0b12017-11-15 17:40:24 +0530247 log<level::INFO>("Refreshing the objects.");
Ratan Gupta16f12882017-09-22 18:26:11 +0530248 manager->createChildObjects();
Ratan Gupta310a0b12017-11-15 17:40:24 +0530249 log<level::INFO>("Refreshing complete.");
Ratan Gupta16f12882017-09-22 18:26:11 +0530250 }
251}
252
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -0800253void reloadNetworkd()
254{
255 if (manager)
256 {
257 log<level::INFO>("Sending networkd reload");
258 manager->doReloadConfigs();
259 log<level::INFO>("Done networkd reload");
260 }
261}
262
William A. Kennington III217bb3f2022-09-29 13:43:13 -0700263void initializeTimers(sdeventplus::Event& event)
Ratan Gupta16f12882017-09-22 18:26:11 +0530264{
William A. Kennington III3a70fa22018-09-20 18:48:20 -0700265 refreshObjectTimer =
266 std::make_unique<Timer>(event, std::bind(refreshObjects));
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -0800267 reloadTimer = std::make_unique<Timer>(event, std::bind(reloadNetworkd));
Ratan Gupta16f12882017-09-22 18:26:11 +0530268}
269
William A. Kennington III217bb3f2022-09-29 13:43:13 -0700270void termCb(sdeventplus::source::Signal& signal, const struct signalfd_siginfo*)
271{
272 log<level::NOTICE>("Got TERM, exiting");
273 signal.get_event().exit(0);
274}
275
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700276int main()
Ratan Gupta8c834932017-04-14 16:30:24 +0530277{
William A. Kennington III217bb3f2022-09-29 13:43:13 -0700278 auto event = sdeventplus::Event::get_default();
279 stdplus::signal::block(SIGTERM);
280 sdeventplus::source::Signal(event, SIGTERM, termCb).set_floating(true);
281
282 initializeTimers(event);
Ratan Guptaa54d8f82017-09-08 17:05:46 +0530283
Ratan Guptacb7098d2017-04-14 17:46:05 +0530284 auto bus = sdbusplus::bus::new_default();
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530285 // Attach the bus to sd_event to service user requests
William A. Kennington III217bb3f2022-09-29 13:43:13 -0700286 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530287
Ratan Guptacb7098d2017-04-14 17:46:05 +0530288 // Add sdbusplus Object Manager for the 'root' path of the network manager.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500289 sdbusplus::server::manager_t objManager(bus, DEFAULT_OBJPATH);
William A. Kennington III5f1eb462019-02-12 19:47:51 -0800290 bus.request_name(DEFAULT_BUSNAME);
Ratan Guptacb7098d2017-04-14 17:46:05 +0530291
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700292 manager = std::make_unique<Manager>(bus, DEFAULT_OBJPATH, NETWORK_CONF_DIR);
Ratan Guptacb7098d2017-04-14 17:46:05 +0530293
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530294 // RTNETLINK event handler
William A. Kennington III71590bf2022-10-31 14:14:16 -0700295 netlink::Server svr(event, *manager);
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530296
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700297#ifdef SYNC_MAC_FROM_INVENTORY
Manojkiran Edacc099a82020-05-11 14:25:16 +0530298 std::ifstream in(configFile);
299 nlohmann::json configJson;
300 in >> configJson;
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700301 watchEthernetInterface(bus, configJson);
Manojkiran Edacc099a82020-05-11 14:25:16 +0530302#endif
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700303
304 // Trigger the initial object scan
William A. Kennington III26c40a42021-11-03 18:27:52 -0700305 // This is intentionally deferred, to ensure that systemd-networkd is
306 // fully configured.
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700307 refreshObjectTimer->restartOnce(refreshTimeout);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700308
William A. Kennington III217bb3f2022-09-29 13:43:13 -0700309 return event.loop();
William A. Kennington III4fd52ae2022-09-30 13:49:39 -0700310}
311
312} // namespace network
313} // namespace phosphor
314
315int main(int /*argc*/, char** /*argv*/)
316{
317 try
318 {
319 return phosphor::network::main();
320 }
321 catch (const std::exception& e)
322 {
323 auto msg = fmt::format("FAILED: {}", e.what());
324 log<level::ERR>(msg.c_str(), entry("ERROR", e.what()));
325 return 1;
326 }
Ratan Gupta8c834932017-04-14 16:30:24 +0530327}