diff options
author | Jason M. Bills <jason.m.bills@linux.intel.com> | 2018-12-19 03:51:18 +0300 |
---|---|---|
committer | Ed Tanous <ed.tanous@intel.com> | 2019-07-11 04:26:07 +0300 |
commit | f5c9f8bda365b90c978a95738b66419ad21df27f (patch) | |
tree | 7a4f6a1c75a9312323fd099de3d06edfb829430e | |
parent | 7052517fd63c5ed8bd16bc5225c4992a23a176f6 (diff) | |
download | bmcweb-f5c9f8bda365b90c978a95738b66419ad21df27f.tar.xz |
Add Redfish PCIe information
This adds the capability to get PCIe device information from
D-Bus and display it in the appropriate Redfish PCIeDevice
and PCIeFunction objects.
Tested: Passed the Redfish validator for the new PCIeDevice
and PCIeFunction objects.
Change-Id: I06f3b0e7d283e48d2235b7d34f78f603b22de79f
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
-rw-r--r-- | redfish-core/include/redfish.hpp | 5 | ||||
-rw-r--r-- | redfish-core/lib/pcie.hpp | 345 | ||||
-rw-r--r-- | redfish-core/lib/systems.hpp | 2 |
3 files changed, 352 insertions, 0 deletions
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp index 44cc74c0f5..21d6500ffd 100644 --- a/redfish-core/include/redfish.hpp +++ b/redfish-core/include/redfish.hpp @@ -24,6 +24,7 @@ #include "../lib/managers.hpp" #include "../lib/message_registries.hpp" #include "../lib/network_protocol.hpp" +#include "../lib/pcie.hpp" #include "../lib/power.hpp" #include "../lib/redfish_sessions.hpp" #include "../lib/roles.hpp" @@ -132,6 +133,10 @@ class RedfishService nodes.emplace_back(std::make_unique<HTTPSCertificate>(app)); nodes.emplace_back(std::make_unique<LDAPCertificateCollection>(app)); nodes.emplace_back(std::make_unique<LDAPCertificate>(app)); + + nodes.emplace_back(std::make_unique<SystemPCIeFunction>(app)); + nodes.emplace_back(std::make_unique<SystemPCIeDevice>(app)); + for (const auto& node : nodes) { node->initPrivileges(); diff --git a/redfish-core/lib/pcie.hpp b/redfish-core/lib/pcie.hpp new file mode 100644 index 0000000000..6b8600f081 --- /dev/null +++ b/redfish-core/lib/pcie.hpp @@ -0,0 +1,345 @@ +/* +// Copyright (c) 2018 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#pragma once + +#include "node.hpp" + +#include <boost/system/linux_error.hpp> + +namespace redfish +{ + +static constexpr char const *pcieService = "xyz.openbmc_project.PCIe"; +static constexpr char const *pciePath = "/xyz/openbmc_project/PCIe"; +static constexpr char const *pcieDeviceInterface = + "xyz.openbmc_project.PCIe.Device"; + +static inline void getPCIeDeviceList(std::shared_ptr<AsyncResp> asyncResp) +{ + auto getPCIeMapCallback = + [asyncResp](const boost::system::error_code ec, + std::vector<std::string> &pcieDevicePaths) { + if (ec) + { + BMCWEB_LOG_DEBUG << "failed to get PCIe device paths ec: " + << ec.message(); + messages::internalError(asyncResp->res); + return; + } + nlohmann::json &pcieDeviceList = + asyncResp->res.jsonValue["PCIeDevices"]; + pcieDeviceList = nlohmann::json::array(); + for (const std::string &pcieDevicePath : pcieDevicePaths) + { + size_t devStart = pcieDevicePath.rfind("/"); + if (devStart == std::string::npos) + { + continue; + } + + std::string devName = pcieDevicePath.substr(devStart + 1); + if (devName.empty()) + { + continue; + } + pcieDeviceList.push_back( + {{"@odata.id", + "/redfish/v1/Systems/system/PCIeDevices/" + devName}}); + } + asyncResp->res.jsonValue["PCIeDevices@odata.count"] = + pcieDeviceList.size(); + }; + crow::connections::systemBus->async_method_call( + std::move(getPCIeMapCallback), "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", + std::string(pciePath) + "/", 1, std::array<std::string, 0>()); +} + +class SystemPCIeDevice : public Node +{ + public: + SystemPCIeDevice(CrowApp &app) : + Node(app, "/redfish/v1/Systems/system/PCIeDevices/<str>/", + std::string()) + { + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; + } + + private: + void doGet(crow::Response &res, const crow::Request &req, + const std::vector<std::string> ¶ms) override + { + std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); + if (params.size() != 1) + { + messages::internalError(asyncResp->res); + return; + } + const std::string &device = params[0]; + + auto getPCIeDeviceCallback = + [asyncResp, + device](const boost::system::error_code ec, + boost::container::flat_map< + std::string, sdbusplus::message::variant<std::string>> + &pcieDevProperties) { + if (ec) + { + BMCWEB_LOG_DEBUG + << "failed to get PCIe Device properties ec: " + << static_cast<int>(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; + } + + asyncResp->res.jsonValue = { + {"@odata.type", "#PCIeDevice.v1_2_0.PCIeDevice"}, + {"@odata.context", + "/redfish/v1/$metadata#PCIeDevice.v1_2_0.PCIeDevice"}, + {"@odata.id", + "/redfish/v1/Systems/system/PCIeDevices/" + device}, + {"Name", "PCIe Device"}, + {"Id", device}}; + + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties["Manufacturer"]); + property) + { + asyncResp->res.jsonValue["Manufacturer"] = *property; + } + + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties["DeviceType"]); + property) + { + asyncResp->res.jsonValue["DeviceType"] = *property; + } + + nlohmann::json &pcieFunctionList = + asyncResp->res.jsonValue["Links"]["PCIeFunctions"]; + pcieFunctionList = nlohmann::json::array(); + static constexpr const int maxPciFunctionNum = 8; + for (int functionNum = 0; functionNum < maxPciFunctionNum; + functionNum++) + { + // Check if this function exists by looking for a device ID + std::string devIDProperty = + "Function" + std::to_string(functionNum) + "DeviceId"; + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties[devIDProperty]); + property && !property->empty()) + { + pcieFunctionList.push_back( + {{"@odata.id", + "/redfish/v1/Systems/system/PCIeDevices/" + + device + "/PCIeFunctions/" + + std::to_string(functionNum)}}); + } + } + asyncResp->res.jsonValue["Links"]["PCIeFunctions@odata.count"] = + pcieFunctionList.size(); + }; + std::string escapedPath = std::string(pciePath) + "/" + device; + dbus::utility::escapePathForDbus(escapedPath); + crow::connections::systemBus->async_method_call( + std::move(getPCIeDeviceCallback), pcieService, escapedPath, + "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface); + } +}; + +class SystemPCIeFunction : public Node +{ + public: + SystemPCIeFunction(CrowApp &app) : + Node( + app, + "/redfish/v1/Systems/system/PCIeDevices/<str>/PCIeFunctions/<str>/", + std::string(), std::string()) + { + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; + } + + private: + void doGet(crow::Response &res, const crow::Request &req, + const std::vector<std::string> ¶ms) override + { + std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); + if (params.size() != 2) + { + messages::internalError(asyncResp->res); + return; + } + const std::string &device = params[0]; + const std::string &function = params[1]; + + auto getPCIeDeviceCallback = + [asyncResp, device, function]( + const boost::system::error_code ec, + boost::container::flat_map< + std::string, sdbusplus::message::variant<std::string>> + &pcieDevProperties) { + if (ec) + { + BMCWEB_LOG_DEBUG + << "failed to get PCIe Device properties ec: " + << static_cast<int>(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 devIDProperty = "Function" + function + "DeviceId"; + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties[devIDProperty]); + property && property->empty()) + { + messages::resourceNotFound(asyncResp->res, "PCIeFunction", + function); + return; + } + + asyncResp->res.jsonValue = { + {"@odata.type", "#PCIeFunction.v1_2_0.PCIeFunction"}, + {"@odata.context", + "/redfish/v1/$metadata#PCIeFunction.PCIeFunction"}, + {"@odata.id", "/redfish/v1/Systems/system/PCIeDevices/" + + device + "/PCIeFunctions/" + function}, + {"Name", "PCIe Function"}, + {"Id", function}, + {"FunctionId", std::stoi(function)}, + {"Links", + {{"PCIeDevice", + {{"@odata.id", + "/redfish/v1/Systems/system/PCIeDevices/" + + device}}}}}}; + + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties["Function" + function + + "DeviceId"]); + property) + { + asyncResp->res.jsonValue["DeviceId"] = *property; + } + + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties["Function" + function + + "VendorId"]); + property) + { + asyncResp->res.jsonValue["VendorId"] = *property; + } + + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties["Function" + function + + "FunctionType"]); + property) + { + asyncResp->res.jsonValue["FunctionType"] = *property; + } + + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties["Function" + function + + "DeviceClass"]); + property) + { + asyncResp->res.jsonValue["DeviceClass"] = *property; + } + + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties["Function" + function + + "ClassCode"]); + property) + { + asyncResp->res.jsonValue["ClassCode"] = *property; + } + + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties["Function" + function + + "RevisionId"]); + property) + { + asyncResp->res.jsonValue["RevisionId"] = *property; + } + + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties["Function" + function + + "SubsystemId"]); + property) + { + asyncResp->res.jsonValue["SubsystemId"] = *property; + } + + if (std::string *property = + sdbusplus::message::variant_ns::get_if<std::string>( + &pcieDevProperties["Function" + function + + "SubsystemVendorId"]); + property) + { + asyncResp->res.jsonValue["SubsystemVendorId"] = *property; + } + }; + std::string escapedPath = std::string(pciePath) + "/" + device; + dbus::utility::escapePathForDbus(escapedPath); + crow::connections::systemBus->async_method_call( + std::move(getPCIeDeviceCallback), pcieService, escapedPath, + "org.freedesktop.DBus.Properties", "GetAll", pcieDeviceInterface); + } +}; + +} // namespace redfish diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp index e5f47a1bb6..1a94139abf 100644 --- a/redfish-core/lib/systems.hpp +++ b/redfish-core/lib/systems.hpp @@ -16,6 +16,7 @@ #pragma once #include "health.hpp" +#include "pcie.hpp" #include "redfish_util.hpp" #include <boost/container/flat_map.hpp> @@ -1298,6 +1299,7 @@ class Systems : public Node getComputerSystem(asyncResp); getHostState(asyncResp); getBootProperties(asyncResp); + getPCIeDeviceList(asyncResp); } void doPatch(crow::Response &res, const crow::Request &req, |