Refactor SystemPCIeFunction method
Move SystemPCIeFunction to a separate method, and refactor the code.
Validate the PCIe device path and add link header.
Tested: Validator passed
```
{
"@odata.id": "/redfish/v1/Systems/system/PCIeDevices/pcie_card7/PCIeFunctions/0",
"@odata.type": "#PCIeFunction.v1_2_3.PCIeFunction",
"ClassCode": "0x020000",
"DeviceId": "0x1657",
"FunctionId": 0,
"Id": "0",
"Links": {
"PCIeDevice": {
"@odata.id": "/redfish/v1/Systems/system/PCIeDevices/pcie_card7"
}
},
"Name": "PCIe Function",
"RevisionId": "0x01",
"SubsystemId": "0x0420",
"SubsystemVendorId": "0x1014",
"VendorId": "0x14e4"
}
```
Change-Id: I99add03210983a255a615512b6137d04982f83a5
Signed-off-by: Lakshmi Yadlapati <lakshmiy@us.ibm.com>
diff --git a/redfish-core/lib/pcie.hpp b/redfish-core/lib/pcie.hpp
index 4bf5626..f38ab51 100644
--- a/redfish-core/lib/pcie.hpp
+++ b/redfish-core/lib/pcie.hpp
@@ -442,6 +442,130 @@
std::bind_front(handlePCIeFunctionCollectionGet, std::ref(app)));
}
+inline bool validatePCIeFunctionId(
+ const std::string& pcieFunctionId,
+ const dbus::utility::DBusPropertiesMap& pcieDevProperties)
+{
+ std::string functionName = "Function" + pcieFunctionId;
+ std::string devIDProperty = functionName + "DeviceId";
+
+ const std::string* devIdProperty = nullptr;
+ for (const auto& property : pcieDevProperties)
+ {
+ if (property.first == devIDProperty)
+ {
+ devIdProperty = std::get_if<std::string>(&property.second);
+ break;
+ }
+ }
+ return (devIdProperty != nullptr && !devIdProperty->empty());
+}
+
+inline void addPCIeFunctionProperties(
+ crow::Response& resp, const std::string& pcieFunctionId,
+ const dbus::utility::DBusPropertiesMap& pcieDevProperties)
+{
+ std::string functionName = "Function" + pcieFunctionId;
+ if (!validatePCIeFunctionId(pcieFunctionId, pcieDevProperties))
+ {
+ messages::resourceNotFound(resp, "PCIeFunction", pcieFunctionId);
+ return;
+ }
+ for (const auto& property : pcieDevProperties)
+ {
+ const std::string* strProperty =
+ std::get_if<std::string>(&property.second);
+
+ if (property.first == functionName + "DeviceId")
+ {
+ resp.jsonValue["DeviceId"] = *strProperty;
+ }
+ if (property.first == functionName + "VendorId")
+ {
+ resp.jsonValue["VendorId"] = *strProperty;
+ }
+ // TODO: FunctionType and DeviceClass are Redfish enums. The D-Bus
+ // property strings should be mapped correctly to ensure these
+ // strings are Redfish enum values. For now just check for empty.
+ if (property.first == functionName + "FunctionType")
+ {
+ if (!strProperty->empty())
+ {
+ resp.jsonValue["FunctionType"] = *strProperty;
+ }
+ }
+ if (property.first == functionName + "DeviceClass")
+ {
+ if (!strProperty->empty())
+ {
+ resp.jsonValue["DeviceClass"] = *strProperty;
+ }
+ }
+ if (property.first == functionName + "ClassCode")
+ {
+ resp.jsonValue["ClassCode"] = *strProperty;
+ }
+ if (property.first == functionName + "RevisionId")
+ {
+ resp.jsonValue["RevisionId"] = *strProperty;
+ }
+ if (property.first == functionName + "SubsystemId")
+ {
+ resp.jsonValue["SubsystemId"] = *strProperty;
+ }
+ if (property.first == functionName + "SubsystemVendorId")
+ {
+ resp.jsonValue["SubsystemVendorId"] = *strProperty;
+ }
+ }
+}
+
+inline void addPCIeFunctionCommonProperties(crow::Response& resp,
+ const std::string& pcieDeviceId,
+ const std::string& pcieFunctionId)
+{
+ resp.addHeader(
+ boost::beast::http::field::link,
+ "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
+ resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
+ resp.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
+ "redfish", "v1", "Systems", "system", "PCIeDevices", pcieDeviceId,
+ "PCIeFunctions", pcieFunctionId);
+ resp.jsonValue["Name"] = "PCIe Function";
+ resp.jsonValue["Id"] = pcieFunctionId;
+ resp.jsonValue["FunctionId"] = std::stoi(pcieFunctionId);
+ resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
+ crow::utility::urlFromPieces("redfish", "v1", "Systems", "system",
+ "PCIeDevices", pcieDeviceId);
+}
+
+inline void
+ handlePCIeFunctionGet(App& app, const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& aResp,
+ const std::string& pcieDeviceId,
+ const std::string& pcieFunctionId)
+{
+ if (!redfish::setUpRedfishRoute(app, req, aResp))
+ {
+ return;
+ }
+
+ getValidPCIeDevicePath(
+ pcieDeviceId, aResp,
+ [aResp, pcieDeviceId, pcieFunctionId](const std::string& pcieDevicePath,
+ const std::string& service) {
+ getPCIeDeviceProperties(
+ aResp, pcieDevicePath, service,
+ [aResp, pcieDeviceId, pcieFunctionId](
+ const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
+ addPCIeFunctionCommonProperties(aResp->res, pcieDeviceId,
+ pcieFunctionId);
+ addPCIeFunctionProperties(aResp->res, pcieFunctionId,
+ pcieDevProperties);
+ });
+ });
+}
+
inline void requestRoutesSystemPCIeFunction(App& app)
{
BMCWEB_ROUTE(
@@ -449,114 +573,7 @@
"/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/")
.privileges(redfish::privileges::getPCIeFunction)
.methods(boost::beast::http::verb::get)(
- [&app](const crow::Request& req,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
- const std::string& device, const std::string& function) {
- if (!redfish::setUpRedfishRoute(app, req, asyncResp))
- {
- return;
- }
- auto getPCIeDeviceCallback =
- [asyncResp, device, function](
- const boost::system::error_code& ec,
- const dbus::utility::DBusPropertiesMap& pcieDevProperties) {
- if (ec)
- {
- BMCWEB_LOG_DEBUG
- << "failed to get PCIe Device properties ec: " << ec.value()
- << ": " << ec.message();
- if (ec.value() ==
- boost::system::linux_error::bad_request_descriptor)
- {
- messages::resourceNotFound(asyncResp->res, "PCIeDevice",
- device);
- }
- else
- {
- messages::internalError(asyncResp->res);
- }
- return;
- }
-
- // Check if this function exists by looking for a device
- // ID
- std::string functionName = "Function" + function;
- std::string devIDProperty = functionName + "DeviceId";
-
- const std::string* devIdProperty = nullptr;
- for (const auto& property : pcieDevProperties)
- {
- if (property.first == devIDProperty)
- {
- devIdProperty = std::get_if<std::string>(&property.second);
- continue;
- }
- }
- if (devIdProperty == nullptr || devIdProperty->empty())
- {
- messages::resourceNotFound(asyncResp->res, "PCIeFunction",
- function);
- return;
- }
-
- asyncResp->res.jsonValue["@odata.type"] =
- "#PCIeFunction.v1_2_0.PCIeFunction";
- asyncResp->res.jsonValue["@odata.id"] =
- crow::utility::urlFromPieces("redfish", "v1", "Systems",
- "system", "PCIeDevices", device,
- "PCIeFunctions", function);
- asyncResp->res.jsonValue["Name"] = "PCIe Function";
- asyncResp->res.jsonValue["Id"] = function;
- asyncResp->res.jsonValue["FunctionId"] = std::stoi(function);
- asyncResp->res.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
- crow::utility::urlFromPieces("redfish", "v1", "Systems",
- "system", "PCIeDevices", device);
-
- for (const auto& property : pcieDevProperties)
- {
- const std::string* strProperty =
- std::get_if<std::string>(&property.second);
- if (property.first == functionName + "DeviceId")
- {
- asyncResp->res.jsonValue["DeviceId"] = *strProperty;
- }
- if (property.first == functionName + "VendorId")
- {
- asyncResp->res.jsonValue["VendorId"] = *strProperty;
- }
- if (property.first == functionName + "FunctionType")
- {
- asyncResp->res.jsonValue["FunctionType"] = *strProperty;
- }
- if (property.first == functionName + "DeviceClass")
- {
- asyncResp->res.jsonValue["DeviceClass"] = *strProperty;
- }
- if (property.first == functionName + "ClassCode")
- {
- asyncResp->res.jsonValue["ClassCode"] = *strProperty;
- }
- if (property.first == functionName + "RevisionId")
- {
- asyncResp->res.jsonValue["RevisionId"] = *strProperty;
- }
- if (property.first == functionName + "SubsystemId")
- {
- asyncResp->res.jsonValue["SubsystemId"] = *strProperty;
- }
- if (property.first == functionName + "SubsystemVendorId")
- {
- asyncResp->res.jsonValue["SubsystemVendorId"] =
- *strProperty;
- }
- }
- };
- std::string escapedPath = std::string(pciePath) + "/" + device;
- dbus::utility::escapePathForDbus(escapedPath);
- sdbusplus::asio::getAllProperties(
- *crow::connections::systemBus, pcieService, escapedPath,
- pcieDeviceInterface, std::move(getPCIeDeviceCallback));
- });
+ std::bind_front(handlePCIeFunctionGet, std::ref(app)));
}
} // namespace redfish