blob: d19c2cbef0d4f45baa1c37dbc9b4a41698bb7656 [file] [log] [blame]
Matt Spinler99196682019-12-11 11:23:20 -06001#pragma once
2
3#include "data_interface.hpp"
4
5#include <stdint.h>
6
7#include <chrono>
8#include <functional>
Matt Spinlera44efe42020-03-03 10:30:16 -06009#include <phosphor-logging/log.hpp>
Matt Spinler99196682019-12-11 11:23:20 -060010#include <sdeventplus/event.hpp>
11#include <sdeventplus/source/io.hpp>
12
13namespace openpower
14{
15namespace pels
16{
17
18/**
19 * @brief Return codes from sending a command
20 */
21enum class CmdStatus
22{
23 success,
24 failure
25};
26
27/**
28 * @brief Return codes from the command response
29 */
30enum class ResponseStatus
31{
32 success,
33 failure
34};
35
36/**
37 * @class HostInterface
38 *
39 * An abstract base class for sending the 'New PEL available' command
40 * to the host. Used so that the PLDM interfaces can be mocked for
41 * testing the HostNotifier code. The response to this command is
42 * asynchronous, with the intent that other code registers a callback
43 * function to run when the response is received.
44 */
45class HostInterface
46{
47 public:
48 HostInterface() = delete;
49 virtual ~HostInterface() = default;
50 HostInterface(const HostInterface&) = default;
51 HostInterface& operator=(const HostInterface&) = default;
52 HostInterface(HostInterface&&) = default;
53 HostInterface& operator=(HostInterface&&) = default;
54
55 /**
56 * @brief Constructor
57 *
58 * @param[in] event - The sd_event object pointer
59 * @param[in] dataIface - The DataInterface object
60 */
61 HostInterface(sd_event* event, DataInterfaceBase& dataIface) :
62 _event(event), _dataIface(dataIface)
63 {
64 }
65
66 /**
67 * @brief Pure virtual function for sending the 'new PEL available'
68 * asynchronous command to the host.
69 *
70 * @param[in] id - The ID of the new PEL
71 * @param[in] size - The size of the new PEL
72 *
73 * @return CmdStatus - If the send was successful or not
74 */
75 virtual CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) = 0;
76
77 /**
78 * @brief Returns the amount of time to wait before retrying after
79 * a failed send command.
80 *
81 * @return milliseconds - The amount of time to wait
82 */
83 virtual std::chrono::milliseconds getSendRetryDelay() const
84 {
85 return _defaultSendRetryDelay;
86 }
87
88 /**
89 * @brief Returns the amount of time to wait before retrying after
90 * a command receive.
91 *
92 * @return milliseconds - The amount of time to wait
93 */
94 virtual std::chrono::milliseconds getReceiveRetryDelay() const
95 {
96 return _defaultReceiveRetryDelay;
97 }
98
99 /**
100 * @brief Returns the amount of time to wait before retrying if the
101 * host firmware's PEL storage was full and it can't store
102 * any more logs until it is freed up somehow.
103 *
104 * In this class to help with mocking.
105 *
106 * @return milliseconds - The amount of time to wait
107 */
108 virtual std::chrono::milliseconds getHostFullRetryDelay() const
109 {
110 return _defaultHostFullRetryDelay;
111 }
112
Matt Spinlere5f75082022-01-24 16:09:51 -0600113 /**
114 * @brief Returns the amount of time to wait after the host is up
115 * before sending commands.
116 *
117 * In this class to help with mocking.
118 *
119 * @return milliseconds - The amount of time to wait
120 */
121 virtual std::chrono::milliseconds getHostUpDelay() const
122 {
123 return _defaultHostUpDelay;
124 }
125
Matt Spinler99196682019-12-11 11:23:20 -0600126 using ResponseFunction = std::function<void(ResponseStatus)>;
127
128 /**
129 * @brief Sets the function to call on the command receive.
130 *
131 * The success/failure status is passed to the function.
132 *
133 * @param[in] func - The callback function
134 */
135 void setResponseFunction(ResponseFunction func)
136 {
137 _responseFunc = std::move(func);
138 }
139
140 /**
Matt Spinlera44efe42020-03-03 10:30:16 -0600141 * @brief Call the response function
142 *
143 * @param[in] status - The status given to the function
144 */
145 void callResponseFunc(ResponseStatus status)
146 {
147 if (_responseFunc)
148 {
149 try
150 {
151 (*_responseFunc)(status);
152 }
153 catch (const std::exception& e)
154 {
155 using namespace phosphor::logging;
156 log<level::ERR>(
157 "Host iface response callback threw an exception",
158 entry("ERROR=%s", e.what()));
159 }
160 }
161 }
162
163 /**
Matt Spinler99196682019-12-11 11:23:20 -0600164 * @brief Returns the event object in use
165 *
166 * @return sdeventplus::Event& - The event object
167 */
168 sdeventplus::Event& getEvent()
169 {
170 return _event;
171 }
172
173 /**
174 * @brief Pure virtual function to cancel an in-progress command
175 *
176 * 'In progress' means after the send but before the receive
177 */
178 virtual void cancelCmd() = 0;
179
180 /**
181 * @brief Says if the command is in progress (after send/before receive)
182 *
183 * @return bool - If command is in progress
184 */
185 bool cmdInProgress() const
186 {
187 return _inProgress;
188 }
189
190 protected:
191 /**
192 * @brief Pure virtual function for implementing the asynchronous
193 * command response callback.
194 *
195 * @param[in] io - The sdeventplus IO object that the callback is
196 * invoked from.
197 * @param[in] fd - The file descriptor being used
198 * @param[in] revents - The event status bits
199 */
200 virtual void receive(sdeventplus::source::IO& io, int fd,
201 uint32_t revents) = 0;
202
203 /**
204 * @brief An optional function to call on a successful command response.
205 */
206 std::optional<ResponseFunction> _responseFunc;
207
208 /**
209 * @brief The sd_event wrapper object needed for response callbacks
210 */
211 sdeventplus::Event _event;
212
213 /**
214 * @brief The DataInterface object
215 */
216 DataInterfaceBase& _dataIface;
217
218 /**
219 * @brief Tracks status of after a command is sent and before the
220 * response is received.
221 */
222 bool _inProgress = false;
223
224 private:
225 /**
226 * @brief The default amount of time to wait before retrying
227 * a failed send.
Matt Spinler99196682019-12-11 11:23:20 -0600228 */
Matt Spinler3a4243a2020-03-03 16:51:08 -0600229 const std::chrono::milliseconds _defaultSendRetryDelay{1000};
Matt Spinler99196682019-12-11 11:23:20 -0600230
231 /**
232 * @brief The default amount of time to wait
233 * before retrying after a failed receive.
234 */
235 const std::chrono::milliseconds _defaultReceiveRetryDelay{1000};
236
237 /**
238 * @brief The default amount of time to wait when the host said it
239 * was full before sending the PEL again.
240 */
241 const std::chrono::milliseconds _defaultHostFullRetryDelay{60000};
Matt Spinlere5f75082022-01-24 16:09:51 -0600242
243 /**
244 * @brief The default amount of time to wait after the host is up
245 * before sending up the PELs.
246 */
247 const std::chrono::milliseconds _defaultHostUpDelay{60000};
Matt Spinler99196682019-12-11 11:23:20 -0600248};
249
250} // namespace pels
251} // namespace openpower