| #include "network_adapter.hpp" | |
| #include <cstdint> | |
| #include <limits> | |
| #include <memory> | |
| #include <optional> | |
| #include <string> | |
| #include <vector> | |
| #include <gmock/gmock.h> | |
| #include <gtest/gtest.h> | |
| #include "http_response.hpp" | |
| #include "dbus_utility.hpp" | |
| #include "dbus_utils.hpp" | |
| #include "test/redfish-core/lib/snapshot_fixture.hpp" | |
| #include <nlohmann/json.hpp> | |
| #include "managed_store.hpp" | |
| #include "managed_store_types.hpp" | |
| #include "test/g3/mock_managed_store.hpp" | |
| #include "test/g3/mock_managed_store_test.hpp" | |
| #include "sdbusplus/message/native_types.hpp" | |
| namespace redfish { | |
| namespace { | |
| using ::dbus::utility::DBusInteracesMap; | |
| using ::dbus::utility::DBusPropertiesMap; | |
| using ::dbus::utility::DbusVariantType; | |
| using ::dbus::utility::ManagedObjectType; | |
| using ::dbus::utility::MapperGetSubTreePathsResponse; | |
| using ::managedStore::KeyType; | |
| using ::managedStore::ManagedType; | |
| using ::managedStore::ValueType; | |
| using ::testing::Contains; | |
| MapperGetSubTreePathsResponse CreateMockNcsiSubTree() { | |
| return MapperGetSubTreePathsResponse( | |
| {"/xyz/openbmc_project/inventory/system/cable/NcsiCable/ncsi"}); | |
| } | |
| class NetworkAdapterTest : public SnapshotFixture { | |
| protected: | |
| void SetUp() override { | |
| SnapshotFixture::SetUp(); | |
| ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance() | |
| .SetHasBmcDirectEthernet(false); | |
| } | |
| void TearDown() override { | |
| ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance() | |
| .SetHasBmcDirectEthernet(false); | |
| SnapshotFixture::TearDown(); | |
| } | |
| }; | |
| TEST_F(NetworkAdapterTest, GetNetworkAdaptersReturnsCorrectResponse) { | |
| handleChassisNetworkAdapterCollectionGetSysfs(share_async_resp_, | |
| "chassis1V2ND"); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters"); | |
| EXPECT_EQ(json["@odata.type"], | |
| "#NetworkAdapterCollection.NetworkAdapterCollection"); | |
| EXPECT_EQ(json["Name"], | |
| "Network adapter Collection for chassis chassis1V2ND"); | |
| EXPECT_THAT(json["Members"], | |
| Contains(nlohmann::json( | |
| {{"@odata.id", | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0"}}))); | |
| EXPECT_EQ(json["Members@odata.count"], 1); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkAdapterReturnsCorrectResponse) { | |
| handleChassisNetworkAdapterGetSysfs(share_async_resp_, "chassis1V2ND", "0"); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0"); | |
| EXPECT_EQ(json["@odata.type"], "#NetworkAdapter.NetworkAdapter"); | |
| EXPECT_EQ(json["Name"], "Network adapter"); | |
| EXPECT_EQ(json["Ports"]["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports"); | |
| } | |
| TEST_F(NetworkAdapterTest, GetPortCollectionReturnsCorrectResponse) { | |
| handleNetworkPortCollectionGetSysfs(share_async_resp_, "chassis1V2ND", "0"); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports"); | |
| EXPECT_EQ(json["@odata.type"], "#PortCollection.PortCollection"); | |
| EXPECT_THAT(json["Members"], | |
| Contains(nlohmann::json({{"@odata.id", | |
| "/redfish/v1/Chassis/chassis1V2ND/" | |
| "NetworkAdapters/0/Ports/ncsi"}}))); | |
| EXPECT_THAT(json["Members"], | |
| Contains(nlohmann::json({{"@odata.id", | |
| "/redfish/v1/Chassis/chassis1V2ND/" | |
| "NetworkAdapters/0/Ports/gusbem0"}}))); | |
| EXPECT_THAT(json["Members"], | |
| Contains(nlohmann::json({{"@odata.id", | |
| "/redfish/v1/Chassis/chassis1V2ND/" | |
| "NetworkAdapters/0/Ports/front"}}))); | |
| EXPECT_THAT( | |
| json["Members"], | |
| Contains(nlohmann::json({{"@odata.id", | |
| "/redfish/v1/Chassis/chassis1V2ND/" | |
| "NetworkAdapters/0/Ports/enu1u1u1u1"}}))); | |
| EXPECT_EQ(json["Members@odata.count"], 4); | |
| EXPECT_EQ(json["Name"], "Network ports"); | |
| } | |
| TEST_F(NetworkAdapterTest, GetPortsReturnsCorrectResponse1) { | |
| KeyType key(ManagedType::kManagedSubtreePaths, | |
| "/xyz/openbmc_project/inventory/system/cable/", 0, | |
| {"xyz.openbmc_project.Configuration.Port"}); | |
| std::shared_ptr<ValueType> mockNcsiSubTreeResponse = | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| CreateMockNcsiSubTree()); | |
| ASSERT_TRUE( | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()) | |
| ->upsertMockObjectIntoManagedStore(key, mockNcsiSubTreeResponse) | |
| .ok()); | |
| handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0", "ncsi"); | |
| RunIoUntilDone(); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/ncsi"); | |
| EXPECT_EQ(json["@odata.type"], "#Port.Port"); | |
| EXPECT_EQ(json["Id"], "ncsi"); | |
| EXPECT_EQ(json["CurrentSpeedGbps"], 0.1); | |
| EXPECT_EQ(json["Name"], "ncsi"); | |
| EXPECT_THAT(json["Ethernet"]["AssociatedMACAddresses"], | |
| Contains("24:95:2f:8f:18:0c")); | |
| EXPECT_EQ(json["Ethernet"]["AssociatedMACAddresses"].size(), 1); | |
| EXPECT_EQ(json["LinkState"], "Enabled"); | |
| EXPECT_EQ(json["LinkStatus"], "LinkUp"); | |
| EXPECT_EQ(json["Oem"]["Google"]["ConnectionPath"], "SIDE"); | |
| EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "NCSI"); | |
| EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"], "/phys/NCSI"); | |
| EXPECT_EQ( | |
| json["Metrics"]["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/ncsi/Metrics"); | |
| } | |
| TEST_F(NetworkAdapterTest, GetPortsReturnsCorrectResponse2) { | |
| handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0", "gusbem0"); | |
| RunIoUntilDone(); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/gusbem0"); | |
| EXPECT_EQ(json["@odata.type"], "#Port.Port"); | |
| EXPECT_EQ(json["Id"], "gusbem0"); | |
| EXPECT_EQ(json["CurrentSpeedGbps"], 0.0); | |
| EXPECT_EQ(json["Name"], "gusbem0"); | |
| EXPECT_THAT(json["Ethernet"]["AssociatedMACAddresses"], | |
| Contains("3a:1b:f6:ef:56:62")); | |
| EXPECT_EQ(json["Ethernet"]["AssociatedMACAddresses"].size(), 1); | |
| EXPECT_EQ(json["LinkState"], "Enabled"); | |
| EXPECT_EQ(json["LinkStatus"], "LinkUp"); | |
| EXPECT_EQ(json["Metrics"]["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/gusbem0/" | |
| "Metrics"); | |
| } | |
| TEST_F(NetworkAdapterTest, GetPortsReturnsCorrectResponse3) { | |
| ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance() | |
| .SetHasBmcDirectEthernet(true); | |
| KeyType key( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/board/chassis1V2ND/BmcNet"), | |
| "xyz.openbmc_project.Configuration.BmcNet", "LocationCode"); | |
| std::shared_ptr<ValueType> mockBmcNetLocation = | |
| managedStore::MockManagedStoreTest::CreateValueType("1G_LAN"); | |
| ASSERT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()) | |
| ->upsertMockObjectIntoManagedStore(key, mockBmcNetLocation) | |
| .ok()); | |
| handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0", "front"); | |
| RunIoUntilDone(); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front"); | |
| EXPECT_EQ(json["@odata.type"], "#Port.Port"); | |
| EXPECT_EQ(json["Id"], "front"); | |
| EXPECT_EQ(json["CurrentSpeedGbps"], 1); | |
| EXPECT_EQ(json["Name"], "front"); | |
| EXPECT_THAT(json["Ethernet"]["AssociatedMACAddresses"], | |
| Contains("24:95:2f:8f:18:0c")); | |
| EXPECT_EQ(json["Ethernet"]["AssociatedMACAddresses"].size(), 1); | |
| EXPECT_EQ(json["LinkState"], "Enabled"); | |
| EXPECT_EQ(json["LinkStatus"], "LinkUp"); | |
| EXPECT_EQ(json["Oem"]["Google"]["ConnectionPath"], "DIRECT"); | |
| EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "1G_LAN"); | |
| EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"], | |
| "/phys/DC_SCM/1G_LAN"); | |
| EXPECT_EQ( | |
| json["Metrics"]["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front/Metrics"); | |
| } | |
| TEST_F(NetworkAdapterTest, | |
| GetPortsReturnsCorrectResponseWithoutDirectEthernetRole) { | |
| ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance() | |
| .SetHasBmcDirectEthernet(false); | |
| KeyType key( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/board/chassis1V2ND/BmcNet"), | |
| "xyz.openbmc_project.Configuration.BmcNet", "LocationCode"); | |
| std::shared_ptr<ValueType> mockBmcNetLocation = | |
| managedStore::MockManagedStoreTest::CreateValueType("1G_LAN"); | |
| ASSERT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()) | |
| ->upsertMockObjectIntoManagedStore(key, mockBmcNetLocation) | |
| .ok()); | |
| handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0", "front"); | |
| RunIoUntilDone(); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front"); | |
| EXPECT_EQ(json["@odata.type"], "#Port.Port"); | |
| EXPECT_EQ(json["Id"], "front"); | |
| EXPECT_EQ(json["CurrentSpeedGbps"], 1); | |
| EXPECT_EQ(json["Name"], "front"); | |
| EXPECT_THAT(json["Ethernet"]["AssociatedMACAddresses"], | |
| Contains("24:95:2f:8f:18:0c")); | |
| EXPECT_EQ(json["Ethernet"]["AssociatedMACAddresses"].size(), 1); | |
| EXPECT_EQ(json["LinkState"], "Enabled"); | |
| EXPECT_EQ(json["LinkStatus"], "LinkUp"); | |
| EXPECT_FALSE(json.contains("Location")); | |
| EXPECT_FALSE(json.contains("Oem")); | |
| EXPECT_EQ( | |
| json["Metrics"]["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front/Metrics"); | |
| } | |
| TEST_F(NetworkAdapterTest, GetPortsReturnsCorrectResponse4) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| // Mock BmcNet Side Configuration for ConnectionPath | |
| managedStore::KeyType bmcNetSideKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "board/chassis1V2ND/enu1u1u1u1"), | |
| "xyz.openbmc_project.Configuration.BmcNet_Side", ""); | |
| dbus::utility::DBusPropertiesMap bmcNetSideProperties; | |
| bmcNetSideProperties.emplace_back( | |
| "LocationCode", dbus::utility::DbusVariantType("SIDEBAND_LOC")); | |
| bmcNetSideProperties.emplace_back( | |
| "PartLocationContext", | |
| dbus::utility::DbusVariantType("SIDEBAND_CONTEXT")); | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| bmcNetSideKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| bmcNetSideProperties)) | |
| .ok()); | |
| handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0", | |
| "enu1u1u1u1"); | |
| RunIoUntilDone(); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["Id"], "enu1u1u1u1"); | |
| EXPECT_EQ(json["Oem"]["Google"]["ConnectionPath"], "SIDEBAND"); | |
| EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "SIDEBAND_LOC"); | |
| EXPECT_EQ(json["Location"]["PartLocationContext"], "SIDEBAND_CONTEXT"); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortMetricReturnsCorrectResponse1) { | |
| handleNetworkPortMetricGetSysfs(share_async_resp_, "chassis1V2ND", "0", | |
| "ncsi"); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ( | |
| json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/ncsi/Metrics"); | |
| EXPECT_EQ(json["@odata.type"], "#PortMetrics.PortMetrics"); | |
| EXPECT_EQ(json["Name"], "Network port metrics"); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["CarrierChanges"], 1); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXCRCErrors"], 4); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXErrors"], 4); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPackets"], 3016523); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPacketsDropped"], 0); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortMetricReturnsCorrectResponse2) { | |
| handleNetworkPortMetricGetSysfs(share_async_resp_, "chassis1V2ND", "0", | |
| "gusbem0"); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/gusbem0/" | |
| "Metrics"); | |
| EXPECT_EQ(json["@odata.type"], "#PortMetrics.PortMetrics"); | |
| EXPECT_EQ(json["Name"], "Network port metrics"); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["CarrierChanges"], 4); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXCRCErrors"], 0); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXErrors"], 0); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPackets"], 13218); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPacketsDropped"], 0); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortMetricReturnsCorrectResponse3) { | |
| handleNetworkPortMetricGetSysfs(share_async_resp_, "chassis1V2ND", "0", | |
| "front"); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ( | |
| json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front/Metrics"); | |
| EXPECT_EQ(json["@odata.type"], "#PortMetrics.PortMetrics"); | |
| EXPECT_EQ(json["Name"], "Network port metrics"); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["CarrierChanges"], 1); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXCRCErrors"], 0); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXErrors"], 0); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPackets"], 458937); | |
| EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPacketsDropped"], 0); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortMetricDBusReturnsCorrectResponse) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| // 1. Mock port Inventory SubTree | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse portSubTree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(portSubTree)) | |
| .ok()); | |
| // 2. Mock PortECC properties | |
| managedStore::KeyType eccKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Metrics.PortECC", ""); | |
| dbus::utility::DBusPropertiesMap eccProperties; | |
| eccProperties.emplace_back("CorrectedBits", | |
| dbus::utility::DbusVariantType(uint64_t{42})); | |
| eccProperties.emplace_back("SymbolErrorRXBytes", | |
| dbus::utility::DbusVariantType(uint64_t{7})); | |
| std::vector<uint64_t> perLaneCounters = {10, 20, 30, 40}; | |
| eccProperties.emplace_back("RawErrorsPerLane", | |
| dbus::utility::DbusVariantType(perLaneCounters)); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| eccKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| eccProperties)) | |
| .ok()); | |
| // 3. Mock PortPacketCounters properties | |
| managedStore::KeyType packetKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Metrics.PortPacketCounters", ""); | |
| dbus::utility::DBusPropertiesMap packetProperties; | |
| packetProperties.emplace_back("RXBroadcastPkts", | |
| dbus::utility::DbusVariantType(uint64_t{100})); | |
| packetProperties.emplace_back("RXMulticastPkts", | |
| dbus::utility::DbusVariantType(uint64_t{200})); | |
| packetProperties.emplace_back("RXUnicastPkts", | |
| dbus::utility::DbusVariantType(uint64_t{300})); | |
| packetProperties.emplace_back("TXBroadcastPkts", | |
| dbus::utility::DbusVariantType(uint64_t{400})); | |
| packetProperties.emplace_back("TXMulticastPkts", | |
| dbus::utility::DbusVariantType(uint64_t{500})); | |
| packetProperties.emplace_back("TXUnicastPkts", | |
| dbus::utility::DbusVariantType(uint64_t{600})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| packetKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| packetProperties)) | |
| .ok()); | |
| // 4. Mock EthPort properties | |
| managedStore::KeyType ethKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Metrics.EthPort", ""); | |
| dbus::utility::DBusPropertiesMap ethProperties; | |
| ethProperties.emplace_back("RXFCSErrors", | |
| dbus::utility::DbusVariantType(uint64_t{3})); | |
| ethProperties.emplace_back("RXAlignmentErrors", | |
| dbus::utility::DbusVariantType(uint64_t{1})); | |
| ethProperties.emplace_back("PauseXOFFFramesReceived", | |
| dbus::utility::DbusVariantType(uint64_t{5})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| ethKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| ethProperties)) | |
| .ok()); | |
| // 5. Mock IBPort properties | |
| managedStore::KeyType ibKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Metrics.IBPort", ""); | |
| dbus::utility::DBusPropertiesMap ibProperties; | |
| ibProperties.emplace_back("BitErrorRate", | |
| dbus::utility::DbusVariantType(double{1e-12})); | |
| ibProperties.emplace_back("LinkDownCount", | |
| dbus::utility::DbusVariantType(uint64_t{2})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| ibKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(ibProperties)) | |
| .ok()); | |
| // 6. Mock PortMetricsOem2 properties | |
| managedStore::KeyType oem2Key( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Metrics.PortMetricsOem2", ""); | |
| dbus::utility::DBusPropertiesMap oem2Properties; | |
| oem2Properties.emplace_back( | |
| "RXBytes", dbus::utility::DbusVariantType(uint64_t{1048576})); | |
| oem2Properties.emplace_back( | |
| "TXBytes", dbus::utility::DbusVariantType(uint64_t{2097152})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| oem2Key, managedStore::MockManagedStoreTest::CreateValueType( | |
| oem2Properties)) | |
| .ok()); | |
| // 7. Mock PCIeECC properties | |
| managedStore::KeyType pcieKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.PCIe.PCIeECC", ""); | |
| dbus::utility::DBusPropertiesMap pcieProperties; | |
| pcieProperties.emplace_back("ceCount", | |
| dbus::utility::DbusVariantType(uint64_t{9})); | |
| pcieProperties.emplace_back("ueCount", | |
| dbus::utility::DbusVariantType(uint64_t{0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pcieKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| pcieProperties)) | |
| .ok()); | |
| handleNetworkPortMetricGetDBus(share_async_resp_, "chassis0", "adapter0", | |
| "Port_1"); | |
| RunIoUntilDone(); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ( | |
| json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/Port_1/" | |
| "Metrics"); | |
| EXPECT_EQ(json["@odata.type"], "#PortMetrics.v1_3_0.PortMetrics"); | |
| EXPECT_EQ(json["Name"], "Port_1 Metrics"); | |
| EXPECT_EQ(json["Id"], "Metrics"); | |
| EXPECT_EQ(json["CorrectableBitErrors"], 42); | |
| EXPECT_EQ(json["RXBroadcastPackets"], 100); | |
| EXPECT_EQ(json["RXMulticastPackets"], 200); | |
| EXPECT_EQ(json["RXUnicastPackets"], 300); | |
| EXPECT_EQ(json["TXBroadcastPackets"], 400); | |
| EXPECT_EQ(json["TXMulticastPackets"], 500); | |
| EXPECT_EQ(json["TXUnicastPackets"], 600); | |
| EXPECT_EQ(json["RXFCSErrors"], 3); | |
| EXPECT_EQ(json["RXAlignmentErrors"], 1); | |
| EXPECT_EQ(json["RXBytes"], 1048576); | |
| EXPECT_EQ(json["TXBytes"], 2097152); | |
| EXPECT_EQ(json["Oem"]["Google"]["TransceiverTelemetry"]["FECCorrectedCount"], | |
| 42); | |
| EXPECT_EQ( | |
| json["Oem"]["Google"]["TransceiverTelemetry"]["FECUncorrectableCount"], | |
| 7); | |
| EXPECT_EQ(json["Oem"]["Google"]["TransceiverTelemetry"]["PerLaneFECCounters"], | |
| (std::vector<uint64_t>{10, 20, 30, 40})); | |
| EXPECT_DOUBLE_EQ(json["Oem"]["Google"]["TransceiverTelemetry"]["BitErrorRate"] | |
| .get<double>(), | |
| 1e-12); | |
| EXPECT_EQ(json["LinkDownCount"], 2); | |
| EXPECT_EQ(json["Oem"]["Google"]["PCIeErrors"]["ceCount"], 9); | |
| EXPECT_EQ(json["Oem"]["Google"]["PCIeErrors"]["ueCount"], 0); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortDBusParallelMergedPldmPriority) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| // 1. Mock Mapper GetSubTree returning both PLDM and NSM endpoints | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}, | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| // 2. Mock PLDM port properties (authoritative for link telemetry) | |
| managedStore::KeyType pldmPropKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.PLDM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/" | |
| "Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap pldmProps; | |
| pldmProps.emplace_back( | |
| "LinkState", dbus::utility::DbusVariantType(std::string("Enabled"))); | |
| pldmProps.emplace_back("LinkStatus", | |
| dbus::utility::DbusVariantType(std::string("LinkUp"))); | |
| pldmProps.emplace_back("CurrentSpeedGbps", | |
| dbus::utility::DbusVariantType(double{200.0})); | |
| pldmProps.emplace_back("PortNumber", | |
| dbus::utility::DbusVariantType(uint32_t{0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pldmPropKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(pldmProps)) | |
| .ok()); | |
| // 3. Mock NSM port properties (empty/unpopulated link telemetry, valid | |
| // PortNumber) | |
| managedStore::KeyType nsmPropKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap nsmProps; | |
| nsmProps.emplace_back("LinkState", | |
| dbus::utility::DbusVariantType(std::string(""))); | |
| nsmProps.emplace_back("LinkStatus", | |
| dbus::utility::DbusVariantType(std::string(""))); | |
| nsmProps.emplace_back("CurrentSpeedGbps", | |
| dbus::utility::DbusVariantType(double{0.0})); | |
| nsmProps.emplace_back("PortNumber", | |
| dbus::utility::DbusVariantType(uint32_t{1})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| nsmPropKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(nsmProps)) | |
| .ok()); | |
| // 4. Mock Port LocationCode decorator (from PortLocationCodeMap) | |
| managedStore::KeyType portLocCodeKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode"); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portLocCodeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(std::string("port0_dev")))) | |
| .ok()); | |
| // 5. Mock chassis paths | |
| managedStore::KeyType chassisPathsKey( | |
| ManagedType::kManagedSubtreePaths, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Board", | |
| "xyz.openbmc_project.Inventory.Item.Chassis"}); | |
| std::vector<std::string> chassisPaths = { | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0"}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| chassisPathsKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(chassisPaths)) | |
| .ok()); | |
| // 6. Mock chassis object interfaces | |
| managedStore::KeyType chassisObjKey( | |
| ManagedType::kManagedMapperObject, | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0", | |
| std::vector<std::string>{ | |
| "xyz.openbmc_project.Inventory.Decorator.LocationCode", | |
| "xyz.openbmc_project.Inventory.Decorator.Location"}); | |
| dbus::utility::MapperGetObject chassisObj = { | |
| {"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Decorator.LocationCode", | |
| "xyz.openbmc_project.Inventory.Decorator.Location"}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| chassisObjKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(chassisObj)) | |
| .ok()); | |
| // 7. Mock chassis LocationCode and LocationType | |
| managedStore::KeyType chassisLocCodeKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0"), | |
| "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode"); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| chassisLocCodeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(std::string("chassis0_loc")))) | |
| .ok()); | |
| managedStore::KeyType chassisLocTypeKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0"), | |
| "xyz.openbmc_project.Inventory.Decorator.Location", "LocationType"); | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| chassisLocTypeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Decorator." | |
| "Location.LocationTypes.Embedded")))) | |
| .ok()); | |
| // 8. Mock chassis0 contained_by -> carrier_board | |
| managedStore::KeyType chassisContainedByKey( | |
| ManagedType::kManagedAssociatedSubtree, | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/contained_by", | |
| "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Board", | |
| "xyz.openbmc_project.Inventory.Item.Chassis"}); | |
| dbus::utility::MapperGetSubTreeResponse chassisContainedBy = { | |
| {"/xyz/openbmc_project/inventory/system/board/carrier_board", | |
| {{"xyz.openbmc_project.EntityManager", | |
| {"xyz.openbmc_project.Inventory.Item.Board"}}}}}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| chassisContainedByKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| chassisContainedBy)) | |
| .ok()); | |
| // 9. Mock carrier_board LocationCode | |
| managedStore::KeyType carrierLocCodeKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/board/carrier_board"), | |
| "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode"); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| carrierLocCodeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(std::string("CARRIER")))) | |
| .ok()); | |
| // 10. Mock carrier_board contained_by -> system_board | |
| managedStore::KeyType carrierContainedByKey( | |
| ManagedType::kManagedAssociatedSubtree, | |
| "/xyz/openbmc_project/inventory/system/board/carrier_board/contained_by", | |
| "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Board", | |
| "xyz.openbmc_project.Inventory.Item.Chassis"}); | |
| dbus::utility::MapperGetSubTreeResponse carrierContainedBy = { | |
| {"/xyz/openbmc_project/inventory/system/board/system_board", | |
| {{"xyz.openbmc_project.EntityManager", | |
| {"xyz.openbmc_project.Inventory.Item.Board"}}}}}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| carrierContainedByKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| carrierContainedBy)) | |
| .ok()); | |
| // 11. Mock system_board LocationCode | |
| managedStore::KeyType systemBoardLocCodeKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/board/system_board"), | |
| "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode"); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| systemBoardLocCodeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(std::string("SYSTEM_PLANE")))) | |
| .ok()); | |
| // 12. Mock system_board contained_by -> empty | |
| managedStore::KeyType systemBoardContainedByKey( | |
| ManagedType::kManagedAssociatedSubtree, | |
| "/xyz/openbmc_project/inventory/system/board/system_board/contained_by", | |
| "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Board", | |
| "xyz.openbmc_project.Inventory.Item.Chassis"}); | |
| dbus::utility::MapperGetSubTreeResponse systemBoardContainedBy = {}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| systemBoardContainedByKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| systemBoardContainedBy)) | |
| .ok()); | |
| // 13. Mock system_board attached_cables -> empty | |
| managedStore::KeyType attachedCablesKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.ObjectMapper", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/board/system_board/" | |
| "attached_cables"), | |
| "xyz.openbmc_project.Association", "endpoints"); | |
| std::vector<std::string> emptyCables; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| attachedCablesKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(emptyCables))) | |
| .ok()); | |
| handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1"); | |
| RunIoUntilDone(); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ( | |
| json["@odata.id"], | |
| "/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/Port_1"); | |
| EXPECT_EQ(json["Id"], "Port_1"); | |
| EXPECT_EQ(json["Name"], "Port_1"); | |
| EXPECT_EQ(json["Status"]["State"], "Enabled"); | |
| EXPECT_EQ(json["Status"]["Health"], "OK"); | |
| EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "port0_dev"); | |
| EXPECT_EQ(json["Location"]["PartLocation"]["LocationType"], "Embedded"); | |
| EXPECT_EQ(json["Location"]["PartLocationContext"], "SYSTEM_PLANE/CARRIER"); | |
| EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"], | |
| "/phys/SYSTEM_PLANE/CARRIER:device:port0_dev"); | |
| EXPECT_EQ(json["LinkState"], "Enabled"); | |
| EXPECT_EQ(json["LinkStatus"], "LinkUp"); | |
| EXPECT_DOUBLE_EQ(json["CurrentSpeedGbps"].get<double>(), 200.0); | |
| EXPECT_EQ(json["Metrics"]["@odata.id"], | |
| "/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/" | |
| "Port_1/Metrics"); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortDBusPldmOnly) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| managedStore::KeyType pldmPropKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.PLDM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/" | |
| "Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap pldmProps; | |
| pldmProps.emplace_back( | |
| "LinkState", dbus::utility::DbusVariantType(std::string("Enabled"))); | |
| pldmProps.emplace_back("LinkStatus", | |
| dbus::utility::DbusVariantType(std::string("LinkUp"))); | |
| pldmProps.emplace_back("CurrentSpeedGbps", | |
| dbus::utility::DbusVariantType(double{100.0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pldmPropKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(pldmProps)) | |
| .ok()); | |
| handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1"); | |
| RunIoUntilDone(); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["Status"]["State"], "Enabled"); | |
| EXPECT_EQ(json["Status"]["Health"], "OK"); | |
| EXPECT_EQ(json["LinkState"], "Enabled"); | |
| EXPECT_EQ(json["LinkStatus"], "LinkUp"); | |
| EXPECT_DOUBLE_EQ(json["CurrentSpeedGbps"].get<double>(), 100.0); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortDBusPldmPriorityOverNonEmptyNsm) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| // 1. Mock Mapper GetSubTree returning both PLDM and NSM endpoints | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}, | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| // 2. Mock PLDM port properties (authoritative for base link telemetry) | |
| managedStore::KeyType pldmPropKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.PLDM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/" | |
| "Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap pldmProps; | |
| pldmProps.emplace_back( | |
| "LinkState", dbus::utility::DbusVariantType(std::string("Enabled"))); | |
| pldmProps.emplace_back("LinkStatus", | |
| dbus::utility::DbusVariantType(std::string("LinkUp"))); | |
| pldmProps.emplace_back("CurrentSpeedGbps", | |
| dbus::utility::DbusVariantType(double{100.0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pldmPropKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(pldmProps)) | |
| .ok()); | |
| // 3. Mock NSM port properties with conflicting non-empty link telemetry | |
| managedStore::KeyType nsmPropKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap nsmProps; | |
| nsmProps.emplace_back( | |
| "LinkState", dbus::utility::DbusVariantType(std::string("Disabled"))); | |
| nsmProps.emplace_back( | |
| "LinkStatus", dbus::utility::DbusVariantType(std::string("LinkDown"))); | |
| nsmProps.emplace_back("CurrentSpeedGbps", | |
| dbus::utility::DbusVariantType(double{400.0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| nsmPropKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(nsmProps)) | |
| .ok()); | |
| handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["Status"]["State"], "Enabled"); | |
| EXPECT_EQ(json["Status"]["Health"], "OK"); | |
| EXPECT_EQ(json["LinkState"], "Enabled"); | |
| EXPECT_EQ(json["LinkStatus"], "LinkUp"); | |
| EXPECT_DOUBLE_EQ(json["CurrentSpeedGbps"].get<double>(), 100.0); | |
| } | |
| TEST_F(NetworkAdapterTest, | |
| GetNetworkPortDBusMissingPropertiesReturnsInternalError) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| managedStore::KeyType nsmPropKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap nsmProps; | |
| nsmProps.emplace_back("LinkState", | |
| dbus::utility::DbusVariantType(std::string(""))); | |
| nsmProps.emplace_back("LinkStatus", | |
| dbus::utility::DbusVariantType(std::string(""))); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| nsmPropKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(nsmProps)) | |
| .ok()); | |
| handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), | |
| boost::beast::http::status::internal_server_error); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortDBusPldmMissingFallsBackToNsm) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}, | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| // PLDM has empty properties (fails to provide telemetry) | |
| managedStore::KeyType pldmPropKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.PLDM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/" | |
| "Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap pldmProps; | |
| pldmProps.emplace_back("LinkState", | |
| dbus::utility::DbusVariantType(std::string(""))); | |
| pldmProps.emplace_back("LinkStatus", | |
| dbus::utility::DbusVariantType(std::string(""))); | |
| pldmProps.emplace_back("CurrentSpeedGbps", | |
| dbus::utility::DbusVariantType(double{0.0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pldmPropKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(pldmProps)) | |
| .ok()); | |
| // NSM has valid properties (provides fallback telemetry) | |
| managedStore::KeyType nsmPropKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap nsmProps; | |
| nsmProps.emplace_back("LinkState", | |
| dbus::utility::DbusVariantType(std::string("Enabled"))); | |
| nsmProps.emplace_back("LinkStatus", | |
| dbus::utility::DbusVariantType(std::string("LinkUp"))); | |
| nsmProps.emplace_back("CurrentSpeedGbps", | |
| dbus::utility::DbusVariantType(double{200.0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| nsmPropKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(nsmProps)) | |
| .ok()); | |
| handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["LinkState"], "Enabled"); | |
| EXPECT_EQ(json["LinkStatus"], "LinkUp"); | |
| EXPECT_DOUBLE_EQ(json["CurrentSpeedGbps"].get<double>(), 200.0); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortDBusBothMissingReturnsInternalError) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}, | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| // Both PLDM and NSM have empty properties | |
| managedStore::KeyType pldmPropKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.PLDM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/" | |
| "Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap pldmProps; | |
| pldmProps.emplace_back("LinkState", | |
| dbus::utility::DbusVariantType(std::string(""))); | |
| pldmProps.emplace_back("LinkStatus", | |
| dbus::utility::DbusVariantType(std::string(""))); | |
| pldmProps.emplace_back("CurrentSpeedGbps", | |
| dbus::utility::DbusVariantType(double{0.0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pldmPropKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(pldmProps)) | |
| .ok()); | |
| managedStore::KeyType nsmPropKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap nsmProps; | |
| nsmProps.emplace_back("LinkState", | |
| dbus::utility::DbusVariantType(std::string(""))); | |
| nsmProps.emplace_back("LinkStatus", | |
| dbus::utility::DbusVariantType(std::string(""))); | |
| nsmProps.emplace_back("CurrentSpeedGbps", | |
| dbus::utility::DbusVariantType(double{0.0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| nsmPropKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(nsmProps)) | |
| .ok()); | |
| handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), | |
| boost::beast::http::status::internal_server_error); | |
| } | |
| TEST_F(NetworkAdapterTest, | |
| NetworkAdapterCollectionDBusDeduplicatesMultipleEndpoints) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType chassisSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Board", | |
| "xyz.openbmc_project.Inventory.Item.Chassis"}); | |
| dbus::utility::MapperGetSubTreeResponse chassisSubtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.Board"}}}}}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| chassisSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| chassisSubtree)) | |
| .ok()); | |
| managedStore::KeyType assocKey( | |
| managedStore::ManagedType::kManagedProperty, | |
| "xyz.openbmc_project.ObjectMapper", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/network_adapter"), | |
| "xyz.openbmc_project.Association", "endpoints"); | |
| dbus::utility::MapperEndPoints endpoints = { | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0", | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0"}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| assocKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(endpoints))) | |
| .ok()); | |
| handleChassisNetworkAdapterCollectionGetDBus(share_async_resp_, "chassis0"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.type"], | |
| "#NetworkAdapterCollection.NetworkAdapterCollection"); | |
| EXPECT_EQ(json["Members@odata.count"], 1); | |
| EXPECT_EQ(json["Members"].size(), 1); | |
| EXPECT_EQ(json["Members"][0]["@odata.id"], | |
| "/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0"); | |
| } | |
| TEST_F(NetworkAdapterTest, | |
| NetworkPortCollectionDBusDeduplicatesMultipleEndpoints) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType adapterSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.NetworkAdapter"}); | |
| dbus::utility::MapperGetSubTreeResponse adapterSubtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.NetworkAdapter"}}}}, | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.NetworkAdapter"}}}}}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| adapterSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| adapterSubtree)) | |
| .ok()); | |
| managedStore::KeyType pldmAssocKey( | |
| managedStore::ManagedType::kManagedProperty, | |
| "xyz.openbmc_project.ObjectMapper", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/" | |
| "all_ports"), | |
| "xyz.openbmc_project.Association", "endpoints"); | |
| dbus::utility::MapperEndPoints pldmEndpoints = { | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1", | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_2"}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pldmAssocKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(pldmEndpoints))) | |
| .ok()); | |
| managedStore::KeyType nsmAssocKey( | |
| managedStore::ManagedType::kManagedProperty, | |
| "xyz.openbmc_project.ObjectMapper", | |
| sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/" | |
| "chassis/chassis0/NetworkAdapters/" | |
| "adapter0/all_ports"), | |
| "xyz.openbmc_project.Association", "endpoints"); | |
| dbus::utility::MapperEndPoints nsmEndpoints = { | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1", | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_3"}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| nsmAssocKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(nsmEndpoints))) | |
| .ok()); | |
| handleNetworkPortCollectionGetDBus(share_async_resp_, "chassis0", "adapter0"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.type"], "#PortCollection.PortCollection"); | |
| EXPECT_EQ(json["Members@odata.count"], 3); | |
| EXPECT_EQ(json["Members"].size(), 3); | |
| EXPECT_EQ( | |
| json["Members"][0]["@odata.id"], | |
| "/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/Port_1"); | |
| EXPECT_EQ( | |
| json["Members"][1]["@odata.id"], | |
| "/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/Port_2"); | |
| EXPECT_EQ( | |
| json["Members"][2]["@odata.id"], | |
| "/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/Port_3"); | |
| } | |
| TEST(FindPortProviderEndpointsTest, IgnoresEmptyConnectionAndReturnsEndpoints) { | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1", | |
| {}}, | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}, | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| PortProviderEndpoints ep = | |
| findPortProviderEndpoints(subtree, "chassis0", "adapter0", "Port_1"); | |
| EXPECT_EQ( | |
| ep.pldm.first, | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1"); | |
| EXPECT_EQ(ep.pldm.second, "xyz.openbmc_project.PLDM"); | |
| EXPECT_EQ( | |
| ep.nsm.first, | |
| "/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/" | |
| "adapter0/Ports/Port_1"); | |
| EXPECT_EQ(ep.nsm.second, "xyz.openbmc_project.NSM"); | |
| } | |
| TEST_F(NetworkAdapterTest, | |
| BuildNetworkPortDBusReturnsNotFoundWhenBothEndpointsEmpty) { | |
| buildNetworkPortDBus(share_async_resp_, "chassis0", "adapter0", "Port_1", | |
| /*pldmEndpoint=*/{"", ""}, /*nsmEndpoint=*/{"", ""}); | |
| EXPECT_EQ(share_async_resp_->res.result(), | |
| boost::beast::http::status::not_found); | |
| } | |
| TEST_F(NetworkAdapterTest, | |
| NetworkPortGetDBusReturnsNotFoundWhenNoMatchingEndpoints) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/" | |
| "Port_99", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), | |
| boost::beast::http::status::not_found); | |
| } | |
| TEST_F(NetworkAdapterTest, | |
| GetNetworkPortMetricsDBusPopulatesExtendedIBPortCounters) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| managedStore::KeyType eccKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1"), | |
| "xyz.openbmc_project.Metrics.PortECC", ""); | |
| dbus::utility::DBusPropertiesMap eccProperties; | |
| eccProperties.emplace_back("SymbolErrorRXBytes", | |
| dbus::utility::DbusVariantType(uint64_t{13})); | |
| eccProperties.emplace_back( | |
| "RawErrorsPerLane", | |
| dbus::utility::DbusVariantType(std::vector<uint64_t>{33193642, 0, 0, 0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| eccKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| eccProperties)) | |
| .ok()); | |
| managedStore::KeyType pktKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1"), | |
| "xyz.openbmc_project.Metrics.PortPacketCounters", ""); | |
| dbus::utility::DBusPropertiesMap pktProperties; | |
| pktProperties.emplace_back("RXUnicastPkts", | |
| dbus::utility::DbusVariantType(uint64_t{1000})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pktKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| pktProperties)) | |
| .ok()); | |
| managedStore::KeyType ethKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1"), | |
| "xyz.openbmc_project.Metrics.EthPort", ""); | |
| dbus::utility::DBusPropertiesMap ethProperties; | |
| ethProperties.emplace_back("RXFCSErrors", | |
| dbus::utility::DbusVariantType(uint64_t{12})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| ethKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| ethProperties)) | |
| .ok()); | |
| managedStore::KeyType ibKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1"), | |
| "xyz.openbmc_project.Metrics.IBPort", ""); | |
| dbus::utility::DBusPropertiesMap ibProperties; | |
| ibProperties.emplace_back("LinkDownCount", | |
| dbus::utility::DbusVariantType(uint64_t{4})); | |
| ibProperties.emplace_back("RXErrors", | |
| dbus::utility::DbusVariantType(uint64_t{5})); | |
| ibProperties.emplace_back("TXDiscardPkts", | |
| dbus::utility::DbusVariantType(uint64_t{6})); | |
| ibProperties.emplace_back("RXPkts", | |
| dbus::utility::DbusVariantType(uint64_t{1500})); | |
| ibProperties.emplace_back("TXPkts", | |
| dbus::utility::DbusVariantType(uint64_t{2500})); | |
| ibProperties.emplace_back("SymbolErrors", | |
| dbus::utility::DbusVariantType(uint64_t{19})); | |
| ibProperties.emplace_back("UnintentionalLinkDownCount", | |
| dbus::utility::DbusVariantType(uint64_t{2})); | |
| ibProperties.emplace_back("IntentionalLinkDownCount", | |
| dbus::utility::DbusVariantType(uint64_t{1})); | |
| ibProperties.emplace_back("LinkErrorRecoveryCounter", | |
| dbus::utility::DbusVariantType(uint64_t{3})); | |
| ibProperties.emplace_back("RXRemotePhysicalErrorPkts", | |
| dbus::utility::DbusVariantType(uint64_t{7})); | |
| ibProperties.emplace_back("RXSwitchRelayErrorPkts", | |
| dbus::utility::DbusVariantType(uint64_t{8})); | |
| ibProperties.emplace_back("VL15DroppedPkts", | |
| dbus::utility::DbusVariantType(uint64_t{9})); | |
| ibProperties.emplace_back("EffectiveError", | |
| dbus::utility::DbusVariantType(uint64_t{10})); | |
| ibProperties.emplace_back("TotalRawError", | |
| dbus::utility::DbusVariantType(uint64_t{11})); | |
| ibProperties.emplace_back("EffectiveBER", | |
| dbus::utility::DbusVariantType(double{2.5e-13})); | |
| ibProperties.emplace_back("TotalRawBER", | |
| dbus::utility::DbusVariantType(double{1.5e-9})); | |
| ibProperties.emplace_back( | |
| "PerLaneRawBER", | |
| dbus::utility::DbusVariantType( | |
| std::vector<double>{1.1e-7, 2.2e-7, 3.3e-7, 4.4e-7})); | |
| ibProperties.emplace_back( | |
| "LinkDownReasonCode", | |
| dbus::utility::DbusVariantType( | |
| std::string("xyz.openbmc_project.Metrics.IBPort.LinkDownReasonCodes." | |
| "NoLinkDown"))); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| ibKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(ibProperties)) | |
| .ok()); | |
| handleNetworkPortMetricGetDBus(share_async_resp_, "CX9_0", "CX9_0_NIC_1", | |
| "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| // Frame and discard counters are emitted under the DMTF Networking object, | |
| // not at the top level. | |
| EXPECT_FALSE(json.contains("RXPackets")); | |
| EXPECT_FALSE(json.contains("TXPackets")); | |
| EXPECT_FALSE(json.contains("TXDiscards")); | |
| EXPECT_EQ(json["RXUnicastPackets"], 1000); | |
| EXPECT_EQ(json["RXFCSErrors"], 12); | |
| EXPECT_EQ(json["LinkDownCount"], 4); | |
| EXPECT_EQ(json["RXErrors"], 5); | |
| EXPECT_EQ(json["Networking"]["TXDiscards"], 6); | |
| EXPECT_EQ(json["Networking"]["RXFrames"], 1500); | |
| EXPECT_EQ(json["Networking"]["TXFrames"], 2500); | |
| // SymbolErrors comes only from IBPort; PortECC SymbolErrorRXBytes feeds | |
| // FECUncorrectableCount only. | |
| EXPECT_EQ(json["SymbolErrors"], 19); | |
| const nlohmann::json& transceiver = | |
| json["Oem"]["Google"]["TransceiverTelemetry"]; | |
| EXPECT_EQ(transceiver["FECUncorrectableCount"], 13); | |
| EXPECT_EQ(transceiver["PerLaneFECCounters"], | |
| (std::vector<uint64_t>{33193642, 0, 0, 0})); | |
| EXPECT_EQ(transceiver["UnintentionalLinkDownCount"], 2); | |
| EXPECT_EQ(transceiver["IntentionalLinkDownCount"], 1); | |
| EXPECT_EQ(transceiver["LinkErrorRecoveryCount"], 3); | |
| EXPECT_EQ(transceiver["RXRemotePhysicalErrors"], 7); | |
| EXPECT_EQ(transceiver["RXSwitchRelayErrors"], 8); | |
| EXPECT_EQ(transceiver["VL15Dropped"], 9); | |
| EXPECT_EQ(transceiver["EffectiveError"], 10); | |
| EXPECT_EQ(transceiver["TotalRawError"], 11); | |
| EXPECT_DOUBLE_EQ(transceiver["EffectiveBER"].get<double>(), 2.5e-13); | |
| EXPECT_DOUBLE_EQ(transceiver["TotalRawBER"].get<double>(), 1.5e-9); | |
| EXPECT_EQ(transceiver["PerLaneRawBER"], | |
| (std::vector<double>{1.1e-7, 2.2e-7, 3.3e-7, 4.4e-7})); | |
| EXPECT_EQ(transceiver["LinkDownReasonCode"], "NoLinkDown"); | |
| } | |
| TEST(DbusUtilsTest, StripDbusEnumPrefix) { | |
| EXPECT_EQ(dbus_utils::stripDbusEnumPrefix( | |
| "xyz.openbmc_project.Metrics.IBPort.LinkDownReasonCodes." | |
| "NoLinkDown"), | |
| "NoLinkDown"); | |
| EXPECT_EQ(dbus_utils::stripDbusEnumPrefix("NoLinkDown"), "NoLinkDown"); | |
| EXPECT_EQ(dbus_utils::stripDbusEnumPrefix("a.b."), "a.b."); | |
| EXPECT_EQ(dbus_utils::stripDbusEnumPrefix(""), ""); | |
| } | |
| TEST(FecHistogramBinsTest, PlacesBinsByIndexAndZerosInvalidValues) { | |
| dbus::utility::HistogramBucketData bucketData = { | |
| {0, {0.0, 1.0, 100.0}}, | |
| {2, {2.0, 3.0, -5.0}}, | |
| {1, {1.0, 2.0, 25.0}}, | |
| {3, {3.0, 4.0, std::numeric_limits<double>::quiet_NaN()}}, | |
| {4, {4.0, 5.0, std::numeric_limits<double>::infinity()}}, | |
| {5, {5.0, 6.0, 18446744073709551616.0}}, | |
| {6, {6.0, 7.0, 4.0}}, | |
| {99, {99.0, 100.0, 42.0}}, | |
| }; | |
| std::optional<std::vector<uint64_t>> bins = | |
| fecHistogramBins(dbus::utility::DbusVariantType(bucketData), | |
| /*numOfBuckets=*/7); | |
| ASSERT_TRUE(bins.has_value()); | |
| EXPECT_EQ(*bins, (std::vector<uint64_t>{100, 25, 0, 0, 0, 0, 4})); | |
| } | |
| TEST(FecHistogramBinsTest, PlacesSparseBucketsAtTheirIndices) { | |
| dbus::utility::HistogramBucketData sparseBuckets = { | |
| {0, {0.0, 1.0, 1000.0}}, | |
| {5, {5.0, 6.0, 12.0}}, | |
| {15, {15.0, 16.0, 3.0}}, | |
| }; | |
| std::optional<std::vector<uint64_t>> bins = | |
| fecHistogramBins(dbus::utility::DbusVariantType(sparseBuckets), | |
| /*numOfBuckets=*/16); | |
| ASSERT_TRUE(bins.has_value()); | |
| EXPECT_EQ(*bins, (std::vector<uint64_t>{1000, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 3})); | |
| EXPECT_EQ(fecHistogramBins(dbus::utility::DbusVariantType(sparseBuckets), | |
| /*numOfBuckets=*/std::nullopt), | |
| bins); | |
| } | |
| TEST(FecHistogramBinsTest, ReturnsNulloptForEmptyOrNonBucketVariant) { | |
| EXPECT_EQ(fecHistogramBins(dbus::utility::DbusVariantType( | |
| dbus::utility::HistogramBucketData{}), | |
| /*numOfBuckets=*/std::nullopt), | |
| std::nullopt); | |
| EXPECT_EQ(fecHistogramBins(dbus::utility::DbusVariantType(uint64_t{42}), | |
| /*numOfBuckets=*/std::nullopt), | |
| std::nullopt); | |
| dbus::utility::HistogramBucketData singleBucket = {{0, {0.0, 1.0, 10.0}}}; | |
| EXPECT_EQ(fecHistogramBins(dbus::utility::DbusVariantType(singleBucket), | |
| /*numOfBuckets=*/0), | |
| std::nullopt); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortMetricsDBusPopulatesFECHistogramBins) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| managedStore::KeyType histKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1/Histograms/FEC_0"), | |
| "com.nvidia.Histogram.BucketInfo", ""); | |
| dbus::utility::HistogramBucketData bucketData = { | |
| {0, {0.0, 1.0, 100.0}}, | |
| {1, {1.0, 2.0, 25.0}}, | |
| {2, {2.0, 3.0, -5.0}}, | |
| {3, {3.0, 4.0, std::numeric_limits<double>::quiet_NaN()}}, | |
| {4, {4.0, 5.0, std::numeric_limits<double>::infinity()}}, | |
| {5, {5.0, 6.0, 4.0}}, | |
| {6, {6.0, 7.0, 0.0}}, | |
| }; | |
| dbus::utility::DBusPropertiesMap histProperties; | |
| histProperties.emplace_back("BucketData", | |
| dbus::utility::DbusVariantType(bucketData)); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| histKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| histProperties)) | |
| .ok()); | |
| managedStore::KeyType formatKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1/Histograms/FEC_0"), | |
| "com.nvidia.Histogram.Decorator.Format", ""); | |
| dbus::utility::DBusPropertiesMap formatProperties; | |
| formatProperties.emplace_back( | |
| "UnitOfMeasure", | |
| dbus::utility::DbusVariantType(std::string( | |
| "com.nvidia.Histogram.Decorator.Format.BucketUnits.Count"))); | |
| formatProperties.emplace_back("NumOfBuckets", | |
| dbus::utility::DbusVariantType(uint64_t{7})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| formatKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| formatProperties)) | |
| .ok()); | |
| handleNetworkPortMetricGetDBus(share_async_resp_, "CX9_0", "CX9_0_NIC_1", | |
| "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["Oem"]["Google"]["TransceiverTelemetry"]["FECHistogramBins"], | |
| (std::vector<uint64_t>{100, 25, 0, 0, 0, 4, 0})); | |
| } | |
| TEST_F(NetworkAdapterTest, | |
| GetNetworkPortMetricsDBusKeepsFECHistogramBinsEmptyForEmptyBucketData) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| // nsmd publishes FEC_0 with empty BucketData when the device reports no | |
| // histogram buckets (NumOfBuckets 0). | |
| managedStore::KeyType histKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1/Histograms/FEC_0"), | |
| "com.nvidia.Histogram.BucketInfo", ""); | |
| dbus::utility::DBusPropertiesMap histProperties; | |
| histProperties.emplace_back( | |
| "BucketData", | |
| dbus::utility::DbusVariantType(dbus::utility::HistogramBucketData{})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| histKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| histProperties)) | |
| .ok()); | |
| managedStore::KeyType oem2Key( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1"), | |
| "xyz.openbmc_project.Metrics.PortMetricsOem2", ""); | |
| dbus::utility::DBusPropertiesMap oem2Properties; | |
| oem2Properties.emplace_back( | |
| "RXBytes", dbus::utility::DbusVariantType(uint64_t{1048576})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| oem2Key, managedStore::MockManagedStoreTest::CreateValueType( | |
| oem2Properties)) | |
| .ok()); | |
| handleNetworkPortMetricGetDBus(share_async_resp_, "CX9_0", "CX9_0_NIC_1", | |
| "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["Oem"]["Google"]["TransceiverTelemetry"]["FECHistogramBins"], | |
| nlohmann::json::array()); | |
| EXPECT_EQ(json["RXBytes"], 1048576); | |
| } | |
| TEST_F(NetworkAdapterTest, GetNetworkPortDBusPopulatesPortInfoAndMacAddresses) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType portSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Port"}); | |
| dbus::utility::MapperGetSubTreeResponse subtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.Port"}}}}}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(subtree)) | |
| .ok()); | |
| managedStore::KeyType nsmPortKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1"), | |
| "xyz.openbmc_project.Inventory.Item.Port", ""); | |
| dbus::utility::DBusPropertiesMap nsmPortProps; | |
| nsmPortProps.emplace_back( | |
| "LinkState", dbus::utility::DbusVariantType(std::string("Enabled"))); | |
| nsmPortProps.emplace_back( | |
| "LinkStatus", dbus::utility::DbusVariantType(std::string("LinkUp"))); | |
| nsmPortProps.emplace_back("CurrentSpeedGbps", | |
| dbus::utility::DbusVariantType(double{400.0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| nsmPortKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(nsmPortProps)) | |
| .ok()); | |
| managedStore::KeyType portInfoKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1"), | |
| "xyz.openbmc_project.Inventory.Decorator.PortInfo", ""); | |
| dbus::utility::DBusPropertiesMap portInfoProps; | |
| portInfoProps.emplace_back( | |
| "Type", dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Decorator.PortInfo.PortType." | |
| "BidirectionalPort"))); | |
| portInfoProps.emplace_back( | |
| "Protocol", dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Decorator.PortInfo." | |
| "PortProtocol.Ethernet"))); | |
| portInfoProps.emplace_back("MaxSpeed", | |
| dbus::utility::DbusVariantType(double{800.0})); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portInfoKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| portInfoProps)) | |
| .ok()); | |
| managedStore::KeyType ethMacKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1/Ethernet_MAC_Address"), | |
| "xyz.openbmc_project.Network.MACAddress", "MACAddress"); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| ethMacKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType( | |
| std::string("aa:bb:cc:dd:ee:01")))) | |
| .ok()); | |
| managedStore::KeyType permMacKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1/Permanent_MAC_Address"), | |
| "xyz.openbmc_project.Network.MACAddress", "MACAddress"); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| permMacKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType( | |
| std::string("aa:bb:cc:dd:ee:00")))) | |
| .ok()); | |
| handleNetworkPortGetDBus(share_async_resp_, "CX9_0", "CX9_0_NIC_1", "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["PortType"], "BidirectionalPort"); | |
| EXPECT_EQ(json["PortProtocol"], "Ethernet"); | |
| EXPECT_DOUBLE_EQ(json["MaxSpeedGbps"].get<double>(), 800.0); | |
| EXPECT_EQ(json["MACAddress"], "aa:bb:cc:dd:ee:01"); | |
| EXPECT_EQ(json["Ethernet"]["AssociatedMACAddresses"], | |
| nlohmann::json::array({"aa:bb:cc:dd:ee:01"})); | |
| EXPECT_EQ(json["PermanentMACAddress"], "aa:bb:cc:dd:ee:00"); | |
| EXPECT_EQ(json["Ethernet"]["PermanentMACAddress"], "aa:bb:cc:dd:ee:00"); | |
| // Verify that "Unknown" PortInfo enum values are filtered out. | |
| dbus::utility::DBusPropertiesMap unknownPortInfoProps; | |
| unknownPortInfoProps.emplace_back( | |
| "Type", dbus::utility::DbusVariantType( | |
| std::string("xyz.openbmc_project.Inventory.Decorator." | |
| "PortInfo.PortType.Unknown"))); | |
| unknownPortInfoProps.emplace_back( | |
| "Protocol", | |
| dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Decorator.PortInfo.PortProtocol." | |
| "Unknown"))); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portInfoKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| unknownPortInfoProps)) | |
| .ok()); | |
| share_async_resp_->res.clear(); | |
| handleNetworkPortGetDBus(share_async_resp_, "CX9_0", "CX9_0_NIC_1", "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| EXPECT_FALSE(share_async_resp_->res.jsonValue.contains("PortType")); | |
| EXPECT_FALSE(share_async_resp_->res.jsonValue.contains("PortProtocol")); | |
| // Verify fallback to xyz.openbmc_project.Network.LinkType when PortInfo is | |
| // absent or has Unknown protocol (as on Velorum CX9). | |
| managedStore::KeyType linkTypeKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1"), | |
| "xyz.openbmc_project.Network.LinkType", "LinkType"); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| linkTypeKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Network.LinkType." | |
| "PossibleLinks.Ethernet")))) | |
| .ok()); | |
| share_async_resp_->res.clear(); | |
| handleNetworkPortGetDBus(share_async_resp_, "CX9_0", "CX9_0_NIC_1", "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| EXPECT_EQ(share_async_resp_->res.jsonValue["PortProtocol"], "Ethernet"); | |
| // Verify PortInfo unpack failure returns early gracefully. | |
| dbus::utility::DBusPropertiesMap invalidPortInfoProps; | |
| invalidPortInfoProps.emplace_back( | |
| "MaxSpeed", dbus::utility::DbusVariantType(std::string("invalid"))); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| portInfoKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| invalidPortInfoProps)) | |
| .ok()); | |
| share_async_resp_->res.clear(); | |
| handleNetworkPortGetDBus(share_async_resp_, "CX9_0", "CX9_0_NIC_1", "Port_1"); | |
| RunIoUntilDone(); | |
| EXPECT_FALSE(share_async_resp_->res.jsonValue.contains("MaxSpeedGbps")); | |
| } | |
| TEST_F(NetworkAdapterTest, | |
| GetNetworkAdapterDBusPopulatesAssetLocationAndControllers) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType adapterSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.NetworkAdapter"}); | |
| dbus::utility::MapperGetSubTreeResponse adapterSubtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/CX9_0/CX9_0_NIC_1", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.NetworkAdapter"}}}}, | |
| {"/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1", | |
| {{"xyz.openbmc_project.NSM", | |
| {"xyz.openbmc_project.Inventory.Item.NetworkAdapter"}}}}}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| adapterSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| adapterSubtree)) | |
| .ok()); | |
| managedStore::KeyType adapterAssetKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1"), | |
| "xyz.openbmc_project.Inventory.Decorator.Asset", ""); | |
| dbus::utility::DBusPropertiesMap adapterAssetProps; | |
| adapterAssetProps.emplace_back( | |
| "Manufacturer", dbus::utility::DbusVariantType(std::string("NVIDIA"))); | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| adapterAssetKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| adapterAssetProps)) | |
| .ok()); | |
| managedStore::KeyType chassisAssetKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0"), | |
| "xyz.openbmc_project.Inventory.Decorator.Asset", ""); | |
| dbus::utility::DBusPropertiesMap assetProps; | |
| assetProps.emplace_back( | |
| "Manufacturer", dbus::utility::DbusVariantType(std::string("NVIDIA"))); | |
| assetProps.emplace_back( | |
| "Model", dbus::utility::DbusVariantType(std::string("ConnectX-9"))); | |
| assetProps.emplace_back("PartNumber", dbus::utility::DbusVariantType( | |
| std::string("900-9X81E-00EX-ST0"))); | |
| assetProps.emplace_back("SerialNumber", dbus::utility::DbusVariantType( | |
| std::string("MT2601X00001"))); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| chassisAssetKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(assetProps)) | |
| .ok()); | |
| // Primary NSM adapter object provides LocationCode only; EntityManager | |
| // provides LocationType via Decorator.Location and PartLocationContext via | |
| // Decorator.LocationContext. Verify Devpath is recomputed once all arrive. | |
| managedStore::KeyType nsmLocationCodeKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1"), | |
| "xyz.openbmc_project.Inventory.Decorator.LocationCode", ""); | |
| dbus::utility::DBusPropertiesMap nsmLocCodeProps; | |
| nsmLocCodeProps.emplace_back( | |
| "LocationCode", dbus::utility::DbusVariantType(std::string("cx9_0"))); | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| nsmLocationCodeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| nsmLocCodeProps)) | |
| .ok()); | |
| managedStore::KeyType emLocationTypeKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/CX9_0_NIC_1"), | |
| "xyz.openbmc_project.Inventory.Decorator.Location", ""); | |
| dbus::utility::DBusPropertiesMap emLocTypeProps; | |
| emLocTypeProps.emplace_back( | |
| "LocationType", | |
| dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Decorator.Location.LocationTypes." | |
| "Embedded"))); | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| emLocationTypeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| emLocTypeProps)) | |
| .ok()); | |
| managedStore::KeyType emLocationContextKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/CX9_0_NIC_1"), | |
| "xyz.openbmc_project.Inventory.Decorator.LocationContext", ""); | |
| dbus::utility::DBusPropertiesMap emLocCtxProps; | |
| emLocCtxProps.emplace_back( | |
| "PartLocationContext", | |
| dbus::utility::DbusVariantType(std::string("MIDPLANE/CX9_B_L"))); | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| emLocationContextKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| emLocCtxProps)) | |
| .ok()); | |
| managedStore::KeyType allPortsKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.ObjectMapper", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/all_ports"), | |
| "xyz.openbmc_project.Association", "endpoints"); | |
| dbus::utility::MapperEndPoints portEndpoints = { | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_1", | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/Ports/Port_2"}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| allPortsKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(portEndpoints))) | |
| .ok()); | |
| managedStore::KeyType pcieAssocKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.ObjectMapper", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/NetworkAdapters/" | |
| "CX9_0_NIC_1/pciedevice"), | |
| "xyz.openbmc_project.Association", "endpoints"); | |
| dbus::utility::MapperEndPoints pcieEndpoints = { | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/PCIeDevices/CX9_0"}; | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pcieAssocKey, managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(pcieEndpoints))) | |
| .ok()); | |
| managedStore::KeyType pcieDeviceKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_0/PCIeDevices/" | |
| "CX9_0"), | |
| "xyz.openbmc_project.Inventory.Item.PCIeDevice", ""); | |
| dbus::utility::DBusPropertiesMap pcieProps; | |
| pcieProps.emplace_back("LanesInUse", | |
| dbus::utility::DbusVariantType(uint64_t{16})); | |
| pcieProps.emplace_back("MaxLanes", | |
| dbus::utility::DbusVariantType(uint64_t{16})); | |
| pcieProps.emplace_back( | |
| "PCIeType", | |
| dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Item.PCIeDevice.PCIeTypes.Unknown"))); | |
| pcieProps.emplace_back( | |
| "GenerationInUse", | |
| dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Item.PCIeDevice.PCIeTypes.Gen6"))); | |
| pcieProps.emplace_back( | |
| "MaxPCIeType", | |
| dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Item.PCIeDevice.PCIeTypes.Gen6"))); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pcieDeviceKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(pcieProps)) | |
| .ok()); | |
| handleChassisNetworkAdapterGetDBus(share_async_resp_, "CX9_0", "CX9_0_NIC_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["@odata.id"], | |
| "/redfish/v1/Chassis/CX9_0/NetworkAdapters/CX9_0_NIC_1"); | |
| EXPECT_EQ(json["@odata.type"], "#NetworkAdapter.v1_9_0.NetworkAdapter"); | |
| EXPECT_EQ(json["Id"], "CX9_0_NIC_1"); | |
| EXPECT_EQ(json["Name"], "CX9_0_NIC_1"); | |
| EXPECT_EQ(json["Status"]["State"], "Enabled"); | |
| EXPECT_EQ(json["Status"]["Health"], "OK"); | |
| EXPECT_EQ(json["Manufacturer"], "NVIDIA"); | |
| EXPECT_EQ(json["Model"], "ConnectX-9"); | |
| EXPECT_EQ(json["PartNumber"], "900-9X81E-00EX-ST0"); | |
| EXPECT_EQ(json["SerialNumber"], "MT2601X00001"); | |
| EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "cx9_0"); | |
| EXPECT_EQ(json["Location"]["PartLocation"]["LocationType"], "Embedded"); | |
| EXPECT_EQ(json["Location"]["PartLocationContext"], "MIDPLANE/CX9_B_L"); | |
| EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"], | |
| "/phys/MIDPLANE/CX9_B_L:device:cx9_0"); | |
| EXPECT_EQ(json["Ports"]["@odata.id"], | |
| "/redfish/v1/Chassis/CX9_0/NetworkAdapters/CX9_0_NIC_1/Ports"); | |
| ASSERT_TRUE(json.contains("Controllers")); | |
| ASSERT_EQ(json["Controllers"].size(), 1); | |
| const nlohmann::json& controller = json["Controllers"][0]; | |
| EXPECT_EQ(controller["PCIeInterface"]["LanesInUse"], 16); | |
| EXPECT_EQ(controller["PCIeInterface"]["MaxLanes"], 16); | |
| EXPECT_EQ(controller["PCIeInterface"]["PCIeType"], "Gen6"); | |
| EXPECT_EQ(controller["PCIeInterface"]["MaxPCIeType"], "Gen6"); | |
| EXPECT_FALSE(controller["Links"].contains("PCIeDevices")); | |
| ASSERT_EQ(controller["Links"]["Ports"].size(), 2); | |
| EXPECT_EQ( | |
| controller["Links"]["Ports"][0]["@odata.id"], | |
| "/redfish/v1/Chassis/CX9_0/NetworkAdapters/CX9_0_NIC_1/Ports/Port_1"); | |
| EXPECT_EQ( | |
| controller["Links"]["Ports"][1]["@odata.id"], | |
| "/redfish/v1/Chassis/CX9_0/NetworkAdapters/CX9_0_NIC_1/Ports/Port_2"); | |
| } | |
| TEST_F( | |
| NetworkAdapterTest, | |
| GetNetworkAdapterDBusPldmOnlyFallsBackToEntityManagerChassisAndNsmPCIeDevice) { | |
| auto* mockStore = | |
| dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( | |
| managedStore::GetManagedObjectStore()); | |
| ASSERT_NE(mockStore, nullptr); | |
| managedStore::KeyType adapterSubTreeKey( | |
| ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.NetworkAdapter"}); | |
| dbus::utility::MapperGetSubTreeResponse adapterSubtree = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/CX9_1/CX9_1_NIC_1", | |
| {{"xyz.openbmc_project.PLDM", | |
| {"xyz.openbmc_project.Inventory.Item.NetworkAdapter"}}}}}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| adapterSubTreeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| adapterSubtree)) | |
| .ok()); | |
| managedStore::KeyType chassisLocCodeKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_1"), | |
| "xyz.openbmc_project.Inventory.Decorator.LocationCode", ""); | |
| dbus::utility::DBusPropertiesMap chassisLocCodeProps; | |
| chassisLocCodeProps.emplace_back( | |
| "LocationCode", dbus::utility::DbusVariantType(std::string("cx9_1"))); | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| chassisLocCodeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| chassisLocCodeProps)) | |
| .ok()); | |
| managedStore::KeyType chassisLocTypeKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_1"), | |
| "xyz.openbmc_project.Inventory.Decorator.Location", ""); | |
| dbus::utility::DBusPropertiesMap chassisLocTypeProps; | |
| chassisLocTypeProps.emplace_back( | |
| "LocationType", | |
| dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Decorator.Location.LocationTypes." | |
| "Embedded"))); | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| chassisLocTypeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| chassisLocTypeProps)) | |
| .ok()); | |
| managedStore::KeyType chassisContainedByKey( | |
| ManagedType::kManagedAssociatedSubtree, | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_1/contained_by", | |
| "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Board", | |
| "xyz.openbmc_project.Inventory.Item.Chassis"}); | |
| dbus::utility::MapperGetSubTreeResponse chassisContainedBy = { | |
| {"/xyz/openbmc_project/inventory/system/board/CX9_B_L", | |
| {{"xyz.openbmc_project.EntityManager", | |
| {"xyz.openbmc_project.Inventory.Item.Board"}}}}}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| chassisContainedByKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| chassisContainedBy)) | |
| .ok()); | |
| managedStore::KeyType carrierLocCodeKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/board/CX9_B_L"), | |
| "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode"); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| carrierLocCodeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(std::string("CX9_B_L")))) | |
| .ok()); | |
| managedStore::KeyType carrierContainedByKey( | |
| ManagedType::kManagedAssociatedSubtree, | |
| "/xyz/openbmc_project/inventory/system/board/CX9_B_L/contained_by", | |
| "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Board", | |
| "xyz.openbmc_project.Inventory.Item.Chassis"}); | |
| dbus::utility::MapperGetSubTreeResponse carrierContainedBy = { | |
| {"/xyz/openbmc_project/inventory/system/chassis/MIDPLANE", | |
| {{"xyz.openbmc_project.EntityManager", | |
| {"xyz.openbmc_project.Inventory.Item.Chassis"}}}}}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| carrierContainedByKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| carrierContainedBy)) | |
| .ok()); | |
| managedStore::KeyType midplaneLocCodeKey( | |
| ManagedType::kManagedProperty, "xyz.openbmc_project.EntityManager", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/MIDPLANE"), | |
| "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode"); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| midplaneLocCodeKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| dbus::utility::DbusVariantType(std::string("MIDPLANE")))) | |
| .ok()); | |
| managedStore::KeyType midplaneContainedByKey( | |
| ManagedType::kManagedAssociatedSubtree, | |
| "/xyz/openbmc_project/inventory/system/chassis/MIDPLANE/contained_by", | |
| "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Board", | |
| "xyz.openbmc_project.Inventory.Item.Chassis"}); | |
| dbus::utility::MapperGetSubTreeResponse midplaneContainedBy = {}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| midplaneContainedByKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| midplaneContainedBy)) | |
| .ok()); | |
| managedStore::KeyType nsmChassisAssetKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_1"), | |
| "xyz.openbmc_project.Inventory.Decorator.Asset", ""); | |
| dbus::utility::DBusPropertiesMap nsmChassisAssetProps; | |
| nsmChassisAssetProps.emplace_back( | |
| "Manufacturer", dbus::utility::DbusVariantType(std::string("NVIDIA"))); | |
| nsmChassisAssetProps.emplace_back( | |
| "Model", dbus::utility::DbusVariantType(std::string("ConnectX-9"))); | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| nsmChassisAssetKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| nsmChassisAssetProps)) | |
| .ok()); | |
| managedStore::KeyType pcieDeviceKey( | |
| ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM", | |
| sdbusplus::message::object_path( | |
| "/xyz/openbmc_project/inventory/system/chassis/CX9_1/PCIeDevices/" | |
| "CX9_1"), | |
| "xyz.openbmc_project.Inventory.Item.PCIeDevice", ""); | |
| dbus::utility::DBusPropertiesMap pcieProps; | |
| pcieProps.emplace_back("LanesInUse", | |
| dbus::utility::DbusVariantType(uint64_t{16})); | |
| pcieProps.emplace_back("MaxLanes", | |
| dbus::utility::DbusVariantType(uint64_t{16})); | |
| pcieProps.emplace_back( | |
| "PCIeType", | |
| dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Item.PCIeDevice.PCIeTypes.Gen6"))); | |
| pcieProps.emplace_back( | |
| "MaxPCIeType", | |
| dbus::utility::DbusVariantType(std::string( | |
| "xyz.openbmc_project.Inventory.Item.PCIeDevice.PCIeTypes.Gen6"))); | |
| EXPECT_TRUE( | |
| mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| pcieDeviceKey, | |
| managedStore::MockManagedStoreTest::CreateValueType(pcieProps)) | |
| .ok()); | |
| handleChassisNetworkAdapterGetDBus(share_async_resp_, "CX9_1", "CX9_1_NIC_1"); | |
| RunIoUntilDone(); | |
| EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); | |
| nlohmann::json& json = share_async_resp_->res.jsonValue; | |
| EXPECT_EQ(json["Manufacturer"], "NVIDIA"); | |
| EXPECT_EQ(json["Model"], "ConnectX-9"); | |
| EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "cx9_1"); | |
| EXPECT_EQ(json["Location"]["PartLocation"]["LocationType"], "Embedded"); | |
| EXPECT_EQ(json["Location"]["PartLocationContext"], "MIDPLANE/CX9_B_L"); | |
| EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"], | |
| "/phys/MIDPLANE/CX9_B_L:device:cx9_1"); | |
| ASSERT_TRUE(json.contains("Controllers")); | |
| ASSERT_EQ(json["Controllers"].size(), 1); | |
| EXPECT_EQ(json["Controllers"][0]["PCIeInterface"]["LanesInUse"], 16); | |
| EXPECT_EQ(json["Controllers"][0]["PCIeInterface"]["PCIeType"], "Gen6"); | |
| EXPECT_EQ(json["Controllers"][0]["PCIeInterface"]["MaxPCIeType"], "Gen6"); | |
| // Also cover explicit Devpath and unpack error handling in helper functions. | |
| dbus::utility::DBusPropertiesMap explicitDevpathProps; | |
| explicitDevpathProps.emplace_back( | |
| "Devpath", | |
| dbus::utility::DbusVariantType(std::string("/phys/explicit/devpath"))); | |
| applyNetworkAdapterLocationProperties(share_async_resp_, | |
| explicitDevpathProps); | |
| EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"], | |
| "/phys/explicit/devpath"); | |
| dbus::utility::DBusPropertiesMap invalidLocProps; | |
| invalidLocProps.emplace_back("LocationCode", | |
| dbus::utility::DbusVariantType(uint64_t{123})); | |
| applyNetworkAdapterLocationProperties(share_async_resp_, invalidLocProps); | |
| dbus::utility::DBusPropertiesMap invalidAssetProps; | |
| invalidAssetProps.emplace_back("Manufacturer", | |
| dbus::utility::DbusVariantType(uint64_t{123})); | |
| applyNetworkAdapterAssetProperties(share_async_resp_, invalidAssetProps); | |
| resolveNetworkAdapterUpstreamLocationContext( | |
| share_async_resp_, | |
| "/xyz/openbmc_project/inventory/system/chassis/MIDPLANE"); | |
| RunIoUntilDone(); | |
| managedStore::KeyType noLocContainedByKey( | |
| ManagedType::kManagedAssociatedSubtree, | |
| "/xyz/openbmc_project/inventory/system/chassis/NO_LOC_CHASSIS/" | |
| "contained_by", | |
| "/xyz/openbmc_project/inventory", 0, | |
| {"xyz.openbmc_project.Inventory.Item.Board", | |
| "xyz.openbmc_project.Inventory.Item.Chassis"}); | |
| dbus::utility::MapperGetSubTreeResponse noLocContainedBy = { | |
| {"/xyz/openbmc_project/inventory/system/board/NO_LOC_BOARD", | |
| {{"xyz.openbmc_project.EntityManager", | |
| {"xyz.openbmc_project.Inventory.Item.Board"}}}}}; | |
| EXPECT_TRUE(mockStore | |
| ->upsertMockObjectIntoManagedStore( | |
| noLocContainedByKey, | |
| managedStore::MockManagedStoreTest::CreateValueType( | |
| noLocContainedBy)) | |
| .ok()); | |
| resolveNetworkAdapterUpstreamLocationContext( | |
| share_async_resp_, | |
| "/xyz/openbmc_project/inventory/system/chassis/NO_LOC_CHASSIS"); | |
| RunIoUntilDone(); | |
| } | |
| } // namespace | |
| } // namespace redfish |