blob: 685bb4e17ec954fc5ba791f85c9bb851a1f08c5c [file] [log] [blame]
Jason M. Bills5e049d32018-10-19 12:59:38 -07001/*
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
17#pragma once
18#include <sel_logger.hpp>
19#include <sensorutils.hpp>
Zhikui Ren672bdfc2020-07-14 11:37:01 -070020
Jason M. Bills2b9704d2018-11-02 13:12:09 -070021#include <string_view>
Jason M. Bills2bc9f0d2019-03-27 11:13:12 -070022#include <variant>
Jason M. Bills5e049d32018-10-19 12:59:38 -070023
24enum class thresholdEventOffsets : uint8_t
25{
26 lowerNonCritGoingLow = 0x00,
27 lowerCritGoingLow = 0x02,
28 upperNonCritGoingHigh = 0x07,
29 upperCritGoingHigh = 0x09,
30};
31
32static constexpr const uint8_t thresholdEventDataTriggerReadingByte2 = (1 << 6);
33static constexpr const uint8_t thresholdEventDataTriggerReadingByte3 = (1 << 4);
34
Jason M. Bills60ec28a2019-04-11 16:53:44 -070035static const std::string openBMCMessageRegistryVersion("0.1");
Jason M. Bills2b9704d2018-11-02 13:12:09 -070036
Patrick Williamsccef2272022-07-22 19:26:54 -050037inline static sdbusplus::bus::match_t startThresholdAssertMonitor(
Jason M. Bills5e049d32018-10-19 12:59:38 -070038 std::shared_ptr<sdbusplus::asio::connection> conn)
39{
Patrick Williamsccef2272022-07-22 19:26:54 -050040 auto thresholdAssertMatcherCallback = [conn](sdbusplus::message_t& msg) {
Jason M. Bills5e049d32018-10-19 12:59:38 -070041 // This static set of std::pair<path, event> tracks asserted events to
42 // avoid duplicate logs or deasserts logged without an assert
43 static boost::container::flat_set<std::pair<std::string, std::string>>
44 assertedEvents;
Zhikui Ren25b26e12020-06-26 20:18:19 -070045 std::vector<uint8_t> eventData(selEvtDataMaxSize,
46 selEvtDataUnspecified);
Jason M. Bills5e049d32018-10-19 12:59:38 -070047
48 // Get the event type and assertion details from the message
Zhikui Ren25b26e12020-06-26 20:18:19 -070049 std::string sensorName;
Jason M. Bills5e049d32018-10-19 12:59:38 -070050 std::string thresholdInterface;
Zhikui Ren25b26e12020-06-26 20:18:19 -070051 std::string event;
52 bool assert;
53 double assertValue;
54 try
Jason M. Bills5e049d32018-10-19 12:59:38 -070055 {
Zhikui Ren25b26e12020-06-26 20:18:19 -070056 msg.read(sensorName, thresholdInterface, event, assert,
57 assertValue);
58 }
Patrick Williams3f4cd972021-10-06 12:42:50 -050059 catch (const sdbusplus::exception_t&)
Zhikui Ren25b26e12020-06-26 20:18:19 -070060 {
61 std::cerr << "error getting assert signal data from "
62 << msg.get_path() << "\n";
Jason M. Bills5e049d32018-10-19 12:59:38 -070063 return;
64 }
Jason M. Bills5e049d32018-10-19 12:59:38 -070065
66 // Check the asserted events to determine if we should log this event
67 std::pair<std::string, std::string> pathAndEvent(
68 std::string(msg.get_path()), event);
69 if (assert)
70 {
71 // For asserts, add the event to the set and only log it if it's new
72 if (assertedEvents.insert(pathAndEvent).second == false)
73 {
74 // event is already in the set
75 return;
76 }
77 }
78 else
79 {
80 // For deasserts, remove the event and only log the deassert if it
81 // was asserted
82 if (assertedEvents.erase(pathAndEvent) == 0)
83 {
84 // asserted event was not in the set
85 return;
86 }
87 }
88
89 // Set the IPMI threshold event type based on the event details from the
90 // message
91 if (event == "CriticalAlarmLow")
92 {
93 eventData[0] =
94 static_cast<uint8_t>(thresholdEventOffsets::lowerCritGoingLow);
95 }
96 else if (event == "WarningAlarmLow")
97 {
98 eventData[0] = static_cast<uint8_t>(
99 thresholdEventOffsets::lowerNonCritGoingLow);
100 }
101 else if (event == "WarningAlarmHigh")
102 {
103 eventData[0] = static_cast<uint8_t>(
104 thresholdEventOffsets::upperNonCritGoingHigh);
105 }
106 else if (event == "CriticalAlarmHigh")
107 {
108 eventData[0] =
109 static_cast<uint8_t>(thresholdEventOffsets::upperCritGoingHigh);
110 }
111 // Indicate that bytes 2 and 3 are threshold sensor trigger values
112 eventData[0] |= thresholdEventDataTriggerReadingByte2 |
113 thresholdEventDataTriggerReadingByte3;
114
115 // Get the sensor reading to put in the event data
Patrick Williamsccef2272022-07-22 19:26:54 -0500116 sdbusplus::message_t getSensorValue =
Jason M. Bills5e049d32018-10-19 12:59:38 -0700117 conn->new_method_call(msg.get_sender(), msg.get_path(),
118 "org.freedesktop.DBus.Properties", "GetAll");
119 getSensorValue.append("xyz.openbmc_project.Sensor.Value");
George Hungd9d78962019-03-27 13:25:24 +0800120 boost::container::flat_map<std::string, std::variant<double, int64_t>>
Jason M. Bills5e049d32018-10-19 12:59:38 -0700121 sensorValue;
122 try
123 {
Patrick Williamsccef2272022-07-22 19:26:54 -0500124 sdbusplus::message_t getSensorValueResp =
Jason M. Bills5e049d32018-10-19 12:59:38 -0700125 conn->call(getSensorValue);
126 getSensorValueResp.read(sensorValue);
127 }
Patrick Williams3f4cd972021-10-06 12:42:50 -0500128 catch (const sdbusplus::exception_t&)
Jason M. Bills5e049d32018-10-19 12:59:38 -0700129 {
130 std::cerr << "error getting sensor value from " << msg.get_path()
131 << "\n";
132 return;
133 }
Jason M. Billsbb071fb2019-03-27 11:15:42 -0700134 double max = 0;
135 auto findMax = sensorValue.find("MaxValue");
136 if (findMax != sensorValue.end())
137 {
138 max = std::visit(ipmi::VariantToDoubleVisitor(), findMax->second);
139 }
140 double min = 0;
141 auto findMin = sensorValue.find("MinValue");
142 if (findMin != sensorValue.end())
143 {
144 min = std::visit(ipmi::VariantToDoubleVisitor(), findMin->second);
145 }
George Hungd9d78962019-03-27 13:25:24 +0800146
Jason M. Bills5e049d32018-10-19 12:59:38 -0700147 try
148 {
Zhikui Ren25b26e12020-06-26 20:18:19 -0700149 eventData[1] = ipmi::getScaledIPMIValue(assertValue, max, min);
Jason M. Bills5e049d32018-10-19 12:59:38 -0700150 }
Zhikui Ren672bdfc2020-07-14 11:37:01 -0700151 catch (const std::exception& e)
Jason M. Bills5e049d32018-10-19 12:59:38 -0700152 {
153 std::cerr << e.what();
Zhikui Ren25b26e12020-06-26 20:18:19 -0700154 eventData[1] = selEvtDataUnspecified;
Jason M. Bills5e049d32018-10-19 12:59:38 -0700155 }
156
157 // Get the threshold value to put in the event data
158 // Get the threshold parameter by removing the "Alarm" text from the
159 // event string
160 std::string alarm("Alarm");
161 if (std::string::size_type pos = event.find(alarm);
162 pos != std::string::npos)
163 {
164 event.erase(pos, alarm.length());
165 }
Patrick Williamsccef2272022-07-22 19:26:54 -0500166 sdbusplus::message_t getThreshold =
Jason M. Bills5e049d32018-10-19 12:59:38 -0700167 conn->new_method_call(msg.get_sender(), msg.get_path(),
168 "org.freedesktop.DBus.Properties", "Get");
169 getThreshold.append(thresholdInterface, event);
George Hungd9d78962019-03-27 13:25:24 +0800170 std::variant<double, int64_t> thresholdValue;
Jason M. Bills5e049d32018-10-19 12:59:38 -0700171 try
172 {
Patrick Williamsccef2272022-07-22 19:26:54 -0500173 sdbusplus::message_t getThresholdResp = conn->call(getThreshold);
Jason M. Bills5e049d32018-10-19 12:59:38 -0700174 getThresholdResp.read(thresholdValue);
175 }
Patrick Williams3f4cd972021-10-06 12:42:50 -0500176 catch (const sdbusplus::exception_t&)
Jason M. Bills5e049d32018-10-19 12:59:38 -0700177 {
178 std::cerr << "error getting sensor threshold from "
179 << msg.get_path() << "\n";
180 return;
181 }
Patrick Williams5a18f102024-08-16 15:20:38 -0400182 double thresholdVal =
183 std::visit(ipmi::VariantToDoubleVisitor(), thresholdValue);
Zhikui Ren25b26e12020-06-26 20:18:19 -0700184
185 double scale = 0;
186 auto findScale = sensorValue.find("Scale");
George Hungd9d78962019-03-27 13:25:24 +0800187 if (findScale != sensorValue.end())
188 {
Patrick Williams5a18f102024-08-16 15:20:38 -0400189 scale =
190 std::visit(ipmi::VariantToDoubleVisitor(), findScale->second);
George Hungd9d78962019-03-27 13:25:24 +0800191 thresholdVal *= std::pow(10, scale);
192 }
Jason M. Bills5e049d32018-10-19 12:59:38 -0700193 try
194 {
195 eventData[2] = ipmi::getScaledIPMIValue(thresholdVal, max, min);
196 }
Zhikui Ren672bdfc2020-07-14 11:37:01 -0700197 catch (const std::exception& e)
Jason M. Bills5e049d32018-10-19 12:59:38 -0700198 {
199 std::cerr << e.what();
Zhikui Ren25b26e12020-06-26 20:18:19 -0700200 eventData[2] = selEvtDataUnspecified;
Jason M. Bills5e049d32018-10-19 12:59:38 -0700201 }
202
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700203 std::string threshold;
204 std::string direction;
Patrick Williams5a18f102024-08-16 15:20:38 -0400205 std::string redfishMessageID =
206 "OpenBMC." + openBMCMessageRegistryVersion;
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300207 enum EventType
208 {
209 eventNone,
210 eventInfo,
211 eventWarn,
212 eventErr
213 };
Glukhov Mikhail8cb7d0a2023-04-06 07:21:23 +0300214 [[maybe_unused]] EventType eventType = eventNone;
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700215 if (event == "CriticalLow")
216 {
217 threshold = "critical low";
218 if (assert)
219 {
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300220 eventType = eventErr;
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700221 direction = "low";
Jason M. Bills60ec28a2019-04-11 16:53:44 -0700222 redfishMessageID += ".SensorThresholdCriticalLowGoingLow";
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700223 }
224 else
225 {
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300226 eventType = eventInfo;
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700227 direction = "high";
Jason M. Bills60ec28a2019-04-11 16:53:44 -0700228 redfishMessageID += ".SensorThresholdCriticalLowGoingHigh";
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700229 }
230 }
231 else if (event == "WarningLow")
232 {
233 threshold = "warning low";
234 if (assert)
235 {
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300236 eventType = eventWarn;
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700237 direction = "low";
Jason M. Bills60ec28a2019-04-11 16:53:44 -0700238 redfishMessageID += ".SensorThresholdWarningLowGoingLow";
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700239 }
240 else
241 {
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300242 eventType = eventInfo;
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700243 direction = "high";
Jason M. Bills60ec28a2019-04-11 16:53:44 -0700244 redfishMessageID += ".SensorThresholdWarningLowGoingHigh";
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700245 }
246 }
247 else if (event == "WarningHigh")
248 {
249 threshold = "warning high";
250 if (assert)
251 {
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300252 eventType = eventWarn;
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700253 direction = "high";
Jason M. Bills60ec28a2019-04-11 16:53:44 -0700254 redfishMessageID += ".SensorThresholdWarningHighGoingHigh";
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700255 }
256 else
257 {
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300258 eventType = eventInfo;
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700259 direction = "low";
Jason M. Bills60ec28a2019-04-11 16:53:44 -0700260 redfishMessageID += ".SensorThresholdWarningHighGoingLow";
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700261 }
262 }
263 else if (event == "CriticalHigh")
264 {
265 threshold = "critical high";
266 if (assert)
267 {
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300268 eventType = eventErr;
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700269 direction = "high";
Jason M. Bills60ec28a2019-04-11 16:53:44 -0700270 redfishMessageID += ".SensorThresholdCriticalHighGoingHigh";
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700271 }
272 else
273 {
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300274 eventType = eventInfo;
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700275 direction = "low";
Jason M. Bills60ec28a2019-04-11 16:53:44 -0700276 redfishMessageID += ".SensorThresholdCriticalHighGoingLow";
Jason M. Bills2b9704d2018-11-02 13:12:09 -0700277 }
278 }
279
Konstantin Aladyshevd067a6b2023-03-31 09:22:49 +0000280 std::string journalMsg(
281 std::string(sensorName) + " " + threshold + " threshold " +
282 (assert ? "assert" : "deassert") +
283 ". Reading=" + std::to_string(assertValue) +
284 " Threshold=" + std::to_string(thresholdVal) + ".");
Jason M. Bills5e049d32018-10-19 12:59:38 -0700285
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300286#ifdef SEL_LOGGER_SEND_TO_LOGGING_SERVICE
287 std::string LogLevel = "";
288 switch (eventType)
289 {
290 case eventInfo:
291 {
292 LogLevel =
293 "xyz.openbmc_project.Logging.Entry.Level.Informational";
294 break;
295 }
296 case eventWarn:
297 {
298 LogLevel = "xyz.openbmc_project.Logging.Entry.Level.Warning";
299 break;
300 }
301 case eventErr:
302 {
303 LogLevel = "xyz.openbmc_project.Logging.Entry.Level.Critical";
304 break;
305 }
306 default:
307 {
308 LogLevel = "xyz.openbmc_project.Logging.Entry.Level.Debug";
309 break;
310 }
311 }
312 if (eventType != eventNone)
313 {
Patrick Williams99f69972023-03-28 02:31:11 -0500314 sdbusplus::message_t AddToLog = conn->new_method_call(
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300315 "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
316 "xyz.openbmc_project.Logging.Create", "Create");
317 AddToLog.append(journalMsg, LogLevel,
318 std::map<std::string, std::string>(
319 {{"SENSOR_PATH", std::string(msg.get_path())},
320 {"EVENT", threshold},
321 {"DIRECTION", direction},
322 {"THRESHOLD", std::to_string(thresholdVal)},
323 {"READING", std::to_string(assertValue)}}));
324 conn->call(AddToLog);
325 }
326#else
Jason M. Bills5ff505f2019-04-11 16:58:01 -0700327 selAddSystemRecord(
Konstantin Aladyshev6f5342d2023-04-19 09:23:11 +0000328 conn, journalMsg, std::string(msg.get_path()), eventData, assert,
Jason M. Bills5ff505f2019-04-11 16:58:01 -0700329 selBMCGenID, "REDFISH_MESSAGE_ID=%s", redfishMessageID.c_str(),
330 "REDFISH_MESSAGE_ARGS=%.*s,%f,%f", sensorName.length(),
Zhikui Ren25b26e12020-06-26 20:18:19 -0700331 sensorName.data(), assertValue, thresholdVal);
Glukhov Mikhail3fc535c2023-03-15 09:50:55 +0300332#endif
Jason M. Bills5e049d32018-10-19 12:59:38 -0700333 };
Patrick Williamsccef2272022-07-22 19:26:54 -0500334 sdbusplus::bus::match_t thresholdAssertMatcher(
335 static_cast<sdbusplus::bus_t&>(*conn),
Zhikui Ren25b26e12020-06-26 20:18:19 -0700336 "type='signal', member='ThresholdAsserted'",
337 std::move(thresholdAssertMatcherCallback));
338 return thresholdAssertMatcher;
Jason M. Bills5e049d32018-10-19 12:59:38 -0700339}