BMC RR: check whether the Host is running
This commit checks whether Host is up by sending a request to
Host when pldmd starts up. This does not differentiate the case
when there is a bmc RR or pldmd restarted.
Updates the Host condition accordingly.
Initiates a PDR exchange if Host is running.
Change-Id: I630b342f5f9cc62530e0274f46357d238e92d0c9
Signed-off-by: sampmisr <sampmisr@gmail.com>
diff --git a/host-bmc/host_pdr_handler.cpp b/host-bmc/host_pdr_handler.cpp
index a2d4d17..a786ed4 100644
--- a/host-bmc/host_pdr_handler.cpp
+++ b/host-bmc/host_pdr_handler.cpp
@@ -7,6 +7,10 @@
#include <assert.h>
#include <nlohmann/json.hpp>
+#include <sdeventplus/clock.hpp>
+#include <sdeventplus/exception.hpp>
+#include <sdeventplus/source/io.hpp>
+#include <sdeventplus/source/time.hpp>
#include <fstream>
@@ -482,4 +486,114 @@
this->getHostPDR(nextRecordHandle);
}
+void HostPDRHandler::setHostState()
+{
+ using namespace sdeventplus;
+ using namespace sdeventplus::source;
+ constexpr auto clockId = sdeventplus::ClockId::RealTime;
+ using Clock = Clock<clockId>;
+ using Timer = Time<clockId>;
+
+ auto event1 = sdeventplus::Event::get_default();
+ auto& bus = pldm::utils::DBusHandler::getBus();
+ bus.attach_event(event1.get(), SD_EVENT_PRIORITY_NORMAL);
+
+ responseReceived = false;
+ timeOut = false;
+
+ int fd = pldm_open();
+ if (-1 == fd)
+ {
+ std::cerr << "Failed to connect to mctp demux daemon \n";
+ return;
+ }
+
+ auto timerCallback = [=, this](Timer& /*source*/,
+ Timer::TimePoint /*time*/) {
+ timeOut = true;
+ if (!responseReceived)
+ {
+ std::cout << "PLDM did not get a response from Host"
+ " Host seems to be off \n";
+ }
+ return;
+ };
+
+ Timer time(event1, (Clock(event1).now() + std::chrono::seconds{3}),
+ std::chrono::seconds{1}, std::move(timerCallback));
+
+ auto callback = [=, this](IO& /*io*/, int fd, uint32_t revents) {
+ if (!(revents & EPOLLIN))
+ {
+ return;
+ }
+ uint8_t* responseMsg = nullptr;
+ size_t responseMsgSize{};
+ auto rc =
+ pldm_recv(mctp_eid, fd, insId, &responseMsg, &responseMsgSize);
+ if (rc != PLDM_REQUESTER_SUCCESS)
+ {
+ return;
+ }
+ std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{
+ responseMsg, std::free};
+ auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
+ std::cout << "Getting the response. PLDM RC = " << std::hex
+ << std::showbase
+ << static_cast<uint16_t>(response->payload[0]) << "\n";
+ responseReceived = true;
+ return;
+ };
+ IO io(event1, fd, EPOLLIN, std::move(callback));
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
+ PLDM_GET_PDR_REQ_BYTES);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ uint32_t recordHandle{};
+ insId = requester.getInstanceId(mctp_eid);
+ auto rc =
+ encode_get_pdr_req(insId, recordHandle, 0, PLDM_GET_FIRSTPART,
+ UINT16_MAX, 0, request, PLDM_GET_PDR_REQ_BYTES);
+ if (rc != PLDM_SUCCESS)
+ {
+ requester.markFree(mctp_eid, insId);
+ std::cerr << "Failed to encode_get_pdr_req, rc = " << rc << std::endl;
+ return;
+ }
+ rc = pldm_send(mctp_eid, fd, requestMsg.data(), requestMsg.size());
+ if (0 > rc)
+ {
+ std::cerr << "Failed to send message RC = " << rc
+ << ", errno = " << errno << "\n";
+ return;
+ }
+ while (1)
+ {
+ if (responseReceived)
+ {
+ requester.markFree(mctp_eid, insId);
+ break;
+ }
+ if (timeOut)
+ {
+ requester.markFree(mctp_eid, insId);
+ break;
+ }
+ try
+ {
+ event1.run(std::nullopt);
+ }
+ catch (const sdeventplus::SdEventError& e)
+ {
+ std::cerr << "Failure in processing request.ERROR= " << e.what()
+ << "\n";
+ return;
+ }
+ }
+}
+
+bool HostPDRHandler::isHostUp()
+{
+ return responseReceived;
+}
+
} // namespace pldm
diff --git a/host-bmc/host_pdr_handler.hpp b/host-bmc/host_pdr_handler.hpp
index 2e0d331..96c0226 100644
--- a/host-bmc/host_pdr_handler.hpp
+++ b/host-bmc/host_pdr_handler.hpp
@@ -144,13 +144,6 @@
void parseStateSensorPDRs(const PDRList& stateSensorPDRs,
const TLPDRMap& tlpdrInfo);
- private:
- /** @brief deferred function to fetch PDR from Host, scheduled to work on
- * the event loop. The PDR exchg with the host is async.
- * @param[in] source - sdeventplus event source
- */
- void _fetchPDR(sdeventplus::source::EventBase& source);
-
/** @brief this function sends a GetPDR request to Host firmware.
* And processes the PDRs based on type
*
@@ -158,6 +151,21 @@
*/
void getHostPDR(uint32_t nextRecordHandle = 0);
+ /** @brief set the Host state when pldmd starts
+ */
+ void setHostState();
+
+ /** @brief check whether Host is running when pldmd starts
+ */
+ bool isHostUp();
+
+ private:
+ /** @brief deferred function to fetch PDR from Host, scheduled to work on
+ * the event loop. The PDR exchg with the host is async.
+ * @param[in] source - sdeventplus event source
+ */
+ void _fetchPDR(sdeventplus::source::EventBase& source);
+
/** @brief Merge host firmware's entity association PDRs into BMC's
* @details A merge operation involves adding a pldm_entity under the
* appropriate parent, and updating container ids.
@@ -239,6 +247,13 @@
*/
HostStateSensorMap sensorMap;
bool verbose;
+
+ /** @brief whether response received from Host */
+ bool responseReceived;
+ /** @brief whether timed out waiting for a response from Host */
+ bool timeOut;
+ /** @brief request message instance id */
+ uint8_t insId;
};
} // namespace pldm
diff --git a/pldmd/pldmd.cpp b/pldmd/pldmd.cpp
index 58d71ce..00019f1 100644
--- a/pldmd/pldmd.cpp
+++ b/pldmd/pldmd.cpp
@@ -364,6 +364,19 @@
bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
bus.request_name("xyz.openbmc_project.PLDM");
IO io(event, socketFd(), EPOLLIN, std::move(callback));
+ hostPDRHandler->setHostState();
+ if (hostPDRHandler->isHostUp())
+ {
+ hostPDRHandler->getHostPDR();
+ }
+ else
+ {
+ if (verbose)
+ {
+ std::cout << "Host is not running\n";
+ }
+ }
+
event.loop();
result = shutdown(sockfd, SHUT_RDWR);