monitor: Add ignoring feedback sensors above allowed max
There may be situations where fan rotor feedback speeds above the
allowed range could be ignored, essentially ignoring any overspeed
detections. This adds an optional `ignore_above_max` attribute to the
fan sensors that can be added, set to 'true', to ignore marking that fan
sensor as nonfunctional when its above the allowed max. Without this
attribute, the fan sensor must remain within the allowed min/max range
to be deemed functional. This is the default behavior.
Change-Id: I4876b4c1963a8a1becd55732ca19496f5df6b003
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/monitor/fan.cpp b/monitor/fan.cpp
index 0e2d835..9856242 100644
--- a/monitor/fan.cpp
+++ b/monitor/fan.cpp
@@ -73,7 +73,8 @@
std::get<hasTargetField>(s), std::get<funcDelay>(def),
std::get<targetInterfaceField>(s), std::get<factorField>(s),
std::get<offsetField>(s), std::get<methodField>(def),
- std::get<thresholdField>(s), std::get<timeoutField>(def),
+ std::get<thresholdField>(s), std::get<ignoreAboveMaxField>(s),
+ std::get<timeoutField>(def),
std::get<nonfuncRotorErrDelayField>(def),
std::get<countIntervalField>(def), event));
@@ -364,24 +365,30 @@
auto actual = static_cast<uint64_t>(sensor.getInput());
auto range = sensor.getRange(_deviation);
- return ((actual < range.first) || (actual > range.second));
+ return ((actual < range.first) ||
+ (range.second && actual > range.second.value()));
}
void Fan::updateState(TachSensor& sensor)
{
- auto range = sensor.getRange(_deviation);
-
if (!_system.isPowerOn())
{
return;
}
+ auto range = sensor.getRange(_deviation);
+ std::string rangeMax = "NoMax";
+ if (range.second)
+ {
+ rangeMax = std::to_string(range.second.value());
+ }
+
sensor.setFunctional(!sensor.functional());
getLogger().log(
fmt::format("Setting tach sensor {} functional state to {}. "
"[target = {}, input = {}, allowed range = ({} - {})]",
sensor.name(), sensor.functional(), sensor.getTarget(),
- sensor.getInput(), range.first, range.second));
+ sensor.getInput(), range.first, rangeMax));
// A zero value for _numSensorFailsForNonFunc means we aren't dealing
// with fan FRU functional status, only sensor functional status.
diff --git a/monitor/gen-fan-monitor-defs.py b/monitor/gen-fan-monitor-defs.py
index 1d46f80..c771109 100755
--- a/monitor/gen-fan-monitor-defs.py
+++ b/monitor/gen-fan-monitor-defs.py
@@ -70,13 +70,16 @@
factor = sensor.get('factor', 1)
offset = sensor.get('offset', 0)
threshold = sensor.get('threshold', 1)
+ ignore_above_max = str(sensor.get(
+ 'ignore_above_max', False)).lower()
%> \
SensorDefinition{"${sensor['name']}",
${has_target},
"${target_interface}",
${factor},
${offset},
- ${threshold}},
+ ${threshold},
+ ${ignore_above_max}},
%endfor
},
%if ('condition' in fan_data) and \
diff --git a/monitor/json_parser.cpp b/monitor/json_parser.cpp
index ff86642..1c537e9 100644
--- a/monitor/json_parser.cpp
+++ b/monitor/json_parser.cpp
@@ -164,10 +164,16 @@
{
threshold = sensor["threshold"].get<size_t>();
}
+ // Ignore being above the allowed max is optional, defaults to not
+ bool ignoreAboveMax = false;
+ if (sensor.contains("ignore_above_max"))
+ {
+ ignoreAboveMax = sensor["ignore_above_max"].get<bool>();
+ }
sensorDefs.emplace_back(std::tuple(
sensor["name"].get<std::string>(), sensor["has_target"].get<bool>(),
- targetIntf, factor, offset, threshold));
+ targetIntf, factor, offset, threshold, ignoreAboveMax));
}
return sensorDefs;
diff --git a/monitor/tach_sensor.cpp b/monitor/tach_sensor.cpp
index 91b4091..bc7063c 100644
--- a/monitor/tach_sensor.cpp
+++ b/monitor/tach_sensor.cpp
@@ -26,6 +26,7 @@
#include <experimental/filesystem>
#include <functional>
+#include <optional>
#include <utility>
namespace phosphor
@@ -71,13 +72,15 @@
const std::string& id, bool hasTarget, size_t funcDelay,
const std::string& interface, double factor,
int64_t offset, size_t method, size_t threshold,
- size_t timeout, const std::optional<size_t>& errorDelay,
+ bool ignoreAboveMax, size_t timeout,
+ const std::optional<size_t>& errorDelay,
size_t countInterval, const sdeventplus::Event& event) :
_bus(bus),
_fan(fan), _name(FAN_SENSOR_PATH + id), _invName(path(fan.getName()) / id),
_hasTarget(hasTarget), _funcDelay(funcDelay), _interface(interface),
_factor(factor), _offset(offset), _method(method), _threshold(threshold),
- _timeout(timeout), _timerMode(TimerMode::func),
+ _ignoreAboveMax(ignoreAboveMax), _timeout(timeout),
+ _timerMode(TimerMode::func),
_timer(event, std::bind(&Fan::updateState, &fan, std::ref(*this))),
_errorDelay(errorDelay), _countInterval(countInterval)
{
@@ -190,15 +193,21 @@
return _tachTarget;
}
-std::pair<uint64_t, uint64_t> TachSensor::getRange(const size_t deviation) const
+std::pair<uint64_t, std::optional<uint64_t>>
+ TachSensor::getRange(const size_t deviation) const
{
// Determine min/max range applying the deviation
uint64_t min = getTarget() * (100 - deviation) / 100;
- uint64_t max = getTarget() * (100 + deviation) / 100;
+ std::optional<uint64_t> max = getTarget() * (100 + deviation) / 100;
// Adjust the min/max range by applying the factor & offset
min = min * _factor + _offset;
- max = max * _factor + _offset;
+ max = max.value() * _factor + _offset;
+
+ if (_ignoreAboveMax)
+ {
+ max = std::nullopt;
+ }
return std::make_pair(min, max);
}
diff --git a/monitor/tach_sensor.hpp b/monitor/tach_sensor.hpp
index dc8814f..87c69ac 100644
--- a/monitor/tach_sensor.hpp
+++ b/monitor/tach_sensor.hpp
@@ -10,6 +10,7 @@
#include <sdeventplus/utility/timer.hpp>
#include <chrono>
+#include <optional>
#include <utility>
namespace phosphor
@@ -95,6 +96,7 @@
* @param[in] offset - the offset of the sensor target
* @param[in] method - the method of out of range
* @param[in] threshold - the threshold of counter method
+ * @param[in] ignoreAboveMax - whether to ignore being above max or not
* @param[in] timeout - Normal timeout value to use
* @param[in] errorDelay - Delay in seconds before creating an error
* or std::nullopt if no errors.
@@ -105,9 +107,9 @@
TachSensor(Mode mode, sdbusplus::bus::bus& bus, Fan& fan,
const std::string& id, bool hasTarget, size_t funcDelay,
const std::string& interface, double factor, int64_t offset,
- size_t method, size_t threshold, size_t timeout,
- const std::optional<size_t>& errorDelay, size_t countInterval,
- const sdeventplus::Event& event);
+ size_t method, size_t threshold, bool ignoreAboveMax,
+ size_t timeout, const std::optional<size_t>& errorDelay,
+ size_t countInterval, const sdeventplus::Event& event);
/**
* @brief Reads a property from the input message and stores it in value.
@@ -337,9 +339,10 @@
*
* @param[in] deviation - The configured deviation(in percent) allowed
*
- * @return pair - Min/Max range of speeds allowed
+ * @return pair - Min/Max(optional) range of speeds allowed
*/
- std::pair<uint64_t, uint64_t> getRange(const size_t deviation) const;
+ std::pair<uint64_t, std::optional<uint64_t>>
+ getRange(const size_t deviation) const;
/**
* @brief Processes the current state of the sensor
@@ -458,6 +461,11 @@
const size_t _threshold;
/**
+ * @brief Whether to ignore being above the max or not
+ */
+ const bool _ignoreAboveMax;
+
+ /**
* @brief The counter for count method
*/
size_t _counter = 0;
diff --git a/monitor/types.hpp b/monitor/types.hpp
index faf3b66..1f4b84c 100644
--- a/monitor/types.hpp
+++ b/monitor/types.hpp
@@ -108,9 +108,10 @@
constexpr auto factorField = 3;
constexpr auto offsetField = 4;
constexpr auto thresholdField = 5;
+constexpr auto ignoreAboveMaxField = 6;
using SensorDefinition =
- std::tuple<std::string, bool, std::string, double, int64_t, size_t>;
+ std::tuple<std::string, bool, std::string, double, int64_t, size_t, bool>;
constexpr auto fanNameField = 0;
constexpr auto methodField = 1;