1 #include "config.h" 2 3 #include "mctp_endpoint_discovery.hpp" 4 5 #include "common/types.hpp" 6 #include "common/utils.hpp" 7 8 #include <phosphor-logging/lg2.hpp> 9 10 #include <algorithm> 11 #include <fstream> 12 #include <iostream> 13 #include <map> 14 #include <string> 15 #include <string_view> 16 #include <vector> 17 18 using namespace sdbusplus::bus::match::rules; 19 20 PHOSPHOR_LOG2_USING; 21 22 namespace pldm 23 { 24 MctpDiscovery::MctpDiscovery( 25 sdbusplus::bus::bus& bus, 26 std::initializer_list<MctpDiscoveryHandlerIntf*> list) : 27 bus(bus), 28 mctpEndpointAddedSignal( 29 bus, interfacesAdded(MCTPPath), 30 std::bind_front(&MctpDiscovery::discoverEndpoints, this)), 31 mctpEndpointRemovedSignal( 32 bus, interfacesRemoved(MCTPPath), 33 std::bind_front(&MctpDiscovery::removeEndpoints, this)), 34 handlers(list) 35 { 36 getMctpInfos(existingMctpInfos); 37 handleMctpEndpoints(existingMctpInfos); 38 } 39 40 void MctpDiscovery::getMctpInfos(MctpInfos& mctpInfos) 41 { 42 // Find all implementations of the MCTP Endpoint interface 43 pldm::utils::GetSubTreeResponse mapperResponse; 44 try 45 { 46 mapperResponse = pldm::utils::DBusHandler().getSubtree( 47 MCTPPath, 0, std::vector<std::string>({MCTPInterface})); 48 } 49 catch (const sdbusplus::exception_t& e) 50 { 51 error("getSubtree call failed with, {ERROR} {PATH} {INTERFACE}", 52 "ERROR", e, "PATH", MCTPPath, "INTERFACE", MCTPInterface); 53 return; 54 } 55 56 for (const auto& [path, services] : mapperResponse) 57 { 58 for (const auto& serviceIter : services) 59 { 60 const std::string& service = serviceIter.first; 61 try 62 { 63 auto properties = 64 pldm::utils::DBusHandler().getDbusPropertiesVariant( 65 service.c_str(), path.c_str(), MCTPInterface); 66 67 if (properties.contains("NetworkId") && 68 properties.contains("EID") && 69 properties.contains("SupportedMessageTypes")) 70 { 71 auto networkId = 72 std::get<NetworkId>(properties.at("NetworkId")); 73 auto eid = std::get<mctp_eid_t>(properties.at("EID")); 74 auto types = std::get<std::vector<uint8_t>>( 75 properties.at("SupportedMessageTypes")); 76 if (std::find(types.begin(), types.end(), mctpTypePLDM) != 77 types.end()) 78 { 79 info("Adding Endpoint networkId={NETWORK} EID={EID}", 80 "NETWORK", networkId, "EID", unsigned(eid)); 81 mctpInfos.emplace_back( 82 MctpInfo(eid, emptyUUID, "", networkId)); 83 } 84 } 85 } 86 catch (const sdbusplus::exception_t& e) 87 { 88 error( 89 "Error reading MCTP Endpoint property, {ERROR} {SERVICE} {PATH}", 90 "ERROR", e, "SERVICE", service, "PATH", path); 91 return; 92 } 93 } 94 } 95 } 96 97 void MctpDiscovery::getAddedMctpInfos(sdbusplus::message_t& msg, 98 MctpInfos& mctpInfos) 99 { 100 using ObjectPath = sdbusplus::message::object_path; 101 ObjectPath objPath; 102 using Property = std::string; 103 using PropertyMap = std::map<Property, dbus::Value>; 104 std::map<std::string, PropertyMap> interfaces; 105 106 try 107 { 108 msg.read(objPath, interfaces); 109 } 110 catch (const sdbusplus::exception_t& e) 111 { 112 error("Error reading MCTP Endpoint addedInterace message, {ERROR}", 113 "ERROR", e); 114 return; 115 } 116 117 for (const auto& [intfName, properties] : interfaces) 118 { 119 if (intfName == MCTPInterface) 120 { 121 if (properties.contains("NetworkId") && 122 properties.contains("EID") && 123 properties.contains("SupportedMessageTypes")) 124 { 125 auto networkId = 126 std::get<NetworkId>(properties.at("NetworkId")); 127 auto eid = std::get<mctp_eid_t>(properties.at("EID")); 128 auto types = std::get<std::vector<uint8_t>>( 129 properties.at("SupportedMessageTypes")); 130 if (std::find(types.begin(), types.end(), mctpTypePLDM) != 131 types.end()) 132 { 133 info("Adding Endpoint networkId={NETWORK} EID={EID}", 134 "NETWORK", networkId, "EID", unsigned(eid)); 135 mctpInfos.emplace_back( 136 MctpInfo(eid, emptyUUID, "", networkId)); 137 } 138 } 139 } 140 } 141 } 142 143 void MctpDiscovery::addToExistingMctpInfos(const MctpInfos& addedInfos) 144 { 145 for (const auto& mctpInfo : addedInfos) 146 { 147 if (std::find(existingMctpInfos.begin(), existingMctpInfos.end(), 148 mctpInfo) == existingMctpInfos.end()) 149 { 150 existingMctpInfos.emplace_back(mctpInfo); 151 } 152 } 153 } 154 155 void MctpDiscovery::removeFromExistingMctpInfos(MctpInfos& mctpInfos, 156 MctpInfos& removedInfos) 157 { 158 for (const auto& mctpInfo : existingMctpInfos) 159 { 160 if (std::find(mctpInfos.begin(), mctpInfos.end(), mctpInfo) == 161 mctpInfos.end()) 162 { 163 removedInfos.emplace_back(mctpInfo); 164 } 165 } 166 for (const auto& mctpInfo : removedInfos) 167 { 168 info("Removing Endpoint networkId={NETWORK} EID={EID}", "NETWORK", 169 std::get<3>(mctpInfo), "EID", unsigned(std::get<0>(mctpInfo))); 170 existingMctpInfos.erase(std::remove(existingMctpInfos.begin(), 171 existingMctpInfos.end(), mctpInfo), 172 existingMctpInfos.end()); 173 } 174 } 175 176 void MctpDiscovery::discoverEndpoints(sdbusplus::message_t& msg) 177 { 178 MctpInfos addedInfos; 179 getAddedMctpInfos(msg, addedInfos); 180 addToExistingMctpInfos(addedInfos); 181 handleMctpEndpoints(addedInfos); 182 } 183 184 void MctpDiscovery::removeEndpoints(sdbusplus::message_t&) 185 { 186 MctpInfos mctpInfos; 187 MctpInfos removedInfos; 188 getMctpInfos(mctpInfos); 189 removeFromExistingMctpInfos(mctpInfos, removedInfos); 190 handleRemovedMctpEndpoints(removedInfos); 191 } 192 193 void MctpDiscovery::handleMctpEndpoints(const MctpInfos& mctpInfos) 194 { 195 for (const auto& handler : handlers) 196 { 197 if (handler) 198 { 199 handler->handleMctpEndpoints(mctpInfos); 200 } 201 } 202 } 203 204 void MctpDiscovery::handleRemovedMctpEndpoints(const MctpInfos& mctpInfos) 205 { 206 for (const auto& handler : handlers) 207 { 208 if (handler) 209 { 210 handler->handleRemovedMctpEndpoints(mctpInfos); 211 } 212 } 213 } 214 215 } // namespace pldm 216