blob: f46254fcfe1a6b1b161a251b59655c43763beb80 [file] [log] [blame]
Qiang XUe28d1fa2019-02-27 13:50:56 +08001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
Ed Tanous8a57ec02020-10-09 12:46:52 -070017#include <ChassisIntrusionSensor.hpp>
18#include <Utils.hpp>
Ed Tanous8a57ec02020-10-09 12:46:52 -070019#include <boost/asio/io_service.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070020#include <boost/container/flat_map.hpp>
Patrick Williams0c42f402021-08-27 16:05:45 -050021#include <phosphor-logging/lg2.hpp>
Qiang XUe28d1fa2019-02-27 13:50:56 +080022#include <sdbusplus/asio/connection.hpp>
23#include <sdbusplus/asio/object_server.hpp>
24#include <sdbusplus/asio/sd_event.hpp>
25#include <sdbusplus/bus.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070026#include <sdbusplus/bus/match.hpp>
Qiang XUe28d1fa2019-02-27 13:50:56 +080027#include <sdbusplus/exception.hpp>
28#include <sdbusplus/server.hpp>
29#include <sdbusplus/timer.hpp>
James Feist38fb5982020-05-28 10:09:54 -070030
31#include <array>
Ed Tanous8a57ec02020-10-09 12:46:52 -070032#include <charconv>
James Feist38fb5982020-05-28 10:09:54 -070033#include <chrono>
34#include <ctime>
35#include <fstream>
36#include <functional>
37#include <iostream>
38#include <memory>
Patrick Venture96e97db2019-10-31 13:44:38 -070039#include <stdexcept>
40#include <string>
41#include <utility>
42#include <vector>
Qiang XUe28d1fa2019-02-27 13:50:56 +080043
Ed Tanous8a57ec02020-10-09 12:46:52 -070044static constexpr bool debug = false;
Qiang XUe28d1fa2019-02-27 13:50:56 +080045
Zev Weiss054aad82022-08-18 01:37:34 -070046static constexpr const char* sensorType = "ChassisIntrusionSensor";
47static constexpr const char* nicType = "NIC";
Brandon Kim66558232021-11-09 16:53:08 -080048static constexpr auto nicTypes{std::to_array<const char*>({nicType})};
Qiang XUe28d1fa2019-02-27 13:50:56 +080049
Qiang XU88b7f282019-08-14 22:51:43 +080050namespace fs = std::filesystem;
51
Qiang XUe28d1fa2019-02-27 13:50:56 +080052static bool getIntrusionSensorConfig(
Lei YUba637932021-03-17 10:35:00 +080053 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
ZhikuiRenba8a8bf2020-01-09 15:55:43 -080054 IntrusionSensorType* pType, int* pBusId, int* pSlaveAddr,
Qiang XUe28d1fa2019-02-27 13:50:56 +080055 bool* pGpioInverted)
56{
57 // find matched configuration according to sensor type
58 ManagedObjectType sensorConfigurations;
59 bool useCache = false;
60
61 if (!getSensorConfiguration(sensorType, dbusConnection,
62 sensorConfigurations, useCache))
63 {
64 std::cerr << "error communicating to entity manager\n";
65 return false;
66 }
67
68 const SensorData* sensorData = nullptr;
Zev Weissafd15042022-07-18 12:28:40 -070069 const std::pair<std::string, SensorBaseConfigMap>* baseConfiguration =
70 nullptr;
Qiang XUe28d1fa2019-02-27 13:50:56 +080071
72 // Get bus and addr of matched configuration
Zev Weissf343b8a2022-08-12 18:21:01 -070073 for (const auto& [path, cfgData] : sensorConfigurations)
Qiang XUe28d1fa2019-02-27 13:50:56 +080074 {
75 baseConfiguration = nullptr;
Zev Weissf343b8a2022-08-12 18:21:01 -070076 sensorData = &cfgData;
Qiang XUe28d1fa2019-02-27 13:50:56 +080077
78 // match sensor type
Zev Weiss054aad82022-08-18 01:37:34 -070079 auto sensorBase = sensorData->find(configInterfaceName(sensorType));
Qiang XUe28d1fa2019-02-27 13:50:56 +080080 if (sensorBase == sensorData->end())
81 {
82 std::cerr << "error finding base configuration \n";
83 continue;
84 }
85
86 baseConfiguration = &(*sensorBase);
87
88 // judge class, "Gpio" or "I2C"
89 auto findClass = baseConfiguration->second.find("Class");
90 if (findClass != baseConfiguration->second.end() &&
Patrick Williams94733252020-05-13 11:44:58 -050091 std::get<std::string>(findClass->second) == "Gpio")
Qiang XUe28d1fa2019-02-27 13:50:56 +080092 {
93 *pType = IntrusionSensorType::gpio;
94 }
95 else
96 {
97 *pType = IntrusionSensorType::pch;
98 }
99
100 // case to find GPIO info
101 if (*pType == IntrusionSensorType::gpio)
102 {
ZhikuiRenba8a8bf2020-01-09 15:55:43 -0800103 auto findGpioPolarity =
104 baseConfiguration->second.find("GpioPolarity");
Qiang XUe28d1fa2019-02-27 13:50:56 +0800105
ZhikuiRenba8a8bf2020-01-09 15:55:43 -0800106 if (findGpioPolarity == baseConfiguration->second.end())
Qiang XUe28d1fa2019-02-27 13:50:56 +0800107 {
ZhikuiRenba8a8bf2020-01-09 15:55:43 -0800108 std::cerr << "error finding gpio polarity in configuration \n";
Qiang XUe28d1fa2019-02-27 13:50:56 +0800109 continue;
110 }
111
112 try
113 {
Qiang XUe28d1fa2019-02-27 13:50:56 +0800114 *pGpioInverted =
Patrick Williams94733252020-05-13 11:44:58 -0500115 (std::get<std::string>(findGpioPolarity->second) == "Low");
Qiang XUe28d1fa2019-02-27 13:50:56 +0800116 }
117 catch (const std::bad_variant_access& e)
118 {
119 std::cerr << "invalid value for gpio info in config. \n";
120 continue;
121 }
122
Ed Tanous8a57ec02020-10-09 12:46:52 -0700123 if (debug)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800124 {
ZhikuiRenba8a8bf2020-01-09 15:55:43 -0800125 std::cout << "find chassis intrusion sensor polarity inverted "
126 "flag is "
127 << *pGpioInverted << "\n";
Qiang XUe28d1fa2019-02-27 13:50:56 +0800128 }
129
130 return true;
131 }
132
133 // case to find I2C info
Ed Tanous8a57ec02020-10-09 12:46:52 -0700134 if (*pType == IntrusionSensorType::pch)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800135 {
136 auto findBus = baseConfiguration->second.find("Bus");
137 auto findAddress = baseConfiguration->second.find("Address");
138 if (findBus == baseConfiguration->second.end() ||
139 findAddress == baseConfiguration->second.end())
140 {
141 std::cerr << "error finding bus or address in configuration \n";
142 continue;
143 }
144
145 try
146 {
Patrick Williams94733252020-05-13 11:44:58 -0500147 *pBusId = std::get<uint64_t>(findBus->second);
148 *pSlaveAddr = std::get<uint64_t>(findAddress->second);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800149 }
150 catch (const std::bad_variant_access& e)
151 {
152 std::cerr << "invalid value for bus or address in config. \n";
153 continue;
154 }
155
Ed Tanous8a57ec02020-10-09 12:46:52 -0700156 if (debug)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800157 {
158 std::cout << "find matched bus " << *pBusId
159 << ", matched slave addr " << *pSlaveAddr << "\n";
160 }
161 return true;
162 }
163 }
164
Qiang XU74ddf862019-09-12 17:12:13 +0800165 std::cerr << "can't find matched I2C or GPIO configuration for intrusion "
166 "sensor. \n";
Qiang XUe28d1fa2019-02-27 13:50:56 +0800167 *pBusId = -1;
168 *pSlaveAddr = -1;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800169 return false;
170}
171
Qiang XU88b7f282019-08-14 22:51:43 +0800172static constexpr bool debugLanLeash = false;
173boost::container::flat_map<int, bool> lanStatusMap;
Qiang XU74ddf862019-09-12 17:12:13 +0800174boost::container::flat_map<int, std::string> lanInfoMap;
Qiang XU88b7f282019-08-14 22:51:43 +0800175boost::container::flat_map<std::string, int> pathSuffixMap;
176
Lei YUba637932021-03-17 10:35:00 +0800177static void getNicNameInfo(
178 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
Qiang XU74ddf862019-09-12 17:12:13 +0800179{
180 auto getter = std::make_shared<GetSensorConfiguration>(
Zev Weissafd15042022-07-18 12:28:40 -0700181 dbusConnection, [](const ManagedObjectType& sensorConfigurations) {
182 // Get NIC name and save to map
183 lanInfoMap.clear();
Zev Weissf343b8a2022-08-12 18:21:01 -0700184 for (const auto& [path, cfgData] : sensorConfigurations)
Qiang XU74ddf862019-09-12 17:12:13 +0800185 {
Zev Weissafd15042022-07-18 12:28:40 -0700186 const std::pair<std::string, SensorBaseConfigMap>*
187 baseConfiguration = nullptr;
Qiang XU74ddf862019-09-12 17:12:13 +0800188
Zev Weissafd15042022-07-18 12:28:40 -0700189 // find base configuration
Zev Weiss054aad82022-08-18 01:37:34 -0700190 auto sensorBase = cfgData.find(configInterfaceName(nicType));
Zev Weissf343b8a2022-08-12 18:21:01 -0700191 if (sensorBase == cfgData.end())
Qiang XU74ddf862019-09-12 17:12:13 +0800192 {
Zev Weissafd15042022-07-18 12:28:40 -0700193 continue;
194 }
195 baseConfiguration = &(*sensorBase);
196
197 auto findEthIndex = baseConfiguration->second.find("EthIndex");
198 auto findName = baseConfiguration->second.find("Name");
199
200 if (findEthIndex != baseConfiguration->second.end() &&
201 findName != baseConfiguration->second.end())
202 {
203 const auto* pEthIndex =
204 std::get_if<uint64_t>(&findEthIndex->second);
205 const auto* pName =
206 std::get_if<std::string>(&findName->second);
207 if (pEthIndex != nullptr && pName != nullptr)
Qiang XU74ddf862019-09-12 17:12:13 +0800208 {
Zev Weissafd15042022-07-18 12:28:40 -0700209 lanInfoMap[*pEthIndex] = *pName;
210 if (debugLanLeash)
211 {
212 std::cout << "find name of eth" << *pEthIndex
213 << " is " << *pName << "\n";
214 }
Qiang XU74ddf862019-09-12 17:12:13 +0800215 }
216 }
217 }
218
Zev Weissafd15042022-07-18 12:28:40 -0700219 if (lanInfoMap.empty())
220 {
221 std::cerr << "can't find matched NIC name. \n";
222 }
Ed Tanous8a17c302021-09-02 15:07:11 -0700223 });
Qiang XU74ddf862019-09-12 17:12:13 +0800224
225 getter->getConfiguration(
226 std::vector<std::string>{nicTypes.begin(), nicTypes.end()});
227}
228
Patrick Williams92f8f512022-07-22 19:26:55 -0500229static void processLanStatusChange(sdbusplus::message_t& message)
Qiang XU88b7f282019-08-14 22:51:43 +0800230{
231 const std::string& pathName = message.get_path();
232 std::string interfaceName;
Zev Weissafd15042022-07-18 12:28:40 -0700233 SensorBaseConfigMap properties;
Qiang XU88b7f282019-08-14 22:51:43 +0800234 message.read(interfaceName, properties);
235
236 auto findStateProperty = properties.find("OperationalState");
237 if (findStateProperty == properties.end())
238 {
239 return;
240 }
Qiang XU74ddf862019-09-12 17:12:13 +0800241 std::string* pState =
242 std::get_if<std::string>(&(findStateProperty->second));
Qiang XU88b7f282019-08-14 22:51:43 +0800243 if (pState == nullptr)
244 {
245 std::cerr << "invalid OperationalState \n";
246 return;
247 }
248
249 bool newLanConnected = (*pState == "routable" || *pState == "carrier" ||
250 *pState == "degraded");
251
252 // get ethNum from path. /org/freedesktop/network1/link/_32 for eth0
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500253 size_t pos = pathName.find("/_");
Qiang XU88b7f282019-08-14 22:51:43 +0800254 if (pos == std::string::npos || pathName.length() <= pos + 2)
255 {
256 std::cerr << "unexpected path name " << pathName << "\n";
257 return;
258 }
259 std::string suffixStr = pathName.substr(pos + 2);
260
261 auto findEthNum = pathSuffixMap.find(suffixStr);
262 if (findEthNum == pathSuffixMap.end())
263 {
264 std::cerr << "unexpected eth for suffixStr " << suffixStr << "\n";
265 return;
266 }
267 int ethNum = findEthNum->second;
Qiang XU74ddf862019-09-12 17:12:13 +0800268
269 // get lan status from map
Qiang XU88b7f282019-08-14 22:51:43 +0800270 auto findLanStatus = lanStatusMap.find(ethNum);
271 if (findLanStatus == lanStatusMap.end())
272 {
273 std::cerr << "unexpected eth " << ethNum << " in lanStatusMap \n";
274 return;
275 }
276 bool oldLanConnected = findLanStatus->second;
277
Qiang XU74ddf862019-09-12 17:12:13 +0800278 // get lan info from map
Ed Tanous2049bd22022-07-09 07:20:26 -0700279 std::string lanInfo;
280 if (!lanInfoMap.empty())
Qiang XU74ddf862019-09-12 17:12:13 +0800281 {
282 auto findLanInfo = lanInfoMap.find(ethNum);
283 if (findLanInfo == lanInfoMap.end())
284 {
285 std::cerr << "unexpected eth " << ethNum << " in lanInfoMap \n";
286 }
287 else
288 {
289 lanInfo = "(" + findLanInfo->second + ")";
290 }
291 }
292
Qiang XU88b7f282019-08-14 22:51:43 +0800293 if (debugLanLeash)
294 {
295 std::cout << "ethNum = " << ethNum << ", state = " << *pState
296 << ", oldLanConnected = "
297 << (oldLanConnected ? "true" : "false")
298 << ", newLanConnected = "
299 << (newLanConnected ? "true" : "false") << "\n";
300 }
301
302 if (oldLanConnected != newLanConnected)
303 {
Qiang XU74ddf862019-09-12 17:12:13 +0800304 std::string strEthNum = "eth" + std::to_string(ethNum) + lanInfo;
Ed Tanous2049bd22022-07-09 07:20:26 -0700305 const auto* strState = newLanConnected ? "connected" : "lost";
306 const auto* strMsgId =
Qiang XU74ddf862019-09-12 17:12:13 +0800307 newLanConnected ? "OpenBMC.0.1.LanRegained" : "OpenBMC.0.1.LanLost";
Patrick Williams0c42f402021-08-27 16:05:45 -0500308
309 lg2::info("{ETHDEV} LAN leash {STATE}", "ETHDEV", strEthNum, "STATE",
310 strState, "REDFISH_MESSAGE_ID", strMsgId,
311 "REDFISH_MESSAGE_ARGS", strEthNum);
312
Qiang XU88b7f282019-08-14 22:51:43 +0800313 lanStatusMap[ethNum] = newLanConnected;
Qiang XU88b7f282019-08-14 22:51:43 +0800314 }
315}
316
Lei YUdd68d4a2021-03-16 22:17:23 +0800317/** @brief Initialize the lan status.
318 *
319 * @return true on success and false on failure
320 */
Lei YUba637932021-03-17 10:35:00 +0800321static bool initializeLanStatus(
322 const std::shared_ptr<sdbusplus::asio::connection>& conn)
Qiang XU88b7f282019-08-14 22:51:43 +0800323{
Qiang XU74ddf862019-09-12 17:12:13 +0800324 // init lan port name from configuration
325 getNicNameInfo(conn);
326
327 // get eth info from sysfs
Qiang XU88b7f282019-08-14 22:51:43 +0800328 std::vector<fs::path> files;
329 if (!findFiles(fs::path("/sys/class/net/"), R"(eth\d+/ifindex)", files))
330 {
331 std::cerr << "No eth in system\n";
Lei YUdd68d4a2021-03-16 22:17:23 +0800332 return false;
Qiang XU88b7f282019-08-14 22:51:43 +0800333 }
334
335 // iterate through all found eth files, and save ifindex
Ed Tanous8a57ec02020-10-09 12:46:52 -0700336 for (const fs::path& fileName : files)
Qiang XU88b7f282019-08-14 22:51:43 +0800337 {
338 if (debugLanLeash)
339 {
340 std::cout << "Reading " << fileName << "\n";
341 }
342 std::ifstream sysFile(fileName);
343 if (!sysFile.good())
344 {
345 std::cerr << "Failure reading " << fileName << "\n";
346 continue;
347 }
348 std::string line;
349 getline(sysFile, line);
350 const uint8_t ifindex = std::stoi(line);
351 // pathSuffix is ASCII of ifindex
352 const std::string& pathSuffix = std::to_string(ifindex + 30);
353
354 // extract ethNum
355 const std::string& fileStr = fileName.string();
356 const int pos = fileStr.find("eth");
357 const std::string& ethNumStr = fileStr.substr(pos + 3);
358 int ethNum = 0;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700359 std::from_chars_result r = std::from_chars(
360 ethNumStr.data(), ethNumStr.data() + ethNumStr.size(), ethNum);
361 if (r.ec != std::errc())
Qiang XU88b7f282019-08-14 22:51:43 +0800362 {
363 std::cerr << "invalid ethNum string: " << ethNumStr << "\n";
364 continue;
365 }
366
367 // save pathSuffix
368 pathSuffixMap[pathSuffix] = ethNum;
369 if (debugLanLeash)
370 {
371 std::cout << "ethNum = " << std::to_string(ethNum)
372 << ", ifindex = " << line
373 << ", pathSuffix = " << pathSuffix << "\n";
374 }
375
Qiang XU74ddf862019-09-12 17:12:13 +0800376 // init lan connected status from networkd
Qiang XU88b7f282019-08-14 22:51:43 +0800377 conn->async_method_call(
378 [ethNum](boost::system::error_code ec,
379 const std::variant<std::string>& property) {
Ed Tanousbb679322022-05-16 16:10:00 -0700380 lanStatusMap[ethNum] = false;
381 if (ec)
382 {
383 std::cerr << "Error reading init status of eth" << ethNum
384 << "\n";
385 return;
386 }
387 const std::string* pState = std::get_if<std::string>(&property);
388 if (pState == nullptr)
389 {
390 std::cerr << "Unable to read lan status value\n";
391 return;
392 }
393 bool isLanConnected =
394 (*pState == "routable" || *pState == "carrier" ||
395 *pState == "degraded");
396 if (debugLanLeash)
397 {
398 std::cout << "ethNum = " << std::to_string(ethNum)
399 << ", init LAN status = "
400 << (isLanConnected ? "true" : "false") << "\n";
401 }
402 lanStatusMap[ethNum] = isLanConnected;
Qiang XU88b7f282019-08-14 22:51:43 +0800403 },
404 "org.freedesktop.network1",
405 "/org/freedesktop/network1/link/_" + pathSuffix,
406 "org.freedesktop.DBus.Properties", "Get",
407 "org.freedesktop.network1.Link", "OperationalState");
408 }
Lei YUdd68d4a2021-03-16 22:17:23 +0800409 return true;
Qiang XU88b7f282019-08-14 22:51:43 +0800410}
411
Qiang XUe28d1fa2019-02-27 13:50:56 +0800412int main()
413{
ZhikuiRenba8a8bf2020-01-09 15:55:43 -0800414 int busId = -1;
415 int slaveAddr = -1;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800416 bool gpioInverted = false;
417 IntrusionSensorType type = IntrusionSensorType::gpio;
418
419 // setup connection to dbus
420 boost::asio::io_service io;
421 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
422 auto objServer = sdbusplus::asio::object_server(systemBus);
423
424 // setup object server, define interface
425 systemBus->request_name("xyz.openbmc_project.IntrusionSensor");
426
427 std::shared_ptr<sdbusplus::asio::dbus_interface> ifaceChassis =
428 objServer.add_interface(
429 "/xyz/openbmc_project/Intrusion/Chassis_Intrusion",
430 "xyz.openbmc_project.Chassis.Intrusion");
431
432 ChassisIntrusionSensor chassisIntrusionSensor(io, ifaceChassis);
433
434 if (getIntrusionSensorConfig(systemBus, &type, &busId, &slaveAddr,
ZhikuiRenba8a8bf2020-01-09 15:55:43 -0800435 &gpioInverted))
Qiang XUe28d1fa2019-02-27 13:50:56 +0800436 {
ZhikuiRenba8a8bf2020-01-09 15:55:43 -0800437 chassisIntrusionSensor.start(type, busId, slaveAddr, gpioInverted);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800438 }
439
440 // callback to handle configuration change
Patrick Williams92f8f512022-07-22 19:26:55 -0500441 std::function<void(sdbusplus::message_t&)> eventHandler =
442 [&](sdbusplus::message_t& message) {
Ed Tanousbb679322022-05-16 16:10:00 -0700443 if (message.is_method_error())
444 {
445 std::cerr << "callback method error\n";
446 return;
447 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800448
Ed Tanousbb679322022-05-16 16:10:00 -0700449 std::cout << "rescan due to configuration change \n";
450 if (getIntrusionSensorConfig(systemBus, &type, &busId, &slaveAddr,
451 &gpioInverted))
452 {
453 chassisIntrusionSensor.start(type, busId, slaveAddr, gpioInverted);
454 }
455 };
Qiang XUe28d1fa2019-02-27 13:50:56 +0800456
Zev Weiss214d9712022-08-12 12:54:31 -0700457 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
458 setupPropertiesChangedMatches(
459 *systemBus, std::to_array<const char*>({sensorType}), eventHandler);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800460
Lei YUdd68d4a2021-03-16 22:17:23 +0800461 if (initializeLanStatus(systemBus))
462 {
463 // add match to monitor lan status change
Patrick Williams92f8f512022-07-22 19:26:55 -0500464 sdbusplus::bus::match_t lanStatusMatch(
465 static_cast<sdbusplus::bus_t&>(*systemBus),
Lei YUdd68d4a2021-03-16 22:17:23 +0800466 "type='signal', member='PropertiesChanged',"
467 "arg0namespace='org.freedesktop.network1.Link'",
Patrick Williams92f8f512022-07-22 19:26:55 -0500468 [](sdbusplus::message_t& msg) { processLanStatusChange(msg); });
Lei YUdd68d4a2021-03-16 22:17:23 +0800469
470 // add match to monitor entity manager signal about nic name config
471 // change
Patrick Williams92f8f512022-07-22 19:26:55 -0500472 sdbusplus::bus::match_t lanConfigMatch(
473 static_cast<sdbusplus::bus_t&>(*systemBus),
Lei YUdd68d4a2021-03-16 22:17:23 +0800474 "type='signal', member='PropertiesChanged',path_namespace='" +
Zev Weiss054aad82022-08-18 01:37:34 -0700475 std::string(inventoryPath) + "',arg0namespace='" +
476 configInterfaceName(nicType) + "'",
Patrick Williams92f8f512022-07-22 19:26:55 -0500477 [&systemBus](sdbusplus::message_t& msg) {
Ed Tanousbb679322022-05-16 16:10:00 -0700478 if (msg.is_method_error())
479 {
480 std::cerr << "callback method error\n";
481 return;
482 }
483 getNicNameInfo(systemBus);
Lei YUdd68d4a2021-03-16 22:17:23 +0800484 });
485 }
Qiang XU88b7f282019-08-14 22:51:43 +0800486
Qiang XUe28d1fa2019-02-27 13:50:56 +0800487 io.run();
488
489 return 0;
490}