monitor: Support a separate upper deviation
Add an optional 'upper_deviation' field to the fan monitor config and if
supplied it will be used for the allowed deviation when the fan value is
over the target. If not supplied it will work as today and the single
deviation value will be used for both the upper and lower bounds.
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I085dc1996832e79b94bd1df3a05681d107f466eb
diff --git a/docs/monitor/deviation.md b/docs/monitor/deviation.md
index cd7a784..ddedbea 100644
--- a/docs/monitor/deviation.md
+++ b/docs/monitor/deviation.md
@@ -6,6 +6,11 @@
requested target before being deemed out-of-spec and not functioning as expected
according to the target requested.
+## Upper Deviation
+
+If 'upper_deviation' is specified, it will be used for the deviation above the
+target instead of 'deviation'.
+
## Attribute Value(s)
integer (0 - 100)
@@ -22,6 +27,7 @@
"allowed_out_of_range_time": 30,
"functional_delay": 5,
<b><i>"deviation": 15</i></b>,
+ <b><i>"upper_deviation": 30</i></b>,
"num_sensors_nonfunc_for_fan_nonfunc": 1,
"monitor_start_delay": 30,
"fan_missing_error_delay": 20,
diff --git a/monitor/fan.cpp b/monitor/fan.cpp
index a421290..2c29cb3 100644
--- a/monitor/fan.cpp
+++ b/monitor/fan.cpp
@@ -40,6 +40,7 @@
System& system) :
_bus(bus),
_name(def.name), _deviation(def.deviation),
+ _upperDeviation(def.upperDeviation),
_numSensorFailsForNonFunc(def.numSensorFailsForNonfunc),
_trustManager(trust),
#ifdef MONITOR_USE_JSON
@@ -359,7 +360,7 @@
}
auto actual = static_cast<uint64_t>(sensor.getInput());
- auto range = sensor.getRange(_deviation);
+ auto range = sensor.getRange(_deviation, _upperDeviation);
return ((actual < range.first) ||
(range.second && actual > range.second.value()));
@@ -372,7 +373,7 @@
return;
}
- auto range = sensor.getRange(_deviation);
+ auto range = sensor.getRange(_deviation, _upperDeviation);
std::string rangeMax = "NoMax";
if (range.second)
{
diff --git a/monitor/fan.hpp b/monitor/fan.hpp
index 75c2213..5892ba2 100644
--- a/monitor/fan.hpp
+++ b/monitor/fan.hpp
@@ -258,6 +258,13 @@
const size_t _deviation;
/**
+ * @brief The percentage that the input speed must be above
+ * the target speed to be considered an error.
+ * Between 0 and 100.
+ */
+ const size_t _upperDeviation;
+
+ /**
* The number of sensors that must be nonfunctional at the
* same time in order for the fan to be set to nonfunctional
* in the inventory.
diff --git a/monitor/gen-fan-monitor-defs.py b/monitor/gen-fan-monitor-defs.py
index bbd8368..dac5de7 100755
--- a/monitor/gen-fan-monitor-defs.py
+++ b/monitor/gen-fan-monitor-defs.py
@@ -55,6 +55,7 @@
${fan_data.get('functional_delay', 0)},
${fan_data.get('allowed_out_of_range_time', {})},
${fan_data['deviation']},
+ ${fan_data.get('upper_deviation', fan_data['deviation'])},
${fan_data['num_sensors_nonfunc_for_fan_nonfunc']},
0, // Monitor start delay - not used in YAML configs
0, // Count interval - not used in YAML configs
diff --git a/monitor/json_parser.cpp b/monitor/json_parser.cpp
index d81d767..4d06540 100644
--- a/monitor/json_parser.cpp
+++ b/monitor/json_parser.cpp
@@ -221,6 +221,24 @@
throw std::runtime_error(msg.c_str());
}
+ // Upper deviation defaults to the deviation value and
+ // can also be separately specified.
+ size_t upperDeviation = deviation;
+ if (fan.contains("upper_deviation"))
+ {
+ upperDeviation = fan["upper_deviation"].get<size_t>();
+ if (100 < upperDeviation)
+ {
+ auto msg =
+ fmt::format("Invalid upper_deviation of {} found, must "
+ "be between 0 and 100",
+ upperDeviation);
+
+ log<level::ERR>(msg.c_str());
+ throw std::runtime_error(msg.c_str());
+ }
+ }
+
// Construct the sensor definitions for this fan
auto sensorDefs = getSensorDefs(fan["sensors"]);
@@ -361,6 +379,7 @@
.funcDelay = funcDelay,
.timeout = timeout,
.deviation = deviation,
+ .upperDeviation = upperDeviation,
.numSensorFailsForNonfunc = nonfuncSensorsCount,
.monitorStartDelay = monitorDelay,
.countInterval = countInterval,
diff --git a/monitor/tach_sensor.cpp b/monitor/tach_sensor.cpp
index 9e05009..3030d5c 100644
--- a/monitor/tach_sensor.cpp
+++ b/monitor/tach_sensor.cpp
@@ -207,11 +207,12 @@
}
std::pair<uint64_t, std::optional<uint64_t>>
- TachSensor::getRange(const size_t deviation) const
+ TachSensor::getRange(const size_t lowerDeviation,
+ const size_t upperDeviation) const
{
// Determine min/max range applying the deviation
- uint64_t min = getTarget() * (100 - deviation) / 100;
- std::optional<uint64_t> max = getTarget() * (100 + deviation) / 100;
+ uint64_t min = getTarget() * (100 - lowerDeviation) / 100;
+ std::optional<uint64_t> max = getTarget() * (100 + upperDeviation) / 100;
// Adjust the min/max range by applying the factor & offset
min = min * _factor + _offset;
diff --git a/monitor/tach_sensor.hpp b/monitor/tach_sensor.hpp
index 875c578..b4dc5b5 100644
--- a/monitor/tach_sensor.hpp
+++ b/monitor/tach_sensor.hpp
@@ -344,12 +344,16 @@
/**
* @brief Get the current allowed range of speeds
*
- * @param[in] deviation - The configured deviation(in percent) allowed
+ * @param[in] lowerDeviation - The configured lower deviation(in percent)
+ * allowed
+ * @param[in] upperDeviation - The configured upper deviation(in percent)
+ * allowed
*
* @return pair - Min/Max(optional) range of speeds allowed
*/
std::pair<uint64_t, std::optional<uint64_t>>
- getRange(const size_t deviation) const;
+ getRange(const size_t lowerDeviation,
+ const size_t upperDeviation) const;
/**
* @brief Processes the current state of the sensor
diff --git a/monitor/types.hpp b/monitor/types.hpp
index 30b416f..fd53522 100644
--- a/monitor/types.hpp
+++ b/monitor/types.hpp
@@ -121,6 +121,7 @@
size_t funcDelay;
size_t timeout;
size_t deviation;
+ size_t upperDeviation;
size_t numSensorFailsForNonfunc;
size_t monitorStartDelay;
size_t countInterval;