platform-mc: Added EventManager
Added eventManager to handle sensor event class(00h) which is defined in
table 11 of DSP0248 v1.3.0. In this commit, the eventManager supports to
receive event asynchronously. The commit will also log the Ipmitool SEL
log and Redfish log for PLDM sensor event messages.
Change-Id: I1b337ccae454067841ffbbd8754631216a995542
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Signed-off-by: Gilbert Chen <gilbertc@nvidia.com>
diff --git a/platform-mc/test/event_manager_test.cpp b/platform-mc/test/event_manager_test.cpp
new file mode 100644
index 0000000..01abf42
--- /dev/null
+++ b/platform-mc/test/event_manager_test.cpp
@@ -0,0 +1,390 @@
+#include "libpldm/base.h"
+#include "libpldm/entity.h"
+#include "libpldm/platform.h"
+
+#include "common/instance_id.hpp"
+#include "common/types.hpp"
+#include "mock_event_manager.hpp"
+#include "mock_terminus_manager.hpp"
+#include "platform-mc/platform_manager.hpp"
+#include "platform-mc/terminus_manager.hpp"
+#include "test/test_instance_id.hpp"
+
+#include <gtest/gtest.h>
+
+using ::testing::_;
+using ::testing::Return;
+
+class EventManagerTest : public testing::Test
+{
+ protected:
+ EventManagerTest() :
+ bus(pldm::utils::DBusHandler::getBus()),
+ event(sdeventplus::Event::get_default()), instanceIdDb(),
+ reqHandler(pldmTransport, event, instanceIdDb, false,
+ std::chrono::seconds(1), 2, std::chrono::milliseconds(100)),
+ terminusManager(event, reqHandler, instanceIdDb, termini, nullptr),
+ eventManager(terminusManager, termini),
+ platformManager(terminusManager, termini)
+ {}
+
+ PldmTransport* pldmTransport = nullptr;
+ sdbusplus::bus::bus& bus;
+ sdeventplus::Event event;
+ TestInstanceIdDb instanceIdDb;
+ pldm::requester::Handler<pldm::requester::Request> reqHandler;
+ pldm::platform_mc::MockTerminusManager terminusManager;
+ pldm::platform_mc::MockEventManager eventManager;
+ pldm::platform_mc::PlatformManager platformManager;
+ pldm::platform_mc::TerminiMapper termini{};
+};
+
+TEST_F(EventManagerTest, processNumericSensorEventTest)
+{
+#define SENSOR_READING 50
+#define WARNING_HIGH 45
+ pldm_tid_t tid = 1;
+ termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
+ tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM);
+ std::vector<uint8_t> pdr1{
+ 0x1,
+ 0x0,
+ 0x0,
+ 0x0, // record handle
+ 0x1, // PDRHeaderVersion
+ PLDM_NUMERIC_SENSOR_PDR, // PDRType
+ 0x0,
+ 0x0, // recordChangeNumber
+ PLDM_PDR_NUMERIC_SENSOR_PDR_MIN_LENGTH,
+ 0, // dataLength
+ 0,
+ 0, // PLDMTerminusHandle
+ 0x1,
+ 0x0, // sensorID=1
+ PLDM_ENTITY_POWER_SUPPLY,
+ 0, // entityType=Power Supply(120)
+ 1,
+ 0, // entityInstanceNumber
+ 1,
+ 0, // containerID=1
+ PLDM_NO_INIT, // sensorInit
+ false, // sensorAuxiliaryNamesPDR
+ PLDM_SENSOR_UNIT_DEGRESS_C, // baseUint(2)=degrees C
+ 0, // unitModifier = 0
+ 0, // rateUnit
+ 0, // baseOEMUnitHandle
+ 0, // auxUnit
+ 0, // auxUnitModifier
+ 0, // auxRateUnit
+ 0, // rel
+ 0, // auxOEMUnitHandle
+ true, // isLinear
+ PLDM_SENSOR_DATA_SIZE_UINT8, // sensorDataSize
+ 0,
+ 0,
+ 0x80,
+ 0x3f, // resolution=1.0
+ 0,
+ 0,
+ 0,
+ 0, // offset=0
+ 0,
+ 0, // accuracy
+ 0, // plusTolerance
+ 0, // minusTolerance
+ 2, // hysteresis = 2
+ 0x1b, // supportedThresholds
+ 0, // thresholdAndHysteresisVolatility
+ 0,
+ 0,
+ 0x80,
+ 0x3f, // stateTransistionInterval=1.0
+ 0,
+ 0,
+ 0x80,
+ 0x3f, // updateInverval=1.0
+ 255, // maxReadable
+ 0, // minReadable
+ PLDM_RANGE_FIELD_FORMAT_UINT8, // rangeFieldFormat
+ 0x18, // rangeFieldsupport
+ 0, // nominalValue
+ 0, // normalMax
+ 0, // normalMin
+ WARNING_HIGH, // warningHigh
+ 20, // warningLow
+ 60, // criticalHigh
+ 10, // criticalLow
+ 0, // fatalHigh
+ 0 // fatalLow
+ };
+
+ std::vector<uint8_t> pdr2{
+ 0x1, 0x0, 0x0,
+ 0x0, // record handle
+ 0x1, // PDRHeaderVersion
+ PLDM_ENTITY_AUXILIARY_NAMES_PDR, // PDRType
+ 0x1,
+ 0x0, // recordChangeNumber
+ 0x11,
+ 0, // dataLength
+ /* Entity Auxiliary Names PDR Data*/
+ 3,
+ 0x80, // entityType system software
+ 0x1,
+ 0x0, // Entity instance number =1
+ 0,
+ 0, // Overal system
+ 0, // shared Name Count one name only
+ 01, // nameStringCount
+ 0x65, 0x6e, 0x00,
+ 0x00, // Language Tag "en"
+ 0x53, 0x00, 0x30, 0x00,
+ 0x00 // Entity Name "S0"
+ };
+
+ // add dummy numeric sensor
+ termini[tid]->pdrs.emplace_back(pdr1);
+ termini[tid]->pdrs.emplace_back(pdr2);
+ termini[tid]->parseTerminusPDRs();
+ EXPECT_EQ(1, termini[tid]->numericSensors.size());
+
+ uint8_t platformEventStatus = 0;
+
+ std::vector<uint8_t> eventData{
+ 0x1,
+ 0x0, // sensor id
+ PLDM_NUMERIC_SENSOR_STATE,
+ PLDM_SENSOR_UPPERWARNING,
+ PLDM_SENSOR_NORMAL,
+ PLDM_SENSOR_DATA_SIZE_UINT8,
+ SENSOR_READING};
+ auto rc = eventManager.handlePlatformEvent(
+ tid, 0x00, PLDM_SENSOR_EVENT, eventData.data(), eventData.size());
+ EXPECT_EQ(PLDM_SUCCESS, rc);
+ EXPECT_EQ(PLDM_EVENT_NO_LOGGING, platformEventStatus);
+}
+
+TEST_F(EventManagerTest, SetEventReceiverTest)
+{
+ // Add terminus
+ auto mappedTid = terminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
+ auto tid = mappedTid.value();
+ termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
+ tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM);
+ auto terminus = termini[tid];
+
+ /* Set supported command by terminus */
+ auto size = PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
+ std::vector<uint8_t> pldmCmds(size);
+ uint8_t type = PLDM_PLATFORM;
+ uint8_t cmd = PLDM_GET_PDR_REPOSITORY_INFO;
+ auto idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
+ pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
+ cmd = PLDM_GET_PDR;
+ idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
+ pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
+ cmd = PLDM_EVENT_MESSAGE_SUPPORTED;
+ idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
+ pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
+ cmd = PLDM_EVENT_MESSAGE_BUFFER_SIZE;
+ idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
+ pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
+ cmd = PLDM_SET_EVENT_RECEIVER;
+ idx = type * (PLDM_MAX_CMDS_PER_TYPE / 8) + (cmd / 8);
+ pldmCmds[idx] = pldmCmds[idx] | (1 << (cmd % 8));
+ termini[tid]->setSupportedCommands(pldmCmds);
+
+ EXPECT_EQ(true, termini[tid]->doesSupportCommand(PLDM_PLATFORM,
+ PLDM_SET_EVENT_RECEIVER));
+ EXPECT_EQ(true, termini[tid]->doesSupportCommand(
+ PLDM_PLATFORM, PLDM_EVENT_MESSAGE_BUFFER_SIZE));
+ EXPECT_EQ(true, termini[tid]->doesSupportCommand(
+ PLDM_PLATFORM, PLDM_EVENT_MESSAGE_SUPPORTED));
+ EXPECT_EQ(true,
+ termini[tid]->doesSupportCommand(PLDM_PLATFORM, PLDM_GET_PDR));
+ EXPECT_EQ(true, termini[tid]->doesSupportCommand(
+ PLDM_PLATFORM, PLDM_GET_PDR_REPOSITORY_INFO));
+
+ // queue getPDRRepositoryInfo response
+ const size_t getPDRRepositoryInfoLen =
+ PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + getPDRRepositoryInfoLen>
+ getPDRRepositoryInfoResp{
+ 0x0, 0x02, 0x50, PLDM_SUCCESS,
+ 0x0, // repositoryState
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // updateTime
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // OEMUpdateTime
+ 2, 0x0, 0x0, 0x0, // recordCount
+ 0x0, 0x1, 0x0, 0x0, // repositorySize
+ 59, 0x0, 0x0, 0x0, // largestRecordSize
+ 0x0 // dataTransferHandleTimeout
+ };
+ auto rc = terminusManager.enqueueResponse(
+ reinterpret_cast<pldm_msg*>(getPDRRepositoryInfoResp.data()),
+ sizeof(getPDRRepositoryInfoResp));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ // queue getPDR responses
+ const size_t getPdrRespLen = 81;
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrRespLen> getPdrResp{
+ 0x0, 0x02, 0x51, PLDM_SUCCESS, 0x1, 0x0, 0x0, 0x0, // nextRecordHandle
+ 0x0, 0x0, 0x0, 0x0, // nextDataTransferHandle
+ 0x5, // transferFlag
+ 69, 0x0, // responseCount
+ // numeric Sensor PDR
+ 0x0, 0x0, 0x0,
+ 0x0, // record handle
+ 0x1, // PDRHeaderVersion
+ PLDM_NUMERIC_SENSOR_PDR, // PDRType
+ 0x0,
+ 0x0, // recordChangeNumber
+ PLDM_PDR_NUMERIC_SENSOR_PDR_FIXED_LENGTH +
+ PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_SENSOR_DATA_SIZE_MIN_LENGTH +
+ PLDM_PDR_NUMERIC_SENSOR_PDR_VARIED_RANGE_FIELD_MIN_LENGTH,
+ 0, // dataLength
+ 0,
+ 0, // PLDMTerminusHandle
+ 0x1,
+ 0x0, // sensorID=1
+ 120,
+ 0, // entityType=Power Supply(120)
+ 1,
+ 0, // entityInstanceNumber
+ 0x1,
+ 0x0, // containerID=1
+ PLDM_NO_INIT, // sensorInit
+ false, // sensorAuxiliaryNamesPDR
+ PLDM_SENSOR_UNIT_DEGRESS_C, // baseUint(2)=degrees C
+ 1, // unitModifier = 1
+ 0, // rateUnit
+ 0, // baseOEMUnitHandle
+ 0, // auxUnit
+ 0, // auxUnitModifier
+ 0, // auxRateUnit
+ 0, // rel
+ 0, // auxOEMUnitHandle
+ true, // isLinear
+ PLDM_SENSOR_DATA_SIZE_UINT8, // sensorDataSize
+ 0, 0, 0xc0,
+ 0x3f, // resolution=1.5
+ 0, 0, 0x80,
+ 0x3f, // offset=1.0
+ 0,
+ 0, // accuracy
+ 0, // plusTolerance
+ 0, // minusTolerance
+ 2, // hysteresis
+ 0, // supportedThresholds
+ 0, // thresholdAndHysteresisVolatility
+ 0, 0, 0x80,
+ 0x3f, // stateTransistionInterval=1.0
+ 0, 0, 0x80,
+ 0x3f, // updateInverval=1.0
+ 255, // maxReadable
+ 0, // minReadable
+ PLDM_RANGE_FIELD_FORMAT_UINT8, // rangeFieldFormat
+ 0, // rangeFieldsupport
+ 0, // nominalValue
+ 0, // normalMax
+ 0, // normalMin
+ 0, // warningHigh
+ 0, // warningLow
+ 0, // criticalHigh
+ 0, // criticalLow
+ 0, // fatalHigh
+ 0 // fatalLow
+ };
+ rc = terminusManager.enqueueResponse(
+ reinterpret_cast<pldm_msg*>(getPdrResp.data()), sizeof(getPdrResp));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ const size_t getPdrAuxNameRespLen = 39;
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + getPdrAuxNameRespLen>
+ getPdrAuxNameResp{
+ 0x0, 0x02, 0x51, PLDM_SUCCESS, 0x0, 0x0, 0x0,
+ 0x0, // nextRecordHandle
+ 0x0, 0x0, 0x0, 0x0, // nextDataTransferHandle
+ 0x5, // transferFlag
+ 0x1b, 0x0, // responseCount
+ // Common PDR Header
+ 0x1, 0x0, 0x0,
+ 0x0, // record handle
+ 0x1, // PDRHeaderVersion
+ PLDM_ENTITY_AUXILIARY_NAMES_PDR, // PDRType
+ 0x1,
+ 0x0, // recordChangeNumber
+ 0x11,
+ 0, // dataLength
+ /* Entity Auxiliary Names PDR Data*/
+ 3,
+ 0x80, // entityType system software
+ 0x1,
+ 0x0, // Entity instance number =1
+ 0,
+ 0, // Overal system
+ 0, // shared Name Count one name only
+ 01, // nameStringCount
+ 0x65, 0x6e, 0x00,
+ 0x00, // Language Tag "en"
+ 0x53, 0x00, 0x30, 0x00,
+ 0x00 // Entity Name "S0"
+ };
+ rc = terminusManager.enqueueResponse(
+ reinterpret_cast<pldm_msg*>(getPdrAuxNameResp.data()),
+ sizeof(getPdrAuxNameResp));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ // queue eventMessageBufferSize response(bufferSize=32)
+ const size_t eventMessageBufferSizeRespLen = 3;
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + eventMessageBufferSizeRespLen>
+ eventMessageBufferSizeResp{0x0, 0x02, 0x0d, PLDM_SUCCESS, 32, 0};
+ rc = terminusManager.enqueueResponse(
+ reinterpret_cast<pldm_msg*>(eventMessageBufferSizeResp.data()),
+ sizeof(eventMessageBufferSizeResp));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ // queue eventMessageSupported response
+ const size_t eventMessageSupportedLen = 7;
+ PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + eventMessageSupportedLen>
+ eventMessageSupportedResp{0x0, 0x02, 0x0c, PLDM_SUCCESS,
+ 0x0, // synchronyConfiguration
+ 0x06, // synchronyConfigurationSupported
+ 3, // numberEventClassReturned
+ 0x0, 0x5, 0xfa};
+ rc = terminusManager.enqueueResponse(
+ reinterpret_cast<pldm_msg*>(eventMessageSupportedResp.data()),
+ sizeof(eventMessageSupportedResp));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ // queue SetEventReceiver response
+ const size_t SetEventReceiverLen = 1;
+ PLDM_GET_PDR_REPOSITORY_INFO_RESP_BYTES;
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + SetEventReceiverLen>
+ SetEventReceiverResp{0x0, 0x02, 0x04, PLDM_SUCCESS};
+ rc = terminusManager.enqueueResponse(
+ reinterpret_cast<pldm_msg*>(SetEventReceiverResp.data()),
+ sizeof(SetEventReceiverResp));
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ // should finish immediately
+ stdexec::sync_wait(platformManager.initTerminus());
+ EXPECT_EQ(true, terminus->initialized);
+ EXPECT_EQ(32, terminus->maxBufferSize);
+ EXPECT_EQ(0x06, terminus->synchronyConfigurationSupported.byte);
+ EXPECT_EQ(2, terminus->pdrs.size());
+ EXPECT_EQ(1, terminus->numericSensors.size());
+}
+
+TEST_F(EventManagerTest, updateAvailableState)
+{
+ pldm_tid_t tid = 1;
+ eventManager.updateAvailableState(tid, true);
+ EXPECT_EQ(true, eventManager.getAvailableState(tid));
+ eventManager.updateAvailableState(tid, false);
+ EXPECT_EQ(false, eventManager.getAvailableState(tid));
+ eventManager.updateAvailableState(2, false);
+ EXPECT_EQ(false, eventManager.getAvailableState(tid));
+}