1 #pragma once 2 3 #include "data_interface.hpp" 4 5 #include <libpldm/transport.h> 6 #include <stdint.h> 7 8 #include <phosphor-logging/lg2.hpp> 9 #include <sdeventplus/event.hpp> 10 #include <sdeventplus/source/io.hpp> 11 12 #include <chrono> 13 #include <functional> 14 15 namespace openpower 16 { 17 namespace pels 18 { 19 20 /** 21 * @brief Return codes from sending a command 22 */ 23 enum class CmdStatus 24 { 25 success, 26 failure 27 }; 28 29 /** 30 * @brief Return codes from the command response 31 */ 32 enum class ResponseStatus 33 { 34 success, 35 failure 36 }; 37 38 /** 39 * @class HostInterface 40 * 41 * An abstract base class for sending the 'New PEL available' command 42 * to the host. Used so that the PLDM interfaces can be mocked for 43 * testing the HostNotifier code. The response to this command is 44 * asynchronous, with the intent that other code registers a callback 45 * function to run when the response is received. 46 */ 47 class HostInterface 48 { 49 public: 50 HostInterface() = delete; 51 virtual ~HostInterface() = default; 52 HostInterface(const HostInterface&) = default; 53 HostInterface& operator=(const HostInterface&) = default; 54 HostInterface(HostInterface&&) = default; 55 HostInterface& operator=(HostInterface&&) = default; 56 57 /** 58 * @brief Constructor 59 * 60 * @param[in] event - The sd_event object pointer 61 * @param[in] dataIface - The DataInterface object 62 */ HostInterface(sd_event * event,DataInterfaceBase & dataIface)63 HostInterface(sd_event* event, DataInterfaceBase& dataIface) : 64 _event(event), _dataIface(dataIface) 65 {} 66 67 /** 68 * @brief Pure virtual function for sending the 'new PEL available' 69 * asynchronous command to the host. 70 * 71 * @param[in] id - The ID of the new PEL 72 * @param[in] size - The size of the new PEL 73 * 74 * @return CmdStatus - If the send was successful or not 75 */ 76 virtual CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) = 0; 77 78 /** 79 * @brief Returns the amount of time to wait before retrying after 80 * a failed send command. 81 * 82 * @return milliseconds - The amount of time to wait 83 */ getSendRetryDelay() const84 virtual std::chrono::milliseconds getSendRetryDelay() const 85 { 86 return _defaultSendRetryDelay; 87 } 88 89 /** 90 * @brief Returns the amount of time to wait before retrying after 91 * a command receive. 92 * 93 * @return milliseconds - The amount of time to wait 94 */ getReceiveRetryDelay() const95 virtual std::chrono::milliseconds getReceiveRetryDelay() const 96 { 97 return _defaultReceiveRetryDelay; 98 } 99 100 /** 101 * @brief Returns the amount of time to wait before retrying if the 102 * host firmware's PEL storage was full and it can't store 103 * any more logs until it is freed up somehow. 104 * 105 * In this class to help with mocking. 106 * 107 * @return milliseconds - The amount of time to wait 108 */ getHostFullRetryDelay() const109 virtual std::chrono::milliseconds getHostFullRetryDelay() const 110 { 111 return _defaultHostFullRetryDelay; 112 } 113 114 /** 115 * @brief Returns the amount of time to wait after the host is up 116 * before sending commands. 117 * 118 * In this class to help with mocking. 119 * 120 * @return milliseconds - The amount of time to wait 121 */ getHostUpDelay() const122 virtual std::chrono::milliseconds getHostUpDelay() const 123 { 124 return _defaultHostUpDelay; 125 } 126 127 using ResponseFunction = std::function<void(ResponseStatus)>; 128 129 /** 130 * @brief Sets the function to call on the command receive. 131 * 132 * The success/failure status is passed to the function. 133 * 134 * @param[in] func - The callback function 135 */ setResponseFunction(ResponseFunction func)136 void setResponseFunction(ResponseFunction func) 137 { 138 _responseFunc = std::move(func); 139 } 140 141 /** 142 * @brief Call the response function 143 * 144 * @param[in] status - The status given to the function 145 */ callResponseFunc(ResponseStatus status)146 void callResponseFunc(ResponseStatus status) 147 { 148 if (_responseFunc) 149 { 150 try 151 { 152 (*_responseFunc)(status); 153 } 154 catch (const std::exception& e) 155 { 156 lg2::error( 157 "Host iface response callback threw an exception: {EX}", 158 "EX", e); 159 } 160 } 161 } 162 163 /** 164 * @brief Returns the event object in use 165 * 166 * @return sdeventplus::Event& - The event object 167 */ getEvent()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 */ cmdInProgress() const185 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 * @param[in] transport - The transport data pointer 200 */ 201 virtual void receive(sdeventplus::source::IO& io, int fd, uint32_t revents, 202 pldm_transport* transport) = 0; 203 204 /** 205 * @brief An optional function to call on a successful command response. 206 */ 207 std::optional<ResponseFunction> _responseFunc; 208 209 /** 210 * @brief The sd_event wrapper object needed for response callbacks 211 */ 212 sdeventplus::Event _event; 213 214 /** 215 * @brief The DataInterface object 216 */ 217 DataInterfaceBase& _dataIface; 218 219 /** 220 * @brief Tracks status of after a command is sent and before the 221 * response is received. 222 */ 223 bool _inProgress = false; 224 225 private: 226 /** 227 * @brief The default amount of time to wait before retrying 228 * a failed send. 229 */ 230 const std::chrono::milliseconds _defaultSendRetryDelay{1000}; 231 232 /** 233 * @brief The default amount of time to wait 234 * before retrying after a failed receive. 235 */ 236 const std::chrono::milliseconds _defaultReceiveRetryDelay{1000}; 237 238 /** 239 * @brief The default amount of time to wait when the host said it 240 * was full before sending the PEL again. 241 */ 242 const std::chrono::milliseconds _defaultHostFullRetryDelay{60000}; 243 244 /** 245 * @brief The default amount of time to wait after the host is up 246 * before sending up the PELs. 247 */ 248 const std::chrono::milliseconds _defaultHostUpDelay{60000}; 249 }; 250 251 } // namespace pels 252 } // namespace openpower 253