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