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/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