blob: 16f05f17732c084c6ba280fa96c19cb780ce79b8 [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 *
Andrew Geisslerafc369a2021-06-03 14:17:16 -050058 * @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
Patrick Venture8f6c5152018-09-11 17:45:33 -070065 */
Patrick Williams73bd5272022-07-22 19:26:57 -050066 Watchdog(sdbusplus::bus_t& bus, const char* objPath,
William A. Kennington IIIf505fc02018-09-12 18:30:09 -070067 const sdeventplus::Event& event,
William A. Kennington III3bb2f402018-09-13 00:35:47 -070068 ActionTargetMap&& actionTargetMap = {},
Ofer Yehiellic35135d2019-06-14 11:30:25 -070069 std::optional<Fallback>&& fallback = std::nullopt,
Andrew Geisslerafc369a2021-06-03 14:17:16 -050070 uint64_t minInterval = DEFAULT_MIN_INTERVAL_MS,
71 uint64_t defaultInterval = 0) :
Patrick Venture8f6c5152018-09-11 17:45:33 -070072 WatchdogInherits(bus, objPath),
William A. Kennington III3bb2f402018-09-13 00:35:47 -070073 bus(bus), actionTargetMap(std::move(actionTargetMap)),
Willy Tucf4ce3c2021-12-09 20:39:37 -080074 fallback(fallback), minInterval(minInterval),
Willy Tu9ef0d0f2021-07-06 22:36:23 -070075 timer(event, std::bind(&Watchdog::timeOutHandler, this)),
76 objPath(objPath)
Patrick Venture8f6c5152018-09-11 17:45:33 -070077 {
Andrew Geisslerafc369a2021-06-03 14:17:16 -050078 // Use default if passed in otherwise just use default that comes
79 // with object
80 if (defaultInterval)
81 {
82 interval(defaultInterval);
83 }
84 else
85 {
86 interval(interval());
87 }
Patrick Venture8f6c5152018-09-11 17:45:33 -070088 // We need to poke the enable mechanism to make sure that the timer
89 // enters the fallback state if the fallback is always enabled.
90 tryFallbackOrDisable();
91 }
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +053092
Patrick Venture8f6c5152018-09-11 17:45:33 -070093 /** @brief Resets the TimeRemaining to the configured Interval
94 * Optionally enables the watchdog.
95 *
96 * @param[in] enableWatchdog - Should the call enable the watchdog
97 */
98 void resetTimeRemaining(bool enableWatchdog) override;
William A. Kennington III1726df62018-04-23 10:28:28 -070099
Patrick Venture8f6c5152018-09-11 17:45:33 -0700100 /** @brief Since we are overriding the setter-enabled but not the
101 * getter-enabled, we need to have this using in order to
102 * allow passthrough usage of the getter-enabled.
103 */
104 using Base::Watchdog::enabled;
Vishwanatha Subbanna00bd3772017-05-31 14:53:42 +0530105
Patrick Venture8f6c5152018-09-11 17:45:33 -0700106 /** @brief Enable or disable watchdog
107 * If a watchdog state is changed from disable to enable,
108 * the watchdog timer is set with the default expiration
109 * interval and it starts counting down.
110 * If a watchdog is already enabled, setting @value to true
111 * has no effect.
112 *
113 * @param[in] value - 'true' to enable. 'false' to disable
114 *
115 * @return : applied value if success, previous value otherwise
116 */
117 bool enabled(bool value) override;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530118
Patrick Venture8f6c5152018-09-11 17:45:33 -0700119 /** @brief Gets the remaining time before watchdog expires.
120 *
121 * @return 0 if watchdog is expired.
122 * Remaining time in milliseconds otherwise.
123 */
124 uint64_t timeRemaining() const override;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530125
Patrick Venture8f6c5152018-09-11 17:45:33 -0700126 /** @brief Reset timer to expire after new timeout in milliseconds.
127 *
128 * @param[in] value - the time in milliseconds after which
129 * the watchdog will expire
130 *
131 * @return: updated timeout value if watchdog is enabled.
132 * 0 otherwise.
133 */
134 uint64_t timeRemaining(uint64_t value) override;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530135
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700136 /** @brief Get value of Interval
137 *
138 *
139 * @return: current interval
140 *
141 */
142 using WatchdogInherits::interval;
143
144 /** @brief Set value of Interval
145 *
146 * @param[in] value - interval time to set
147 *
148 * @return: interval that was set
149 *
150 */
Willy Tucf4ce3c2021-12-09 20:39:37 -0800151 uint64_t interval(uint64_t value) override;
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700152
Patrick Venture8f6c5152018-09-11 17:45:33 -0700153 /** @brief Tells if the referenced timer is expired or not */
154 inline auto timerExpired() const
155 {
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700156 return timer.hasExpired();
Patrick Venture8f6c5152018-09-11 17:45:33 -0700157 }
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530158
Patrick Venture8f6c5152018-09-11 17:45:33 -0700159 /** @brief Tells if the timer is running or not */
160 inline bool timerEnabled() const
161 {
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700162 return timer.isEnabled();
Patrick Venture8f6c5152018-09-11 17:45:33 -0700163 }
William A. Kennington III0650a3f2018-03-01 10:53:25 -0800164
Patrick Venture8f6c5152018-09-11 17:45:33 -0700165 private:
166 /** @brief sdbusplus handle */
Patrick Williams73bd5272022-07-22 19:26:57 -0500167 sdbusplus::bus_t& bus;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530168
Patrick Venture8f6c5152018-09-11 17:45:33 -0700169 /** @brief Map of systemd units to be started when the timer expires */
William A. Kennington III3bb2f402018-09-13 00:35:47 -0700170 ActionTargetMap actionTargetMap;
Vishwanatha Subbanna3473d702017-05-30 16:38:50 +0530171
Patrick Venture8f6c5152018-09-11 17:45:33 -0700172 /** @brief Fallback timer options */
William A. Kennington III73c2cfb2018-09-12 18:01:37 -0700173 std::optional<Fallback> fallback;
William A. Kennington IIId1331082018-02-27 18:47:05 -0800174
Ofer Yehiellic35135d2019-06-14 11:30:25 -0700175 /** @brief Minimum watchdog interval value */
176 uint64_t minInterval;
177
Patrick Venture8f6c5152018-09-11 17:45:33 -0700178 /** @brief Contained timer object */
William A. Kennington IIIf505fc02018-09-12 18:30:09 -0700179 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
Vishwanatha Subbanna8c5a2292017-05-30 15:34:23 +0530180
Patrick Venture8f6c5152018-09-11 17:45:33 -0700181 /** @brief Optional Callback handler on timer expirartion */
182 void timeOutHandler();
William A. Kennington III825f4982018-02-27 19:10:56 -0800183
Patrick Venture8f6c5152018-09-11 17:45:33 -0700184 /** @brief Attempt to enter the fallback watchdog or disables it */
185 void tryFallbackOrDisable();
Willy Tu9ef0d0f2021-07-06 22:36:23 -0700186
187 /** @brief Object path of the watchdog */
188 std::string_view objPath;
Vishwanatha Subbannad7a3f132017-05-29 19:39:08 +0530189};
190
191} // namespace watchdog
192} // namespace phosphor