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), mctpEndpointAddedSignal( 28 bus, interfacesAdded(MCTPPath), 29 std::bind_front(&MctpDiscovery::discoverEndpoints, this)), 30 mctpEndpointRemovedSignal( 31 bus, interfacesRemoved(MCTPPath), 32 std::bind_front(&MctpDiscovery::removeEndpoints, this)), 33 handlers(list) 34 { 35 getMctpInfos(existingMctpInfos); 36 handleMctpEndpoints(existingMctpInfos); 37 } 38 39 void MctpDiscovery::getMctpInfos(MctpInfos& mctpInfos) 40 { 41 // Find all implementations of the MCTP Endpoint interface 42 pldm::utils::GetSubTreeResponse mapperResponse; 43 try 44 { 45 mapperResponse = pldm::utils::DBusHandler().getSubtree( 46 MCTPPath, 0, std::vector<std::string>({MCTPInterface})); 47 } 48 catch (const sdbusplus::exception_t& e) 49 { 50 error( 51 "Failed to getSubtree call at path '{PATH}' and interface '{INTERFACE}', error - {ERROR} ", 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( 80 "Adding Endpoint networkId '{NETWORK}' and EID '{EID}'", 81 "NETWORK", networkId, "EID", eid); 82 mctpInfos.emplace_back( 83 MctpInfo(eid, emptyUUID, "", networkId)); 84 } 85 } 86 } 87 catch (const sdbusplus::exception_t& e) 88 { 89 error( 90 "Error reading MCTP Endpoint property at path '{PATH}' and service '{SERVICE}', error - {ERROR}", 91 "ERROR", e, "SERVICE", service, "PATH", path); 92 return; 93 } 94 } 95 } 96 } 97 98 void MctpDiscovery::getAddedMctpInfos(sdbusplus::message_t& msg, 99 MctpInfos& mctpInfos) 100 { 101 using ObjectPath = sdbusplus::message::object_path; 102 ObjectPath objPath; 103 using Property = std::string; 104 using PropertyMap = std::map<Property, dbus::Value>; 105 std::map<std::string, PropertyMap> interfaces; 106 107 try 108 { 109 msg.read(objPath, interfaces); 110 } 111 catch (const sdbusplus::exception_t& e) 112 { 113 error( 114 "Error reading MCTP Endpoint added interface message, error - {ERROR}", 115 "ERROR", e); 116 return; 117 } 118 119 for (const auto& [intfName, properties] : interfaces) 120 { 121 if (intfName == MCTPInterface) 122 { 123 if (properties.contains("NetworkId") && 124 properties.contains("EID") && 125 properties.contains("SupportedMessageTypes")) 126 { 127 auto networkId = 128 std::get<NetworkId>(properties.at("NetworkId")); 129 auto eid = std::get<mctp_eid_t>(properties.at("EID")); 130 auto types = std::get<std::vector<uint8_t>>( 131 properties.at("SupportedMessageTypes")); 132 if (std::find(types.begin(), types.end(), mctpTypePLDM) != 133 types.end()) 134 { 135 info( 136 "Adding Endpoint networkId '{NETWORK}' and EID '{EID}'", 137 "NETWORK", networkId, "EID", eid); 138 mctpInfos.emplace_back( 139 MctpInfo(eid, emptyUUID, "", networkId)); 140 } 141 } 142 } 143 } 144 } 145 146 void MctpDiscovery::addToExistingMctpInfos(const MctpInfos& addedInfos) 147 { 148 for (const auto& mctpInfo : addedInfos) 149 { 150 if (std::find(existingMctpInfos.begin(), existingMctpInfos.end(), 151 mctpInfo) == existingMctpInfos.end()) 152 { 153 existingMctpInfos.emplace_back(mctpInfo); 154 } 155 } 156 } 157 158 void MctpDiscovery::removeFromExistingMctpInfos(MctpInfos& mctpInfos, 159 MctpInfos& removedInfos) 160 { 161 for (const auto& mctpInfo : existingMctpInfos) 162 { 163 if (std::find(mctpInfos.begin(), mctpInfos.end(), mctpInfo) == 164 mctpInfos.end()) 165 { 166 removedInfos.emplace_back(mctpInfo); 167 } 168 } 169 for (const auto& mctpInfo : removedInfos) 170 { 171 info("Removing Endpoint networkId '{NETWORK}' and EID '{EID}'", 172 "NETWORK", std::get<3>(mctpInfo), "EID", std::get<0>(mctpInfo)); 173 existingMctpInfos.erase(std::remove(existingMctpInfos.begin(), 174 existingMctpInfos.end(), mctpInfo), 175 existingMctpInfos.end()); 176 } 177 } 178 179 void MctpDiscovery::discoverEndpoints(sdbusplus::message_t& msg) 180 { 181 MctpInfos addedInfos; 182 getAddedMctpInfos(msg, addedInfos); 183 addToExistingMctpInfos(addedInfos); 184 handleMctpEndpoints(addedInfos); 185 } 186 187 void MctpDiscovery::removeEndpoints(sdbusplus::message_t&) 188 { 189 MctpInfos mctpInfos; 190 MctpInfos removedInfos; 191 getMctpInfos(mctpInfos); 192 removeFromExistingMctpInfos(mctpInfos, removedInfos); 193 handleRemovedMctpEndpoints(removedInfos); 194 } 195 196 void MctpDiscovery::handleMctpEndpoints(const MctpInfos& mctpInfos) 197 { 198 for (const auto& handler : handlers) 199 { 200 if (handler) 201 { 202 handler->handleMctpEndpoints(mctpInfos); 203 } 204 } 205 } 206 207 void MctpDiscovery::handleRemovedMctpEndpoints(const MctpInfos& mctpInfos) 208 { 209 for (const auto& handler : handlers) 210 { 211 if (handler) 212 { 213 handler->handleRemovedMctpEndpoints(mctpInfos); 214 } 215 } 216 } 217 218 } // namespace pldm 219