| #include "config.h" |
| |
| #include "mctp_endpoint_discovery.hpp" |
| |
| #include "common/types.hpp" |
| #include "common/utils.hpp" |
| |
| #include <phosphor-logging/lg2.hpp> |
| |
| #include <algorithm> |
| #include <fstream> |
| #include <iostream> |
| #include <map> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| using namespace sdbusplus::bus::match::rules; |
| |
| PHOSPHOR_LOG2_USING; |
| |
| namespace pldm |
| { |
| MctpDiscovery::MctpDiscovery( |
| sdbusplus::bus_t& bus, |
| std::initializer_list<MctpDiscoveryHandlerIntf*> 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<std::string>({MCTPInterface})); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| error("getSubtree call failed with, {ERROR} {PATH} {INTERFACE}", |
| "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<NetworkId>(properties.at("NetworkId")); |
| auto eid = std::get<mctp_eid_t>(properties.at("EID")); |
| auto types = std::get<std::vector<uint8_t>>( |
| properties.at("SupportedMessageTypes")); |
| if (std::find(types.begin(), types.end(), mctpTypePLDM) != |
| types.end()) |
| { |
| info("Adding Endpoint networkId={NETWORK} EID={EID}", |
| "NETWORK", networkId, "EID", unsigned(eid)); |
| mctpInfos.emplace_back( |
| MctpInfo(eid, emptyUUID, "", networkId)); |
| } |
| } |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| error( |
| "Error reading MCTP Endpoint property, {ERROR} {SERVICE} {PATH}", |
| "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<Property, dbus::Value>; |
| std::map<std::string, PropertyMap> interfaces; |
| |
| try |
| { |
| msg.read(objPath, interfaces); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| error("Error reading MCTP Endpoint addedInterace message, {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<NetworkId>(properties.at("NetworkId")); |
| auto eid = std::get<mctp_eid_t>(properties.at("EID")); |
| auto types = std::get<std::vector<uint8_t>>( |
| properties.at("SupportedMessageTypes")); |
| if (std::find(types.begin(), types.end(), mctpTypePLDM) != |
| types.end()) |
| { |
| info("Adding Endpoint networkId={NETWORK} EID={EID}", |
| "NETWORK", networkId, "EID", unsigned(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} EID={EID}", "NETWORK", |
| std::get<3>(mctpInfo), "EID", unsigned(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 |