oem_ibm: Reset Watchdog Timer
The watchdog timer is started as soon as the BMC
is powered on. Host sends GetTID to BMC, BMC
responds to that and sends SetEventReceiver
command with a specified time interval(Heartbeat). Host
is supposed to send PlatformEventMessage to BMC
within the elapsed interval.
We use the same infrastructure as that of surveillance
for implementing host watchdog. The difference between
surveillance and host watchdog is that-
-> Surveillance is host monitoring the BMC if it is
functioning and its us up and running and if the BMC
fails to respond to ping from host, then host will
reset the BMC
-> Watchdog is BMC monitoring if the host boots without
failures, and if host does not respond to pings from
BMC after the watchdog interval, then the watchdog app
triggers a host dump.
Watchdog monitoring is followed by surveillance.
This commit adds change to reset the watchdog
timer on receiving PlatformEventMessage for
heartbeat elapsed time from Host
Tester with pldmtool:
./pldmtool raw -d 0x80 0x02 0x0A 0x01 0x01 0x06 0x01 0x01
Request Message:
08 01 80 02 0a 01 01 06 01 01
Received Msg
08 01 80 02 0a 01 01 06 01 01
Sending Msg
00 02 0a 00 00
Received Msg
08 01 00 02 0a 00 00
Response Message:
08 01 00 02 0a 00 00
Signed-off-by: Sagar Srinivas <sagar.srinivas@ibm.com>
Change-Id: I9fea658c3f2d3086ad2574ef827a5154dac6960e
diff --git a/libpldmresponder/base.hpp b/libpldmresponder/base.hpp
index 195e221..0603b77 100644
--- a/libpldmresponder/base.hpp
+++ b/libpldmresponder/base.hpp
@@ -1,9 +1,8 @@
#pragma once
#include "libpldm/base.h"
-#include "libpldm/platform.h"
-#include "pldmd/dbus_impl_requester.hpp"
+#include "libpldmresponder/platform.hpp"
#include "pldmd/handler.hpp"
#include "requester/handler.hpp"
@@ -27,9 +26,11 @@
{
public:
Handler(uint8_t eid, Requester& requester, sdeventplus::Event& event,
+ pldm::responder::oem_platform::Handler* oemPlatformHandler,
pldm::requester::Handler<pldm::requester::Request>* handler) :
eid(eid),
- requester(requester), event(event), handler(handler)
+ requester(requester), event(event),
+ oemPlatformHandler(oemPlatformHandler), handler(handler)
{
handlers.emplace(PLDM_GET_PLDM_TYPES,
[this](const pldm_msg* request, size_t payloadLength) {
@@ -103,6 +104,9 @@
*/
sdeventplus::Event& event;
+ /** @brief OEM platform handler */
+ pldm::responder::oem_platform::Handler* oemPlatformHandler;
+
/** @brief PLDM request handler */
pldm::requester::Handler<pldm::requester::Request>* handler;
diff --git a/libpldmresponder/oem_handler.hpp b/libpldmresponder/oem_handler.hpp
index fcf844b..a0f8586 100644
--- a/libpldmresponder/oem_handler.hpp
+++ b/libpldmresponder/oem_handler.hpp
@@ -68,6 +68,15 @@
*/
virtual void buildOEMPDR(pdr_utils::Repo& repo) = 0;
+ /** @brief Interface to check if the watchdog timer is running
+ *
+ * @return - true if watchdog is running, false otherwise
+ * */
+ virtual bool watchDogRunning() = 0;
+
+ /** @brief Interface to reset the watchdog timer */
+ virtual void resetWatchDogTimer() = 0;
+
virtual ~Handler() = default;
protected:
diff --git a/libpldmresponder/platform.cpp b/libpldmresponder/platform.cpp
index 73274ac..1b4c8f5 100644
--- a/libpldmresponder/platform.cpp
+++ b/libpldmresponder/platform.cpp
@@ -316,6 +316,10 @@
if (eventClass == PLDM_HEARTBEAT_TIMER_ELAPSED_EVENT)
{
rc = PLDM_SUCCESS;
+ if (oemPlatformHandler)
+ {
+ oemPlatformHandler->resetWatchDogTimer();
+ }
}
else
{
diff --git a/libpldmresponder/test/libpldmresponder_base_test.cpp b/libpldmresponder/test/libpldmresponder_base_test.cpp
index 19b870b..9be09ff 100644
--- a/libpldmresponder/test/libpldmresponder_base_test.cpp
+++ b/libpldmresponder/test/libpldmresponder_base_test.cpp
@@ -32,7 +32,7 @@
auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
// payload length will be 0 in this case
size_t requestPayloadLength = 0;
- base::Handler handler(mctpEid, requester, event, nullptr);
+ base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
auto response = handler.getPLDMTypes(request, requestPayloadLength);
// Need to support OEM type.
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
@@ -49,7 +49,7 @@
requestPayload{};
auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
- base::Handler handler(mctpEid, requester, event, nullptr);
+ base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
auto response = handler.getPLDMCommands(request, requestPayloadLength);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
uint8_t* payload_ptr = responsePtr->payload;
@@ -66,7 +66,7 @@
request->payload[0] = 0xFF;
size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
- base::Handler handler(mctpEid, requester, event, nullptr);
+ base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
auto response = handler.getPLDMCommands(request, requestPayloadLength);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
uint8_t* payload_ptr = responsePtr->payload;
@@ -91,7 +91,7 @@
ASSERT_EQ(0, rc);
- base::Handler handler(mctpEid, requester, event, nullptr);
+ base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
auto response = handler.getPLDMVersion(request, requestPayloadLength);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
@@ -122,7 +122,7 @@
ASSERT_EQ(0, rc);
- base::Handler handler(mctpEid, requester, event, nullptr);
+ base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
auto response = handler.getPLDMVersion(request, requestPayloadLength - 1);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
@@ -147,7 +147,7 @@
auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
size_t requestPayloadLength = 0;
- base::Handler handler(mctpEid, requester, event, nullptr);
+ base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
auto response = handler.getTID(request, requestPayloadLength);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
diff --git a/oem/ibm/libpldmresponder/oem_ibm_handler.cpp b/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
index 71393cb..b3b1961 100644
--- a/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
+++ b/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
@@ -491,6 +491,57 @@
}
});
}
+
+bool pldm::responder::oem_ibm_platform::Handler::watchDogRunning()
+{
+ static constexpr auto watchDogObjectPath =
+ "/xyz/openbmc_project/watchdog/host0";
+ static constexpr auto watchDogEnablePropName = "Enabled";
+ static constexpr auto watchDogInterface =
+ "xyz.openbmc_project.State.Watchdog";
+ bool isWatchDogRunning = false;
+ try
+ {
+ isWatchDogRunning = pldm::utils::DBusHandler().getDbusProperty<bool>(
+ watchDogObjectPath, watchDogEnablePropName, watchDogInterface);
+ }
+ catch (const std::exception& e)
+ {
+ return false;
+ }
+ return isWatchDogRunning;
+}
+
+void pldm::responder::oem_ibm_platform::Handler::resetWatchDogTimer()
+{
+ static constexpr auto watchDogService = "xyz.openbmc_project.Watchdog";
+ static constexpr auto watchDogObjectPath =
+ "/xyz/openbmc_project/watchdog/host0";
+ static constexpr auto watchDogInterface =
+ "xyz.openbmc_project.State.Watchdog";
+ static constexpr auto watchDogResetPropName = "ResetTimeRemaining";
+
+ bool wdStatus = watchDogRunning();
+ if (wdStatus == false)
+ {
+ return;
+ }
+ try
+ {
+ auto& bus = pldm::utils::DBusHandler::getBus();
+ auto resetMethod =
+ bus.new_method_call(watchDogService, watchDogObjectPath,
+ watchDogInterface, watchDogResetPropName);
+ resetMethod.append(true);
+ bus.call_noreply(resetMethod);
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "Failed To reset watchdog timer"
+ << "ERROR=" << e.what() << std::endl;
+ return;
+ }
+}
} // namespace oem_ibm_platform
} // namespace responder
} // namespace pldm
diff --git a/oem/ibm/libpldmresponder/oem_ibm_handler.hpp b/oem/ibm/libpldmresponder/oem_ibm_handler.hpp
index 4a91dcc..db89acf 100644
--- a/oem/ibm/libpldmresponder/oem_ibm_handler.hpp
+++ b/oem/ibm/libpldmresponder/oem_ibm_handler.hpp
@@ -146,6 +146,17 @@
*/
void _processSystemReboot(sdeventplus::source::EventBase& source);
+ /** @brief To check if the watchdog app is running
+ *
+ * @return the running status of watchdog app
+ */
+ bool watchDogRunning();
+
+ /** @brief Method to reset the Watchdog timer on receiving platform Event
+ * Message for heartbeat elapsed time from Hostboot
+ */
+ void resetWatchDogTimer();
+
~Handler() = default;
pldm::responder::CodeUpdate* codeUpdate; //!< pointer to CodeUpdate object
diff --git a/pldmd/pldmd.cpp b/pldmd/pldmd.cpp
index b1d2904..8431dda 100644
--- a/pldmd/pldmd.cpp
+++ b/pldmd/pldmd.cpp
@@ -223,9 +223,6 @@
hostEID, &dbusImplReq, &reqHandler));
#endif
invoker.registerHandler(
- PLDM_BASE, std::make_unique<base::Handler>(hostEID, dbusImplReq, event,
- &reqHandler));
- invoker.registerHandler(
PLDM_BIOS, std::make_unique<bios::Handler>(sockfd, hostEID,
&dbusImplReq, &reqHandler));
auto fruHandler = std::make_unique<fru::Handler>(
@@ -246,6 +243,10 @@
#endif
invoker.registerHandler(PLDM_PLATFORM, std::move(platformHandler));
+ invoker.registerHandler(
+ PLDM_BASE,
+ std::make_unique<base::Handler>(hostEID, dbusImplReq, event,
+ oemPlatformHandler.get(), &reqHandler));
invoker.registerHandler(PLDM_FRU, std::move(fruHandler));
dbus_api::Pdr dbusImplPdr(bus, "/xyz/openbmc_project/pldm", pdrRepo.get());
sdbusplus::xyz::openbmc_project::PLDM::server::Event dbusImplEvent(