blob: ee818f304da2c6127e7ed791d7b8d9d8e669d7e2 [file] [log] [blame]
#pragma once
#include "data_interface.hpp"
#include <stdint.h>
#include <phosphor-logging/log.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)
{
using namespace phosphor::logging;
log<level::ERR>(
"Host iface response callback threw an exception",
entry("ERROR=%s", e.what()));
}
}
}
/**
* @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
*/
virtual void receive(sdeventplus::source::IO& io, int fd,
uint32_t revents) = 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