| #pragma once |
| |
| #include "data_interface.hpp" |
| |
| #include <libpldm/transport.h> |
| #include <stdint.h> |
| |
| #include <phosphor-logging/lg2.hpp> |
| #include <sdeventplus/event.hpp> |
| #include <sdeventplus/source/io.hpp> |
| |
| #include <chrono> |
| #include <functional> |
| |
| namespace openpower |
| { |
| namespace pels |
| { |
| |
| /** |
| * @brief Return codes from sending a command |
| */ |
| enum class CmdStatus |
| { |
| success, |
| failure |
| }; |
| |
| /** |
| * @brief Return codes from the command response |
| */ |
| enum class ResponseStatus |
| { |
| success, |
| failure |
| }; |
| |
| /** |
| * @class HostInterface |
| * |
| * An abstract base class for sending the 'New PEL available' command |
| * to the host. Used so that the PLDM interfaces can be mocked for |
| * testing the HostNotifier code. The response to this command is |
| * asynchronous, with the intent that other code registers a callback |
| * function to run when the response is received. |
| */ |
| class HostInterface |
| { |
| public: |
| HostInterface() = delete; |
| virtual ~HostInterface() = default; |
| HostInterface(const HostInterface&) = default; |
| HostInterface& operator=(const HostInterface&) = default; |
| HostInterface(HostInterface&&) = default; |
| HostInterface& operator=(HostInterface&&) = default; |
| |
| /** |
| * @brief Constructor |
| * |
| * @param[in] event - The sd_event object pointer |
| * @param[in] dataIface - The DataInterface object |
| */ |
| HostInterface(sd_event* event, DataInterfaceBase& dataIface) : |
| _event(event), _dataIface(dataIface) |
| {} |
| |
| /** |
| * @brief Pure virtual function for sending the 'new PEL available' |
| * asynchronous command to the host. |
| * |
| * @param[in] id - The ID of the new PEL |
| * @param[in] size - The size of the new PEL |
| * |
| * @return CmdStatus - If the send was successful or not |
| */ |
| virtual CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) = 0; |
| |
| /** |
| * @brief Returns the amount of time to wait before retrying after |
| * a failed send command. |
| * |
| * @return milliseconds - The amount of time to wait |
| */ |
| virtual std::chrono::milliseconds getSendRetryDelay() const |
| { |
| return _defaultSendRetryDelay; |
| } |
| |
| /** |
| * @brief Returns the amount of time to wait before retrying after |
| * a command receive. |
| * |
| * @return milliseconds - The amount of time to wait |
| */ |
| virtual std::chrono::milliseconds getReceiveRetryDelay() const |
| { |
| return _defaultReceiveRetryDelay; |
| } |
| |
| /** |
| * @brief Returns the amount of time to wait before retrying if the |
| * host firmware's PEL storage was full and it can't store |
| * any more logs until it is freed up somehow. |
| * |
| * In this class to help with mocking. |
| * |
| * @return milliseconds - The amount of time to wait |
| */ |
| virtual std::chrono::milliseconds getHostFullRetryDelay() const |
| { |
| return _defaultHostFullRetryDelay; |
| } |
| |
| /** |
| * @brief Returns the amount of time to wait after the host is up |
| * before sending commands. |
| * |
| * In this class to help with mocking. |
| * |
| * @return milliseconds - The amount of time to wait |
| */ |
| virtual std::chrono::milliseconds getHostUpDelay() const |
| { |
| return _defaultHostUpDelay; |
| } |
| |
| using ResponseFunction = std::function<void(ResponseStatus)>; |
| |
| /** |
| * @brief Sets the function to call on the command receive. |
| * |
| * The success/failure status is passed to the function. |
| * |
| * @param[in] func - The callback function |
| */ |
| void setResponseFunction(ResponseFunction func) |
| { |
| _responseFunc = std::move(func); |
| } |
| |
| /** |
| * @brief Call the response function |
| * |
| * @param[in] status - The status given to the function |
| */ |
| void callResponseFunc(ResponseStatus status) |
| { |
| if (_responseFunc) |
| { |
| try |
| { |
| (*_responseFunc)(status); |
| } |
| catch (const std::exception& e) |
| { |
| lg2::error( |
| "Host iface response callback threw an exception: {EX}", |
| "EX", e); |
| } |
| } |
| } |
| |
| /** |
| * @brief Returns the event object in use |
| * |
| * @return sdeventplus::Event& - The event object |
| */ |
| sdeventplus::Event& getEvent() |
| { |
| return _event; |
| } |
| |
| /** |
| * @brief Pure virtual function to cancel an in-progress command |
| * |
| * 'In progress' means after the send but before the receive |
| */ |
| virtual void cancelCmd() = 0; |
| |
| /** |
| * @brief Says if the command is in progress (after send/before receive) |
| * |
| * @return bool - If command is in progress |
| */ |
| bool cmdInProgress() const |
| { |
| return _inProgress; |
| } |
| |
| protected: |
| /** |
| * @brief Pure virtual function for implementing the asynchronous |
| * command response callback. |
| * |
| * @param[in] io - The sdeventplus IO object that the callback is |
| * invoked from. |
| * @param[in] fd - The file descriptor being used |
| * @param[in] revents - The event status bits |
| * @param[in] transport - The transport data pointer |
| */ |
| virtual void receive(sdeventplus::source::IO& io, int fd, uint32_t revents, |
| pldm_transport* transport) = 0; |
| |
| /** |
| * @brief An optional function to call on a successful command response. |
| */ |
| std::optional<ResponseFunction> _responseFunc; |
| |
| /** |
| * @brief The sd_event wrapper object needed for response callbacks |
| */ |
| sdeventplus::Event _event; |
| |
| /** |
| * @brief The DataInterface object |
| */ |
| DataInterfaceBase& _dataIface; |
| |
| /** |
| * @brief Tracks status of after a command is sent and before the |
| * response is received. |
| */ |
| bool _inProgress = false; |
| |
| private: |
| /** |
| * @brief The default amount of time to wait before retrying |
| * a failed send. |
| */ |
| const std::chrono::milliseconds _defaultSendRetryDelay{1000}; |
| |
| /** |
| * @brief The default amount of time to wait |
| * before retrying after a failed receive. |
| */ |
| const std::chrono::milliseconds _defaultReceiveRetryDelay{1000}; |
| |
| /** |
| * @brief The default amount of time to wait when the host said it |
| * was full before sending the PEL again. |
| */ |
| const std::chrono::milliseconds _defaultHostFullRetryDelay{60000}; |
| |
| /** |
| * @brief The default amount of time to wait after the host is up |
| * before sending up the PELs. |
| */ |
| const std::chrono::milliseconds _defaultHostUpDelay{60000}; |
| }; |
| |
| } // namespace pels |
| } // namespace openpower |