BMCNet: add service label for direct and side path interface

Read service label from EM config and build the full devpath.

Tested: https://paste.googleplex.com/5311451901984768
Google-Bug-Id: 423003861
Fusion-Link: https://fusion2.corp.google.com/ci/guitar/projects/null/activity/ef260aee-26e0-4c19-93f3-889f6798f469/overview
https://fusion2.corp.google.com/ci/guitar/projects/null/activity/5a178d4b-ceed-43a0-8f48-b5ea3fd929f8/overview
Change-Id: I8cd03be2dd5f2f1c9edff8aeb3cbba0440792975
Signed-off-by: Yuxiao Zhang <yuxiaozhang@google.com>
diff --git a/config/bmcweb_config.h.in b/config/bmcweb_config.h.in
index 1879717..0f11993 100644
--- a/config/bmcweb_config.h.in
+++ b/config/bmcweb_config.h.in
@@ -80,4 +80,7 @@
 constexpr const char* snapshotFilepath_platform5_config0 = "@SNAPSHOT_FILEPATH_PLATFORM5_CONFIG0@";
 
 constexpr const char* sysfsNetBasePathUT = "@SYSFS_BASE_PATH_UT@/sys/class/net";
+
+constexpr const char* bmcDirectPathIntf = "@BMC_DIRECT_PATH_INTF@";
+constexpr const char* bmcSidePathIntf = "@BMC_SIDE_PATH_INTF@";
 // clang-format on
diff --git a/config/meson.build b/config/meson.build
index b5b425f..3a5c3c6 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -67,6 +67,10 @@
 # gBMCweb sysfs UT
 conf_data.set('SYSFS_BASE_PATH_UT', get_option('sysfs-base-path-ut'))
 
+# BMCNet metric interface
+conf_data.set('BMC_DIRECT_PATH_INTF', get_option('bmc-direct-path-intf'))
+conf_data.set('BMC_SIDE_PATH_INTF', get_option('bmc-side-path-intf'))
+
 conf_h_dep = declare_dependency(
     include_directories: include_directories('.'),
     sources: configure_file(
diff --git a/meson_options.txt b/meson_options.txt
index d0a9c39..f2a2f61 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -841,3 +841,7 @@
 )
 
 option('extra-service-flags', type: 'string', description: 'Extra service flags to pass into the authz_server service')
+
+option('bmc-direct-path-intf', type: 'string', value: 'front', description: 'BMC direct path network interface name')
+
+option('bmc-side-path-intf', type: 'string', value: 'ncsi', description: 'BMC side path network interface name')
diff --git a/redfish-core/include/utils/location_utils.hpp b/redfish-core/include/utils/location_utils.hpp
index 85e0d73..980e861 100644
--- a/redfish-core/include/utils/location_utils.hpp
+++ b/redfish-core/include/utils/location_utils.hpp
@@ -57,7 +57,14 @@
                             const nlohmann::json::json_pointer& jsonPtr,
                             const std::string& associationPath,
                             const std::string& locationCode = "");
