1 #pragma once
2 
3 #include "config.h"
4 
5 #include "tach_sensor.hpp"
6 #include "trust_manager.hpp"
7 #include "types.hpp"
8 
9 #include <sdbusplus/bus.hpp>
10 #include <sdeventplus/event.hpp>
11 
12 #include <tuple>
13 #include <vector>
14 
15 namespace phosphor
16 {
17 namespace fan
18 {
19 namespace monitor
20 {
21 
22 class System;
23 
24 /**
25  * @class InvalidSensorError
26  *
27  * An exception type for sensors that don't exist or
28  * are otherwise inaccessible.
29  */
30 class InvalidSensorError : public std::exception
31 {};
32 
33 /**
34  * @class Fan
35  *
36  * Represents a fan, which can contain 1 or more sensors which
37  * loosely correspond to rotors.  See below.
38  *
39  * There is a sensor when hwmon exposes one, which means there is a
40  * speed value to be read.  Sometimes there is a sensor per rotor,
41  * and other times multiple rotors just use 1 sensor total where
42  * the sensor reports the slowest speed of all of the rotors.
43  *
44  * A rotor's speed is set by writing the Target value of a sensor.
45  * Sometimes each sensor in a fan supports having a Target, and other
46  * times not all of them do.  A TachSensor object knows if it supports
47  * the Target property.
48  *
49  * The strategy for monitoring fan speeds is as follows:
50  *
51  * Every time a Target (new speed written) or Input (actual speed read)
52  * sensor changes, check if the input value is within some range of the target
53  * value.  If it isn't, start a timer at the end of which the sensor will be
54  * set to not functional.  If enough sensors in the fan are now nonfunctional,
55  * set the whole fan to nonfunctional in the inventory.
56  *
57  * When sensor inputs come back within a specified range of the target,
58  * stop its timer if running, make the sensor functional again if it wasn't,
59  * and if enough sensors in the fan are now functional set the whole fan
60  * back to functional in the inventory.
61  */
62 class Fan
63 {
64     using Property = std::string;
65     using Value = std::variant<bool>;
66     using PropertyMap = std::map<Property, Value>;
67 
68     using Interface = std::string;
69     using InterfaceMap = std::map<Interface, PropertyMap>;
70 
71     using Object = sdbusplus::message::object_path;
72     using ObjectMap = std::map<Object, InterfaceMap>;
73 
74   public:
75     Fan() = delete;
76     Fan(const Fan&) = delete;
77     Fan(Fan&&) = default;
78     Fan& operator=(const Fan&) = delete;
79     Fan& operator=(Fan&&) = default;
80     ~Fan() = default;
81 
82     /**
83      * @brief Constructor
84      *
85      * @param mode - mode of fan monitor
86      * @param bus - the dbus object
87      * @param event - event loop reference
88      * @param trust - the tach trust manager
89      * @param def - the fan definition structure
90      * @param system - Reference to the system object
91      */
92     Fan(Mode mode, sdbusplus::bus::bus& bus, const sdeventplus::Event& event,
93         std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
94         System& system);
95 
96     /**
97      * @brief Callback function for when an input sensor changes
98      *
99      * Starts a timer, where if it expires then the sensor
100      * was out of range for too long and can be considered not functional.
101      */
102     void tachChanged(TachSensor& sensor);
103 
104     /**
105      * @brief Calls tachChanged(sensor) on each sensor
106      */
107     void tachChanged();
108 
109     /**
110      * @brief The callback function for the method
111      *
112      * Sets the sensor to not functional.
113      * If enough sensors are now not functional,
114      * updates the functional status of the whole
115      * fan in the inventory.
116      *
117      * @param[in] sensor - the sensor for state update
118      */
119     void updateState(TachSensor& sensor);
120 
121     /**
122      * @brief Get the name of the fan
123      *
124      * @return - The fan name
125      */
126     inline const std::string& getName() const
127     {
128         return _name;
129     }
130 
131     /**
132      * @brief Finds the target speed of this fan
133      *
134      * Finds the target speed from the list of sensors that make up this
135      * fan. At least one sensor should contain a target speed value.
136      *
137      * @return - The target speed found from the list of sensors on the fan
138      */
139     uint64_t findTargetSpeed();
140 
141     /**
142      * @brief Returns the contained TachSensor objects
143      *
144      * @return std::vector<std::shared_ptr<TachSensor>> - The sensors
145      */
146     const std::vector<std::shared_ptr<TachSensor>>& sensors() const
147     {
148         return _sensors;
149     }
150 
151     /**
152      * @brief Returns the presence status of the fan
153      *
154      * @return bool - If the fan is present or not
155      */
156     bool present() const
157     {
158         return _present;
159     }
160 
161     /**
162      * @brief Called from TachSensor when its error timer expires
163      *        so an event log calling out the fan can be created.
164      *
165      * @param[in] sensor - The nonfunctional sensor
166      */
167     void sensorErrorTimerExpired(const TachSensor& sensor);
168 
169     /**
170      * @brief Process the state of the given tach sensor without checking
171      * any trust groups the sensor may be included in
172      *
173      * @param[in] sensor - Tach sensor to process
174      *
175      * This function is intended to check the current state of a tach sensor
176      * regardless of whether or not the tach sensor is configured to be in any
177      * trust groups.
178      */
179     void process(TachSensor& sensor);
180 
181     /**
182      * @brief The function that runs when the power state changes
183      *
184      * @param[in] powerStateOn - If power is now on or not
185      */
186     void powerStateChanged(bool powerStateOn);
187 
188   private:
189     /**
190      * @brief Returns true if the sensor input is not within
191      * some deviation of the target.
192      *
193      * @param[in] sensor - the sensor to check
194      */
195     bool outOfRange(const TachSensor& sensor);
196 
197     /**
198      * @brief Returns the number sensors that are nonfunctional
199      */
200     size_t countNonFunctionalSensors();
201 
202     /**
203      * @brief Updates the Functional property in the inventory
204      *        for the fan based on the value passed in.
205      *
206      * @param[in] functional - If the Functional property should
207      *                         be set to true or false.
208      */
209     void updateInventory(bool functional);
210 
211     /**
212      * @brief Called by _monitorTimer to start fan monitoring some
213      *        amount of time after startup.
214      */
215     void startMonitor();
216 
217     /**
218      * @brief Called when the fan presence property changes on D-Bus
219      *
220      * @param[in] msg - The message from the propertiesChanged signal
221      */
222     void presenceChanged(sdbusplus::message::message& msg);
223 
224     /**
225      * @brief Called when there is an interfacesAdded signal on the
226      *        fan D-Bus path so the code can look for the 'Present'
227      *        property value.
228      *
229      * @param[in] msg - The message from the interfacesAdded signal
230      */
231     void presenceIfaceAdded(sdbusplus::message::message& msg);
232 
233     /**
234      * @brief the dbus object
235      */
236     sdbusplus::bus::bus& _bus;
237 
238     /**
239      * @brief The inventory name of the fan
240      */
241     const std::string _name;
242 
243     /**
244      * @brief The percentage that the input speed must be below
245      *        the target speed to be considered an error.
246      *        Between 0 and 100.
247      */
248     const size_t _deviation;
249 
250     /**
251      * The number of sensors that must be nonfunctional at the
252      * same time in order for the fan to be set to nonfunctional
253      * in the inventory.
254      */
255     const size_t _numSensorFailsForNonFunc;
256 
257     /**
258      * The number of failed sensors
259      */
260     size_t _numFailedSensor = 0;
261 
262     /**
263      * @brief The current functional state of the fan
264      */
265     bool _functional = true;
266 
267     /**
268      * The sensor objects for the fan
269      */
270     std::vector<std::shared_ptr<TachSensor>> _sensors;
271 
272     /**
273      * The tach trust manager object
274      */
275     std::unique_ptr<trust::Manager>& _trustManager;
276 
277 #ifdef MONITOR_USE_JSON
278     /**
279      * @brief The number of seconds to wait after startup until
280      *        fan sensors should checked against their targets.
281      */
282     size_t _monitorDelay;
283 
284     /**
285      * @brief Expires after _monitorDelay to start fan monitoring.
286      */
287     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _monitorTimer;
288 #endif
289 
290     /**
291      * @brief Set to true when monitoring can start.
292      */
293     bool _monitorReady = false;
294 
295     /**
296      * @brief Reference to the System object
297      */
298     System& _system;
299 
300     /**
301      * @brief The match object for propertiesChanged signals
302      *        for the inventory item interface to track the
303      *        Present property.
304      */
305     sdbusplus::bus::match::match _presenceMatch;
306 
307     /**
308      * @brief The match object for the interfacesAdded signal
309      *        for the interface that has the Present property.
310      */
311     sdbusplus::bus::match::match _presenceIfaceAddedMatch;
312 
313     /**
314      * @brief The current presence state
315      */
316     bool _present = false;
317 
318     /**
319      * @brief The number of seconds to wait after a fan is removed before
320      *        creating an event log for it.  If std::nullopt, then no
321      *        event log will be created.
322      */
323     const std::optional<size_t> _fanMissingErrorDelay;
324 
325     /**
326      * @brief The timer that uses the _fanMissingErrorDelay timeout,
327      *        at the end of which an event log will be created.
328      */
329     std::unique_ptr<
330         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
331         _fanMissingErrorTimer;
332 };
333 
334 } // namespace monitor
335 } // namespace fan
336 } // namespace phosphor
337