blob: 9fe7e0af219d40f84c5491a84df43e806e7ed90d [file] [log] [blame]
George Hung486e42e2021-04-14 20:20:42 +08001/*
2// Copyright (c) 2021 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
Lei YU9916d412025-02-06 11:51:18 +000018#include "threshold_event_monitor.hpp"
19
George Hung486e42e2021-04-14 20:20:42 +080020#include <boost/container/flat_map.hpp>
Lei YU9916d412025-02-06 11:51:18 +000021#include <sdbusplus/bus/match.hpp>
George Hung486e42e2021-04-14 20:20:42 +080022#include <sel_logger.hpp>
23#include <sensorutils.hpp>
24
25#include <map>
26#include <string_view>
27#include <variant>
28
Patrick Williamsccef2272022-07-22 19:26:54 -050029using sdbusMatch = std::shared_ptr<sdbusplus::bus::match_t>;
George Hung486e42e2021-04-14 20:20:42 +080030static sdbusMatch warningLowAssertedMatcher;
31static sdbusMatch warningLowDeassertedMatcher;
32static sdbusMatch warningHighAssertedMatcher;
33static sdbusMatch warningHighDeassertedMatcher;
34static sdbusMatch criticalLowAssertedMatcher;
35static sdbusMatch criticalLowDeassertedMatcher;
36static sdbusMatch criticalHighAssertedMatcher;
37static sdbusMatch criticalHighDeassertedMatcher;
38
39static boost::container::flat_map<std::string, sdbusMatch> matchers = {
40 {"WarningLowAlarmAsserted", warningLowAssertedMatcher},
41 {"WarningLowAlarmDeasserted", warningLowDeassertedMatcher},
42 {"WarningHighAlarmAsserted", warningHighAssertedMatcher},
43 {"WarningHighAlarmDeasserted", warningHighDeassertedMatcher},
44 {"CriticalLowAlarmAsserted", criticalLowAssertedMatcher},
45 {"CriticalLowAlarmDeasserted", criticalLowDeassertedMatcher},
46 {"CriticalHighAlarmAsserted", criticalHighAssertedMatcher},
47 {"CriticalHighAlarmDeasserted", criticalHighDeassertedMatcher}};
48
49void generateEvent(std::string signalName,
50 std::shared_ptr<sdbusplus::asio::connection> conn,
Patrick Williamsccef2272022-07-22 19:26:54 -050051 sdbusplus::message_t& msg)
George Hung486e42e2021-04-14 20:20:42 +080052{
53 double assertValue;
54 try
55 {
56 msg.read(assertValue);
57 }
Patrick Williams3f4cd972021-10-06 12:42:50 -050058 catch (const sdbusplus::exception_t&)
George Hung486e42e2021-04-14 20:20:42 +080059 {
60 std::cerr << "error getting assert signal data from " << msg.get_path()
61 << "\n";
62 return;
63 }
64
65 std::string event;
66 std::string thresholdInterface;
67 std::string threshold;
68 std::string direction;
69 bool assert = false;
70 std::vector<uint8_t> eventData(selEvtDataMaxSize, selEvtDataUnspecified);
71 std::string redfishMessageID = "OpenBMC." + openBMCMessageRegistryVersion;
72
73 if (signalName == "WarningLowAlarmAsserted" ||
74 signalName == "WarningLowAlarmDeasserted")
75 {
76 event = "WarningLow";
77 thresholdInterface = "xyz.openbmc_project.Sensor.Threshold.Warning";
78 eventData[0] =
79 static_cast<uint8_t>(thresholdEventOffsets::lowerNonCritGoingLow);
80 threshold = "warning low";
81 if (signalName == "WarningLowAlarmAsserted")
82 {
83 assert = true;
84 direction = "low";
85 redfishMessageID += ".SensorThresholdWarningLowGoingLow";
86 }
87 else if (signalName == "WarningLowAlarmDeasserted")
88 {
89 direction = "high";
90 redfishMessageID += ".SensorThresholdWarningLowGoingHigh";
91 }
92 }
93 else if (signalName == "WarningHighAlarmAsserted" ||
94 signalName == "WarningHighAlarmDeasserted")
95 {
96 event = "WarningHigh";
97 thresholdInterface = "xyz.openbmc_project.Sensor.Threshold.Warning";
98 eventData[0] =
99 static_cast<uint8_t>(thresholdEventOffsets::upperNonCritGoingHigh);
100 threshold = "warning high";
101 if (signalName == "WarningHighAlarmAsserted")
102 {
103 assert = true;
104 direction = "high";
105 redfishMessageID += ".SensorThresholdWarningHighGoingHigh";
106 }
107 else if (signalName == "WarningHighAlarmDeasserted")
108 {
109 direction = "low";
110 redfishMessageID += ".SensorThresholdWarningHighGoingLow";
111 }
112 }
113 else if (signalName == "CriticalLowAlarmAsserted" ||
114 signalName == "CriticalLowAlarmDeasserted")
115 {
116 event = "CriticalLow";
117 thresholdInterface = "xyz.openbmc_project.Sensor.Threshold.Critical";
118 eventData[0] =
119 static_cast<uint8_t>(thresholdEventOffsets::lowerCritGoingLow);
120 threshold = "critical low";
121 if (signalName == "CriticalLowAlarmAsserted")
122 {
123 assert = true;
124 direction = "low";
125 redfishMessageID += ".SensorThresholdCriticalLowGoingLow";
126 }
127 else if (signalName == "CriticalLowAlarmDeasserted")
128 {
129 direction = "high";
130 redfishMessageID += ".SensorThresholdCriticalLowGoingHigh";
131 }
132 }
133 else if (signalName == "CriticalHighAlarmAsserted" ||
134 signalName == "CriticalHighAlarmDeasserted")
135 {
136 event = "CriticalHigh";
137 thresholdInterface = "xyz.openbmc_project.Sensor.Threshold.Critical";
138 eventData[0] =
139 static_cast<uint8_t>(thresholdEventOffsets::upperCritGoingHigh);
140 threshold = "critical high";
141 if (signalName == "CriticalHighAlarmAsserted")
142 {
143 assert = true;
144 direction = "high";
145 redfishMessageID += ".SensorThresholdCriticalHighGoingHigh";
146 }
147 else if (signalName == "CriticalHighAlarmDeasserted")
148 {
149 direction = "low";
150 redfishMessageID += ".SensorThresholdCriticalHighGoingLow";
151 }
152 }
153 // Indicate that bytes 2 and 3 are threshold sensor trigger values
154 eventData[0] |= thresholdEventDataTriggerReadingByte2 |
155 thresholdEventDataTriggerReadingByte3;
156
157 // Get the sensor reading to put in the event data
Patrick Williamsccef2272022-07-22 19:26:54 -0500158 sdbusplus::message_t getSensorValue =
George Hung486e42e2021-04-14 20:20:42 +0800159 conn->new_method_call(msg.get_sender(), msg.get_path(),
160 "org.freedesktop.DBus.Properties", "GetAll");
161 getSensorValue.append("xyz.openbmc_project.Sensor.Value");
162 boost::container::flat_map<std::string, std::variant<double, int64_t>>
163 sensorValue;
164 try
165 {
Patrick Williamsccef2272022-07-22 19:26:54 -0500166 sdbusplus::message_t getSensorValueResp = conn->call(getSensorValue);
George Hung486e42e2021-04-14 20:20:42 +0800167 getSensorValueResp.read(sensorValue);
168 }
Patrick Williams3f4cd972021-10-06 12:42:50 -0500169 catch (const sdbusplus::exception_t&)
George Hung486e42e2021-04-14 20:20:42 +0800170 {
171 std::cerr << "error getting sensor value from " << msg.get_path()
172 << "\n";
173 return;
174 }
175 double max = 0;
176 auto findMax = sensorValue.find("MaxValue");
177 if (findMax != sensorValue.end())
178 {
179 max = std::visit(ipmi::VariantToDoubleVisitor(), findMax->second);
180 }
181 double min = 0;
182 auto findMin = sensorValue.find("MinValue");
183 if (findMin != sensorValue.end())
184 {
185 min = std::visit(ipmi::VariantToDoubleVisitor(), findMin->second);
186 }
187
188 try
189 {
190 eventData[1] = ipmi::getScaledIPMIValue(assertValue, max, min);
191 }
192 catch (const std::exception& e)
193 {
194 std::cerr << e.what();
195 eventData[1] = selEvtDataUnspecified;
196 }
197
198 // Get the threshold value to put in the event data
Patrick Williamsccef2272022-07-22 19:26:54 -0500199 sdbusplus::message_t getThreshold =
George Hung486e42e2021-04-14 20:20:42 +0800200 conn->new_method_call(msg.get_sender(), msg.get_path(),
201 "org.freedesktop.DBus.Properties", "Get");
202 getThreshold.append(thresholdInterface, event);
203 std::variant<double, int64_t> thresholdValue;
204 try
205 {
Patrick Williamsccef2272022-07-22 19:26:54 -0500206 sdbusplus::message_t getThresholdResp = conn->call(getThreshold);
George Hung486e42e2021-04-14 20:20:42 +0800207 getThresholdResp.read(thresholdValue);
208 }
Patrick Williams3f4cd972021-10-06 12:42:50 -0500209 catch (const sdbusplus::exception_t&)
George Hung486e42e2021-04-14 20:20:42 +0800210 {
211 std::cerr << "error getting sensor threshold from " << msg.get_path()
212 << "\n";
213 return;
214 }
Patrick Williams5a18f102024-08-16 15:20:38 -0400215 double thresholdVal =
216 std::visit(ipmi::VariantToDoubleVisitor(), thresholdValue);
George Hung486e42e2021-04-14 20:20:42 +0800217
218 double scale = 0;
219 auto findScale = sensorValue.find("Scale");
220 if (findScale != sensorValue.end())
221 {
222 scale = std::visit(ipmi::VariantToDoubleVisitor(), findScale->second);
223 thresholdVal *= std::pow(10, scale);
224 }
225 try
226 {
227 eventData[2] = ipmi::getScaledIPMIValue(thresholdVal, max, min);
228 }
229 catch (const std::exception& e)
230 {
231 std::cerr << e.what();
232 eventData[2] = selEvtDataUnspecified;
233 }
234
235 std::string_view sensorName(msg.get_path());
236 sensorName.remove_prefix(
237 std::min(sensorName.find_last_of("/") + 1, sensorName.size()));
238
239 std::string journalMsg(std::string(sensorName) + " sensor crossed a " +
240 threshold + " threshold going " + direction +
241 ". Reading=" + std::to_string(assertValue) +
242 " Threshold=" + std::to_string(thresholdVal) + ".");
243
Konstantin Aladyshev6f5342d2023-04-19 09:23:11 +0000244 selAddSystemRecord(conn, journalMsg, std::string(msg.get_path()), eventData,
George Hung486e42e2021-04-14 20:20:42 +0800245 assert, selBMCGenID, "REDFISH_MESSAGE_ID=%s",
246 redfishMessageID.c_str(),
247 "REDFISH_MESSAGE_ARGS=%.*s,%f,%f", sensorName.length(),
248 sensorName.data(), assertValue, thresholdVal);
249}
250
251inline static void startThresholdAlarmMonitor(
252 std::shared_ptr<sdbusplus::asio::connection> conn)
253{
254 for (auto iter = matchers.begin(); iter != matchers.end(); iter++)
255 {
Patrick Williamsccef2272022-07-22 19:26:54 -0500256 iter->second = std::make_shared<sdbusplus::bus::match_t>(
257 static_cast<sdbusplus::bus_t&>(*conn),
George Hung486e42e2021-04-14 20:20:42 +0800258 "type='signal',member=" + iter->first,
Patrick Williamsccef2272022-07-22 19:26:54 -0500259 [conn, iter](sdbusplus::message_t& msg) {
Patrick Williams5a18f102024-08-16 15:20:38 -0400260 generateEvent(iter->first, conn, msg);
261 });
George Hung486e42e2021-04-14 20:20:42 +0800262 }
263}