blob: 668d8e47b27793dcbbd1fc91b9537acb1edf1e37 [file]
#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