blob: a0693eefe714fac8cc34f91aa30dfb7e55f38b8d [file] [log] [blame]
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +05301#pragma once
2
William A. Kennington III73c2cfb2018-09-12 18:01:37 -07003#include <functional>
William A. Kennington III73c2cfb2018-09-12 18:01:37 -07004#include <optional>
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +05305#include <sdbusplus/bus.hpp>
6#include <sdbusplus/server/object.hpp>
William A. Kennington IIIf505fc02018-09-12 18:30:09 -07007#include <sdeventplus/event.hpp>
8#include <sdeventplus/utility/timer.hpp>
Willy Tu9ef0d0f2021-07-06 22:36:23 -07009#include <string_view>
William A. Kennington III3bb2f402018-09-13 00:35:47 -070010#include <unordered_map>
William A. Kennington III73c2cfb2018-09-12 18:01:37 -070011#include <utility>
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053012#include <xyz/openbmc_project/State/Watchdog/server.hpp>
William A. Kennington III73c2cfb2018-09-12 18:01:37 -070013
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053014namespace phosphor
15{
16namespace watchdog
17{
William A. Kennington III3bb2f402018-09-13 00:35:47 -070018
Ofer Yehiellic35135d2019-06-14 11:30:25 -070019constexpr auto DEFAULT_MIN_INTERVAL_MS = 0;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053020namespace Base = sdbusplus::xyz::openbmc_project::State::server;
Patrick Williams73bd5272022-07-22 19:26:57 -050021using WatchdogInherits = sdbusplus::server::object_t<Base::Watchdog>;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053022
23/** @class Watchdog
24 * @brief OpenBMC watchdog implementation.
25 * @details A concrete implementation for the
26 * xyz.openbmc_project.State.Watchdog DBus API.
27 */
28class Watchdog : public WatchdogInherits
29{
Patrick Venture8f6c5152018-09-11 17:45:33 -070030 public:
31 Watchdog() = delete;
32 ~Watchdog() = default;
33 Watchdog(const Watchdog&) = delete;
34 Watchdog& operator=(const Watchdog&) = delete;
35 Watchdog(Watchdog&&) = delete;
36 Watchdog& operator=(Watchdog&&) = delete;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053037
Patrick Venture8f6c5152018-09-11 17:45:33 -070038 /** @brief Type used to hold the name of a systemd target.
39 */
40 using TargetName = std::string;
William A. Kennington III1232a152018-02-02 15:57:34 -080041
William A. Kennington III3bb2f402018-09-13 00:35:47 -070042 /** @brief Type used to store the mapping of a Watchdog timeout
43 * action to a systemd target.
44 */
45 using ActionTargetMap = std::unordered_map<Action, TargetName>;
46
Patrick Venture8f6c5152018-09-11 17:45:33 -070047 /** @brief Type used to specify the parameters of a fallback watchdog
48 */
49 struct Fallback
50 {
51 Action action;
52 uint64_t interval;
53 bool always;
54 };
William A. Kennington IIId1331082018-02-27 18:47:05 -080055
Patrick Venture8f6c5152018-09-11 17:45:33 -070056 /** @brief Constructs the Watchdog object
57 *
William A. Kennington IIId1b1e792022-11-21 18:29:11 -080058 * @param[in] bus - DBus bus to attach to.
59 * @param[in] objPath - Object path to attach to.
60 * @param[in] event - reference to sdeventplus::Event loop
61 * @param[in] actionTargets - map of systemd targets called on timeout
62 * @param[in] fallback - fallback watchdog
63 * @param[in] minInterval - minimum intervale value allowed
64 * @param[in] defaultInterval - default interval to start with
65 * @param[in] exitAfterTimeout - should the event loop be terminated
Patrick Venture8f6c5152018-09-11 17:45:33 -070066 */
Patrick Williams73bd5272022-07-22 19:26:57 -050067 Watchdog(sdbusplus::bus_t& bus, const char* objPath,
William A. Kennington IIIf505fc02018-09-12 18:30:09 -070068 const sdeventplus::Event& event,
William A. Kennington III3bb2f402018-09-13 00:35:47 -070069 ActionTargetMap&& actionTargetMap = {},
Ofer Yehiellic35135d2019-06-14 11:30:25 -070070 std::optional<Fallback>&& fallback = std::nullopt,
Andrew Geisslerafc369a2021-06-03 14:17:16 -050071 uint64_t minInterval = DEFAULT_MIN_INTERVAL_MS,
William A. Kennington IIId1b1e792022-11-21 18:29:11 -080072 uint64_t defaultInterval = 0, bool exitAfterTimeout = false) :
Patrick Venture8f6c5152018-09-11 17:45:33 -070073 WatchdogInherits(bus, objPath),
William A. Kennington III3bb2f402018-09-13 00:35:47 -070074 bus(bus), actionTargetMap(std::move(actionTargetMap)),
Willy Tucf4ce3c2021-12-09 20:39:37 -080075 fallback(fallback), minInterval(minInterval),
Willy Tu9ef0d0f2021-07-06 22:36:23 -070076 timer(event, std::bind(&Watchdog::timeOutHandler, this)),
William A. Kennington IIId1b1e792022-11-21 18:29:11 -080077 objPath(objPath), exitAfterTimeout(exitAfterTimeout)
Patrick Venture8f6c5152018-09-11 17:45:33 -070078 {
Andrew Geisslerafc369a2021-06-03 14:17:16 -050079 // Use default if passed in otherwise just use default that comes
80 // with object
81 if (defaultInterval)
82 {
83 interval(defaultInterval);
84 }
85 else
86 {
87 interval(interval());
88 }
Patrick Venture8f6c5152018-09-11 17:45:33 -070089 // We need to poke the enable mechanism to make sure that the timer
90 // enters the fallback state if the fallback is always enabled.
91 tryFallbackOrDisable();
92 }
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053093
Patrick Venture8f6c5152018-09-11 17:45:33 -070094 /** @brief Resets the TimeRemaining to the configured Interval
95 * Optionally enables the watchdog.
96 *
97 * @param[in] enableWatchdog - Should the call enable the watchdog
98 */
99 void resetTimeRemaining(bool enableWatchdog) override;
William A. Kennington III1726df62018-04-23 10:28:28 -0700100
Patrick Venture8f6c5152018-09-11 17:45:33 -0700101 /** @brief Since we are overriding the setter-enabled but not the
102 * getter-enabled, we need to have this using in order to
103 * allow passthrough usage of the getter-enabled.
104 */
105 using Base::Watchdog::enabled;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530106
Patrick Venture8f6c5152018-09-11 17:45:33 -0700107 /** @brief Enable or disable watchdog
108 * If a watchdog state is changed from disable to enable,
109 * the watchdog timer is set with the default expiration
110 * interval and it starts counting down.
111 * If a watchdog is already enabled, setting @value to true
112 * has no effect.
113 *
114 * @param[in] value - 'true' to enable. 'false' to disable
115 *
116 * @return : applied value if success, previous value otherwise
117 */
118 bool enabled(bool value) override;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530119
Patrick Venture8f6c5152018-09-11 17:45:33 -0700120 /** @brief Gets the remaining time before watchdog expires.
121 *
122 * @return 0 if watchdog is expired.
123 * Remaining time in milliseconds otherwise.
124 */
125 uint64_t timeRemaining() const override;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530126
Patrick Venture8f6c5152018-09-11 17:45:33 -0700127 /** @brief Reset timer to expire after new timeout in milliseconds.
128 *
129 * @param[in] value - the time in milliseconds after which
130 * the watchdog will expire
131 *
132 * @return: updated timeout value if watchdog is enabled.
133 * 0 otherwise.
134 */
135 uint64_t timeRemaining(uint64_t value) override;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530136
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700137 /** @brief Get value of Interval
138 *
139 *
140 * @return: current interval
141 *
142 */
143 using WatchdogInherits::interval;
144
145 /** @brief Set value of Interval
146 *
147 * @param[in] value - interval time to set
148 *
149 * @return: interval that was set
150 *
151 */
Willy Tucf4ce3c2021-12-09 20:39:37 -0800152 uint64_t interval(uint64_t value) override;
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700153
Patrick Venture8f6c5152018-09-11 17:45:33 -0700154 /** @brief Tells if the referenced timer is expired or not */
155 inline auto timerExpired() const
156 {
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700157 return timer.hasExpired();
Patrick Venture8f6c5152018-09-11 17:45:33 -0700158 }
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530159
Patrick Venture8f6c5152018-09-11 17:45:33 -0700160 /** @brief Tells if the timer is running or not */
161 inline bool timerEnabled() const
162 {
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700163 return timer.isEnabled();
Patrick Venture8f6c5152018-09-11 17:45:33 -0700164 }
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800165
Patrick Venture8f6c5152018-09-11 17:45:33 -0700166 private:
167 /** @brief sdbusplus handle */
Patrick Williams73bd5272022-07-22 19:26:57 -0500168 sdbusplus::bus_t& bus;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530169
Patrick Venture8f6c5152018-09-11 17:45:33 -0700170 /** @brief Map of systemd units to be started when the timer expires */
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700171 ActionTargetMap actionTargetMap;
Vishwanatha Subbanna3473d702017-05-30 16:38:50 +0530172
Patrick Venture8f6c5152018-09-11 17:45:33 -0700173 /** @brief Fallback timer options */
William A. Kennington III73c2cfb2018-09-12 18:01:37 -0700174 std::optional<Fallback> fallback;
William A. Kennington IIId1331082018-02-27 18:47:05 -0800175
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700176 /** @brief Minimum watchdog interval value */
177 uint64_t minInterval;
178
Patrick Venture8f6c5152018-09-11 17:45:33 -0700179 /** @brief Contained timer object */
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700180 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +0530181
Patrick Venture8f6c5152018-09-11 17:45:33 -0700182 /** @brief Optional Callback handler on timer expirartion */
183 void timeOutHandler();
William A. Kennington III825f4982018-02-27 19:10:56 -0800184
Patrick Venture8f6c5152018-09-11 17:45:33 -0700185 /** @brief Attempt to enter the fallback watchdog or disables it */
186 void tryFallbackOrDisable();
Willy Tu9ef0d0f2021-07-06 22:36:23 -0700187
188 /** @brief Object path of the watchdog */
189 std::string_view objPath;
William A. Kennington IIId1b1e792022-11-21 18:29:11 -0800190
191 /** @brief Do we terminate after exit */
192 bool exitAfterTimeout;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530193};
194
195} // namespace watchdog
196} // namespace phosphor