requester: associate Entity Manager configs with MCTP endpoints
Currently, pldmd listens for new MCTP endpoint exposed by mctpd, but
they only shows their EID, Network Id, and SupportedMessageTypes, which
cannot fulfill some requirements, e.g., get the device's name or which
board it belongs to.
In openbmc, the additional information are exposed by Entity
Manager[1][2], so add this ability to `MctpDiscovery, it queries the
association between MCTP endpoints and Entity Manager configurations
from MCTP Reactor, when a new MCTP endpoint has been register by mctpd.
Added unit test for this commit to validate the association does work,
passed.
[1]: https://github.com/openbmc/entity-manager/blob/master/schemas/mctp.json
[2]: https://gerrit.openbmc.org/c/openbmc/dbus-sensors/+/69111
Change-Id: Ibf1717f1840e527f21bd8397e747ae121e2dcd25
Signed-off-by: Unive Tien <unive.tien.wiwynn@gmail.com>
diff --git a/common/test/mocked_utils.hpp b/common/test/mocked_utils.hpp
index ad6f8dc..1cec506 100644
--- a/common/test/mocked_utils.hpp
+++ b/common/test/mocked_utils.hpp
@@ -72,4 +72,13 @@
MOCK_METHOD(pldm::utils::GetSubTreePathsResponse, getSubTreePaths,
(const std::string&, int, const std::vector<std::string>&),
(const override));
+
+ MOCK_METHOD(pldm::utils::GetAssociatedSubTreeResponse, getAssociatedSubTree,
+ (const sdbusplus::message::object_path&,
+ const sdbusplus::message::object_path&, int,
+ const std::vector<std::string>&),
+ (const override));
+
+ MOCK_METHOD(pldm::utils::PropertyMap, getDbusPropertiesVariant,
+ (const char*, const char*, const char*), (const override));
};
diff --git a/common/types.hpp b/common/types.hpp
index 3c3613d..68d3c3c 100644
--- a/common/types.hpp
+++ b/common/types.hpp
@@ -32,14 +32,19 @@
*/
using NetworkId = uint32_t;
+/** @brief Type definition of MCTP name in string
+ */
+using MctpInfoName = std::optional<std::string>;
+
/** @brief Type definition of MCTP interface information between two endpoints.
* eid : Endpoint EID in byte. Defined to match with MCTP D-Bus
* interface
* UUID : Endpoint UUID which is used to different the endpoints
* MctpMedium: Endpoint MCTP Medium info (Resersed)
* NetworkId: MCTP network index
+ * name: Alias name of the endpoint, e.g. BMC, NIC, etc.
*/
-using MctpInfo = std::tuple<eid, UUID, MctpMedium, NetworkId>;
+using MctpInfo = std::tuple<eid, UUID, MctpMedium, NetworkId, MctpInfoName>;
/** @brief Type definition of MCTP endpoint D-Bus properties in
* xyz.openbmc_project.MCTP.Endpoint D-Bus interface.
@@ -79,9 +84,9 @@
using Interfaces = std::vector<std::string>;
using Property = std::string;
using PropertyType = std::string;
-using Value =
- std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t,
- uint64_t, double, std::string, std::vector<uint8_t>>;
+using Value = std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
+ int64_t, uint64_t, double, std::string,
+ std::vector<uint8_t>, std::vector<uint64_t>>;
using PropertyMap = std::map<Property, Value>;
using InterfaceMap = std::map<Interface, PropertyMap>;
@@ -89,6 +94,10 @@
} // namespace dbus
+/** @brief Binding of MCTP endpoint EID to Entity Manager's D-Bus object path
+ */
+using Configurations = std::map<dbus::ObjectPath, MctpInfo>;
+
namespace fw_update
{
diff --git a/common/utils.cpp b/common/utils.cpp
index 59b5d23..06c256c 100644
--- a/common/utils.cpp
+++ b/common/utils.cpp
@@ -408,6 +408,22 @@
return bus.call(method, dbusTimeout).unpack<PropertyValue>();
}
+GetAssociatedSubTreeResponse DBusHandler::getAssociatedSubTree(
+ const sdbusplus::message::object_path& objectPath,
+ const sdbusplus::message::object_path& subtree, int depth,
+ const std::vector<std::string>& ifaceList) const
+{
+ auto& bus = DBusHandler::getBus();
+ auto method = bus.new_method_call(
+ ObjectMapper::default_service, ObjectMapper::instance_path,
+ ObjectMapper::interface, "GetAssociatedSubTree");
+ method.append(objectPath, subtree, depth, ifaceList);
+ auto reply = bus.call(method, dbusTimeout);
+ GetAssociatedSubTreeResponse response;
+ reply.read(response);
+ return response;
+}
+
ObjectValueTree DBusHandler::getManagedObj(const char* service,
const char* rootPath)
{
diff --git a/common/utils.hpp b/common/utils.hpp
index 9964188..358d0d7 100644
--- a/common/utils.hpp
+++ b/common/utils.hpp
@@ -72,6 +72,7 @@
constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
constexpr auto mapperService = ObjectMapper::default_service;
constexpr auto inventoryPath = "/xyz/openbmc_project/inventory";
+
/** @struct CustomFD
*
* RAII wrapper for file descriptor.
@@ -174,7 +175,7 @@
using PropertyValue =
std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t,
uint64_t, double, std::string, std::vector<uint8_t>,
- std::vector<std::string>>;
+ std::vector<uint64_t>, std::vector<std::string>>;
using DbusProp = std::string;
using DbusChangedProps = std::map<DbusProp, PropertyValue>;
using DBusInterfaceAdded = std::vector<
@@ -194,6 +195,8 @@
using MapperServiceMap = std::vector<std::pair<ServiceName, Interfaces>>;
using GetSubTreeResponse = std::vector<std::pair<ObjectPath, MapperServiceMap>>;
using GetSubTreePathsResponse = std::vector<std::string>;
+using GetAssociatedSubTreeResponse =
+ std::map<std::string, std::map<std::string, std::vector<std::string>>>;
using GetAncestorsResponse =
std::vector<std::pair<ObjectPath, MapperServiceMap>>;
using PropertyMap = std::map<std::string, PropertyValue>;
@@ -232,6 +235,11 @@
virtual PropertyMap getDbusPropertiesVariant(
const char* serviceName, const char* objPath,
const char* dbusInterface) const = 0;
+
+ virtual GetAssociatedSubTreeResponse getAssociatedSubTree(
+ const sdbusplus::message::object_path& objectPath,
+ const sdbusplus::message::object_path& subtree, int depth,
+ const std::vector<std::string>& ifaceList) const = 0;
};
/**
@@ -362,6 +370,19 @@
return std::get<Property>(VariantValue);
}
+ /** @brief Get the associated subtree from the mapper
+ *
+ * @param[in] path - The D-Bus object path
+ *
+ * @param[in] interface - The D-Bus interface
+ *
+ * @return GetAssociatedSubtreeResponse - The associated subtree
+ */
+ GetAssociatedSubTreeResponse getAssociatedSubTree(
+ const sdbusplus::message::object_path& objectPath,
+ const sdbusplus::message::object_path& subtree, int depth,
+ const std::vector<std::string>& ifaceList) const override;
+
/** @brief Set Dbus property
*
* @param[in] dBusMap - Object path, property name, interface and property
diff --git a/libpldmresponder/fru.hpp b/libpldmresponder/fru.hpp
index 490f5d1..d4e0ff4 100644
--- a/libpldmresponder/fru.hpp
+++ b/libpldmresponder/fru.hpp
@@ -24,9 +24,10 @@
namespace dbus
{
-using Value = std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
- int64_t, uint64_t, double, std::string,
- std::vector<uint8_t>, std::vector<std::string>>;
+using Value =
+ std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t,
+ uint64_t, double, std::string, std::vector<uint8_t>,
+ std::vector<uint64_t>, std::vector<std::string>>;
using PropertyMap = std::map<Property, Value>;
using InterfaceMap = std::map<Interface, PropertyMap>;
using ObjectValueTree = std::map<sdbusplus::message::object_path, InterfaceMap>;
diff --git a/platform-mc/test/event_manager_test.cpp b/platform-mc/test/event_manager_test.cpp
index bb4706f..79aa0f4 100644
--- a/platform-mc/test/event_manager_test.cpp
+++ b/platform-mc/test/event_manager_test.cpp
@@ -171,7 +171,8 @@
TEST_F(EventManagerTest, SetEventReceiverTest)
{
// Add terminus
- auto mappedTid = terminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
+ auto mappedTid =
+ terminusManager.mapTid(pldm::MctpInfo(10, "", "", 1, std::nullopt));
auto tid = mappedTid.value();
termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM, event);
@@ -363,7 +364,7 @@
EXPECT_EQ(rc, PLDM_SUCCESS);
terminusManager.updateMctpEndpointAvailability(
- pldm::MctpInfo(10, "", "", 1), true);
+ pldm::MctpInfo(10, "", "", 1, std::nullopt), true);
// queue SetEventReceiver response
const size_t SetEventReceiverLen = 1;
@@ -401,7 +402,8 @@
TEST_F(EventManagerTest, pollForPlatformEventTaskMultipartTransferTest)
{
// Add terminus
- auto mappedTid = terminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
+ auto mappedTid =
+ terminusManager.mapTid(pldm::MctpInfo(10, "", "", 1, std::nullopt));
auto tid = mappedTid.value();
termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM, event);
@@ -493,7 +495,7 @@
EXPECT_EQ(rc, PLDM_SUCCESS);
terminusManager.updateMctpEndpointAvailability(
- pldm::MctpInfo(10, "", "", 1), true);
+ pldm::MctpInfo(10, "", "", 1, std::nullopt), true);
EXPECT_CALL(eventManager, processCperEvent(_, _, _, _))
.Times(1)
diff --git a/platform-mc/test/platform_manager_test.cpp b/platform-mc/test/platform_manager_test.cpp
index 5f0fe35..b1353e7 100644
--- a/platform-mc/test/platform_manager_test.cpp
+++ b/platform-mc/test/platform_manager_test.cpp
@@ -35,7 +35,8 @@
TEST_F(PlatformManagerTest, initTerminusTest)
{
// Add terminus
- auto mappedTid = mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
+ auto mappedTid =
+ mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1, std::nullopt));
auto tid = mappedTid.value();
termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM, event);
@@ -184,7 +185,7 @@
EXPECT_EQ(rc, PLDM_SUCCESS);
mockTerminusManager.updateMctpEndpointAvailability(
- pldm::MctpInfo(10, "", "", 1), true);
+ pldm::MctpInfo(10, "", "", 1, std::nullopt), true);
stdexec::sync_wait(platformManager.initTerminus());
EXPECT_EQ(true, terminus->initialized);
@@ -200,7 +201,8 @@
TEST_F(PlatformManagerTest, parseTerminusNameTest)
{
// Add terminus
- auto mappedTid = mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
+ auto mappedTid =
+ mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1, std::nullopt));
auto tid = mappedTid.value();
termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM, event);
@@ -349,7 +351,7 @@
EXPECT_EQ(rc, PLDM_SUCCESS);
mockTerminusManager.updateMctpEndpointAvailability(
- pldm::MctpInfo(10, "", "", 1), true);
+ pldm::MctpInfo(10, "", "", 1, std::nullopt), true);
stdexec::sync_wait(platformManager.initTerminus());
EXPECT_EQ(true, terminus->initialized);
@@ -360,7 +362,8 @@
TEST_F(PlatformManagerTest, initTerminusDontSupportGetPDRTest)
{
// Add terminus
- auto mappedTid = mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
+ auto mappedTid =
+ mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1, std::nullopt));
auto tid = mappedTid.value();
termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM, event);
@@ -478,7 +481,8 @@
TEST_F(PlatformManagerTest, negativeInitTerminusTest1)
{
// terminus doesn't Type2 support
- auto mappedTid = mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
+ auto mappedTid =
+ mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1, std::nullopt));
auto tid = mappedTid.value();
termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
tid, 1 << PLDM_BASE, event);
@@ -496,7 +500,8 @@
TEST_F(PlatformManagerTest, negativeInitTerminusTest2)
{
// terminus responses error
- auto mappedTid = mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1));
+ auto mappedTid =
+ mockTerminusManager.mapTid(pldm::MctpInfo(10, "", "", 1, std::nullopt));
auto tid = mappedTid.value();
termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
tid, 1 << PLDM_BASE | 1 << PLDM_PLATFORM, event);
diff --git a/platform-mc/test/terminus_manager_test.cpp b/platform-mc/test/terminus_manager_test.cpp
index 52abfc8..85ecb57 100644
--- a/platform-mc/test/terminus_manager_test.cpp
+++ b/platform-mc/test/terminus_manager_test.cpp
@@ -52,7 +52,7 @@
TEST_F(TerminusManagerTest, mapTidTest)
{
- pldm::MctpInfo mctpInfo1(8, "", "", 0);
+ pldm::MctpInfo mctpInfo1(8, "", "", 0, std::nullopt);
auto mappedTid1 = terminusManager.mapTid(mctpInfo1);
EXPECT_NE(mappedTid1, std::nullopt);
@@ -73,38 +73,38 @@
TEST_F(TerminusManagerTest, negativeMapTidTest)
{
// map null EID(0) to TID
- pldm::MctpInfo m0(0, "", "", 0);
+ pldm::MctpInfo m0(0, "", "", 0, std::nullopt);
auto mappedTid = terminusManager.mapTid(m0);
EXPECT_EQ(mappedTid, std::nullopt);
// map broadcast EID(0xff) to TID
- pldm::MctpInfo m1(0xff, "", "", 0);
+ pldm::MctpInfo m1(0xff, "", "", 0, std::nullopt);
mappedTid = terminusManager.mapTid(m1);
EXPECT_EQ(mappedTid, std::nullopt);
// map EID to tid which has been assigned
- pldm::MctpInfo m2(9, "", "", 1);
- pldm::MctpInfo m3(10, "", "", 1);
+ pldm::MctpInfo m2(9, "", "", 1, std::nullopt);
+ pldm::MctpInfo m3(10, "", "", 1, std::nullopt);
auto mappedTid2 = terminusManager.mapTid(m2);
auto mappedTid3 = terminusManager.storeTerminusInfo(m3, mappedTid2.value());
EXPECT_NE(mappedTid2, std::nullopt);
EXPECT_EQ(mappedTid3, std::nullopt);
// map two mctpInfo with same EID but different network Id
- pldm::MctpInfo m4(12, "", "", 1);
- pldm::MctpInfo m5(12, "", "", 2);
+ pldm::MctpInfo m4(12, "", "", 1, std::nullopt);
+ pldm::MctpInfo m5(12, "", "", 2, std::nullopt);
auto mappedTid4 = terminusManager.mapTid(m4);
auto mappedTid5 = terminusManager.mapTid(m5);
EXPECT_NE(mappedTid4.value(), mappedTid5.value());
// map same mctpInfo twice
- pldm::MctpInfo m6(12, "", "", 3);
+ pldm::MctpInfo m6(12, "", "", 3, std::nullopt);
auto mappedTid6 = terminusManager.mapTid(m6);
auto mappedTid6_1 = terminusManager.mapTid(m6);
EXPECT_EQ(mappedTid6.value(), mappedTid6_1.value());
// look up an unmapped MctpInfo to TID
- pldm::MctpInfo m7(1, "", "", 0);
+ pldm::MctpInfo m7(1, "", "", 0, std::nullopt);
auto mappedTid7 = terminusManager.toTid(m7);
EXPECT_EQ(mappedTid7, std::nullopt);
@@ -158,7 +158,7 @@
EXPECT_EQ(rc, PLDM_SUCCESS);
pldm::MctpInfos mctpInfos{};
- mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
+ mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1, std::nullopt));
mockTerminusManager.discoverMctpTerminus(mctpInfos);
EXPECT_EQ(1, termini.size());
@@ -203,7 +203,7 @@
EXPECT_EQ(rc, PLDM_SUCCESS);
pldm::MctpInfos mctpInfos{};
- mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
+ mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1, std::nullopt));
mockTerminusManager.discoverMctpTerminus(mctpInfos);
EXPECT_EQ(0, termini.size());
@@ -279,7 +279,7 @@
EXPECT_EQ(rc, PLDM_SUCCESS);
pldm::MctpInfos mctpInfos{};
- mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
+ mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1, std::nullopt));
mockTerminusManager.discoverMctpTerminus(mctpInfos);
EXPECT_EQ(1, termini.size());
@@ -465,7 +465,7 @@
EXPECT_EQ(rc, PLDM_SUCCESS);
pldm::MctpInfos mctpInfos{};
- mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1));
+ mctpInfos.emplace_back(pldm::MctpInfo(12, "", "", 1, std::nullopt));
mockTerminusManager.discoverMctpTerminus(mctpInfos);
EXPECT_EQ(1, termini.size());
EXPECT_EQ(true, termini.contains(1));
@@ -544,7 +544,7 @@
TEST_F(TerminusManagerTest, getActiveEidByNameTest)
{
// Add terminus
- pldm::MctpInfo mctpInfo(10, "", "", 1);
+ pldm::MctpInfo mctpInfo(10, "", "", 1, std::nullopt);
auto mappedTid = mockTerminusManager.mapTid(mctpInfo);
auto tid = mappedTid.value();
termini[tid] = std::make_shared<pldm::platform_mc::Terminus>(
diff --git a/requester/mctp_endpoint_discovery.cpp b/requester/mctp_endpoint_discovery.cpp
index 6833684..ac1277f 100644
--- a/requester/mctp_endpoint_discovery.cpp
+++ b/requester/mctp_endpoint_discovery.cpp
@@ -83,9 +83,11 @@
if (std::find(types.begin(), types.end(), mctpTypePLDM) !=
types.end())
{
- mctpInfoMap[MctpInfo(std::get<eid>(epProps), uuid, "",
- std::get<NetworkId>(epProps))] =
- availability;
+ auto mctpInfo =
+ MctpInfo(std::get<eid>(epProps), uuid, "",
+ std::get<NetworkId>(epProps), std::nullopt);
+ searchConfigurationFor(pldm::utils::DBusHandler(), mctpInfo);
+ mctpInfoMap[std::move(mctpInfo)] = availability;
}
}
}
@@ -231,7 +233,11 @@
info(
"Adding Endpoint networkId '{NETWORK}' and EID '{EID}' UUID '{UUID}'",
"NETWORK", networkId, "EID", eid, "UUID", uuid);
- mctpInfos.emplace_back(MctpInfo(eid, uuid, "", networkId));
+ auto mctpInfo =
+ MctpInfo(eid, uuid, "", networkId, std::nullopt);
+ searchConfigurationFor(pldm::utils::DBusHandler(),
+ mctpInfo);
+ mctpInfos.emplace_back(std::move(mctpInfo));
}
}
}
@@ -316,7 +322,8 @@
const UUID& uuid = getEndpointUUIDProp(service, objPath);
MctpInfo mctpInfo(std::get<eid>(epProps), uuid, "",
- std::get<NetworkId>(epProps));
+ std::get<NetworkId>(epProps), std::nullopt);
+ searchConfigurationFor(pldm::utils::DBusHandler(), mctpInfo);
if (!std::ranges::contains(existingMctpInfos, mctpInfo))
{
if (availability)
@@ -360,6 +367,7 @@
}
removeFromExistingMctpInfos(mctpInfos, removedInfos);
handleRemovedMctpEndpoints(removedInfos);
+ removeConfigs(removedInfos);
}
void MctpDiscovery::handleMctpEndpoints(const MctpInfos& mctpInfos)
@@ -368,6 +376,7 @@
{
if (handler)
{
+ handler->handleConfigurations(configurations);
handler->handleMctpEndpoints(mctpInfos);
}
}
@@ -396,4 +405,105 @@
}
}
+std::string MctpDiscovery::getNameFromProperties(
+ const utils::PropertyMap& properties)
+{
+ if (!properties.contains("Name"))
+ {
+ error("Missing name property");
+ return "";
+ }
+ return std::get<std::string>(properties.at("Name"));
+}
+
+std::string MctpDiscovery::constructMctpReactorObjectPath(
+ const MctpInfo& mctpInfo)
+{
+ const auto networkId = std::get<NetworkId>(mctpInfo);
+ const auto eid = std::get<pldm::eid>(mctpInfo);
+ return std::string{MCTPPath} + "/networks/" + std::to_string(networkId) +
+ "/endpoints/" + std::to_string(eid) + "/configured_by";
+}
+
+void MctpDiscovery::searchConfigurationFor(
+ const pldm::utils::DBusHandler& handler, MctpInfo& mctpInfo)
+{
+ const auto mctpReactorObjectPath = constructMctpReactorObjectPath(mctpInfo);
+ try
+ {
+ std::string associatedObjPath;
+ std::string associatedService;
+ std::string associatedInterface;
+ sdbusplus::message::object_path inventorySubtreePath(
+ inventorySubtreePathStr);
+
+ //"/{board or chassis type}/{board or chassis}/{device}"
+ auto constexpr subTreeDepth = 3;
+ auto response = handler.getAssociatedSubTree(
+ mctpReactorObjectPath, inventorySubtreePath, subTreeDepth,
+ interfaceFilter);
+ if (response.empty())
+ {
+ warning("No associated subtree found for path {PATH}", "PATH",
+ mctpReactorObjectPath);
+ return;
+ }
+ // Assume the first entry is the one we want
+ auto subTree = response.begin();
+ associatedObjPath = subTree->first;
+ auto associatedServiceProp = subTree->second;
+ if (associatedServiceProp.empty())
+ {
+ warning("No associated service found for path {PATH}", "PATH",
+ mctpReactorObjectPath);
+ return;
+ }
+ // Assume the first entry is the one we want
+ auto entry = associatedServiceProp.begin();
+ associatedService = entry->first;
+ auto dBusIntfList = entry->second;
+ auto associatedInterfaceItr = std::find_if(
+ dBusIntfList.begin(), dBusIntfList.end(), [](const auto& intf) {
+ return std::find(interfaceFilter.begin(), interfaceFilter.end(),
+ intf) != interfaceFilter.end();
+ });
+ if (associatedInterfaceItr == dBusIntfList.end())
+ {
+ error("No associated interface found for path {PATH}", "PATH",
+ mctpReactorObjectPath);
+ return;
+ }
+ associatedInterface = *associatedInterfaceItr;
+ auto mctpTargetProperties = handler.getDbusPropertiesVariant(
+ associatedService.c_str(), associatedObjPath.c_str(),
+ associatedInterface.c_str());
+ auto name = getNameFromProperties(mctpTargetProperties);
+ if (!name.empty())
+ {
+ std::get<std::optional<std::string>>(mctpInfo) = name;
+ }
+ configurations.emplace(associatedObjPath, mctpInfo);
+ }
+ catch (const std::exception& e)
+ {
+ error(
+ "Error getting associated subtree for path {PATH}, error - {ERROR}",
+ "PATH", mctpReactorObjectPath, "ERROR", e);
+ return;
+ }
+}
+
+void MctpDiscovery::removeConfigs(const MctpInfos& removedInfos)
+{
+ for (const auto& mctpInfo : removedInfos)
+ {
+ auto eidToRemove = std::get<eid>(mctpInfo);
+ std::erase_if(configurations, [eidToRemove](const auto& config) {
+ auto& [__, mctpInfo] = config;
+ auto eidValue = std::get<eid>(mctpInfo);
+ return eidValue == eidToRemove;
+ });
+ }
+}
+
} // namespace pldm
diff --git a/requester/mctp_endpoint_discovery.hpp b/requester/mctp_endpoint_discovery.hpp
index 026e155..7692849 100644
--- a/requester/mctp_endpoint_discovery.hpp
+++ b/requester/mctp_endpoint_discovery.hpp
@@ -11,6 +11,8 @@
#include <initializer_list>
#include <vector>
+class TestMctpDiscovery;
+
namespace pldm
{
@@ -21,6 +23,12 @@
constexpr const char* MCTPPath = "/au/com/codeconstruct/mctp1";
constexpr const char* MCTPInterfaceCC = "au.com.codeconstruct.MCTP.Endpoint1";
constexpr const char* MCTPConnectivityProp = "Connectivity";
+constexpr const char* inventorySubtreePathStr =
+ "/xyz/openbmc_project/inventory/system";
+
+const std::vector<std::string> interfaceFilter = {
+ "xyz.openbmc_project.Configuration.MCTPI2CTarget",
+ "xyz.openbmc_project.Configuration.MCTPI3CTarget"};
/** @class MctpDiscoveryHandlerIntf
*
@@ -42,6 +50,8 @@
virtual std::optional<mctp_eid_t> getActiveEidByName(
const std::string& terminusName) = 0;
+ virtual void handleConfigurations(const Configurations& /*configurations*/)
+ {}
virtual ~MctpDiscoveryHandlerIntf() {}
};
@@ -156,6 +166,8 @@
void removeFromExistingMctpInfos(MctpInfos& mctpInfos,
MctpInfos& removedInfos);
+ friend class ::TestMctpDiscovery;
+
private:
/** @brief Get MCTP Endpoint D-Bus Properties in the
* `xyz.openbmc_project.MCTP.Endpoint` D-Bus interface
@@ -190,6 +202,39 @@
Availability getEndpointConnectivityProp(const std::string& path);
static constexpr uint8_t mctpTypePLDM = 1;
+
+ /** @brief Construct the MCTP reactor object path
+ *
+ * @param[in] mctpInfo - information of discovered MCTP endpoint
+ *
+ * @return the MCTP reactor object path
+ */
+ std::string constructMctpReactorObjectPath(const MctpInfo& mctpInfo);
+
+ /** @brief Search for associated configuration for the MctpInfo.
+ *
+ * @param[in] mctpInfo - information of discovered MCTP endpoint
+ */
+ void searchConfigurationFor(const pldm::utils::DBusHandler& handler,
+ MctpInfo& mctpInfo);
+
+ /** @brief Remove configuration associated with the removed MCTP endpoint.
+ *
+ * @param[in] removedInfos - the removed MCTP endpoints
+ */
+ void removeConfigs(const MctpInfos& removedInfos);
+
+ /** @brief An internal helper function to get the name property from the
+ * properties
+ * @param[in] properties - the properties of the D-Bus object
+ * @return the name property
+ */
+ std::string getNameFromProperties(const utils::PropertyMap& properties);
+
+ /** @brief The configuration contains D-Bus path and the MCTP endpoint
+ * information.
+ */
+ Configurations configurations;
};
} // namespace pldm
diff --git a/requester/test/mctp_endpoint_discovery_test.cpp b/requester/test/mctp_endpoint_discovery_test.cpp
index 01e5eb0..3647d11 100644
--- a/requester/test/mctp_endpoint_discovery_test.cpp
+++ b/requester/test/mctp_endpoint_discovery_test.cpp
@@ -1,5 +1,6 @@
#include "config.h"
+#include "common/test/mocked_utils.hpp"
#include "common/types.hpp"
#include "common/utils.hpp"
#include "requester/test/mock_mctp_discovery_handler_intf.hpp"
@@ -9,6 +10,22 @@
using ::testing::_;
+class TestMctpDiscovery : public ::testing::Test
+{
+ public:
+ static const pldm::Configurations& getConfigurations(
+ const pldm::MctpDiscovery& mctpDiscovery)
+ {
+ return mctpDiscovery.configurations;
+ }
+ static void searchConfigurationFor(pldm::MctpDiscovery& mctpDiscovery,
+ pldm::utils::DBusHandler& handler,
+ pldm::MctpInfo& mctpInfo)
+ {
+ mctpDiscovery.searchConfigurationFor(handler, mctpInfo);
+ }
+};
+
TEST(MctpEndpointDiscoveryTest, SingleHandleMctpEndpoint)
{
auto& bus = pldm::utils::DBusHandler::getBus();
@@ -53,8 +70,8 @@
auto& bus = pldm::utils::DBusHandler::getBus();
pldm::MockManager manager;
const pldm::MctpInfos& mctpInfos = {
- pldm::MctpInfo(11, pldm::emptyUUID, "", 1),
- pldm::MctpInfo(12, pldm::emptyUUID, "abc", 1)};
+ pldm::MctpInfo(11, pldm::emptyUUID, "", 1, std::nullopt),
+ pldm::MctpInfo(12, pldm::emptyUUID, "abc", 1, std::nullopt)};
auto mctpDiscoveryHandler = std::make_unique<pldm::MctpDiscovery>(
bus, std::initializer_list<pldm::MctpDiscoveryHandlerIntf*>{&manager});
@@ -71,7 +88,7 @@
auto& bus = pldm::utils::DBusHandler::getBus();
pldm::MockManager manager;
const pldm::MctpInfos& mctpInfos = {
- pldm::MctpInfo(11, pldm::emptyUUID, "", 1)};
+ pldm::MctpInfo(11, pldm::emptyUUID, "", 1, std::nullopt)};
auto mctpDiscoveryHandler = std::make_unique<pldm::MctpDiscovery>(
bus, std::initializer_list<pldm::MctpDiscoveryHandlerIntf*>{&manager});
@@ -84,8 +101,8 @@
auto& bus = pldm::utils::DBusHandler::getBus();
pldm::MockManager manager;
const pldm::MctpInfos& mctpInfos = {
- pldm::MctpInfo(11, pldm::emptyUUID, "def", 2),
- pldm::MctpInfo(12, pldm::emptyUUID, "abc", 1)};
+ pldm::MctpInfo(11, pldm::emptyUUID, "def", 2, std::nullopt),
+ pldm::MctpInfo(12, pldm::emptyUUID, "abc", 1, std::nullopt)};
auto mctpDiscoveryHandler = std::make_unique<pldm::MctpDiscovery>(
bus, std::initializer_list<pldm::MctpDiscoveryHandlerIntf*>{&manager});
@@ -97,7 +114,8 @@
EXPECT_EQ(std::get<3>(mctpInfo), 1);
pldm::MctpInfos removedInfos;
pldm::MctpInfos remainMctpInfos;
- remainMctpInfos.emplace_back(pldm::MctpInfo(12, pldm::emptyUUID, "abc", 1));
+ remainMctpInfos.emplace_back(
+ pldm::MctpInfo(12, pldm::emptyUUID, "abc", 1, std::nullopt));
mctpDiscoveryHandler->removeFromExistingMctpInfos(remainMctpInfos,
removedInfos);
@@ -118,8 +136,8 @@
auto& bus = pldm::utils::DBusHandler::getBus();
pldm::MockManager manager;
const pldm::MctpInfos& mctpInfos = {
- pldm::MctpInfo(11, pldm::emptyUUID, "def", 2),
- pldm::MctpInfo(12, pldm::emptyUUID, "abc", 1)};
+ pldm::MctpInfo(11, pldm::emptyUUID, "def", 2, std::nullopt),
+ pldm::MctpInfo(12, pldm::emptyUUID, "abc", 1, std::nullopt)};
auto mctpDiscoveryHandler = std::make_unique<pldm::MctpDiscovery>(
bus, std::initializer_list<pldm::MctpDiscoveryHandlerIntf*>{&manager});
@@ -136,3 +154,90 @@
mctpDiscoveryHandler->removeEndpoints(msg);
EXPECT_EQ(mctpDiscoveryHandler->existingMctpInfos.size(), 0);
}
+
+TEST(MctpEndpointDiscoveryTest, goodSearchConfigurationFor)
+{
+ MockdBusHandler mockedDbusHandler;
+ auto& bus = mockedDbusHandler.getBus();
+ pldm::MockManager manager;
+ const pldm::MctpInfos& mctpInfos = {
+ pldm::MctpInfo(10, pldm::emptyUUID, "abc", 1, std::nullopt)};
+
+ constexpr auto mockedDbusPath =
+ "/xyz/openbmc_project/inventory/system/board/Mocked_Board_Slot_1/MockedDevice";
+ constexpr auto mockedService = "xyz.openbmc_project.EntityManager";
+ std::vector<std::string> mockedInterfaces{
+ "xyz.openbmc_project.Configuration.MCTPI2CTarget",
+ "xyz.openbmc_project.Configuration.MCTPI3CTarget"};
+
+ pldm::utils::GetAssociatedSubTreeResponse
+ mockedGetAssociatedSubTreeResponse{
+ {mockedDbusPath, {{mockedService, mockedInterfaces}}}};
+
+ EXPECT_CALL(mockedDbusHandler, getAssociatedSubTree(_, _, _, _))
+ .WillOnce(testing::Return(mockedGetAssociatedSubTreeResponse));
+
+ pldm::utils::PropertyMap mockGetI2CTargetPropertiesResponse{
+ {"Address", uint64_t(0x1)},
+ {"Bus", uint64_t(0)},
+ {"Name", std::string("MockedDevice")}};
+
+ EXPECT_CALL(mockedDbusHandler, getDbusPropertiesVariant(_, _, _))
+ .WillOnce(testing::Return(mockGetI2CTargetPropertiesResponse));
+
+ auto mctpDiscoveryHandler = std::make_unique<pldm::MctpDiscovery>(
+ bus, std::initializer_list<pldm::MctpDiscoveryHandlerIntf*>{&manager});
+ mctpDiscoveryHandler->addToExistingMctpInfos(mctpInfos);
+ EXPECT_EQ(mctpDiscoveryHandler->existingMctpInfos.size(), 1);
+ pldm::MctpInfo mctpInfo = mctpDiscoveryHandler->existingMctpInfos.back();
+ EXPECT_EQ(std::get<0>(mctpInfo), 10);
+ EXPECT_EQ(std::get<2>(mctpInfo), "abc");
+ EXPECT_EQ(std::get<3>(mctpInfo), 1);
+ TestMctpDiscovery::searchConfigurationFor(*mctpDiscoveryHandler,
+ mockedDbusHandler, mctpInfo);
+ EXPECT_EQ(std::get<4>(mctpInfo),
+ std::optional<std::string>("MockedDevice"));
+ auto configuration =
+ TestMctpDiscovery::getConfigurations(*mctpDiscoveryHandler);
+ EXPECT_EQ(configuration.size(), 1);
+}
+
+TEST(MctpEndpointDiscoveryTest, badSearchConfigurationFor)
+{
+ MockdBusHandler mockedDbusHandler;
+ auto& bus = mockedDbusHandler.getBus();
+ pldm::MockManager manager;
+ const pldm::MctpInfos& mctpInfos = {
+ pldm::MctpInfo(10, pldm::emptyUUID, "abc", 1, std::nullopt)};
+
+ constexpr auto mockedDbusPath =
+ "/xyz/openbmc_project/inventory/system/board/Mocked_Board_Slot_1/MockedDevice";
+ constexpr auto mockedService = "xyz.openbmc_project.EntityManager";
+ std::vector<std::string> mockedInterfaces{
+ "xyz.openbmc_project.Configuration.MCTPPCIETarget",
+ "xyz.openbmc_project.Configuration.MCTPUSBTarget"};
+
+ pldm::utils::GetAssociatedSubTreeResponse
+ mockedGetAssociatedSubTreeResponse{
+ {mockedDbusPath, {{mockedService, mockedInterfaces}}}};
+
+ EXPECT_CALL(mockedDbusHandler, getAssociatedSubTree(_, _, _, _))
+ .WillOnce(testing::Return(mockedGetAssociatedSubTreeResponse));
+
+ pldm::utils::PropertyMap mockGetI2CTargetPropertiesResponse{
+ {"Address", uint64_t(0x1)}, {"Bus", uint64_t(0)}};
+
+ auto mctpDiscoveryHandler = std::make_unique<pldm::MctpDiscovery>(
+ bus, std::initializer_list<pldm::MctpDiscoveryHandlerIntf*>{&manager});
+ mctpDiscoveryHandler->addToExistingMctpInfos(mctpInfos);
+ EXPECT_EQ(mctpDiscoveryHandler->existingMctpInfos.size(), 1);
+ pldm::MctpInfo mctpInfo = mctpDiscoveryHandler->existingMctpInfos.back();
+ EXPECT_EQ(std::get<0>(mctpInfo), 10);
+ EXPECT_EQ(std::get<2>(mctpInfo), "abc");
+ EXPECT_EQ(std::get<3>(mctpInfo), 1);
+ TestMctpDiscovery::searchConfigurationFor(*mctpDiscoveryHandler,
+ mockedDbusHandler, mctpInfo);
+ auto configuration =
+ TestMctpDiscovery::getConfigurations(*mctpDiscoveryHandler);
+ EXPECT_EQ(configuration.size(), 0);
+}