blob: fa4efe5c74f10dc5b2b077e8625ba74d9eac96a5 [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"
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05306
Ratan Guptaf6657382017-11-10 17:58:17 +05307#include <linux/netlink.h>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +05308
Manojkiran Edacc099a82020-05-11 14:25:16 +05309#include <filesystem>
10#include <fstream>
William A. Kennington III3a70fa22018-09-20 18:48:20 -070011#include <functional>
Ratan Guptaf6657382017-11-10 17:58:17 +053012#include <memory>
William A. Kennington IIIde433b72021-05-17 22:59:28 -070013#ifdef SYNC_MAC_FROM_INVENTORY
Manojkiran Edacc099a82020-05-11 14:25:16 +053014#include <nlohmann/json.hpp>
William A. Kennington IIIde433b72021-05-17 22:59:28 -070015#endif
Ratan Guptaf6657382017-11-10 17:58:17 +053016#include <phosphor-logging/elog-errors.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053017#include <phosphor-logging/log.hpp>
Ratan Guptacb7098d2017-04-14 17:46:05 +053018#include <sdbusplus/bus.hpp>
Manojkiran Edacc099a82020-05-11 14:25:16 +053019#include <sdbusplus/bus/match.hpp>
Ratan Guptacb7098d2017-04-14 17:46:05 +053020#include <sdbusplus/server/manager.hpp>
William A. Kennington III3a70fa22018-09-20 18:48:20 -070021#include <sdeventplus/event.hpp>
Ratan Guptaf6657382017-11-10 17:58:17 +053022#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053023
William A. Kennington III09095f82018-09-27 12:05:12 -070024using phosphor::logging::elog;
25using phosphor::logging::entry;
26using phosphor::logging::level;
27using phosphor::logging::log;
28using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Manojkiran Edacc099a82020-05-11 14:25:16 +053029using DbusObjectPath = std::string;
30using DbusInterface = std::string;
31using PropertyValue = std::string;
William A. Kennington III09095f82018-09-27 12:05:12 -070032
William A. Kennington III483e7772019-02-12 19:03:15 -080033constexpr char NETWORK_CONF_DIR[] = "/etc/systemd/network";
34
William A. Kennington III5f1eb462019-02-12 19:47:51 -080035constexpr char DEFAULT_OBJPATH[] = "/xyz/openbmc_project/network";
36
Manojkiran Edacc099a82020-05-11 14:25:16 +053037constexpr auto firstBootPath = "/var/lib/network/firstBoot_";
38constexpr auto configFile = "/usr/share/network/config.json";
39
40constexpr auto invNetworkIntf =
41 "xyz.openbmc_project.Inventory.Item.NetworkInterface";
42
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +053043namespace phosphor
44{
45namespace network
46{
47
48std::unique_ptr<phosphor::network::Manager> manager = nullptr;
William A. Kennington III3a70fa22018-09-20 18:48:20 -070049std::unique_ptr<Timer> refreshObjectTimer = nullptr;
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -080050std::unique_ptr<Timer> reloadTimer = nullptr;
Ratan Guptaa54d8f82017-09-08 17:05:46 +053051
William A. Kennington III6f39c5e2021-05-13 18:39:23 -070052#ifdef SYNC_MAC_FROM_INVENTORY
Patrick Williamsc38b0712022-07-22 19:26:54 -050053std::unique_ptr<sdbusplus::bus::match_t> EthInterfaceMatch = nullptr;
Manojkiran Edacc099a82020-05-11 14:25:16 +053054std::vector<std::string> first_boot_status;
55
Patrick Williamsc38b0712022-07-22 19:26:54 -050056bool setInventoryMACOnSystem(sdbusplus::bus_t& bus,
Manojkiran Edacc099a82020-05-11 14:25:16 +053057 const nlohmann::json& configJson,
58 const std::string& intfname)
59{
60 try
61 {
62 auto inventoryMAC = mac_address::getfromInventory(bus, intfname);
63 if (!mac_address::toString(inventoryMAC).empty())
64 {
65 log<level::INFO>("Mac Address in Inventory on "),
66 entry("Interface : ", intfname.c_str()),
67 entry("MAC Address :",
68 (mac_address::toString(inventoryMAC)).c_str());
69 manager->setFistBootMACOnInterface(std::make_pair(
70 intfname.c_str(), mac_address::toString(inventoryMAC)));
71 first_boot_status.push_back(intfname.c_str());
72 bool status = true;
73 for (const auto& keys : configJson.items())
74 {
75 if (!(std::find(first_boot_status.begin(),
76 first_boot_status.end(),
77 keys.key()) != first_boot_status.end()))
78 {
79 log<level::INFO>("Interface MAC is NOT set from VPD"),
80 entry("INTERFACE", keys.key().c_str());
81 status = false;
82 }
83 }
84 if (status)
85 {
86 log<level::INFO>("Removing the match for ethernet interfaces");
87 phosphor::network::EthInterfaceMatch = nullptr;
88 }
89 }
90 else
91 {
92 log<level::INFO>("Nothing is present in Inventory");
93 return false;
94 }
95 }
96 catch (const std::exception& e)
97 {
98 log<level::ERR>("Exception occurred during getting of MAC "
99 "address from Inventory");
100 return false;
101 }
102 return true;
103}
104
105// register the macthes to be monitored from inventory manager
Patrick Williamsc38b0712022-07-22 19:26:54 -0500106void registerSignals(sdbusplus::bus_t& bus, const nlohmann::json& configJson)
Manojkiran Edacc099a82020-05-11 14:25:16 +0530107{
108 log<level::INFO>("Registering the Inventory Signals Matcher");
109
Patrick Williamsc38b0712022-07-22 19:26:54 -0500110 static std::unique_ptr<sdbusplus::bus::match_t> MacAddressMatch;
Manojkiran Edacc099a82020-05-11 14:25:16 +0530111
Patrick Williamsc38b0712022-07-22 19:26:54 -0500112 auto callback = [&](sdbusplus::message_t& m) {
Manojkiran Edacc099a82020-05-11 14:25:16 +0530113 std::map<DbusObjectPath,
114 std::map<DbusInterface, std::variant<PropertyValue>>>
115 interfacesProperties;
116
117 sdbusplus::message::object_path objPath;
118 std::pair<std::string, std::string> ethPair;
119 m.read(objPath, interfacesProperties);
120
121 for (const auto& pattern : configJson.items())
122 {
123 if (objPath.str.find(pattern.value()) != std::string::npos)
124 {
125 for (auto& interface : interfacesProperties)
126 {
127 if (interface.first == invNetworkIntf)
128 {
129 for (const auto& property : interface.second)
130 {
131 if (property.first == "MACAddress")
132 {
133 ethPair = std::make_pair(
134 pattern.key(),
135 std::get<std::string>(property.second));
136 break;
137 }
138 }
139 break;
140 }
141 }
142 if (!(ethPair.first.empty() || ethPair.second.empty()))
143 {
144 manager->setFistBootMACOnInterface(ethPair);
145 }
146 }
147 }
148 };
149
Patrick Williamsc38b0712022-07-22 19:26:54 -0500150 MacAddressMatch = std::make_unique<sdbusplus::bus::match_t>(
Manojkiran Edacc099a82020-05-11 14:25:16 +0530151 bus,
152 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
153 "member='InterfacesAdded',path='/xyz/openbmc_project/"
154 "inventory'",
155 callback);
156}
157
Patrick Williamsc38b0712022-07-22 19:26:54 -0500158void watchEthernetInterface(sdbusplus::bus_t& bus,
Manojkiran Edacc099a82020-05-11 14:25:16 +0530159 const nlohmann::json& configJson)
160{
Patrick Williamsc38b0712022-07-22 19:26:54 -0500161 auto mycallback = [&](sdbusplus::message_t& m) {
Manojkiran Edacc099a82020-05-11 14:25:16 +0530162 std::map<DbusObjectPath,
163 std::map<DbusInterface, std::variant<PropertyValue>>>
164 interfacesProperties;
165
166 sdbusplus::message::object_path objPath;
167 std::pair<std::string, std::string> ethPair;
168 m.read(objPath, interfacesProperties);
169 for (const auto& interfaces : interfacesProperties)
170 {
171 if (interfaces.first ==
172 "xyz.openbmc_project.Network.EthernetInterface")
173 {
174 for (const auto& property : interfaces.second)
175 {
176 if (property.first == "InterfaceName")
177 {
178 std::string infname =
179 std::get<std::string>(property.second);
180
181 if (configJson.find(infname) == configJson.end())
182 {
183 // ethernet interface not found in configJSON
184 // check if it is not sit0 interface, as it is
185 // expected.
186 if (infname != "sit0")
187 {
188 log<level::ERR>(
189 "Wrong Interface Name in Config Json");
190 }
191 }
192 else
193 {
194 if (!phosphor::network::setInventoryMACOnSystem(
195 bus, configJson, infname))
196 {
197 phosphor::network::registerSignals(bus,
198 configJson);
199 phosphor::network::EthInterfaceMatch = nullptr;
200 }
201 }
202 break;
203 }
204 }
205 break;
206 }
207 }
208 };
209 // Incase if phosphor-inventory-manager started early and the VPD is already
210 // collected by the time network service has come up, better to check the
211 // VPD directly and set the MAC Address on the respective Interface.
212
213 bool registeredSignals = false;
214 for (const auto& interfaceString : configJson.items())
215 {
216 if (!std::filesystem::exists(firstBootPath + interfaceString.key()) &&
217 !registeredSignals)
218 {
219
220 log<level::INFO>(
221 "First boot file is not present, check VPD for MAC");
222 phosphor::network::EthInterfaceMatch = std::make_unique<
Patrick Williamsc38b0712022-07-22 19:26:54 -0500223 sdbusplus::bus::match_t>(
Manojkiran Edacc099a82020-05-11 14:25:16 +0530224 bus,
225 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
226 "member='InterfacesAdded',path='/xyz/openbmc_project/network'",
227 mycallback);
228 registeredSignals = true;
229 }
230 }
231}
232
233#endif
234
Ratan Gupta16f12882017-09-22 18:26:11 +0530235/** @brief refresh the network objects. */
Ratan Guptaa54d8f82017-09-08 17:05:46 +0530236void refreshObjects()
237{
Ratan Gupta16f12882017-09-22 18:26:11 +0530238 if (manager)
239 {
Ratan Gupta310a0b12017-11-15 17:40:24 +0530240 log<level::INFO>("Refreshing the objects.");
Ratan Gupta16f12882017-09-22 18:26:11 +0530241 manager->createChildObjects();
Ratan Gupta310a0b12017-11-15 17:40:24 +0530242 log<level::INFO>("Refreshing complete.");
Ratan Gupta16f12882017-09-22 18:26:11 +0530243 }
244}
245
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -0800246void reloadNetworkd()
247{
248 if (manager)
249 {
250 log<level::INFO>("Sending networkd reload");
251 manager->doReloadConfigs();
252 log<level::INFO>("Done networkd reload");
253 }
254}
255
Ratan Gupta16f12882017-09-22 18:26:11 +0530256void initializeTimers()
257{
William A. Kennington III3a70fa22018-09-20 18:48:20 -0700258 auto event = sdeventplus::Event::get_default();
259 refreshObjectTimer =
260 std::make_unique<Timer>(event, std::bind(refreshObjects));
William A. Kennington IIIc7cf25f2021-11-09 16:16:59 -0800261 reloadTimer = std::make_unique<Timer>(event, std::bind(reloadNetworkd));
Ratan Gupta16f12882017-09-22 18:26:11 +0530262}
263
William A. Kennington III3a70fa22018-09-20 18:48:20 -0700264} // namespace network
265} // namespace phosphor
266
Manojkiran Edaaa57fa52020-06-13 14:59:53 +0530267int main(int /*argc*/, char** /*argv*/)
Ratan Gupta8c834932017-04-14 16:30:24 +0530268{
William A. Kennington III3a70fa22018-09-20 18:48:20 -0700269 phosphor::network::initializeTimers();
Ratan Guptaa54d8f82017-09-08 17:05:46 +0530270
Ratan Guptacb7098d2017-04-14 17:46:05 +0530271 auto bus = sdbusplus::bus::new_default();
272
Ratan Gupta0f9dc1b2017-09-03 17:57:50 +0530273 // Need sd_event to watch for OCC device errors
274 sd_event* event = nullptr;
275 auto r = sd_event_default(&event);
276 if (r < 0)
277 {
278 log<level::ERR>("Error creating a default sd_event handler");
279 return r;
280 }
281
282 phosphor::network::EventPtr eventPtr{event};
283 event = nullptr;
284
285 // Attach the bus to sd_event to service user requests
286 bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL);
287
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
Gunnar Mills57d9c502018-09-14 14:42:34 -0500292 phosphor::network::manager = std::make_unique<phosphor::network::Manager>(
William A. Kennington III5f1eb462019-02-12 19:47:51 -0800293 bus, DEFAULT_OBJPATH, NETWORK_CONF_DIR);
Ratan Guptacb7098d2017-04-14 17:46:05 +0530294
Ratan Guptab610caf2017-09-19 09:33:51 +0530295 // create the default network files if the network file
296 // is not there for any interface.
William A. Kennington III9a1d9af2021-11-09 17:51:05 -0800297 if (phosphor::network::manager->createDefaultNetworkFiles())
Ratan Guptae9629412017-12-21 08:20:25 +0530298 {
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700299 phosphor::network::manager->reloadConfigs();
Ratan Guptae9629412017-12-21 08:20:25 +0530300 }
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530301
302 // RTNETLINK event handler
William A. Kennington III32eef712022-01-24 17:03:03 -0800303 phosphor::network::rtnetlink::Server svr(eventPtr);
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530304
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700305#ifdef SYNC_MAC_FROM_INVENTORY
Manojkiran Edacc099a82020-05-11 14:25:16 +0530306 std::ifstream in(configFile);
307 nlohmann::json configJson;
308 in >> configJson;
309 phosphor::network::watchEthernetInterface(bus, configJson);
310#endif
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700311
312 // Trigger the initial object scan
William A. Kennington III26c40a42021-11-03 18:27:52 -0700313 // This is intentionally deferred, to ensure that systemd-networkd is
314 // fully configured.
315 phosphor::network::refreshObjectTimer->restartOnce(
316 phosphor::network::refreshTimeout);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700317
Vishwanatha Subbanna18891c62017-10-17 15:22:46 +0530318 sd_event_loop(eventPtr.get());
Ratan Gupta8c834932017-04-14 16:30:24 +0530319}