#include "config.h" #include "mctp_endpoint_discovery.hpp" #include "common/types.hpp" #include "common/utils.hpp" #include #include #include #include #include #include #include #include using namespace sdbusplus::bus::match::rules; PHOSPHOR_LOG2_USING; namespace pldm { MctpDiscovery::MctpDiscovery( sdbusplus::bus_t& bus, std::initializer_list list) : bus(bus), mctpEndpointAddedSignal( bus, interfacesAdded(MCTPPath), std::bind_front(&MctpDiscovery::discoverEndpoints, this)), mctpEndpointRemovedSignal( bus, interfacesRemoved(MCTPPath), std::bind_front(&MctpDiscovery::removeEndpoints, this)), handlers(list) { getMctpInfos(existingMctpInfos); handleMctpEndpoints(existingMctpInfos); } void MctpDiscovery::getMctpInfos(MctpInfos& mctpInfos) { // Find all implementations of the MCTP Endpoint interface pldm::utils::GetSubTreeResponse mapperResponse; try { mapperResponse = pldm::utils::DBusHandler().getSubtree( MCTPPath, 0, std::vector({MCTPInterface})); } catch (const sdbusplus::exception_t& e) { error( "Failed to getSubtree call at path '{PATH}' and interface '{INTERFACE}', error - {ERROR} ", "ERROR", e, "PATH", MCTPPath, "INTERFACE", MCTPInterface); return; } for (const auto& [path, services] : mapperResponse) { for (const auto& serviceIter : services) { const std::string& service = serviceIter.first; try { auto properties = pldm::utils::DBusHandler().getDbusPropertiesVariant( service.c_str(), path.c_str(), MCTPInterface); if (properties.contains("NetworkId") && properties.contains("EID") && properties.contains("SupportedMessageTypes")) { auto networkId = std::get(properties.at("NetworkId")); auto eid = std::get(properties.at("EID")); auto types = std::get>( properties.at("SupportedMessageTypes")); if (std::find(types.begin(), types.end(), mctpTypePLDM) != types.end()) { info( "Adding Endpoint networkId '{NETWORK}' and EID '{EID}'", "NETWORK", networkId, "EID", eid); mctpInfos.emplace_back( MctpInfo(eid, emptyUUID, "", networkId)); } } } catch (const sdbusplus::exception_t& e) { error( "Error reading MCTP Endpoint property at path '{PATH}' and service '{SERVICE}', error - {ERROR}", "ERROR", e, "SERVICE", service, "PATH", path); return; } } } } void MctpDiscovery::getAddedMctpInfos(sdbusplus::message_t& msg, MctpInfos& mctpInfos) { using ObjectPath = sdbusplus::message::object_path; ObjectPath objPath; using Property = std::string; using PropertyMap = std::map; std::map interfaces; try { msg.read(objPath, interfaces); } catch (const sdbusplus::exception_t& e) { error( "Error reading MCTP Endpoint added interface message, error - {ERROR}", "ERROR", e); return; } for (const auto& [intfName, properties] : interfaces) { if (intfName == MCTPInterface) { if (properties.contains("NetworkId") && properties.contains("EID") && properties.contains("SupportedMessageTypes")) { auto networkId = std::get(properties.at("NetworkId")); auto eid = std::get(properties.at("EID")); auto types = std::get>( properties.at("SupportedMessageTypes")); if (std::find(types.begin(), types.end(), mctpTypePLDM) != types.end()) { info( "Adding Endpoint networkId '{NETWORK}' and EID '{EID}'", "NETWORK", networkId, "EID", eid); mctpInfos.emplace_back( MctpInfo(eid, emptyUUID, "", networkId)); } } } } } void MctpDiscovery::addToExistingMctpInfos(const MctpInfos& addedInfos) { for (const auto& mctpInfo : addedInfos) { if (std::find(existingMctpInfos.begin(), existingMctpInfos.end(), mctpInfo) == existingMctpInfos.end()) { existingMctpInfos.emplace_back(mctpInfo); } } } void MctpDiscovery::removeFromExistingMctpInfos(MctpInfos& mctpInfos, MctpInfos& removedInfos) { for (const auto& mctpInfo : existingMctpInfos) { if (std::find(mctpInfos.begin(), mctpInfos.end(), mctpInfo) == mctpInfos.end()) { removedInfos.emplace_back(mctpInfo); } } for (const auto& mctpInfo : removedInfos) { info("Removing Endpoint networkId '{NETWORK}' and EID '{EID}'", "NETWORK", std::get<3>(mctpInfo), "EID", std::get<0>(mctpInfo)); existingMctpInfos.erase(std::remove(existingMctpInfos.begin(), existingMctpInfos.end(), mctpInfo), existingMctpInfos.end()); } } void MctpDiscovery::discoverEndpoints(sdbusplus::message_t& msg) { MctpInfos addedInfos; getAddedMctpInfos(msg, addedInfos); addToExistingMctpInfos(addedInfos); handleMctpEndpoints(addedInfos); } void MctpDiscovery::removeEndpoints(sdbusplus::message_t&) { MctpInfos mctpInfos; MctpInfos removedInfos; getMctpInfos(mctpInfos); removeFromExistingMctpInfos(mctpInfos, removedInfos); handleRemovedMctpEndpoints(removedInfos); } void MctpDiscovery::handleMctpEndpoints(const MctpInfos& mctpInfos) { for (const auto& handler : handlers) { if (handler) { handler->handleMctpEndpoints(mctpInfos); } } } void MctpDiscovery::handleRemovedMctpEndpoints(const MctpInfos& mctpInfos) { for (const auto& handler : handlers) { if (handler) { handler->handleRemovedMctpEndpoints(mctpInfos); } } } } // namespace pldm