Implement LocationIndicatorActive for Fabric Port

This implements `LocationIndicatorActive` property for Fabric port using
the following methods.
- `getLocationIndicatorActive()`
- `setLocationIndicatorActive()`

Tested:
- Validator passes
- Run GET/PATCH of LocationIndicatorActive

```
$ curl -k -H "X-Auth-Token: $token" -X GET \
    https://${bmc}/redfish/v1/Systems/system/FabricAdapters/pcie_cable_card10/Ports/cxp_top
{

  "@odata.id": "/redfish/v1/Systems/system/FabricAdapters/ \
                pcie_cable_card10/Ports/cxp_top",
  "@odata.type": "#Port.v1_11_0.Port",
  "Id": "Port",
  "LocationIndicatorActive": true,
  "Name": "cxp_top"
}

$ curl -k -H "X-Auth-Token: $token" -X GET \
  https://${bmc}/redfish/v1/Systems/system/FabricAdapters/pcie_cable_card10/Ports/cxp_bot
{
  "@odata.id": "/redfish/v1/Systems/system/FabricAdapters/ \
                pcie_cable_card10/Ports/cxp_bot",
  "@odata.type": "#Port.v1_11_0.Port",
  "Id": "Port",
  "LocationIndicatorActive": false,
  "Name": "cxp_bot"
}
```

```
$ curl -k -H "Content-Type: application/json" -X PATCH -d \
  '{"LocationIndicatorActive":false}' \
  https://${bmc}/redfish/v1/Systems/system/FabricAdapters/pcie_cable_card10/Ports/cxp_top

$ curl -k -H "X-Auth-Token: $token" -X GET \
  https://${bmc}/redfish/v1/Systems/system/FabricAdapters/pcie_cable_card10/Ports/cxp_top
{
  "@odata.id": "/redfish/v1/Systems/system/FabricAdapters/ \
                pcie_cable_card10/Ports/cxp_top",
  "@odata.type": "#Port.v1_11_0.Port",
  "Id": "Port",
  "LocationIndicatorActive": false,
  "Name": "cxp_top"
}
```

Change-Id: I2cfe8a807cd6dc3bf3d6e50658b0d27a1253b887
Signed-off-by: Myung Bae <myungbae@us.ibm.com>
diff --git a/docs/Redfish.md b/docs/Redfish.md
index 41a6b9d..3b91880 100644
--- a/docs/Redfish.md
+++ b/docs/Redfish.md
@@ -866,6 +866,7 @@
 #### Port
 
 - Location
+- LocationIndicatorActive
 - Status
 
 ### /redfish/v1/Systems/system/LogServices/
diff --git a/redfish-core/lib/fabric_ports.hpp b/redfish-core/lib/fabric_ports.hpp
index ad6b75e..524e5d2 100644
--- a/redfish-core/lib/fabric_ports.hpp
+++ b/redfish-core/lib/fabric_ports.hpp
@@ -12,9 +12,11 @@
 #include "generated/enums/resource.hpp"
 #include "http_request.hpp"
 #include "human_sort.hpp"
+#include "led.hpp"
 #include "logging.hpp"
 #include "query.hpp"
 #include "registries/privilege_registry.hpp"
+#include "utils/json_utils.hpp"
 
 #include <asm-generic/errno.h>
 
@@ -28,6 +30,7 @@
 #include <array>
 #include <functional>
 #include <memory>
+#include <optional>
 #include <ranges>
 #include <string>
 #include <string_view>
@@ -158,6 +161,7 @@
     getFabricPortLocation(asyncResp, portPath, serviceName);
     getFabricPortState(asyncResp, portPath, serviceName);
     getFabricPortHealth(asyncResp, portPath, serviceName);
+    getLocationIndicatorActive(asyncResp, portPath);
 }
 
 inline void afterGetValidFabricPortPath(
@@ -424,6 +428,62 @@
         std::bind_front(doHandleFabricPortCollectionGet, asyncResp, systemName,
                         adapterId));
 }
+
+inline void afterHandlePortPatch(
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& portId, const bool locationIndicatorActive,
+    const std::string& portPath, const std::string& /*serviceName*/)
+{
+    if (portPath.empty())
+    {
+        BMCWEB_LOG_WARNING("Port not found");
+        messages::resourceNotFound(asyncResp->res, "Port", portId);
+        return;
+    }
+
+    setLocationIndicatorActive(asyncResp, portPath, locationIndicatorActive);
+}
+
+inline void handlePortPatch(App& app, const crow::Request& req,
+                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                            const std::string& systemName,
+                            const std::string& adapterId,
+                            const std::string& portId)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+    if constexpr (BMCWEB_EXPERIMENTAL_REDFISH_MULTI_COMPUTER_SYSTEM)
+    {
+        // Option currently returns no systems.  TBD
+        messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+                                   systemName);
+        return;
+    }
+    if (systemName != BMCWEB_REDFISH_SYSTEM_URI_NAME)
+    {
+        messages::resourceNotFound(asyncResp->res, "ComputerSystem",
+                                   systemName);
+        return;
+    }
+
+    std::optional<bool> locationIndicatorActive;
+    if (!json_util::readJsonPatch(req, asyncResp->res,
+                                  "LocationIndicatorActive",
+                                  locationIndicatorActive))
+    {
+        return;
+    }
+    if (locationIndicatorActive)
+    {
+        getValidFabricPortPath(
+            asyncResp, adapterId, portId,
+            std::bind_front(afterHandlePortPatch, asyncResp, portId,
+                            *locationIndicatorActive));
+    }
+}
+
 inline void requestRoutesFabricPort(App& app)
 {
     BMCWEB_ROUTE(app,
@@ -447,6 +507,12 @@
         .privileges(redfish::privileges::getPortCollection)
         .methods(boost::beast::http::verb::get)(
             std::bind_front(handleFabricPortCollectionGet, std::ref(app)));
+
+    BMCWEB_ROUTE(app,
+                 "/redfish/v1/Systems/<str>/FabricAdapters/<str>/Ports/<str>/")
+        .privileges(redfish::privileges::patchPort)
+        .methods(boost::beast::http::verb::patch)(
+            std::bind_front(handlePortPatch, std::ref(app)));
 }
 
 } // namespace redfish