platform-mc: Set the local terminus as event receiver
Send `SetEventReceiver` to the discoveried terminus with the
configurable local EID to set the local terminus as event receiver.
Before send `SetEventReceiver` the local terminus also send
`EventMessageSupported` to get the `synchronyConfigurationSupported`.
The `eventMessageGlobalEnable` and `heartbeatTimer` options in the
`SetEventReceiver` command will depend on the responded
`synchronyConfigurationSupported`.
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Signed-off-by: Gilbert Chen <gilbertc@nvidia.com>
Change-Id: Ia798c1cd5d946ac519933bca60620e970fe10b0a
diff --git a/platform-mc/manager.hpp b/platform-mc/manager.hpp
index d8210b4..efbd1cb 100644
--- a/platform-mc/manager.hpp
+++ b/platform-mc/manager.hpp
@@ -33,7 +33,8 @@
explicit Manager(sdeventplus::Event& event, RequesterHandler& handler,
pldm::InstanceIdDb& instanceIdDb) :
- terminusManager(event, handler, instanceIdDb, termini, this),
+ terminusManager(event, handler, instanceIdDb, termini, this,
+ pldm::BmcMctpEid),
platformManager(terminusManager, termini),
sensorManager(event, terminusManager, termini)
{}
diff --git a/platform-mc/platform_manager.cpp b/platform-mc/platform_manager.cpp
index f6ffcc5..35526fb 100644
--- a/platform-mc/platform_manager.cpp
+++ b/platform-mc/platform_manager.cpp
@@ -36,7 +36,111 @@
terminus->parseTerminusPDRs();
}
+
+ auto rc = co_await configEventReceiver(tid);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to config event receiver for terminus with TID: {TID}, error: {ERROR}",
+ "TID", tid, "ERROR", rc);
+ }
}
+
+ co_return PLDM_SUCCESS;
+}
+
+exec::task<int> PlatformManager::configEventReceiver(pldm_tid_t tid)
+{
+ if (!termini.contains(tid))
+ {
+ co_return PLDM_ERROR;
+ }
+
+ auto& terminus = termini[tid];
+ if (!terminus->doesSupportCommand(PLDM_PLATFORM,
+ PLDM_EVENT_MESSAGE_SUPPORTED))
+ {
+ terminus->synchronyConfigurationSupported.byte = 0;
+ }
+ else
+ {
+ /**
+ * Get synchronyConfigurationSupported use PLDM command
+ * eventMessageBufferSize
+ */
+ uint8_t synchronyConfiguration = 0;
+ uint8_t numberEventClassReturned = 0;
+ std::vector<uint8_t> eventClass{};
+ auto rc = co_await eventMessageSupported(
+ tid, 1, synchronyConfiguration,
+ terminus->synchronyConfigurationSupported, numberEventClassReturned,
+ eventClass);
+ if (rc != PLDM_SUCCESS)
+ {
+ lg2::error(
+ "Failed to get event message supported for terminus with TID: {TID}, error: {ERROR}",
+ "TID", tid, "ERROR", rc);
+ terminus->synchronyConfigurationSupported.byte = 0;
+ }
+ }
+
+ if (!terminus->doesSupportCommand(PLDM_PLATFORM, PLDM_SET_EVENT_RECEIVER))
+ {
+ lg2::error("Terminus {TID} does not support Event", "TID", tid);
+ co_return PLDM_ERROR;
+ }
+
+ /**
+ * Set Event receiver base on synchronyConfigurationSupported data
+ * use PLDM command SetEventReceiver
+ */
+ pldm_event_message_global_enable eventMessageGlobalEnable =
+ PLDM_EVENT_MESSAGE_GLOBAL_DISABLE;
+ uint16_t heartbeatTimer = 0;
+
+ /* Use PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE when
+ * for eventMessageGlobalEnable when the terminus supports that type
+ */
+ if (terminus->synchronyConfigurationSupported.byte &
+ (1 << PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE))
+ {
+ heartbeatTimer = HEARTBEAT_TIMEOUT;
+ eventMessageGlobalEnable =
+ PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE;
+ }
+ /* Use PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC when
+ * for eventMessageGlobalEnable when the terminus does not support
+ * PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE
+ * and supports PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC type
+ */
+ else if (terminus->synchronyConfigurationSupported.byte &
+ (1 << PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC))
+ {
+ eventMessageGlobalEnable = PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC;
+ }
+ /* Only use PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_POLLING
+ * for eventMessageGlobalEnable when the terminus only supports
+ * this type
+ */
+ else if (terminus->synchronyConfigurationSupported.byte &
+ (1 << PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_POLLING))
+ {
+ eventMessageGlobalEnable = PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_POLLING;
+ }
+
+ if (eventMessageGlobalEnable != PLDM_EVENT_MESSAGE_GLOBAL_DISABLE)
+ {
+ auto rc = co_await setEventReceiver(tid, eventMessageGlobalEnable,
+ PLDM_TRANSPORT_PROTOCOL_TYPE_MCTP,
+ heartbeatTimer);
+ if (rc != PLDM_SUCCESS)
+ {
+ lg2::error(
+ "Failed to set event receiver for terminus with TID: {TID}, error: {ERROR}",
+ "TID", tid, "ERROR", rc);
+ }
+ }
+
co_return PLDM_SUCCESS;
}
@@ -265,5 +369,122 @@
co_return completionCode;
}
+exec::task<int> PlatformManager::setEventReceiver(
+ pldm_tid_t tid, pldm_event_message_global_enable eventMessageGlobalEnable,
+ pldm_transport_protocol_type protocolType, uint16_t heartbeatTimer)
+{
+ size_t requestBytes = PLDM_SET_EVENT_RECEIVER_REQ_BYTES;
+ /**
+ * Ignore heartbeatTimer bytes when eventMessageGlobalEnable is not
+ * ENABLE_ASYNC_KEEP_ALIVE
+ */
+ if (eventMessageGlobalEnable !=
+ PLDM_EVENT_MESSAGE_GLOBAL_ENABLE_ASYNC_KEEP_ALIVE)
+ {
+ requestBytes = requestBytes - sizeof(heartbeatTimer);
+ }
+ Request request(sizeof(pldm_msg_hdr) + requestBytes);
+ auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
+ auto rc = encode_set_event_receiver_req(
+ 0, eventMessageGlobalEnable, protocolType,
+ terminusManager.getLocalEid(), heartbeatTimer, requestMsg);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to encode request SetEventReceiver for terminus ID {TID}, error {RC} ",
+ "TID", tid, "RC", rc);
+ co_return rc;
+ }
+
+ const pldm_msg* responseMsg = nullptr;
+ size_t responseLen = 0;
+ rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
+ &responseLen);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to send SetEventReceiver message for terminus {TID}, error {RC}",
+ "TID", tid, "RC", rc);
+ co_return rc;
+ }
+
+ uint8_t completionCode;
+ rc = decode_set_event_receiver_resp(responseMsg, responseLen,
+ &completionCode);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to decode response SetEventReceiver for terminus ID {TID}, error {RC} ",
+ "TID", tid, "RC", rc);
+ co_return rc;
+ }
+
+ if (completionCode != PLDM_SUCCESS)
+ {
+ lg2::error(
+ "Error : SetEventReceiver for terminus ID {TID}, complete code {CC}.",
+ "TID", tid, "CC", completionCode);
+ co_return completionCode;
+ }
+
+ co_return completionCode;
+}
+
+exec::task<int> PlatformManager::eventMessageSupported(
+ pldm_tid_t tid, uint8_t formatVersion, uint8_t& synchronyConfiguration,
+ bitfield8_t& synchronyConfigurationSupported,
+ uint8_t& numberEventClassReturned, std::vector<uint8_t>& eventClass)
+{
+ Request request(
+ sizeof(pldm_msg_hdr) + PLDM_EVENT_MESSAGE_SUPPORTED_REQ_BYTES);
+ auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
+ auto rc = encode_event_message_supported_req(0, formatVersion, requestMsg);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to encode request EventMessageSupported for terminus ID {TID}, error {RC} ",
+ "TID", tid, "RC", rc);
+ co_return rc;
+ }
+
+ const pldm_msg* responseMsg = nullptr;
+ size_t responseLen = 0;
+ rc = co_await terminusManager.sendRecvPldmMsg(tid, request, &responseMsg,
+ &responseLen);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to send EventMessageSupported message for terminus {TID}, error {RC}",
+ "TID", tid, "RC", rc);
+ co_return rc;
+ }
+
+ uint8_t completionCode = 0;
+ uint8_t eventClassCount = static_cast<uint8_t>(responseLen) -
+ PLDM_EVENT_MESSAGE_SUPPORTED_MIN_RESP_BYTES;
+ eventClass.resize(eventClassCount);
+
+ rc = decode_event_message_supported_resp(
+ responseMsg, responseLen, &completionCode, &synchronyConfiguration,
+ &synchronyConfigurationSupported, &numberEventClassReturned,
+ eventClass.data(), eventClassCount);
+ if (rc)
+ {
+ lg2::error(
+ "Failed to decode response EventMessageSupported for terminus ID {TID}, error {RC} ",
+ "TID", tid, "RC", rc);
+ co_return rc;
+ }
+
+ if (completionCode != PLDM_SUCCESS)
+ {
+ lg2::error(
+ "Error : EventMessageSupported for terminus ID {TID}, complete code {CC}.",
+ "TID", tid, "CC", completionCode);
+ co_return completionCode;
+ }
+
+ co_return completionCode;
+}
} // namespace platform_mc
} // namespace pldm
diff --git a/platform-mc/platform_manager.hpp b/platform-mc/platform_manager.hpp
index 8d6e7b4..641f16a 100644
--- a/platform-mc/platform_manager.hpp
+++ b/platform-mc/platform_manager.hpp
@@ -40,6 +40,13 @@
*/
exec::task<int> initTerminus();
+ /** @brief Helper to get the supported event messages and set event receiver
+ *
+ * @param[in] tid - Destination TID
+ * @return coroutine return_value - PLDM completion code
+ */
+ exec::task<int> configEventReceiver(pldm_tid_t tid);
+
private:
/** @brief Fetch all PDRs from terminus.
*
@@ -86,6 +93,41 @@
const pldm_tid_t tid, uint8_t& repositoryState, uint32_t& recordCount,
uint32_t& repositorySize, uint32_t& largestRecordSize);
+ /** @brief Send setEventReceiver command to destination EID.
+ *
+ * @param[in] tid - Destination TID
+ * @param[in] eventMessageGlobalEnable - Enable/disable event message
+ * generation from the terminus
+ * @param[in] eventReceiverEid - The EID of eventReceiver that terminus
+ * should send event message to
+ * @param[in] protocolType - Provided in the request to help the responder
+ * verify that the content of the eventReceiverAddressInfo field
+ * @param[in] heartbeatTimer - Amount of time in seconds after each
+ * elapsing of which the terminus shall emit a heartbeat event.
+ * @return coroutine return_value - PLDM completion code
+ */
+ exec::task<int> setEventReceiver(
+ pldm_tid_t tid,
+ pldm_event_message_global_enable eventMessageGlobalEnable,
+ pldm_transport_protocol_type protocolType, uint16_t heartbeatTimer);
+
+ /** @brief send eventMessageSupported
+ * @param[in] tid - Destination TID
+ * @param[in] formatVersion - version of the event format
+ * @param[out] synchronyConfiguration - messaging style most recently
+ * configured via the setEventReceiver command
+ * @param[out] synchronyConfigurationSupported - event messaging styles
+ * supported by the terminus
+ * @param[out] numerEventClassReturned - number of eventClass enumerated
+ * bytes
+ * @param[out] eventClass - vector of eventClass the device can generate
+ * @return coroutine return_value - PLDM completion code
+ */
+ exec::task<int> eventMessageSupported(
+ pldm_tid_t tid, uint8_t formatVersion, uint8_t& synchronyConfiguration,
+ bitfield8_t& synchronyConfigurationSupported,
+ uint8_t& numerEventClassReturned, std::vector<uint8_t>& eventClass);
+
/** reference of TerminusManager for sending PLDM request to terminus*/
TerminusManager& terminusManager;
diff --git a/platform-mc/terminus.cpp b/platform-mc/terminus.cpp
index 7b94bda..575741a 100644
--- a/platform-mc/terminus.cpp
+++ b/platform-mc/terminus.cpp
@@ -14,7 +14,8 @@
{
Terminus::Terminus(pldm_tid_t tid, uint64_t supportedTypes) :
- initialized(false), tid(tid), supportedTypes(supportedTypes)
+ initialized(false), synchronyConfigurationSupported(0), tid(tid),
+ supportedTypes(supportedTypes)
{}
bool Terminus::doesSupportType(uint8_t type)
diff --git a/platform-mc/terminus.hpp b/platform-mc/terminus.hpp
index a819ad7..26a412b 100644
--- a/platform-mc/terminus.hpp
+++ b/platform-mc/terminus.hpp
@@ -133,6 +133,11 @@
/** @brief A flag to indicate if terminus has been initialized */
bool initialized = false;
+ /** @brief This value indicates the event messaging styles supported by the
+ * terminus
+ */
+ bitfield8_t synchronyConfigurationSupported;
+
/** @brief A list of numericSensors */
std::vector<std::shared_ptr<NumericSensor>> numericSensors{};
diff --git a/platform-mc/terminus_manager.hpp b/platform-mc/terminus_manager.hpp
index d485de5..2103fc5 100644
--- a/platform-mc/terminus_manager.hpp
+++ b/platform-mc/terminus_manager.hpp
@@ -51,12 +51,12 @@
TerminusManager& operator=(TerminusManager&&) = delete;
virtual ~TerminusManager() = default;
- explicit TerminusManager(sdeventplus::Event& /* event */,
- RequesterHandler& handler,
- pldm::InstanceIdDb& instanceIdDb,
- TerminiMapper& termini, Manager* manager) :
+ explicit TerminusManager(
+ sdeventplus::Event& /* event */, RequesterHandler& handler,
+ pldm::InstanceIdDb& instanceIdDb, TerminiMapper& termini,
+ Manager* manager, mctp_eid_t localEid) :
handler(handler), instanceIdDb(instanceIdDb), termini(termini),
- tidPool(tidPoolSize, false), manager(manager)
+ tidPool(tidPoolSize, false), manager(manager), localEid(localEid)
{
// DSP0240 v1.1.0 table-8, special value: 0,0xFF = reserved
tidPool[0] = true;
@@ -145,6 +145,15 @@
*/
bool unmapTid(const pldm_tid_t& tid);
+ /** @brief getter of local EID
+ *
+ * @return uint8_t - local EID
+ */
+ mctp_eid_t getLocalEid()
+ {
+ return localEid;
+ }
+
private:
/** @brief Find the terminus object pointer in termini list.
*
@@ -233,6 +242,9 @@
/** @brief A Manager interface for calling the hook functions **/
Manager* manager;
+
+ /** @brief local EID */
+ mctp_eid_t localEid;
};
} // namespace platform_mc
} // namespace pldm
diff --git a/platform-mc/test/mock_terminus_manager.hpp b/platform-mc/test/mock_terminus_manager.hpp
index 4e56a83..94d9c6d 100644
--- a/platform-mc/test/mock_terminus_manager.hpp
+++ b/platform-mc/test/mock_terminus_manager.hpp
@@ -17,7 +17,8 @@
MockTerminusManager(sdeventplus::Event& event, RequesterHandler& handler,
pldm::InstanceIdDb& instanceIdDb,
TerminiMapper& termini, Manager* manager) :
- TerminusManager(event, handler, instanceIdDb, termini, manager)
+ TerminusManager(event, handler, instanceIdDb, termini, manager,
+ pldm::BmcMctpEid)
{}
exec::task<int> sendRecvPldmMsgOverMctp(
diff --git a/platform-mc/test/sensor_manager_test.cpp b/platform-mc/test/sensor_manager_test.cpp
index b3a2d41..65505fb 100644
--- a/platform-mc/test/sensor_manager_test.cpp
+++ b/platform-mc/test/sensor_manager_test.cpp
@@ -17,7 +17,8 @@
bus(pldm::utils::DBusHandler::getBus()),
event(sdeventplus::Event::get_default()), instanceIdDb(),
reqHandler(pldmTransport, event, instanceIdDb, false),
- terminusManager(event, reqHandler, instanceIdDb, termini, nullptr),
+ terminusManager(event, reqHandler, instanceIdDb, termini, nullptr,
+ pldm::BmcMctpEid),
sensorManager(event, terminusManager, termini)
{}
diff --git a/platform-mc/test/terminus_manager_test.cpp b/platform-mc/test/terminus_manager_test.cpp
index 432ba21..6c425f2 100644
--- a/platform-mc/test/terminus_manager_test.cpp
+++ b/platform-mc/test/terminus_manager_test.cpp
@@ -32,7 +32,8 @@
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),
+ terminusManager(event, reqHandler, instanceIdDb, termini, nullptr,
+ pldm::BmcMctpEid),
mockTerminusManager(event, reqHandler, instanceIdDb, termini, nullptr)
{}