blob: bc25fe32667aef517ab760443c49f08d829f24d6 [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
Andrew Jefferye73bd0a2023-01-25 10:39:57 +103017#include "ChassisIntrusionSensor.hpp"
18#include "Utils.hpp"
19
Ed Tanouseacbfdd2024-04-04 12:00:24 -070020#include <boost/asio/error.hpp>
Ed Tanous1f978632023-02-28 18:16:39 -080021#include <boost/asio/io_context.hpp>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070022#include <boost/asio/steady_timer.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070023#include <boost/container/flat_map.hpp>
Patrick Williams0c42f402021-08-27 16:05:45 -050024#include <phosphor-logging/lg2.hpp>
Qiang XUe28d1fa2019-02-27 13:50:56 +080025#include <sdbusplus/asio/connection.hpp>
26#include <sdbusplus/asio/object_server.hpp>
Qiang XUe28d1fa2019-02-27 13:50:56 +080027#include <sdbusplus/bus.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070028#include <sdbusplus/bus/match.hpp>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070029#include <sdbusplus/message.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>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070034#include <cstdint>
James Feist38fb5982020-05-28 10:09:54 -070035#include <ctime>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070036#include <exception>
37#include <filesystem>
James Feist38fb5982020-05-28 10:09:54 -070038#include <fstream>
39#include <functional>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070040#include <map>
James Feist38fb5982020-05-28 10:09:54 -070041#include <memory>
Patrick Venture96e97db2019-10-31 13:44:38 -070042#include <string>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070043#include <system_error>
Patrick Venture96e97db2019-10-31 13:44:38 -070044#include <utility>
Ed Tanouseacbfdd2024-04-04 12:00:24 -070045#include <variant>
Patrick Venture96e97db2019-10-31 13:44:38 -070046#include <vector>
Qiang XUe28d1fa2019-02-27 13:50:56 +080047
Zev Weiss054aad82022-08-18 01:37:34 -070048static constexpr const char* sensorType = "ChassisIntrusionSensor";
49static constexpr const char* nicType = "NIC";
Brandon Kim66558232021-11-09 16:53:08 -080050static constexpr auto nicTypes{std::to_array<const char*>({nicType})};
Qiang XUe28d1fa2019-02-27 13:50:56 +080051
Chau Ly95f49932023-04-19 09:44:55 +000052static const std::map<std::string, std::string> compatibleHwmonNames = {
53 {"Aspeed2600_Hwmon", "intrusion0_alarm"}
54 // Add compatible strings here for new hwmon intrusion detection
55 // drivers that have different hwmon names but would also like to
56 // use the available Hwmon class.
57};
58
Chau Lycebb28c2022-10-21 10:01:52 +000059static void createSensorsFromConfig(
60 boost::asio::io_context& io, sdbusplus::asio::object_server& objServer,
Lei YUba637932021-03-17 10:35:00 +080061 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
Chau Lycebb28c2022-10-21 10:01:52 +000062 std::shared_ptr<ChassisIntrusionSensor>& pSensor)
Qiang XUe28d1fa2019-02-27 13:50:56 +080063{
64 // find matched configuration according to sensor type
65 ManagedObjectType sensorConfigurations;
66 bool useCache = false;
67
68 if (!getSensorConfiguration(sensorType, dbusConnection,
69 sensorConfigurations, useCache))
70 {
George Liue9a1c9c2025-02-20 15:02:35 +080071 lg2::error("error communicating to entity manager");
Chau Lycebb28c2022-10-21 10:01:52 +000072 return;
Qiang XUe28d1fa2019-02-27 13:50:56 +080073 }
74
75 const SensorData* sensorData = nullptr;
Zev Weissafd15042022-07-18 12:28:40 -070076 const std::pair<std::string, SensorBaseConfigMap>* baseConfiguration =
77 nullptr;
Qiang XUe28d1fa2019-02-27 13:50:56 +080078
Zev Weissf343b8a2022-08-12 18:21:01 -070079 for (const auto& [path, cfgData] : sensorConfigurations)
Qiang XUe28d1fa2019-02-27 13:50:56 +080080 {
81 baseConfiguration = nullptr;
Zev Weissf343b8a2022-08-12 18:21:01 -070082 sensorData = &cfgData;
Qiang XUe28d1fa2019-02-27 13:50:56 +080083
84 // match sensor type
Zev Weiss054aad82022-08-18 01:37:34 -070085 auto sensorBase = sensorData->find(configInterfaceName(sensorType));
Qiang XUe28d1fa2019-02-27 13:50:56 +080086 if (sensorBase == sensorData->end())
87 {
George Liue9a1c9c2025-02-20 15:02:35 +080088 lg2::error("error finding base configuration");
Qiang XUe28d1fa2019-02-27 13:50:56 +080089 continue;
90 }
91
92 baseConfiguration = &(*sensorBase);
93
Chau Lyb318dca2022-10-26 04:12:52 +000094 // Rearm defaults to "Automatic" mode
95 bool autoRearm = true;
96 auto findRearm = baseConfiguration->second.find("Rearm");
97 if (findRearm != baseConfiguration->second.end())
98 {
99 std::string rearmStr = std::get<std::string>(findRearm->second);
100 if (rearmStr != "Automatic" && rearmStr != "Manual")
101 {
George Liue9a1c9c2025-02-20 15:02:35 +0800102 lg2::error("Wrong input for Rearm parameter");
Chau Lyb318dca2022-10-26 04:12:52 +0000103 continue;
104 }
105 autoRearm = (rearmStr == "Automatic");
106 }
107
Chau Ly95f49932023-04-19 09:44:55 +0000108 // judge class, "Gpio", "Hwmon" or "I2C"
Qiang XUe28d1fa2019-02-27 13:50:56 +0800109 auto findClass = baseConfiguration->second.find("Class");
Chau Ly95f49932023-04-19 09:44:55 +0000110 if (findClass != baseConfiguration->second.end())
Qiang XUe28d1fa2019-02-27 13:50:56 +0800111 {
Chau Ly95f49932023-04-19 09:44:55 +0000112 auto classString = std::get<std::string>(findClass->second);
113 if (classString == "Gpio")
114 {
115 auto findGpioPolarity =
116 baseConfiguration->second.find("GpioPolarity");
Qiang XUe28d1fa2019-02-27 13:50:56 +0800117
Chau Ly95f49932023-04-19 09:44:55 +0000118 if (findGpioPolarity == baseConfiguration->second.end())
119 {
George Liue9a1c9c2025-02-20 15:02:35 +0800120 lg2::error("error finding gpio polarity in configuration");
Chau Ly95f49932023-04-19 09:44:55 +0000121 continue;
122 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800123
Chau Ly95f49932023-04-19 09:44:55 +0000124 try
Chau Lycebb28c2022-10-21 10:01:52 +0000125 {
Chau Ly95f49932023-04-19 09:44:55 +0000126 bool gpioInverted =
127 (std::get<std::string>(findGpioPolarity->second) ==
128 "Low");
129 pSensor = std::make_shared<ChassisIntrusionGpioSensor>(
Chau Lyb318dca2022-10-26 04:12:52 +0000130 autoRearm, io, objServer, gpioInverted);
Chau Ly95f49932023-04-19 09:44:55 +0000131 pSensor->start();
Alexander Hansen89be6142025-09-18 15:36:16 +0200132 lg2::debug(
133 "find chassis intrusion sensor polarity inverted flag is '{GPIO_INVERTED}'",
134 "GPIO_INVERTED", gpioInverted);
Chau Ly95f49932023-04-19 09:44:55 +0000135 return;
Chau Lycebb28c2022-10-21 10:01:52 +0000136 }
Chau Ly95f49932023-04-19 09:44:55 +0000137 catch (const std::bad_variant_access& e)
Chau Lycebb28c2022-10-21 10:01:52 +0000138 {
George Liue9a1c9c2025-02-20 15:02:35 +0800139 lg2::error("invalid value for gpio info in config.");
Chau Ly95f49932023-04-19 09:44:55 +0000140 continue;
Chau Lycebb28c2022-10-21 10:01:52 +0000141 }
Chau Ly95f49932023-04-19 09:44:55 +0000142 catch (const std::exception& e)
143 {
George Liue9a1c9c2025-02-20 15:02:35 +0800144 lg2::error(
145 "error creating chassis intrusion gpio sensor: '{ERROR}'",
146 "ERROR", e);
Chau Ly95f49932023-04-19 09:44:55 +0000147 continue;
148 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800149 }
Chau Ly95f49932023-04-19 09:44:55 +0000150 // If class string contains Hwmon string
151 else if (classString.find("Hwmon") != std::string::npos)
Qiang XUe28d1fa2019-02-27 13:50:56 +0800152 {
Chau Ly95f49932023-04-19 09:44:55 +0000153 std::string hwmonName;
154 std::map<std::string, std::string>::const_iterator
155 compatIterator = compatibleHwmonNames.find(classString);
156
157 if (compatIterator == compatibleHwmonNames.end())
158 {
George Liue9a1c9c2025-02-20 15:02:35 +0800159 lg2::error("Hwmon Class string is not supported");
Chau Ly95f49932023-04-19 09:44:55 +0000160 continue;
161 }
162
163 hwmonName = compatIterator->second;
164
165 try
166 {
167 pSensor = std::make_shared<ChassisIntrusionHwmonSensor>(
Chau Lyb318dca2022-10-26 04:12:52 +0000168 autoRearm, io, objServer, hwmonName);
Chau Ly95f49932023-04-19 09:44:55 +0000169 pSensor->start();
170 return;
171 }
172 catch (const std::exception& e)
173 {
George Liue9a1c9c2025-02-20 15:02:35 +0800174 lg2::error(
175 "error creating chassis intrusion hwmon sensor: '{ERROR}'",
176 "ERROR", e);
Chau Ly95f49932023-04-19 09:44:55 +0000177 continue;
178 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800179 }
Chau Ly95f49932023-04-19 09:44:55 +0000180 else
Qiang XUe28d1fa2019-02-27 13:50:56 +0800181 {
Chau Ly95f49932023-04-19 09:44:55 +0000182 auto findBus = baseConfiguration->second.find("Bus");
183 auto findAddress = baseConfiguration->second.find("Address");
184 if (findBus == baseConfiguration->second.end() ||
185 findAddress == baseConfiguration->second.end())
186 {
George Liue9a1c9c2025-02-20 15:02:35 +0800187 lg2::error("error finding bus or address in configuration");
Chau Ly95f49932023-04-19 09:44:55 +0000188 continue;
189 }
190 try
191 {
192 int busId = std::get<uint64_t>(findBus->second);
193 int slaveAddr = std::get<uint64_t>(findAddress->second);
194 pSensor = std::make_shared<ChassisIntrusionPchSensor>(
Chau Lyb318dca2022-10-26 04:12:52 +0000195 autoRearm, io, objServer, busId, slaveAddr);
Chau Ly95f49932023-04-19 09:44:55 +0000196 pSensor->start();
Alexander Hansen89be6142025-09-18 15:36:16 +0200197 lg2::debug(
198 "find matched bus '{BUS}', matched slave addr '{ADDR}'",
199 "BUS", busId, "ADDR", slaveAddr);
Chau Ly95f49932023-04-19 09:44:55 +0000200 return;
201 }
202 catch (const std::bad_variant_access& e)
203 {
George Liue9a1c9c2025-02-20 15:02:35 +0800204 lg2::error("invalid value for bus or address in config.");
Chau Ly95f49932023-04-19 09:44:55 +0000205 continue;
206 }
207 catch (const std::exception& e)
208 {
George Liue9a1c9c2025-02-20 15:02:35 +0800209 lg2::error(
210 "error creating chassis intrusion pch sensor: '{ERROR}'",
211 "ERROR", e);
Chau Ly95f49932023-04-19 09:44:55 +0000212 continue;
213 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800214 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800215 }
216 }
217
George Liue9a1c9c2025-02-20 15:02:35 +0800218 lg2::error("Can't find matched I2C, GPIO or Hwmon configuration");
Chau Lycebb28c2022-10-21 10:01:52 +0000219
220 // Make sure nothing runs when there's failure in configuration for the
221 // sensor after rescan
222 if (pSensor)
223 {
George Liue9a1c9c2025-02-20 15:02:35 +0800224 lg2::error("Reset the occupied sensor pointer");
Chau Lycebb28c2022-10-21 10:01:52 +0000225 pSensor = nullptr;
226 }
Qiang XUe28d1fa2019-02-27 13:50:56 +0800227}
228
Qiang XU88b7f282019-08-14 22:51:43 +0800229boost::container::flat_map<int, bool> lanStatusMap;
Qiang XU74ddf862019-09-12 17:12:13 +0800230boost::container::flat_map<int, std::string> lanInfoMap;
Qiang XU88b7f282019-08-14 22:51:43 +0800231boost::container::flat_map<std::string, int> pathSuffixMap;
232
Lei YUba637932021-03-17 10:35:00 +0800233static void getNicNameInfo(
234 const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
Qiang XU74ddf862019-09-12 17:12:13 +0800235{
236 auto getter = std::make_shared<GetSensorConfiguration>(
Patrick Williams597e8422023-10-20 11:19:01 -0500237 dbusConnection, [](const ManagedObjectType& sensorConfigurations) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400238 // Get NIC name and save to map
239 lanInfoMap.clear();
240 for (const auto& [path, cfgData] : sensorConfigurations)
Qiang XU74ddf862019-09-12 17:12:13 +0800241 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400242 const std::pair<std::string, SensorBaseConfigMap>*
243 baseConfiguration = nullptr;
Qiang XU74ddf862019-09-12 17:12:13 +0800244
Patrick Williams2aaf7172024-08-16 15:20:40 -0400245 // find base configuration
246 auto sensorBase = cfgData.find(configInterfaceName(nicType));
247 if (sensorBase == cfgData.end())
Qiang XU74ddf862019-09-12 17:12:13 +0800248 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400249 continue;
250 }
251 baseConfiguration = &(*sensorBase);
252
253 auto findEthIndex = baseConfiguration->second.find("EthIndex");
254 auto findName = baseConfiguration->second.find("Name");
255
256 if (findEthIndex != baseConfiguration->second.end() &&
257 findName != baseConfiguration->second.end())
258 {
259 const auto* pEthIndex =
260 std::get_if<uint64_t>(&findEthIndex->second);
261 const auto* pName =
262 std::get_if<std::string>(&findName->second);
263 if (pEthIndex != nullptr && pName != nullptr)
Qiang XU74ddf862019-09-12 17:12:13 +0800264 {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400265 lanInfoMap[*pEthIndex] = *pName;
Alexander Hansen89be6142025-09-18 15:36:16 +0200266 lg2::debug("find name of eth{ETH_INDEX} is '{NAME}'",
267 "ETH_INDEX", *pEthIndex, "NAME", *pName);
Qiang XU74ddf862019-09-12 17:12:13 +0800268 }
269 }
270 }
271
Patrick Williams2aaf7172024-08-16 15:20:40 -0400272 if (lanInfoMap.empty())
273 {
George Liue9a1c9c2025-02-20 15:02:35 +0800274 lg2::error("can't find matched NIC name.");
Patrick Williams2aaf7172024-08-16 15:20:40 -0400275 }
276 });
Qiang XU74ddf862019-09-12 17:12:13 +0800277
278 getter->getConfiguration(
279 std::vector<std::string>{nicTypes.begin(), nicTypes.end()});
280}
281
Patrick Williams92f8f512022-07-22 19:26:55 -0500282static void processLanStatusChange(sdbusplus::message_t& message)
Qiang XU88b7f282019-08-14 22:51:43 +0800283{
284 const std::string& pathName = message.get_path();
285 std::string interfaceName;
Zev Weissafd15042022-07-18 12:28:40 -0700286 SensorBaseConfigMap properties;
Qiang XU88b7f282019-08-14 22:51:43 +0800287 message.read(interfaceName, properties);
288
289 auto findStateProperty = properties.find("OperationalState");
290 if (findStateProperty == properties.end())
291 {
292 return;
293 }
Qiang XU74ddf862019-09-12 17:12:13 +0800294 std::string* pState =
295 std::get_if<std::string>(&(findStateProperty->second));
Qiang XU88b7f282019-08-14 22:51:43 +0800296 if (pState == nullptr)
297 {
George Liue9a1c9c2025-02-20 15:02:35 +0800298 lg2::error("invalid OperationalState");
Qiang XU88b7f282019-08-14 22:51:43 +0800299 return;
300 }
301
302 bool newLanConnected = (*pState == "routable" || *pState == "carrier" ||
303 *pState == "degraded");
304
305 // get ethNum from path. /org/freedesktop/network1/link/_32 for eth0
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500306 size_t pos = pathName.find("/_");
Qiang XU88b7f282019-08-14 22:51:43 +0800307 if (pos == std::string::npos || pathName.length() <= pos + 2)
308 {
George Liue9a1c9c2025-02-20 15:02:35 +0800309 lg2::error("unexpected path name '{NAME}'", "NAME", pathName);
Qiang XU88b7f282019-08-14 22:51:43 +0800310 return;
311 }
312 std::string suffixStr = pathName.substr(pos + 2);
313
314 auto findEthNum = pathSuffixMap.find(suffixStr);
315 if (findEthNum == pathSuffixMap.end())
316 {
George Liue9a1c9c2025-02-20 15:02:35 +0800317 lg2::error("unexpected eth for suffixStr '{SUFFIX}'", "SUFFIX",
318 suffixStr);
Qiang XU88b7f282019-08-14 22:51:43 +0800319 return;
320 }
321 int ethNum = findEthNum->second;
Qiang XU74ddf862019-09-12 17:12:13 +0800322
323 // get lan status from map
Qiang XU88b7f282019-08-14 22:51:43 +0800324 auto findLanStatus = lanStatusMap.find(ethNum);
325 if (findLanStatus == lanStatusMap.end())
326 {
George Liue9a1c9c2025-02-20 15:02:35 +0800327 lg2::error("unexpected eth{ETH_INDEX} is lanStatusMap", "ETH_INDEX",
328 ethNum);
Qiang XU88b7f282019-08-14 22:51:43 +0800329 return;
330 }
331 bool oldLanConnected = findLanStatus->second;
332
Qiang XU74ddf862019-09-12 17:12:13 +0800333 // get lan info from map
Ed Tanous2049bd22022-07-09 07:20:26 -0700334 std::string lanInfo;
335 if (!lanInfoMap.empty())
Qiang XU74ddf862019-09-12 17:12:13 +0800336 {
337 auto findLanInfo = lanInfoMap.find(ethNum);
338 if (findLanInfo == lanInfoMap.end())
339 {
George Liue9a1c9c2025-02-20 15:02:35 +0800340 lg2::error("unexpected eth{ETH_INDEX} is lanInfoMap", "ETH_INDEX",
341 ethNum);
Qiang XU74ddf862019-09-12 17:12:13 +0800342 }
343 else
344 {
345 lanInfo = "(" + findLanInfo->second + ")";
346 }
347 }
348
Alexander Hansen89be6142025-09-18 15:36:16 +0200349 lg2::debug(
350 "ethNum = {ETH_INDEX}, state = {LAN_STATUS}, oldLanConnected = {OLD_LAN_CONNECTED}, "
351 "newLanConnected = {NEW_LAN_CONNECTED}",
352 "ETH_INDEX", ethNum, "LAN_STATUS", *pState, "OLD_LAN_CONNECTED",
353 (oldLanConnected ? "true" : "false"), "NEW_LAN_CONNECTED",
354 (newLanConnected ? "true" : "false"));
Qiang XU88b7f282019-08-14 22:51:43 +0800355
356 if (oldLanConnected != newLanConnected)
357 {
Qiang XU74ddf862019-09-12 17:12:13 +0800358 std::string strEthNum = "eth" + std::to_string(ethNum) + lanInfo;
Ed Tanous2049bd22022-07-09 07:20:26 -0700359 const auto* strState = newLanConnected ? "connected" : "lost";
Patrick Williams2aaf7172024-08-16 15:20:40 -0400360 const auto* strMsgId =
361 newLanConnected ? "OpenBMC.0.1.LanRegained" : "OpenBMC.0.1.LanLost";
Patrick Williams0c42f402021-08-27 16:05:45 -0500362
George Liue9a1c9c2025-02-20 15:02:35 +0800363 lg2::info("'{ETH_INFO}' LAN leash '{LAN_STATUS}'", "ETH_INFO",
364 strEthNum, "LAN_STATUS", strState, "REDFISH_MESSAGE_ID",
365 strMsgId, "REDFISH_MESSAGE_ARGS", strEthNum);
Patrick Williams0c42f402021-08-27 16:05:45 -0500366
Qiang XU88b7f282019-08-14 22:51:43 +0800367 lanStatusMap[ethNum] = newLanConnected;
Qiang XU88b7f282019-08-14 22:51:43 +0800368 }
369}
370
Lei YUdd68d4a2021-03-16 22:17:23 +0800371/** @brief Initialize the lan status.
372 *
373 * @return true on success and false on failure
374 */
Lei YUba637932021-03-17 10:35:00 +0800375static bool initializeLanStatus(
376 const std::shared_ptr<sdbusplus::asio::connection>& conn)
Qiang XU88b7f282019-08-14 22:51:43 +0800377{
Qiang XU74ddf862019-09-12 17:12:13 +0800378 // init lan port name from configuration
379 getNicNameInfo(conn);
380
381 // get eth info from sysfs
Ed Tanous2e466962025-01-30 10:59:49 -0800382 std::vector<std::filesystem::path> files;
383 if (!findFiles(std::filesystem::path("/sys/class/net/"),
384 R"(eth\d+/ifindex)", files))
Qiang XU88b7f282019-08-14 22:51:43 +0800385 {
George Liue9a1c9c2025-02-20 15:02:35 +0800386 lg2::error("No eth in system");
Lei YUdd68d4a2021-03-16 22:17:23 +0800387 return false;
Qiang XU88b7f282019-08-14 22:51:43 +0800388 }
389
390 // iterate through all found eth files, and save ifindex
Ed Tanous2e466962025-01-30 10:59:49 -0800391 for (const std::filesystem::path& fileName : files)
Qiang XU88b7f282019-08-14 22:51:43 +0800392 {
Alexander Hansen89be6142025-09-18 15:36:16 +0200393 lg2::debug("Reading '{NAME}'", "NAME", fileName);
Qiang XU88b7f282019-08-14 22:51:43 +0800394 std::ifstream sysFile(fileName);
395 if (!sysFile.good())
396 {
George Liue9a1c9c2025-02-20 15:02:35 +0800397 lg2::error("Failure reading '{NAME}'", "NAME", fileName);
Qiang XU88b7f282019-08-14 22:51:43 +0800398 continue;
399 }
400 std::string line;
401 getline(sysFile, line);
402 const uint8_t ifindex = std::stoi(line);
403 // pathSuffix is ASCII of ifindex
404 const std::string& pathSuffix = std::to_string(ifindex + 30);
405
406 // extract ethNum
407 const std::string& fileStr = fileName.string();
408 const int pos = fileStr.find("eth");
409 const std::string& ethNumStr = fileStr.substr(pos + 3);
410 int ethNum = 0;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700411 std::from_chars_result r = std::from_chars(
412 ethNumStr.data(), ethNumStr.data() + ethNumStr.size(), ethNum);
413 if (r.ec != std::errc())
Qiang XU88b7f282019-08-14 22:51:43 +0800414 {
George Liue9a1c9c2025-02-20 15:02:35 +0800415 lg2::error("invalid ethNum string: '{ETH_INDEX}'", "ETH_INDEX",
416 ethNumStr);
Qiang XU88b7f282019-08-14 22:51:43 +0800417 continue;
418 }
419
420 // save pathSuffix
421 pathSuffixMap[pathSuffix] = ethNum;
Alexander Hansen89be6142025-09-18 15:36:16 +0200422 lg2::debug(
423 "ethNum = {ETH_INDEX}, ifindex = {LINE}, pathSuffix = {PATH}",
424 "ETH_INDEX", ethNum, "LINE", line, "PATH", pathSuffix);
Qiang XU88b7f282019-08-14 22:51:43 +0800425
Qiang XU74ddf862019-09-12 17:12:13 +0800426 // init lan connected status from networkd
Qiang XU88b7f282019-08-14 22:51:43 +0800427 conn->async_method_call(
428 [ethNum](boost::system::error_code ec,
429 const std::variant<std::string>& property) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400430 lanStatusMap[ethNum] = false;
431 if (ec)
432 {
George Liue9a1c9c2025-02-20 15:02:35 +0800433 lg2::error("Error reading init status of eth{ETH_INDEX}",
434 "ETH_INDEX", ethNum);
Patrick Williams2aaf7172024-08-16 15:20:40 -0400435 return;
436 }
437 const std::string* pState = std::get_if<std::string>(&property);
438 if (pState == nullptr)
439 {
George Liue9a1c9c2025-02-20 15:02:35 +0800440 lg2::error("Unable to read lan status value");
Patrick Williams2aaf7172024-08-16 15:20:40 -0400441 return;
442 }
443 bool isLanConnected =
444 (*pState == "routable" || *pState == "carrier" ||
445 *pState == "degraded");
Alexander Hansen89be6142025-09-18 15:36:16 +0200446 lg2::debug("ethNum = {ETH_INDEX}, init LAN status = {STATUS}",
447 "ETH_INDEX", ethNum, "STATUS",
448 (isLanConnected ? "true" : "false"));
Patrick Williams2aaf7172024-08-16 15:20:40 -0400449 lanStatusMap[ethNum] = isLanConnected;
450 },
Qiang XU88b7f282019-08-14 22:51:43 +0800451 "org.freedesktop.network1",
452 "/org/freedesktop/network1/link/_" + pathSuffix,
453 "org.freedesktop.DBus.Properties", "Get",
454 "org.freedesktop.network1.Link", "OperationalState");
455 }
Lei YUdd68d4a2021-03-16 22:17:23 +0800456 return true;
Qiang XU88b7f282019-08-14 22:51:43 +0800457}
458
Qiang XUe28d1fa2019-02-27 13:50:56 +0800459int main()
460{
Chau Lycebb28c2022-10-21 10:01:52 +0000461 std::shared_ptr<ChassisIntrusionSensor> intrusionSensor;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800462
463 // setup connection to dbus
Ed Tanous1f978632023-02-28 18:16:39 -0800464 boost::asio::io_context io;
Qiang XUe28d1fa2019-02-27 13:50:56 +0800465 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800466
467 // setup object server, define interface
468 systemBus->request_name("xyz.openbmc_project.IntrusionSensor");
469
Ed Tanous14ed5e92022-07-12 15:50:23 -0700470 sdbusplus::asio::object_server objServer(systemBus, true);
471
Chau Ly889af822023-02-20 07:13:52 +0000472 objServer.add_manager("/xyz/openbmc_project/Chassis");
Ed Tanous14ed5e92022-07-12 15:50:23 -0700473
Chau Lycebb28c2022-10-21 10:01:52 +0000474 createSensorsFromConfig(io, objServer, systemBus, intrusionSensor);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800475
476 // callback to handle configuration change
Ian Woloschin0df80a12023-11-06 14:27:44 +0000477 boost::asio::steady_timer filterTimer(io);
Patrick Williams92f8f512022-07-22 19:26:55 -0500478 std::function<void(sdbusplus::message_t&)> eventHandler =
479 [&](sdbusplus::message_t& message) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400480 if (message.is_method_error())
Ian Woloschin0df80a12023-11-06 14:27:44 +0000481 {
George Liue9a1c9c2025-02-20 15:02:35 +0800482 lg2::error("callback method error");
Ian Woloschin0df80a12023-11-06 14:27:44 +0000483 return;
484 }
Patrick Williams2aaf7172024-08-16 15:20:40 -0400485 // this implicitly cancels the timer
486 filterTimer.expires_after(std::chrono::seconds(1));
487 filterTimer.async_wait([&](const boost::system::error_code& ec) {
488 if (ec == boost::asio::error::operation_aborted)
489 {
490 // timer was cancelled
491 return;
492 }
George Liue9a1c9c2025-02-20 15:02:35 +0800493 lg2::info("rescan due to configuration change");
Patrick Williams2aaf7172024-08-16 15:20:40 -0400494 createSensorsFromConfig(io, objServer, systemBus,
495 intrusionSensor);
496 });
497 };
Qiang XUe28d1fa2019-02-27 13:50:56 +0800498
Zev Weiss214d9712022-08-12 12:54:31 -0700499 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
500 setupPropertiesChangedMatches(
501 *systemBus, std::to_array<const char*>({sensorType}), eventHandler);
Qiang XUe28d1fa2019-02-27 13:50:56 +0800502
Lei YUdd68d4a2021-03-16 22:17:23 +0800503 if (initializeLanStatus(systemBus))
504 {
505 // add match to monitor lan status change
Patrick Williams92f8f512022-07-22 19:26:55 -0500506 sdbusplus::bus::match_t lanStatusMatch(
507 static_cast<sdbusplus::bus_t&>(*systemBus),
Lei YUdd68d4a2021-03-16 22:17:23 +0800508 "type='signal', member='PropertiesChanged',"
509 "arg0namespace='org.freedesktop.network1.Link'",
Patrick Williams92f8f512022-07-22 19:26:55 -0500510 [](sdbusplus::message_t& msg) { processLanStatusChange(msg); });
Lei YUdd68d4a2021-03-16 22:17:23 +0800511
512 // add match to monitor entity manager signal about nic name config
513 // change
Patrick Williams92f8f512022-07-22 19:26:55 -0500514 sdbusplus::bus::match_t lanConfigMatch(
515 static_cast<sdbusplus::bus_t&>(*systemBus),
Lei YUdd68d4a2021-03-16 22:17:23 +0800516 "type='signal', member='PropertiesChanged',path_namespace='" +
Zev Weiss054aad82022-08-18 01:37:34 -0700517 std::string(inventoryPath) + "',arg0namespace='" +
518 configInterfaceName(nicType) + "'",
Patrick Williams92f8f512022-07-22 19:26:55 -0500519 [&systemBus](sdbusplus::message_t& msg) {
Patrick Williams2aaf7172024-08-16 15:20:40 -0400520 if (msg.is_method_error())
521 {
George Liue9a1c9c2025-02-20 15:02:35 +0800522 lg2::error("callback method error");
Patrick Williams2aaf7172024-08-16 15:20:40 -0400523 return;
524 }
525 getNicNameInfo(systemBus);
526 });
Lei YUdd68d4a2021-03-16 22:17:23 +0800527 }
Qiang XU88b7f282019-08-14 22:51:43 +0800528
Qiang XUe28d1fa2019-02-27 13:50:56 +0800529 io.run();
530
531 return 0;
532}