blob: 9aa880b16dade8f8ccf8f59fe21c6021f2ff5414 [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
113 using ResponseFunction = std::function<void(ResponseStatus)>;
114
115 /**
116 * @brief Sets the function to call on the command receive.
117 *
118 * The success/failure status is passed to the function.
119 *
120 * @param[in] func - The callback function
121 */
122 void setResponseFunction(ResponseFunction func)
123 {
124 _responseFunc = std::move(func);
125 }
126
127 /**
Matt Spinlera44efe42020-03-03 10:30:16 -0600128 * @brief Call the response function
129 *
130 * @param[in] status - The status given to the function
131 */
132 void callResponseFunc(ResponseStatus status)
133 {
134 if (_responseFunc)
135 {
136 try
137 {
138 (*_responseFunc)(status);
139 }
140 catch (const std::exception& e)
141 {
142 using namespace phosphor::logging;
143 log<level::ERR>(
144 "Host iface response callback threw an exception",
145 entry("ERROR=%s", e.what()));
146 }
147 }
148 }
149
150 /**
Matt Spinler99196682019-12-11 11:23:20 -0600151 * @brief Returns the event object in use
152 *
153 * @return sdeventplus::Event& - The event object
154 */
155 sdeventplus::Event& getEvent()
156 {
157 return _event;
158 }
159
160 /**
161 * @brief Pure virtual function to cancel an in-progress command
162 *
163 * 'In progress' means after the send but before the receive
164 */
165 virtual void cancelCmd() = 0;
166
167 /**
168 * @brief Says if the command is in progress (after send/before receive)
169 *
170 * @return bool - If command is in progress
171 */
172 bool cmdInProgress() const
173 {
174 return _inProgress;
175 }
176
177 protected:
178 /**
179 * @brief Pure virtual function for implementing the asynchronous
180 * command response callback.
181 *
182 * @param[in] io - The sdeventplus IO object that the callback is
183 * invoked from.
184 * @param[in] fd - The file descriptor being used
185 * @param[in] revents - The event status bits
186 */
187 virtual void receive(sdeventplus::source::IO& io, int fd,
188 uint32_t revents) = 0;
189
190 /**
191 * @brief An optional function to call on a successful command response.
192 */
193 std::optional<ResponseFunction> _responseFunc;
194
195 /**
196 * @brief The sd_event wrapper object needed for response callbacks
197 */
198 sdeventplus::Event _event;
199
200 /**
201 * @brief The DataInterface object
202 */
203 DataInterfaceBase& _dataIface;
204
205 /**
206 * @brief Tracks status of after a command is sent and before the
207 * response is received.
208 */
209 bool _inProgress = false;
210
211 private:
212 /**
213 * @brief The default amount of time to wait before retrying
214 * a failed send.
215 *
216 * It is this value for the case where all instance IDs are used
217 * and it takes this long in the PLDM daemon for them to reset.
218 */
219 const std::chrono::milliseconds _defaultSendRetryDelay{6000};
220
221 /**
222 * @brief The default amount of time to wait
223 * before retrying after a failed receive.
224 */
225 const std::chrono::milliseconds _defaultReceiveRetryDelay{1000};
226
227 /**
228 * @brief The default amount of time to wait when the host said it
229 * was full before sending the PEL again.
230 */
231 const std::chrono::milliseconds _defaultHostFullRetryDelay{60000};
232};
233
234} // namespace pels
235} // namespace openpower