blob: 8b4d956bd0d307f0ebd1333738c748c627f05a3e [file] [log] [blame]
Unive Tien852160b2024-12-06 15:58:21 +08001#include "configuration_discovery_handler.hpp"
2
3#include <phosphor-logging/lg2.hpp>
4
5#include <algorithm>
6
7PHOSPHOR_LOG2_USING;
8
9namespace pldm
10{
11
12void ConfigurationDiscoveryHandler::handleMctpEndpoints(
13 const MctpInfos& newMctpInfos)
14{
15 for (const auto& newMctpInfo : newMctpInfos)
16 {
17 searchConfigurationFor(newMctpInfo);
18 }
19}
20
21void ConfigurationDiscoveryHandler::handleRemovedMctpEndpoints(
22 const MctpInfos& removedMctpInfos)
23{
24 for (const auto& removedMctpInfo : removedMctpInfos)
25 {
26 removeConfigByEid(std::get<0>(removedMctpInfo));
27 }
28}
29
30std::map<std::string, MctpEndpoint>&
31 ConfigurationDiscoveryHandler::getConfigurations()
32{
33 return configurations;
34}
35
36void ConfigurationDiscoveryHandler::searchConfigurationFor(MctpInfo mctpInfo)
37{
38 constexpr auto inventoryPath = "/xyz/openbmc_project/inventory/";
39 constexpr auto depthWithDownstreamDevices = std::ranges::count(
40 "/inventory/system/{BOARD_OR_CHASSIS}/{DEVICE}/{DOWNSTREAM_DEVICE}",
41 '/');
42
43 const std::vector<std::string> mctpEndpoint = {
44 "xyz.openbmc_project.Configuration.MCTPEndpoint"};
45
46 try
47 {
48 auto response = dBusIntf->getSubtree(
49 inventoryPath, depthWithDownstreamDevices, mctpEndpoint);
50
51 for (const auto& [objectPath, serviceMap] : response)
52 {
53 appendConfigIfEidMatch(std::get<eid>(mctpInfo), objectPath,
54 serviceMap);
55 }
56 }
57 catch (const sdbusplus::exception_t& e)
58 {
59 error("{FUNC}: Failed to getSubtree with MCTPEndpoint, error={ERROR}",
60 "FUNC", std::string(__func__), "ERROR", e.what());
61 return;
62 }
63 catch (const std::exception& e)
64 {
65 error("{FUNC}: Unpredicted error occured, error={ERROR}", "FUNC",
66 std::string(__func__), "ERROR", e.what());
67 return;
68 }
69}
70
71void ConfigurationDiscoveryHandler::appendConfigIfEidMatch(
72 uint8_t targetEid, const std::string& configPath,
73 const pldm::utils::MapperServiceMap& serviceMap)
74{
75 if (!configurations.contains(configPath))
76 {
77 const auto& serviceName = serviceMap.at(0).first;
78
79 /** mctpEndpointInterface should be
80 * "xyz.openbmc_project.Configuration.MCTPEndpoint".
81 */
82 const auto& mctpEndpointInterface = serviceMap.at(0).second.at(0);
83 try
84 {
85 auto response = dBusIntf->getAll(serviceName, configPath,
86 mctpEndpointInterface);
87 appendIfEidMatch(targetEid, configPath,
88 parseMctpEndpointFromResponse(response));
89 }
90 catch (const sdbusplus::exception_t& e)
91 {
92 error(
93 "{FUNC}: Failed to getAll of interface={INTERFACE} in path={PATH}, error={ERROR}",
94 "FUNC", std::string(__func__), "INTERFACE",
95 mctpEndpointInterface, "PATH", configPath, "ERROR", e.what());
96 return;
97 }
98 catch (const NoSuchPropertiesException& e)
99 {
100 error("{FUNC}: Insufficient properties in {PATH}, error={ERROR}",
101 "FUNC", std::string(__func__), "PATH", configPath, "ERROR",
102 e.what());
103 return;
104 }
105 catch (const std::exception& e)
106 {
107 error("{FUNC}: Unpredicted error occured, error={ERROR}", "FUNC",
108 std::string(__func__), "ERROR", e.what());
109 return;
110 }
111 }
112}
113
114MctpEndpoint ConfigurationDiscoveryHandler::parseMctpEndpointFromResponse(
115 const pldm::utils::PropertyMap& response)
116{
117 if (response.contains("Address") && response.contains("Bus") &&
118 response.contains("EndpointId") && response.contains("Name"))
119 {
120 auto addressArray =
121 std::get<std::vector<uint64_t>>(response.at("Address"));
122 uint64_t address = 0;
123
124 for (const auto& element : addressArray)
125 {
126 address = (address << 8) | element;
127 }
128
129 auto eid = std::get<uint64_t>(response.at("EndpointId"));
130 auto bus = std::get<uint64_t>(response.at("Bus"));
131 auto componentName = std::get<std::string>(response.at("Name"));
132 if (response.contains("IANA"))
133 {
134 auto iana = std::get<std::string>(response.at("IANA"));
135 return MctpEndpoint{address, eid, bus, componentName, iana};
136 }
137
138 return MctpEndpoint{address, eid, bus, componentName, std::nullopt};
139 }
140 else
141 {
142 std::vector<std::string> missingProperties{};
143 if (response.contains("Address"))
144 missingProperties.emplace_back("Address");
145 if (response.contains("Bus"))
146 missingProperties.emplace_back("Bus");
147 if (response.contains("EndpointId"))
148 missingProperties.emplace_back("EndpointId");
149 if (response.contains("Name"))
150 missingProperties.emplace_back("Name");
151
152 throw NoSuchPropertiesException(missingProperties);
153 }
154}
155
156void ConfigurationDiscoveryHandler::appendIfEidMatch(
157 uint8_t targetEid, const std::string& configPath,
158 const MctpEndpoint& endpoint)
159{
160 if (endpoint.EndpointId == targetEid)
161 {
162 configurations.emplace(configPath, endpoint);
163 }
164}
165
166void ConfigurationDiscoveryHandler::removeConfigByEid(uint8_t eid)
167{
168 for (const auto& [configDbusPath, mctpEndpoint] : configurations)
169 {
170 if (mctpEndpoint.EndpointId == eid)
171 {
172 configurations.erase(configDbusPath);
173 return;
174 }
175 }
176}
177
178} // namespace pldm