+
+void getOemDevpathLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                           const nlohmann::json::json_pointer& jsonPtr,
+                           const std::string& associationPath,
+                           const std::string& locationCode = "");
+
 /**
+ *
  * @brief Fill out location code of a resource by requesting data from the
  * given D-Bus object.
  *
@@ -125,6 +132,41 @@
 }
 
 /**
+ * @brief Fill out Oem devpath of a redfish resource.
+ *
+ * @param[in,out]   asyncResp  Async HTTP response
+ * @param[in]       jsonPtr    Json path of where to put the Oem Devpath
+ * @param[in]       label      Service label to update the Oem Devpath with
+ */
+inline void updateLocationOemDevpath(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const nlohmann::json::json_pointer& jsonPtr, const std::string& label)
+{
+    BMCWEB_LOG_DEBUG << "update devpath" << label << "to Oem/Google/Devpath";
+    const std::string prefix = "/phys/";
+    nlohmann::json& propertyJson =
+        asyncResp->res.jsonValue[jsonPtr]["Oem"]["Google"]["Devpath"];
+    std::string* val = propertyJson.get_ptr<std::string*>();
+    if (val != nullptr && !val->empty())
+    {
+        if (val->rfind(prefix, 0) == 0)
+        {
+            val->erase(0, prefix.length());
+            propertyJson = prefix + label + "/" + *val;
+        }
+        else
+        {
+            BMCWEB_LOG_ERROR << "Oem devpath " << *val << " missing /phys/";
+            return;
+        }
+    }
+    else
+    {
+        propertyJson = prefix + label;
+    }
+}
+
+/**
  * @brief Parses given chassis subtree for object path and connection to retrive
  * chassis location code used to fill PartLocationContext.
  *
@@ -136,7 +178,7 @@
 inline void getAssociatedChassisSubtreeCallback(
     std::unordered_set<std::string> upstreamChassisPaths,
     const nlohmann::json::json_pointer& jsonPtr,
-    const std::string& currentLocationCode,
+    const std::string& currentLocationCode, const bool isOemDevpath,
     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
     const dbus::utility::MapperGetSubTreeResponse& subtree)
 {
@@ -193,8 +235,9 @@
         "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
         requestContext,
         [asyncResp, jsonPtr, chassisPath, currentLocationCode,
-         upstreamChassisPaths](const boost::system::error_code ec2,
-                               const std::string& locationCode) {
+         upstreamChassisPaths,
+         isOemDevpath](const boost::system::error_code ec2,
+                       const std::string& locationCode) {
         if (ec2)
         {
             BMCWEB_LOG_DEBUG << "DBUS response error for Location, ec: "
@@ -203,9 +246,19 @@
         }
 
         std::string nextLocationCode;
-        if (currentLocationCode != locationCode) {
-            updateLocationContext(asyncResp, jsonPtr, locationCode);
-        } else {
+        if (currentLocationCode != locationCode)
+        {
+            if (!isOemDevpath)
+            {
+                updateLocationContext(asyncResp, jsonPtr, locationCode);
+            }
+            else
+            {
+                updateLocationOemDevpath(asyncResp, jsonPtr, locationCode);
+            }
+        }
+        else
+        {
             // Continue checking to see if the locationCode matches
             nextLocationCode = currentLocationCode;
         }
@@ -213,8 +266,9 @@
         chassis_utils::getAssociatedChassisSubtree(
             asyncResp, chassisPath + "/contained_by",
             std::bind_front(getAssociatedChassisSubtreeCallback,
-                            upstreamChassisPaths, jsonPtr, nextLocationCode));
-        });
+                            upstreamChassisPaths, jsonPtr, nextLocationCode,
+                            isOemDevpath));
+    });
 }
 
 /**
@@ -238,7 +292,34 @@
     chassis_utils::getAssociatedChassisSubtree(
         asyncResp, associationPath,
         std::bind_front(getAssociatedChassisSubtreeCallback,
-                        std::move(upstreamChassisPaths), jsonPtr, locationCode));
+                        std::move(upstreamChassisPaths), jsonPtr, locationCode,
+                        false));
+}
+
+/**
+ * @brief Recursively gets LocationCode for upstream chassis to populate oem
+ * devpath. This translates "/phys/A/SL" to "/phys/.../DC_DC_A/DC_A/A/SL"
+ *
+ * @param[in,out]   asyncResp       Async HTTP response
+ * @param[in]       jsonPtr         Json location to fill PartLocationContext
+ * @param[in]       associationPath Path used to associate with upstream chassis
+ */
+inline void
+    getOemDevpathLocation(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                          const nlohmann::json::json_pointer& jsonPtr,
+                          const std::string& associationPath,
+                          const std::string& locationCode)
+{
+    BMCWEB_LOG_DEBUG << "Get chassis endpoints associated with "
+                     << associationPath << " for oem devpath";
+    // Set of chassis object paths used to detect cycle as we resolve usptream
+    // chassis associations to get to root chassis to create PartLocationContext
+    std::unordered_set<std::string> upstreamChassisPaths;
+    chassis_utils::getAssociatedChassisSubtree(
+        asyncResp, associationPath,
+        std::bind_front(getAssociatedChassisSubtreeCallback,
+                        std::move(upstreamChassisPaths), jsonPtr, locationCode,
+                        true));
 }
 
 /**
diff --git a/redfish-core/lib/network_adapter.hpp b/redfish-core/lib/network_adapter.hpp
index dc30726..cfedcf7 100644
--- a/redfish-core/lib/network_adapter.hpp
+++ b/redfish-core/lib/network_adapter.hpp
@@ -243,7 +243,7 @@
     asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
         "redfish", "v1", "Chassis", chassisId, "NetworkAdapters");
     asyncResp->res.jsonValue["Name"] =
-        "Network adapter Collection for chassis bmc";
+        "Network adapter Collection for chassis " + chassisId;
     nlohmann::json& members = asyncResp->res.jsonValue["Members"];
     members = nlohmann::json::array();
     nlohmann::json::object_t member;
@@ -674,14 +674,113 @@
     asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
         "redfish", "v1", "Chassis", chassisId, "NetworkAdapters",
         networkAdapterId, "Ports", portId);
+    asyncResp->res.jsonValue["Id"] = portId;
     asyncResp->res.jsonValue["Metrics"]["@odata.id"] =
         crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId,
                                      "NetworkAdapters", networkAdapterId,
                                      "Ports", portId, "Metrics");
-    if (portId == "front")
+    if (portId == bmcDirectPathIntf)
     {
-        asyncResp->res.jsonValue["Locations"]["ServiceLable"] =
-            "FrontServiceLable";
+        managedStore::ManagedObjectStoreContext requestContext(asyncResp);
+        dbus_utils::getProperty<std::string>(
+            "xyz.openbmc_project.EntityManager",
+            "/xyz/openbmc_project/inventory/system/board/" + chassisId +
+                "/BmcNet",
+            "xyz.openbmc_project.Configuration.BmcNet", "LocationCode",
+            requestContext,
+            [asyncResp, chassisId](const boost::system::error_code& ec,
+                                   const std::string& locationCode) {
+            if (ec)
+            {
+                BMCWEB_LOG_ERROR << "Fail to get LocationCode for front cable: "
+                                 << ec.what();
+                return;
+            }
+            // Get Chassis location code
+            managedStore::ManagedObjectStoreContext requestContext2(asyncResp);
+            dbus_utils::getProperty<std::string>(
+                "xyz.openbmc_project.EntityManager",
+                "/xyz/openbmc_project/inventory/system/board/" + chassisId,
+                "xyz.openbmc_project.Inventory.Decorator.LocationCode",
+                "LocationCode", requestContext2,
+                [asyncResp, locationCode,
+                 chassisId](const boost::system::error_code& ec2,
+                            const std::string& chassisLocationCode) {
+                if (ec2)
+                {
+                    BMCWEB_LOG_ERROR << "Fail to get LocationCode for chassis: "
+                                     << ec2.what();
+                    return;
+                }
+                asyncResp->res
+                    .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
+                    locationCode;
+                asyncResp->res.jsonValue["Oem"]["Google"]["ConnectionPath"] =
+                    "DIRECT";
+                asyncResp->res
+                    .jsonValue["Location"]["Oem"]["Google"]["Devpath"] =
+                    "/phys/" + chassisLocationCode + "/" + locationCode;
+                // recursively find the full devpath for this chassis
+                redfish::location_util::getOemDevpathLocation(
+                    asyncResp, "/Location"_json_pointer,
+                    "/xyz/openbmc_project/inventory/system/board/" + chassisId +
+                        "/contained_by");
+            });
+        });
+    }
+    else if (portId == bmcSidePathIntf)
+    {
+        constexpr std::array<std::string_view, 1> interfaces = {
+            "xyz.openbmc_project.Configuration.Port"};
+        managedStore::ManagedObjectStoreContext requestContext3(asyncResp);
+        managedStore::GetManagedObjectStore()->getSubTreePaths(
+            "/xyz/openbmc_project/inventory/system/cable/", 0, interfaces,
+            requestContext3,
+            [asyncResp, portId](
+                const boost::system::error_code& ec3,
+                const dbus::utility::MapperGetSubTreePathsResponse& cableList) {
+            if (ec3)
+            {
+                BMCWEB_LOG_ERROR << "Fail to get subtree for cables: "
+                                 << ec3.what();
+                return;
+            }
+            for (const auto& pathStr : cableList)
+            {
+                if (pathStr.size() - portId.size() > 0 &&
+                    pathStr.substr(pathStr.size() - portId.size()) == portId)
+                {
+                    // get the cable location code
+                    managedStore::ManagedObjectStoreContext requestContext4(
+                        asyncResp);
+                    dbus_utils::getProperty<std::string>(
+                        "xyz.openbmc_project.EntityManager",
+                        pathStr.substr(0, pathStr.size() - portId.size() - 1),
+                        "xyz.openbmc_project.Inventory.Decorator.LocationCode",
+                        "LocationCode", requestContext4,
+                        [asyncResp](const boost::system::error_code& ec4,
+                                    const std::string& cableLocationCode) {
+                        if (ec4)
+                        {
+                            BMCWEB_LOG_ERROR
+                                << "Fail to get LocationCode for cable: "
+                                << ec4.what();
+                            return;
+                        }
+                        asyncResp->res.jsonValue["Location"]["PartLocation"]
+                                                ["ServiceLabel"] =
+                            cableLocationCode;
+                        asyncResp->res
+                            .jsonValue["Location"]["Oem"]["Google"]["Devpath"] =
+                            "/phys/" + cableLocationCode;
+                        asyncResp->res
+                            .jsonValue["Oem"]["Google"]["ConnectionPath"] =
+                            "SIDE";
+                    });
+                    break;
+                }
+            }
+        });
     }
 
     std::vector<std::string> ethList = sysfsGetEthAddrList(portId);
diff --git a/test/redfish-core/lib/network_adapter_test.cpp b/test/redfish-core/lib/network_adapter_test.cpp
index e00e060..79e4c25 100644
--- a/test/redfish-core/lib/network_adapter_test.cpp
+++ b/test/redfish-core/lib/network_adapter_test.cpp
@@ -5,12 +5,30 @@
 #include "http_response.hpp"
 #include "network_adapter.hpp"
 #include "snapshot_fixture.hpp"
+#include "test/g3/mock_managed_store_test.hpp"
 
 #include <nlohmann/json.hpp>
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+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::ManagedObjectStoreContext;
+using ::managedStore::ManagedType;
+using ::managedStore::SimulateFailedAsyncPostDbusCallThreadSafeAction;
+using ::managedStore::
+    SimulateFailedAsyncPostDbusCallThreadSafeWithEmptyValueAction;
+using ::managedStore::SimulateFailedAsyncSetPropertyDbusCallAction;
+using ::managedStore::SimulateSuccessfulAsyncPostDbusCallThreadSafeAction;
+using ::managedStore::
+    SimulateSuccessfulAsyncPostDbusCallThreadSafeWithValueAction;
+using ::managedStore::SimulateSuccessfulAsyncSetPropertyDbusCallAction;
+using ::managedStore::ValueType;
 using ::testing::Contains;
 
 namespace redfish
@@ -18,69 +36,90 @@
 namespace
 {
 
+MapperGetSubTreePathsResponse CreateMockNcsiSubTree(){
+    return MapperGetSubTreePathsResponse(
+        {"/xyz/openbmc_project/inventory/system/cable/NcsiCable/ncsi"});
+}
+
 TEST_F(SnapshotFixture, GetNetworkAdaptersReturnsCorrectResponse)
 {
-    handleChassisNetworkAdapterCollectionGetSysfs(share_async_resp_, "bmc");
+    handleChassisNetworkAdapterCollectionGetSysfs(share_async_resp_,
+                                                  "chassis1V2ND");
 
     nlohmann::json& json = share_async_resp_->res.jsonValue;
-    EXPECT_EQ(json["@odata.id"], "/redfish/v1/Chassis/bmc/NetworkAdapters");
+    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 bmc");
-    EXPECT_THAT(
-        json["Members"],
-        Contains(nlohmann::json(
-            {{"@odata.id", "/redfish/v1/Chassis/bmc/NetworkAdapters/0"}})));
+    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(SnapshotFixture, GetNetworkAdapterReturnsCorrectResponse)
 {
-    handleChassisNetworkAdapterGetSysfs(share_async_resp_, "bmc", "0");
+    handleChassisNetworkAdapterGetSysfs(share_async_resp_, "chassis1V2ND", "0");
 
     nlohmann::json& json = share_async_resp_->res.jsonValue;
-    EXPECT_EQ(json["@odata.id"], "/redfish/v1/Chassis/bmc/NetworkAdapters/0");
+    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/bmc/NetworkAdapters/0/Ports");
+              "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports");
 }
 
 TEST_F(SnapshotFixture, GetPortCollectionReturnsCorrectResponse)
 {
-    handleNetworkPortCollectionGetSysfs(share_async_resp_, "bmc", "0");
+    handleNetworkPortCollectionGetSysfs(share_async_resp_, "chassis1V2ND", "0");
 
     nlohmann::json& json = share_async_resp_->res.jsonValue;
     EXPECT_EQ(json["@odata.id"],
-              "/redfish/v1/Chassis/bmc/NetworkAdapters/0/Ports");
+              "/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/bmc/NetworkAdapters/0/Ports/ncsi"}})));
+              "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/ncsi"}})));
     EXPECT_THAT(
         json["Members"],
         Contains(nlohmann::json(
             {{"@odata.id",
-              "/redfish/v1/Chassis/bmc/NetworkAdapters/0/Ports/gusbem0"}})));
+              "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/gusbem0"}})));
     EXPECT_THAT(
         json["Members"],
         Contains(nlohmann::json(
             {{"@odata.id",
-              "/redfish/v1/Chassis/bmc/NetworkAdapters/0/Ports/front"}})));
+              "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front"}})));
     EXPECT_EQ(json["Members@odata.count"], 3);
     EXPECT_EQ(json["Name"], "Network ports");
 }
 
 TEST_F(SnapshotFixture, GetPortsReturnsCorrectResponse1)
 {
-    handleNetworkPortGetSysfs(share_async_resp_, "bmc", "0", "ncsi");
 
+    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(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/bmc/NetworkAdapters/0/Ports/ncsi");
+              "/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"],
@@ -88,18 +127,26 @@
     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/bmc/NetworkAdapters/0/Ports/ncsi/Metrics");
+    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(SnapshotFixture, GetPortsReturnsCorrectResponse2)
 {
-    handleNetworkPortGetSysfs(share_async_resp_, "bmc", "0", "gusbem0");
 
+    handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0",
+                              "gusbem0");
+    RunIoUntilDone();
     nlohmann::json& json = share_async_resp_->res.jsonValue;
-    EXPECT_EQ(json["@odata.id"],
-              "/redfish/v1/Chassis/bmc/NetworkAdapters/0/Ports/gusbem0");
+    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"],
@@ -109,17 +156,29 @@
     EXPECT_EQ(json["LinkStatus"], "LinkUp");
     EXPECT_EQ(
         json["Metrics"]["@odata.id"],
-        "/redfish/v1/Chassis/bmc/NetworkAdapters/0/Ports/gusbem0/Metrics");
+        "/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/gusbem0/Metrics");
 }
 
 TEST_F(SnapshotFixture, GetPortsReturnsCorrectResponse3)
 {
-    handleNetworkPortGetSysfs(share_async_resp_, "bmc", "0", "front");
+    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(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/bmc/NetworkAdapters/0/Ports/front");
+              "/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"],
@@ -127,18 +186,24 @@
     EXPECT_EQ(json["Ethernet"]["AssociatedMACAddresses"].size(), 1);
     EXPECT_EQ(json["LinkState"], "Enabled");
     EXPECT_EQ(json["LinkStatus"], "LinkUp");
-    EXPECT_EQ(json["Locations"]["ServiceLable"], "FrontServiceLable");
-    EXPECT_EQ(json["Metrics"]["@odata.id"],
-              "/redfish/v1/Chassis/bmc/NetworkAdapters/0/Ports/front/Metrics");
+    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(SnapshotFixture, GetNetworkPortMetricReturnsCorrectResponse1)
 {
-    handleNetworkPortMetricGetSysfs(share_async_resp_, "bmc", "0", "ncsi");
+    handleNetworkPortMetricGetSysfs(share_async_resp_, "chassis1V2ND", "0",
+                                    "ncsi");
 
     nlohmann::json& json = share_async_resp_->res.jsonValue;
-    EXPECT_EQ(json["@odata.id"],
-              "/redfish/v1/Chassis/bmc/NetworkAdapters/0/Ports/ncsi/Metrics");
+    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);
@@ -150,12 +215,13 @@
 
 TEST_F(SnapshotFixture, GetNetworkPortMetricReturnsCorrectResponse2)
 {
-    handleNetworkPortMetricGetSysfs(share_async_resp_, "bmc", "0", "gusbem0");
+    handleNetworkPortMetricGetSysfs(share_async_resp_, "chassis1V2ND", "0",
+                                    "gusbem0");
 
     nlohmann::json& json = share_async_resp_->res.jsonValue;
     EXPECT_EQ(
         json["@odata.id"],
-        "/redfish/v1/Chassis/bmc/NetworkAdapters/0/Ports/gusbem0/Metrics");
+        "/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);
@@ -167,11 +233,13 @@
 
 TEST_F(SnapshotFixture, GetNetworkPortMetricReturnsCorrectResponse3)
 {
-    handleNetworkPortMetricGetSysfs(share_async_resp_, "bmc", "0", "front");
+    handleNetworkPortMetricGetSysfs(share_async_resp_, "chassis1V2ND", "0",
+                                    "front");
 
     nlohmann::json& json = share_async_resp_->res.jsonValue;
-    EXPECT_EQ(json["@odata.id"],
-              "/redfish/v1/Chassis/bmc/NetworkAdapters/0/Ports/front/Metrics");
+    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);