blob: 6a9c740a1dce5a84a8fc38db164c5ac0b90de6f4 [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
Ratan Guptaf6657382017-11-10 17:58:17 +053010#include <linux/netlink.h>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053011
Manojkiran Edacc099a82020-05-11 14:25:16 +053012#include <filesystem>
13#include <fstream>
William A. Kennington III3a70fa22018-09-20 18:48:20 -070014#include <functional>
Ratan Guptaf6657382017-11-10 17:58:17 +053015#include <memory>
William A. Kennington IIIde433b72021-05-17 22:59:28 -070016#ifdef SYNC_MAC_FROM_INVENTORY
Manojkiran Edacc099a82020-05-11 14:25:16 +053017#include <nlohmann/json.hpp>
William A. Kennington IIIde433b72021-05-17 22:59:28 -070018#endif
Ratan Guptaf6657382017-11-10 17:58:17 +053019#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053020#include <phosphor-logging/log.hpp>
Ratan Guptacb7098d2017-04-14 17:46:05 +053021#include <sdbusplus/bus.hpp>
Manojkiran Edacc099a82020-05-11 14:25:16 +053022#include <sdbusplus/bus/match.hpp>
Ratan Guptacb7098d2017-04-14 17:46:05 +053023#include <sdbusplus/server/manager.hpp>
William A. Kennington III3a70fa22018-09-20 18:48:20 -070024#include <sdeventplus/event.hpp>
Ratan Guptaf6657382017-11-10 17:58:17 +053025#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053026
William A. Kennington III09095f82018-09-27 12:05:12 -070027using phosphor::logging::elog;
28using phosphor::logging::entry;
29using phosphor::logging::level;
30using phosphor::logging::log;
31using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Manojkiran Edacc099a82020-05-11 14:25:16 +053032using DbusObjectPath = std::string;
33using DbusInterface = std::string;
34using PropertyValue = std::string;
William A. Kennington III09095f82018-09-27 12:05:12 -070035
William A. Kennington III483e7772019-02-12 19:03:15 -080036constexpr char NETWORK_CONF_DIR[] = "/etc/systemd/network";
37
William A. Kennington III5f1eb462019-02-12 19:47:51 -080038constexpr char DEFAULT_OBJPATH[] = "/xyz/openbmc_project/network";
39
Manojkiran Edacc099a82020-05-11 14:25:16 +053040constexpr auto firstBootPath = "/var/lib/network/firstBoot_";
41constexpr auto configFile = "/usr/share/network/config.json";
42
43constexpr auto invNetworkIntf =
44 "xyz.openbmc_project.Inventory.Item.NetworkInterface";
45
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053046namespace phosphor
47{
48namespace network
49{
50
51std::unique_ptr<phosphor::network::Manager> manager = nullptr;
William A. Kennington III3a70fa22018-09-20 18:48:20 -070052std::unique_ptr<Timer> refreshObjectTimer = nullptr;
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -080053std::unique_ptr<Timer> reloadTimer = nullptr;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053054
William A. Kennington III6f39c5e2021-05-13 18:39:23 -070055#ifdef SYNC_MAC_FROM_INVENTORY
Patrick Williamsc38b0712022-07-22 19:26:54 -050056std::unique_ptr<sdbusplus::bus::match_t> EthInterfaceMatch = nullptr;
Manojkiran Edacc099a82020-05-11 14:25:16 +053057std::vector<std::string> first_boot_status;
58
Patrick Williamsc38b0712022-07-22 19:26:54 -050059bool setInventoryMACOnSystem(sdbusplus::bus_t& bus,
Manojkiran Edacc099a82020-05-11 14:25:16 +053060 const nlohmann::json& configJson,
61 const std::string& intfname)
62{
63 try
64 {
65 auto inventoryMAC = mac_address::getfromInventory(bus, intfname);
66 if (!mac_address::toString(inventoryMAC).empty())
67 {
68 log<level::INFO>("Mac Address in Inventory on "),
69 entry("Interface : ", intfname.c_str()),
70 entry("MAC Address :",
71 (mac_address::toString(inventoryMAC)).c_str());
72 manager->setFistBootMACOnInterface(std::make_pair(
73 intfname.c_str(), mac_address::toString(inventoryMAC)));
74 first_boot_status.push_back(intfname.c_str());
75 bool status = true;
76 for (const auto& keys : configJson.items())
77 {
78 if (!(std::find(first_boot_status.begin(),
79 first_boot_status.end(),
80 keys.key()) != first_boot_status.end()))
81 {
82 log<level::INFO>("Interface MAC is NOT set from VPD"),
83 entry("INTERFACE", keys.key().c_str());
84 status = false;
85 }
86 }
87 if (status)
88 {
89 log<level::INFO>("Removing the match for ethernet interfaces");
90 phosphor::network::EthInterfaceMatch = nullptr;
91 }
92 }
93 else
94 {
95 log<level::INFO>("Nothing is present in Inventory");
96 return false;
97 }
98 }
99 catch (const std::exception& e)
100 {
101 log<level::ERR>("Exception occurred during getting of MAC "
102 "address from Inventory");
103 return false;
104 }
105 return true;
106}
107
108// register the macthes to be monitored from inventory manager
Patrick Williamsc38b0712022-07-22 19:26:54 -0500109void registerSignals(sdbusplus::bus_t& bus, const nlohmann::json& configJson)
Manojkiran Edacc099a82020-05-11 14:25:16 +0530110{
111 log<level::INFO>("Registering the Inventory Signals Matcher");
112
Patrick Williamsc38b0712022-07-22 19:26:54 -0500113 static std::unique_ptr<sdbusplus::bus::match_t> MacAddressMatch;
Manojkiran Edacc099a82020-05-11 14:25:16 +0530114
Patrick Williamsc38b0712022-07-22 19:26:54 -0500115 auto callback = [&](sdbusplus::message_t& m) {
Manojkiran Edacc099a82020-05-11 14:25:16 +0530116 std::map<DbusObjectPath,
117 std::map<DbusInterface, std::variant<PropertyValue>>>
118 interfacesProperties;
119
120 sdbusplus::message::object_path objPath;
121 std::pair<std::string, std::string> ethPair;
122 m.read(objPath, interfacesProperties);
123
124 for (const auto& pattern : configJson.items())
125 {
126 if (objPath.str.find(pattern.value()) != std::string::npos)
127 {
128 for (auto& interface : interfacesProperties)
129 {
130 if (interface.first == invNetworkIntf)
131 {
132 for (const auto& property : interface.second)
133 {
134 if (property.first == "MACAddress")
135 {
136 ethPair = std::make_pair(
137 pattern.key(),
138 std::get<std::string>(property.second));
139 break;
140 }
141 }
142 break;
143 }
144 }
145 if (!(ethPair.first.empty() || ethPair.second.empty()))
146 {
147 manager->setFistBootMACOnInterface(ethPair);
148 }
149 }
150 }
151 };
152
Patrick Williamsc38b0712022-07-22 19:26:54 -0500153 MacAddressMatch = std::make_unique<sdbusplus::bus::match_t>(
Manojkiran Edacc099a82020-05-11 14:25:16 +0530154 bus,
155 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
156 "member='InterfacesAdded',path='/xyz/openbmc_project/"
157 "inventory'",
158 callback);
159}
160
Patrick Williamsc38b0712022-07-22 19:26:54 -0500161void watchEthernetInterface(sdbusplus::bus_t& bus,
Manojkiran Edacc099a82020-05-11 14:25:16 +0530162 const nlohmann::json& configJson)
163{
Patrick Williamsc38b0712022-07-22 19:26:54 -0500164 auto mycallback = [&](sdbusplus::message_t& m) {
Manojkiran Edacc099a82020-05-11 14:25:16 +0530165 std::map<DbusObjectPath,
166 std::map<DbusInterface, std::variant<PropertyValue>>>
167 interfacesProperties;
168
169 sdbusplus::message::object_path objPath;
170 std::pair<std::string, std::string> ethPair;
171 m.read(objPath, interfacesProperties);
172 for (const auto& interfaces : interfacesProperties)
173 {
174 if (interfaces.first ==
175 "xyz.openbmc_project.Network.EthernetInterface")
176 {
177 for (const auto& property : interfaces.second)
178 {
179 if (property.first == "InterfaceName")
180 {
181 std::string infname =
182 std::get<std::string>(property.second);
183
184 if (configJson.find(infname) == configJson.end())
185 {
186 // ethernet interface not found in configJSON
187 // check if it is not sit0 interface, as it is
188 // expected.
189 if (infname != "sit0")
190 {
191 log<level::ERR>(
192 "Wrong Interface Name in Config Json");
193 }
194 }
195 else
196 {
197 if (!phosphor::network::setInventoryMACOnSystem(
198 bus, configJson, infname))
199 {
200 phosphor::network::registerSignals(bus,
201 configJson);
202 phosphor::network::EthInterfaceMatch = nullptr;
203 }
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");
225 phosphor::network::EthInterfaceMatch = std::make_unique<
Patrick Williamsc38b0712022-07-22 19:26:54 -0500226 sdbusplus::bus::match_t>(
Manojkiran Edacc099a82020-05-11 14:25:16 +0530227 bus,
228 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
229 "member='InterfacesAdded',path='/xyz/openbmc_project/network'",
230 mycallback);
231 registeredSignals = true;
232 }
233 }
234}
235
236#endif
237
Ratan Gupta16f12882017-09-22 18:26:11 +0530238/** @brief refresh the network objects. */
Ratan Guptaa54d8f82017-09-08 17:05:46 +0530239void refreshObjects()
240{
Ratan Gupta16f12882017-09-22 18:26:11 +0530241 if (manager)
242 {
Ratan Gupta310a0b12017-11-15 17:40:24 +0530243 log<level::INFO>("Refreshing the objects.");
Ratan Gupta16f12882017-09-22 18:26:11 +0530244 manager->createChildObjects();
Ratan Gupta310a0b12017-11-15 17:40:24 +0530245 log<level::INFO>("Refreshing complete.");
Ratan Gupta16f12882017-09-22 18:26:11 +0530246 }
247}
248
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -0800249void reloadNetworkd()
250{
251 if (manager)
252 {
253 log<level::INFO>("Sending networkd reload");
254 manager->doReloadConfigs();
255 log<level::INFO>("Done networkd reload");
256 }
257}
258
Ratan Gupta16f12882017-09-22 18:26:11 +0530259void initializeTimers()
260{
William A. Kennington III3a70fa22018-09-20 18:48:20 -0700261 auto event = sdeventplus::Event::get_default();
262 refreshObjectTimer =
263 std::make_unique<Timer>(event, std::bind(refreshObjects));
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -0800264 reloadTimer = std::make_unique<Timer>(event, std::bind(reloadNetworkd));
Ratan Gupta16f12882017-09-22 18:26:11 +0530265}
266
William A. Kennington III3a70fa22018-09-20 18:48:20 -0700267} // namespace network
268} // namespace phosphor
269
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530270int main(int /*argc*/, char** /*argv*/)
Ratan Gupta8c834932017-04-14 16:30:24 +0530271{
William A. Kennington III3a70fa22018-09-20 18:48:20 -0700272 phosphor::network::initializeTimers();
Ratan Guptaa54d8f82017-09-08 17:05:46 +0530273
Ratan Guptacb7098d2017-04-14 17:46:05 +0530274 auto bus = sdbusplus::bus::new_default();
275
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530276 // Need sd_event to watch for OCC device errors
277 sd_event* event = nullptr;
278 auto r = sd_event_default(&event);
279 if (r < 0)
280 {
281 log<level::ERR>("Error creating a default sd_event handler");
282 return r;
283 }
284
285 phosphor::network::EventPtr eventPtr{event};
286 event = nullptr;
287
288 // Attach the bus to sd_event to service user requests
289 bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL);
290
Ratan Guptacb7098d2017-04-14 17:46:05 +0530291 // Add sdbusplus Object Manager for the 'root' path of the network manager.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500292 sdbusplus::server::manager_t objManager(bus, DEFAULT_OBJPATH);
William A. Kennington III5f1eb462019-02-12 19:47:51 -0800293 bus.request_name(DEFAULT_BUSNAME);
Ratan Guptacb7098d2017-04-14 17:46:05 +0530294
Gunnar Mills57d9c502018-09-14 14:42:34 -0500295 phosphor::network::manager = std::make_unique<phosphor::network::Manager>(
William A. Kennington III5f1eb462019-02-12 19:47:51 -0800296 bus, DEFAULT_OBJPATH, NETWORK_CONF_DIR);
Ratan Guptacb7098d2017-04-14 17:46:05 +0530297
Ratan Guptab610caf2017-09-19 09:33:51 +0530298 // create the default network files if the network file
299 // is not there for any interface.
William A. Kennington III9a1d9af2021-11-09 17:51:05 -0800300 if (phosphor::network::manager->createDefaultNetworkFiles())
Ratan Guptae9629412017-12-21 08:20:25 +0530301 {
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700302 phosphor::network::manager->reloadConfigs();
Ratan Guptae9629412017-12-21 08:20:25 +0530303 }
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530304
305 // RTNETLINK event handler
William A. Kennington III32eef712022-01-24 17:03:03 -0800306 phosphor::network::rtnetlink::Server svr(eventPtr);
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530307
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700308#ifdef SYNC_MAC_FROM_INVENTORY
Manojkiran Edacc099a82020-05-11 14:25:16 +0530309 std::ifstream in(configFile);
310 nlohmann::json configJson;
311 in >> configJson;
312 phosphor::network::watchEthernetInterface(bus, configJson);
313#endif
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700314
315 // Trigger the initial object scan
William A. Kennington III26c40a42021-11-03 18:27:52 -0700316 // This is intentionally deferred, to ensure that systemd-networkd is
317 // fully configured.
318 phosphor::network::refreshObjectTimer->restartOnce(
319 phosphor::network::refreshTimeout);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700320
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530321 sd_event_loop(eventPtr.get());
Ratan Gupta8c834932017-04-14 16:30:24 +0530322}