blob: c9f1f9fb00ee03303da0f504e303cad13f029c8d [file]
#pragma once
#include "MCTPDeviceRepository.hpp"
#include "MCTPEndpoint.hpp"
#include "Utils.hpp"
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <vector>
struct AssociationServer
{
virtual ~AssociationServer() = default;
virtual void associate(const std::string& path,
const std::vector<Association>& associations) = 0;
virtual void disassociate(const std::string& path) = 0;
};
enum class MCTPDeviceState
{
// The presence of the device is acknowledged, but we're yet to issue the
// initial setup request. Ensures endpoint state is tracked for at least the
// lifetime of the inventory
Unmanaged,
// The endpoint setup request for the device has been issued, and we're
// asynchronously waiting on the response.
Assigning,
// An endpoint setup request has been previously issued for the device
// but it was not successful. Another setup request will be issued in the
// future.
Unassigned,
// An endpoint setup request was successfully issued for the device. The
// endpoint is currently known to be reachable and both its inventory and
// endpoint object are published.
Assigned,
// The device was removed from inventory while we were waiting for a
// setup call to complete. The anticipated response will inform whether we
// consider the device's lifecycle to be complete, or that it be considered
// recovered.
Quarantine,
// A device's endpoint object was removed while its inventory remained
// present. A future setup request will be issued to recover the endpoint
// configuration.
Lost,
// An endpoint setup request for a lost device has been issued, and we're
// asynchronously waiting on the response.
Recovering,
// The endpoint setup request was successfully issued for a previously
// lost device. As the device is known to currently be responsive, insulate
// the configuration from observation of a subsequent inventory removal.
// Observing an inventory addition subsequent to observation of inventory
// removal transitions the device state back to Assigned.
Recovered,
// Removal of the device from inventory has resulted in a remove call being
// issued for the device's endpoint, and we're asynchronously waiting on
// the response.
Removing,
// Addition of the device's inventory has been observed concurrent to a
// remove call whose response is yet to be observed.
Pending,
};
class MCTPReactor : public std::enable_shared_from_this<MCTPReactor>
{
using MCTPDeviceFactory = std::function<std::shared_ptr<MCTPDevice>(
const std::string& interface, const std::vector<std::uint8_t>& physaddr,
std::optional<std::uint8_t> eid)>;
public:
MCTPReactor() = delete;
MCTPReactor(const MCTPReactor&) = delete;
MCTPReactor(MCTPReactor&&) = delete;
explicit MCTPReactor(AssociationServer& server) : server(server) {}
~MCTPReactor() = default;
MCTPReactor& operator=(const MCTPReactor&) = delete;
MCTPReactor& operator=(MCTPReactor&&) = delete;
void tick();
void manageMCTPDevice(const std::string& path,
const std::shared_ptr<MCTPDevice>& device);
void unmanageMCTPDevice(const sdbusplus::object_path& path);
private:
static std::optional<std::string> findSMBusInterface(int bus);
AssociationServer& server;
MCTPDeviceRepository devices;
std::map<std::size_t, MCTPDeviceState> states;
void deferSetup(const std::shared_ptr<MCTPDevice>& dev);
void setupEndpoint(const std::shared_ptr<MCTPDevice>& dev);
void trackEndpoint(const std::shared_ptr<MCTPEndpoint>& ep);
void untrackEndpoint(const std::shared_ptr<MCTPEndpoint>& ep);
void next(const std::shared_ptr<MCTPDevice>& dev, MCTPDeviceState next);
void terminate(const std::shared_ptr<MCTPDevice>& dev);
};