blob: da1e05a47acd186e0987a68ad68a96049e7c919c [file] [log] [blame]
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +05301#pragma once
2
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +05303#include <sdbusplus/bus.hpp>
4#include <sdbusplus/server/object.hpp>
William A. Kennington IIIf505fc02018-09-12 18:30:09 -07005#include <sdeventplus/event.hpp>
6#include <sdeventplus/utility/timer.hpp>
Patrick Williams6ac6a342023-05-10 07:51:12 -05007#include <xyz/openbmc_project/State/Watchdog/server.hpp>
8
9#include <functional>
10#include <optional>
Willy Tu9ef0d0f2021-07-06 22:36:23 -070011#include <string_view>
William A. Kennington III3bb2f402018-09-13 00:35:47 -070012#include <unordered_map>
William A. Kennington III73c2cfb2018-09-12 18:01:37 -070013#include <utility>
William A. Kennington III73c2cfb2018-09-12 18:01:37 -070014
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053015namespace phosphor
16{
17namespace watchdog
18{
William A. Kennington III3bb2f402018-09-13 00:35:47 -070019
Ofer Yehiellic35135d2019-06-14 11:30:25 -070020constexpr auto DEFAULT_MIN_INTERVAL_MS = 0;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +053021namespace Base = sdbusplus::xyz::openbmc_project::State::server;
Patrick Williams73bd5272022-07-22 19:26:57 -050022using WatchdogInherits = sdbusplus::server::object_t<Base::Watchdog>;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053023
24/** @class Watchdog
25 * @brief OpenBMC watchdog implementation.
26 * @details A concrete implementation for the
27 * xyz.openbmc_project.State.Watchdog DBus API.
28 */
29class Watchdog : public WatchdogInherits
30{
Patrick Venture8f6c5152018-09-11 17:45:33 -070031 public:
32 Watchdog() = delete;
33 ~Watchdog() = default;
34 Watchdog(const Watchdog&) = delete;
35 Watchdog& operator=(const Watchdog&) = delete;
36 Watchdog(Watchdog&&) = delete;
37 Watchdog& operator=(Watchdog&&) = delete;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053038
Patrick Venture8f6c5152018-09-11 17:45:33 -070039 /** @brief Type used to hold the name of a systemd target.
40 */
41 using TargetName = std::string;
William A. Kennington III1232a152018-02-02 15:57:34 -080042
William A. Kennington III3bb2f402018-09-13 00:35:47 -070043 /** @brief Type used to store the mapping of a Watchdog timeout
44 * action to a systemd target.
45 */
46 using ActionTargetMap = std::unordered_map<Action, TargetName>;
47
Patrick Venture8f6c5152018-09-11 17:45:33 -070048 /** @brief Type used to specify the parameters of a fallback watchdog
49 */
50 struct Fallback
51 {
52 Action action;
53 uint64_t interval;
54 bool always;
55 };
William A. Kennington IIId1331082018-02-27 18:47:05 -080056
Patrick Venture8f6c5152018-09-11 17:45:33 -070057 /** @brief Constructs the Watchdog object
58 *
William A. Kennington IIId1b1e792022-11-21 18:29:11 -080059 * @param[in] bus - DBus bus to attach to.
60 * @param[in] objPath - Object path to attach to.
61 * @param[in] event - reference to sdeventplus::Event loop
62 * @param[in] actionTargets - map of systemd targets called on timeout
63 * @param[in] fallback - fallback watchdog
64 * @param[in] minInterval - minimum intervale value allowed
65 * @param[in] defaultInterval - default interval to start with
66 * @param[in] exitAfterTimeout - should the event loop be terminated
Patrick Venture8f6c5152018-09-11 17:45:33 -070067 */
Patrick Williams73bd5272022-07-22 19:26:57 -050068 Watchdog(sdbusplus::bus_t& bus, const char* objPath,
William A. Kennington IIIf505fc02018-09-12 18:30:09 -070069 const sdeventplus::Event& event,
William A. Kennington III3bb2f402018-09-13 00:35:47 -070070 ActionTargetMap&& actionTargetMap = {},
Ofer Yehiellic35135d2019-06-14 11:30:25 -070071 std::optional<Fallback>&& fallback = std::nullopt,
Andrew Geisslerafc369a2021-06-03 14:17:16 -050072 uint64_t minInterval = DEFAULT_MIN_INTERVAL_MS,
William A. Kennington IIId1b1e792022-11-21 18:29:11 -080073 uint64_t defaultInterval = 0, bool exitAfterTimeout = false) :
Patrick Venture8f6c5152018-09-11 17:45:33 -070074 WatchdogInherits(bus, objPath),
William A. Kennington III3bb2f402018-09-13 00:35:47 -070075 bus(bus), actionTargetMap(std::move(actionTargetMap)),
Willy Tucf4ce3c2021-12-09 20:39:37 -080076 fallback(fallback), minInterval(minInterval),
Willy Tu9ef0d0f2021-07-06 22:36:23 -070077 timer(event, std::bind(&Watchdog::timeOutHandler, this)),
William A. Kennington IIId1b1e792022-11-21 18:29:11 -080078 objPath(objPath), exitAfterTimeout(exitAfterTimeout)
Patrick Venture8f6c5152018-09-11 17:45:33 -070079 {
Andrew Geisslerafc369a2021-06-03 14:17:16 -050080 // Use default if passed in otherwise just use default that comes
81 // with object
82 if (defaultInterval)
83 {
84 interval(defaultInterval);
85 }
86 else
87 {
88 interval(interval());
89 }
Patrick Venture8f6c5152018-09-11 17:45:33 -070090 // We need to poke the enable mechanism to make sure that the timer
91 // enters the fallback state if the fallback is always enabled.
92 tryFallbackOrDisable();
93 }
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053094
Patrick Venture8f6c5152018-09-11 17:45:33 -070095 /** @brief Resets the TimeRemaining to the configured Interval
96 * Optionally enables the watchdog.
97 *
98 * @param[in] enableWatchdog - Should the call enable the watchdog
99 */
100 void resetTimeRemaining(bool enableWatchdog) override;
William A. Kennington III1726df62018-04-23 10:28:28 -0700101
Patrick Venture8f6c5152018-09-11 17:45:33 -0700102 /** @brief Since we are overriding the setter-enabled but not the
103 * getter-enabled, we need to have this using in order to
104 * allow passthrough usage of the getter-enabled.
105 */
106 using Base::Watchdog::enabled;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530107
Patrick Venture8f6c5152018-09-11 17:45:33 -0700108 /** @brief Enable or disable watchdog
109 * If a watchdog state is changed from disable to enable,
110 * the watchdog timer is set with the default expiration
111 * interval and it starts counting down.
112 * If a watchdog is already enabled, setting @value to true
113 * has no effect.
114 *
115 * @param[in] value - 'true' to enable. 'false' to disable
116 *
117 * @return : applied value if success, previous value otherwise
118 */
119 bool enabled(bool value) override;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530120
Patrick Venture8f6c5152018-09-11 17:45:33 -0700121 /** @brief Gets the remaining time before watchdog expires.
122 *
123 * @return 0 if watchdog is expired.
124 * Remaining time in milliseconds otherwise.
125 */
126 uint64_t timeRemaining() const override;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530127
Patrick Venture8f6c5152018-09-11 17:45:33 -0700128 /** @brief Reset timer to expire after new timeout in milliseconds.
129 *
130 * @param[in] value - the time in milliseconds after which
131 * the watchdog will expire
132 *
133 * @return: updated timeout value if watchdog is enabled.
134 * 0 otherwise.
135 */
136 uint64_t timeRemaining(uint64_t value) override;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530137
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700138 /** @brief Get value of Interval
139 *
140 *
141 * @return: current interval
142 *
143 */
144 using WatchdogInherits::interval;
145
146 /** @brief Set value of Interval
147 *
148 * @param[in] value - interval time to set
149 *
150 * @return: interval that was set
151 *
152 */
Willy Tucf4ce3c2021-12-09 20:39:37 -0800153 uint64_t interval(uint64_t value) override;
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700154
Patrick Venture8f6c5152018-09-11 17:45:33 -0700155 /** @brief Tells if the referenced timer is expired or not */
156 inline auto timerExpired() const
157 {
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700158 return timer.hasExpired();
Patrick Venture8f6c5152018-09-11 17:45:33 -0700159 }
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530160
Patrick Venture8f6c5152018-09-11 17:45:33 -0700161 /** @brief Tells if the timer is running or not */
162 inline bool timerEnabled() const
163 {
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700164 return timer.isEnabled();
Patrick Venture8f6c5152018-09-11 17:45:33 -0700165 }
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800166
Patrick Venture8f6c5152018-09-11 17:45:33 -0700167 private:
168 /** @brief sdbusplus handle */
Patrick Williams73bd5272022-07-22 19:26:57 -0500169 sdbusplus::bus_t& bus;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530170
Patrick Venture8f6c5152018-09-11 17:45:33 -0700171 /** @brief Map of systemd units to be started when the timer expires */
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700172 ActionTargetMap actionTargetMap;
Vishwanatha Subbanna3473d702017-05-30 16:38:50 +0530173
Patrick Venture8f6c5152018-09-11 17:45:33 -0700174 /** @brief Fallback timer options */
William A. Kennington III73c2cfb2018-09-12 18:01:37 -0700175 std::optional<Fallback> fallback;
William A. Kennington IIId1331082018-02-27 18:47:05 -0800176
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700177 /** @brief Minimum watchdog interval value */
178 uint64_t minInterval;
179
Patrick Venture8f6c5152018-09-11 17:45:33 -0700180 /** @brief Contained timer object */
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700181 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +0530182
Patrick Venture8f6c5152018-09-11 17:45:33 -0700183 /** @brief Optional Callback handler on timer expirartion */
184 void timeOutHandler();
William A. Kennington III825f4982018-02-27 19:10:56 -0800185
Patrick Venture8f6c5152018-09-11 17:45:33 -0700186 /** @brief Attempt to enter the fallback watchdog or disables it */
187 void tryFallbackOrDisable();
Willy Tu9ef0d0f2021-07-06 22:36:23 -0700188
189 /** @brief Object path of the watchdog */
190 std::string_view objPath;
William A. Kennington IIId1b1e792022-11-21 18:29:11 -0800191
192 /** @brief Do we terminate after exit */
193 bool exitAfterTimeout;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530194};
195
196} // namespace watchdog
197} // namespace phosphor