summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>2018-01-23 04:47:06 -0600
committerTom Joseph <tomjoseph@in.ibm.com>2018-02-06 05:17:46 +0000
commit5c0beec1c30e2702e18359989ed16052ae222767 (patch)
tree8302db55f3c85bf3d8214c14f9bc49f09efc56c7
parentb1e8fba50af2310136c6f92ab8765bf27aa5cec2 (diff)
downloadphosphor-host-ipmid-5c0beec1c30e2702e18359989ed16052ae222767.tar.gz
phosphor-host-ipmid-5c0beec1c30e2702e18359989ed16052ae222767.zip
Support Get Sensor Thresholds Command
Adding support for sensor thresholds command Resolves openbmc/openbmc#2624 Change-Id: I904c1b18c8709bceb7ecb7eec6e8e42e1f51525a Signed-off-by: Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>
-rw-r--r--sensorhandler.cpp140
-rw-r--r--sensorhandler.h11
-rw-r--r--types.hpp33
-rw-r--r--utils.cpp25
-rw-r--r--utils.hpp11
5 files changed, 220 insertions, 0 deletions
diff --git a/sensorhandler.cpp b/sensorhandler.cpp
index e6320be..de3c228 100644
--- a/sensorhandler.cpp
+++ b/sensorhandler.cpp
@@ -666,6 +666,141 @@ ipmi_ret_t ipmi_sen_get_sensor_reading(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
return rc;
}
+ipmi_ret_t ipmi_sen_get_sensor_thresholds(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ constexpr auto warningThresholdInterface =
+ "xyz.openbmc_project.Sensor.Threshold.Warning";
+ constexpr auto criticalThresholdInterface =
+ "xyz.openbmc_project.Sensor.Threshold.Critical";
+ constexpr auto valueInterface =
+ "xyz.openbmc_project.Sensor.Value";
+ constexpr auto sensorRoot = "/xyz/openbmc_project/sensors";
+
+ ipmi::sensor::Thresholds thresholds =
+ {
+ {
+ warningThresholdInterface,
+ {
+ {
+ "WarningLow",
+ ipmi::sensor::ThresholdMask::NON_CRITICAL_LOW_MASK,
+ ipmi::sensor::ThresholdIndex::NON_CRITICAL_LOW_IDX
+ },
+ {
+ "WarningHigh",
+ ipmi::sensor::ThresholdMask::NON_CRITICAL_HIGH_MASK,
+ ipmi::sensor::ThresholdIndex::NON_CRITICAL_HIGH_IDX
+ }
+ }
+ },
+ {
+ criticalThresholdInterface,
+ {
+ {
+ "CriticalLow",
+ ipmi::sensor::ThresholdMask::CRITICAL_LOW_MASK,
+ ipmi::sensor::ThresholdIndex::CRITICAL_LOW_IDX
+ },
+ {
+ "CriticalHigh",
+ ipmi::sensor::ThresholdMask::CRITICAL_HIGH_MASK,
+ ipmi::sensor::ThresholdIndex::CRITICAL_HIGH_IDX
+ }
+ }
+ }
+ };
+
+ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+
+ if (*data_len != sizeof(uint8_t))
+ {
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+ auto sensorNum = *(reinterpret_cast<uint8_t*>(request));
+
+ auto responseData =
+ reinterpret_cast<get_sdr::GetSensorThresholdsResponse*>(response);
+
+ responseData->validMask = 0;
+
+ const auto iter = sensors.find(sensorNum);
+ if (iter == sensors.end())
+ {
+ return IPMI_CC_SENSOR_INVALID;
+ }
+
+ const auto sensorInfo = iter->second;
+
+ //Proceed only if the sensor value interface is implemented.
+ if (sensorInfo.propertyInterfaces.find(valueInterface) ==
+ sensorInfo.propertyInterfaces.end())
+ {
+ //return with valid mask as 0
+ return IPMI_CC_OK;
+ }
+
+ std::string service;
+ try
+ {
+ service = ipmi::getService(bus,
+ sensorInfo.sensorInterface,
+ sensorInfo.sensorPath);
+ }
+ catch (const std::runtime_error& e)
+ {
+ log<level::ERR>(e.what());
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ //prevent divide by 0
+ auto coefficientM =
+ sensorInfo.coefficientM ? sensorInfo.coefficientM : 1;
+
+ try
+ {
+ auto mngObjects = ipmi::getManagedObjects(bus,
+ service,
+ sensorRoot);
+
+ auto senIter = mngObjects.find(sensorInfo.sensorPath);
+ if (senIter == mngObjects.end())
+ {
+ return IPMI_CC_SENSOR_INVALID;
+ }
+
+ for (const auto& threshold : thresholds)
+ {
+ auto thresholdType = senIter->second.find(threshold.first);
+ if (thresholdType != senIter->second.end())
+ {
+ for (const auto& threshLevel : threshold.second)
+ {
+ auto val = thresholdType->
+ second[threshLevel.property].get<int64_t>();
+ if (val != 0)
+ {
+ auto idx = static_cast<uint8_t>(threshLevel.idx);
+ responseData->data[idx] = static_cast<uint8_t>(
+ (val - sensorInfo.scaledOffset) / coefficientM);
+ responseData->validMask |=
+ static_cast<uint8_t>(threshLevel.maskValue);
+ }
+ }
+ }
+ }
+ }
+ catch (InternalFailure& e)
+ {
+ //Not able to get the values, reset the mask.
+ responseData->validMask = 0;
+ }
+
+ *data_len = sizeof(get_sdr::GetSensorThresholdsResponse);
+ return IPMI_CC_OK;
+}
+
ipmi_ret_t ipmi_sen_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
ipmi_request_t request, ipmi_response_t response,
ipmi_data_len_t data_len, ipmi_context_t context)
@@ -987,5 +1122,10 @@ void register_netfn_sen_functions()
nullptr, ipmi_sen_get_sdr,
PRIVILEGE_USER);
+ // <Get Sensor Thresholds>
+ ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_THRESHOLDS,
+ nullptr, ipmi_sen_get_sensor_thresholds,
+ PRIVILEGE_USER);
+
return;
}
diff --git a/sensorhandler.h b/sensorhandler.h
index 8995447..1cf43ca 100644
--- a/sensorhandler.h
+++ b/sensorhandler.h
@@ -13,6 +13,7 @@ enum ipmi_netfn_sen_cmds
IPMI_CMD_GET_SENSOR_READING = 0x2D,
IPMI_CMD_GET_SENSOR_TYPE = 0x2F,
IPMI_CMD_SET_SENSOR = 0x30,
+ IPMI_CMD_GET_SENSOR_THRESHOLDS = 0x27,
};
// Discrete sensor types.
@@ -206,6 +207,16 @@ inline void set_owner_lun_channel(uint8_t channel, SensorDataRecordKey* key)
} // namespace key
+/** @struct GetSensorThresholdsResponse
+ *
+ * Response structure for Get Sensor Thresholds command
+ */
+struct GetSensorThresholdsResponse
+{
+ uint8_t validMask; //Indicates which values are valid
+ uint8_t data[6]; //Container for threshold values
+} __attribute__((packed));
+
// Body - full record
#define FULL_RECORD_ID_STR_MAX_LENGTH 16
struct SensorDataFullRecordBody
diff --git a/types.hpp b/types.hpp
index 260deb5..61f3d68 100644
--- a/types.hpp
+++ b/types.hpp
@@ -27,6 +27,11 @@ using ObjectTree = std::map<DbusObjectPath,
using InterfaceList = std::vector<std::string>;
+using DbusInterfaceMap = std::map<DbusInterface, PropertyMap>;
+
+using ObjectValueTree =
+ std::map<sdbusplus::message::object_path, DbusInterfaceMap>;
+
namespace sensor
{
@@ -183,6 +188,34 @@ using InventoryPath = std::string;
using InvObjectIDMap = std::map<InventoryPath, SelData>;
+enum class ThresholdMask
+{
+ NON_CRITICAL_LOW_MASK = 0x01,
+ CRITICAL_LOW_MASK = 0x02,
+ NON_CRITICAL_HIGH_MASK = 0x08,
+ CRITICAL_HIGH_MASK = 0x10,
+};
+
+enum class ThresholdIndex
+{
+ NON_CRITICAL_LOW_IDX = 0,
+ CRITICAL_LOW_IDX = 1,
+ NON_RECOVERABLE_LOW_IDX = 2,
+ NON_CRITICAL_HIGH_IDX = 3,
+ CRITICAL_HIGH_IDX = 4,
+ NON_RECOVERABLE_HIGH_IDX = 5,
+};
+
+struct ThresholdLevel
+{
+ std::string property;
+ ThresholdMask maskValue;
+ ThresholdIndex idx;
+};
+
+using SensorThresholds = std::vector<ThresholdLevel>;
+using Thresholds = std::map<std::string, SensorThresholds>;
+
}// namespace sensor
namespace network
diff --git a/utils.cpp b/utils.cpp
index fa6bd04..bd8fade 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -198,6 +198,31 @@ PropertyMap getAllDbusProperties(sdbusplus::bus::bus& bus,
return properties;
}
+ObjectValueTree getManagedObjects(sdbusplus::bus::bus& bus,
+ const std::string& service,
+ const std::string& objPath)
+{
+ ipmi::ObjectValueTree interfaces;
+
+ auto method = bus.new_method_call(
+ service.c_str(),
+ objPath.c_str(),
+ "org.freedesktop.DBus.ObjectManager",
+ "GetManagedObjects");
+
+ auto reply = bus.call(method);
+
+ if (reply.is_method_error())
+ {
+ log<level::ERR>("Failed to get managed objects",
+ entry("PATH=%s", objPath.c_str()));
+ elog<InternalFailure>();
+ }
+
+ reply.read(interfaces);
+ return interfaces;
+}
+
void setDbusProperty(sdbusplus::bus::bus& bus,
const std::string& service,
const std::string& objPath,
diff --git a/utils.hpp b/utils.hpp
index 1699c52..b4f090f 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -87,6 +87,17 @@ PropertyMap getAllDbusProperties(sdbusplus::bus::bus& bus,
const std::string& objPath,
const std::string& interface);
+/** @brief Gets all managed objects associated with the given object
+ * path and service.
+ * @param[in] bus - D-Bus Bus Object.
+ * @param[in] service - D-Bus service name.
+ * @param[in] objPath - D-Bus object path.
+ * @return On success returns the map of name value pair.
+ */
+ObjectValueTree getManagedObjects(sdbusplus::bus::bus& bus,
+ const std::string& service,
+ const std::string& objPath);
+
/** @brief Sets the property value of the given object.
* @param[in] bus - DBUS Bus Object.
* @param[in] service - Dbus service name.
OpenPOWER on IntegriCloud