blob: 11ebe87491c87d85cb51d248f7ca62cf376245a0 [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
Matt Spinler1b418862023-06-29 12:37:41 -05007#include <phosphor-logging/lg2.hpp>
Matt Spinler99196682019-12-11 11:23:20 -06008#include <sdeventplus/event.hpp>
9#include <sdeventplus/source/io.hpp>
10
Patrick Williams2544b412022-10-04 08:41:06 -050011#include <chrono>
12#include <functional>
13
Matt Spinler99196682019-12-11 11:23:20 -060014namespace openpower
15{
16namespace pels
17{
18
19/**
20 * @brief Return codes from sending a command
21 */
22enum class CmdStatus
23{
24 success,
25 failure
26};
27
28/**
29 * @brief Return codes from the command response
30 */
31enum class ResponseStatus
32{
33 success,
34 failure
35};
36
37/**
38 * @class HostInterface
39 *
40 * An abstract base class for sending the 'New PEL available' command
41 * to the host. Used so that the PLDM interfaces can be mocked for
42 * testing the HostNotifier code. The response to this command is
43 * asynchronous, with the intent that other code registers a callback
44 * function to run when the response is received.
45 */
46class HostInterface
47{
48 public:
49 HostInterface() = delete;
50 virtual ~HostInterface() = default;
51 HostInterface(const HostInterface&) = default;
52 HostInterface& operator=(const HostInterface&) = default;
53 HostInterface(HostInterface&&) = default;
54 HostInterface& operator=(HostInterface&&) = default;
55
56 /**
57 * @brief Constructor
58 *
59 * @param[in] event - The sd_event object pointer
60 * @param[in] dataIface - The DataInterface object
61 */
62 HostInterface(sd_event* event, DataInterfaceBase& dataIface) :
63 _event(event), _dataIface(dataIface)
Patrick Williams2544b412022-10-04 08:41:06 -050064 {}
Matt Spinler99196682019-12-11 11:23:20 -060065
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 {
Matt Spinler1b418862023-06-29 12:37:41 -0500155 lg2::error(
156 "Host iface response callback threw an exception: {EX}",
157 "EX", e);
Matt Spinlera44efe42020-03-03 10:30:16 -0600158 }
159 }
160 }
161
162 /**
Matt Spinler99196682019-12-11 11:23:20 -0600163 * @brief Returns the event object in use
164 *
165 * @return sdeventplus::Event& - The event object
166 */
167 sdeventplus::Event& getEvent()
168 {
169 return _event;
170 }
171
172 /**
173 * @brief Pure virtual function to cancel an in-progress command
174 *
175 * 'In progress' means after the send but before the receive
176 */
177 virtual void cancelCmd() = 0;
178
179 /**
180 * @brief Says if the command is in progress (after send/before receive)
181 *
182 * @return bool - If command is in progress
183 */
184 bool cmdInProgress() const
185 {
186 return _inProgress;
187 }
188
189 protected:
190 /**
191 * @brief Pure virtual function for implementing the asynchronous
192 * command response callback.
193 *
194 * @param[in] io - The sdeventplus IO object that the callback is
195 * invoked from.
196 * @param[in] fd - The file descriptor being used
197 * @param[in] revents - The event status bits
198 */
199 virtual void receive(sdeventplus::source::IO& io, int fd,
200 uint32_t revents) = 0;
201
202 /**
203 * @brief An optional function to call on a successful command response.
204 */
205 std::optional<ResponseFunction> _responseFunc;
206
207 /**
208 * @brief The sd_event wrapper object needed for response callbacks
209 */
210 sdeventplus::Event _event;
211
212 /**
213 * @brief The DataInterface object
214 */
215 DataInterfaceBase& _dataIface;
216
217 /**
218 * @brief Tracks status of after a command is sent and before the
219 * response is received.
220 */
221 bool _inProgress = false;
222
223 private:
224 /**
225 * @brief The default amount of time to wait before retrying
226 * a failed send.
Matt Spinler99196682019-12-11 11:23:20 -0600227 */
Matt Spinler3a4243a2020-03-03 16:51:08 -0600228 const std::chrono::milliseconds _defaultSendRetryDelay{1000};
Matt Spinler99196682019-12-11 11:23:20 -0600229
230 /**
231 * @brief The default amount of time to wait
232 * before retrying after a failed receive.
233 */
234 const std::chrono::milliseconds _defaultReceiveRetryDelay{1000};
235
236 /**
237 * @brief The default amount of time to wait when the host said it
238 * was full before sending the PEL again.
239 */
240 const std::chrono::milliseconds _defaultHostFullRetryDelay{60000};
Matt Spinlere5f75082022-01-24 16:09:51 -0600241
242 /**
243 * @brief The default amount of time to wait after the host is up
244 * before sending up the PELs.
245 */
246 const std::chrono::milliseconds _defaultHostUpDelay{60000};
Matt Spinler99196682019-12-11 11:23:20 -0600247};
248
249} // namespace pels
250} // namespace openpower