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_t& 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( 52 "Failed to getSubtree call at path '{PATH}' and interface '{INTERFACE}', error - {ERROR} ", 53 "ERROR", e, "PATH", MCTPPath, "INTERFACE", MCTPInterface); 54 return; 55 } 56 57 for (const auto& [path, services] : mapperResponse) 58 { 59 for (const auto& serviceIter : services) 60 { 61 const std::string& service = serviceIter.first; 62 try 63 { 64 auto properties = 65 pldm::utils::DBusHandler().getDbusPropertiesVariant( 66 service.c_str(), path.c_str(), MCTPInterface); 67 68 if (properties.contains("NetworkId") && 69 properties.contains("EID") && 70 properties.contains("SupportedMessageTypes")) 71 { 72 auto networkId = 73 std::get<NetworkId>(properties.at("NetworkId")); 74 auto eid = std::get<mctp_eid_t>(properties.at("EID")); 75 auto types = std::get<std::vector<uint8_t>>( 76 properties.at("SupportedMessageTypes")); 77 if (std::find(types.begin(), types.end(), mctpTypePLDM) != 78 types.end()) 79 { 80 info( 81 "Adding Endpoint networkId '{NETWORK}' and EID '{EID}'", 82 "NETWORK", networkId, "EID", eid); 83 mctpInfos.emplace_back( 84 MctpInfo(eid, emptyUUID, "", networkId)); 85 } 86 } 87 } 88 catch (const sdbusplus::exception_t& e) 89 { 90 error( 91 "Error reading MCTP Endpoint property at path '{PATH}' and service '{SERVICE}', error - {ERROR}", 92 "ERROR", e, "SERVICE", service, "PATH", path); 93 return; 94 } 95 } 96 } 97 } 98 99 void MctpDiscovery::getAddedMctpInfos(sdbusplus::message_t& msg, 100 MctpInfos& mctpInfos) 101 { 102 using ObjectPath = sdbusplus::message::object_path; 103 ObjectPath objPath; 104 using Property = std::string; 105 using PropertyMap = std::map<Property, dbus::Value>; 106 std::map<std::string, PropertyMap> interfaces; 107 108 try 109 { 110 msg.read(objPath, interfaces); 111 } 112 catch (const sdbusplus::exception_t& e) 113 { 114 error( 115 "Error reading MCTP Endpoint added interface message, error - {ERROR}", 116 "ERROR", e); 117 return; 118 } 119 120 for (const auto& [intfName, properties] : interfaces) 121 { 122 if (intfName == MCTPInterface) 123 { 124 if (properties.contains("NetworkId") && 125 properties.contains("EID") && 126 properties.contains("SupportedMessageTypes")) 127 { 128 auto networkId = 129 std::get<NetworkId>(properties.at("NetworkId")); 130 auto eid = std::get<mctp_eid_t>(properties.at("EID")); 131 auto types = std::get<std::vector<uint8_t>>( 132 properties.at("SupportedMessageTypes")); 133 if (std::find(types.begin(), types.end(), mctpTypePLDM) != 134 types.end()) 135 { 136 info( 137 "Adding Endpoint networkId '{NETWORK}' and EID '{EID}'", 138 "NETWORK", networkId, "EID", eid); 139 mctpInfos.emplace_back( 140 MctpInfo(eid, emptyUUID, "", networkId)); 141 } 142 } 143 } 144 } 145 } 146 147 void MctpDiscovery::addToExistingMctpInfos(const MctpInfos& addedInfos) 148 { 149 for (const auto& mctpInfo : addedInfos) 150 { 151 if (std::find(existingMctpInfos.begin(), existingMctpInfos.end(), 152 mctpInfo) == existingMctpInfos.end()) 153 { 154 existingMctpInfos.emplace_back(mctpInfo); 155 } 156 } 157 } 158 159 void MctpDiscovery::removeFromExistingMctpInfos(MctpInfos& mctpInfos, 160 MctpInfos& removedInfos) 161 { 162 for (const auto& mctpInfo : existingMctpInfos) 163 { 164 if (std::find(mctpInfos.begin(), mctpInfos.end(), mctpInfo) == 165 mctpInfos.end()) 166 { 167 removedInfos.emplace_back(mctpInfo); 168 } 169 } 170 for (const auto& mctpInfo : removedInfos) 171 { 172 info("Removing Endpoint networkId '{NETWORK}' and EID '{EID}'", 173 "NETWORK", std::get<3>(mctpInfo), "EID", std::get<0>(mctpInfo)); 174 existingMctpInfos.erase(std::remove(existingMctpInfos.begin(), 175 existingMctpInfos.end(), mctpInfo), 176 existingMctpInfos.end()); 177 } 178 } 179 180 void MctpDiscovery::discoverEndpoints(sdbusplus::message_t& msg) 181 { 182 MctpInfos addedInfos; 183 getAddedMctpInfos(msg, addedInfos); 184 addToExistingMctpInfos(addedInfos); 185 handleMctpEndpoints(addedInfos); 186 } 187 188 void MctpDiscovery::removeEndpoints(sdbusplus::message_t&) 189 { 190 MctpInfos mctpInfos; 191 MctpInfos removedInfos; 192 getMctpInfos(mctpInfos); 193 removeFromExistingMctpInfos(mctpInfos, removedInfos); 194 handleRemovedMctpEndpoints(removedInfos); 195 } 196 197 void MctpDiscovery::handleMctpEndpoints(const MctpInfos& mctpInfos) 198 { 199 for (const auto& handler : handlers) 200 { 201 if (handler) 202 { 203 handler->handleMctpEndpoints(mctpInfos); 204 } 205 } 206 } 207 208 void MctpDiscovery::handleRemovedMctpEndpoints(const MctpInfos& mctpInfos) 209 { 210 for (const auto& handler : handlers) 211 { 212 if (handler) 213 { 214 handler->handleRemovedMctpEndpoints(mctpInfos); 215 } 216 } 217 } 218 219 } // namespace pldm 220