diff --git a/redfish-core/lib/processor.hpp b/redfish-core/lib/processor.hpp index 4691fa02d..b520f56b3 100644 --- a/redfish-core/lib/processor.hpp +++ b/redfish-core/lib/processor.hpp @@ -19,12 +19,9 @@ #include "utils/collection.hpp" #include "utils/dbus_utils.hpp" #include "utils/hex_utils.hpp" -#include "utils/hw_isolation.hpp" #include "utils/json_utils.hpp" #include "utils/name_utils.hpp" -#include - #include #include #include @@ -58,10 +55,6 @@ constexpr std::array processorInterfaces = { "xyz.openbmc_project.Inventory.Item.Cpu", "xyz.openbmc_project.Inventory.Item.Accelerator"}; -// Interfaces which imply a D-Bus object represents a Processor Core -constexpr std::array procCoreInterfaces = { - "xyz.openbmc_project.Inventory.Item.CpuCore"}; - /** * @brief Workaround to handle DCM (Dual-Chip Module) package for Redfish * @@ -945,294 +938,6 @@ inline void getProcessorData( } } -inline void handleProcessorPaths( - const std::shared_ptr& asyncResp, - const std::string& processorId, - const std::function& handler, - const boost::system::error_code& ec, - const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) -{ - if (ec) - { - // No processor objects found by mapper - if (ec.value() == boost::system::errc::io_error) - { - BMCWEB_LOG_DEBUG("No processors found"); - handler(""); - return; - } - - BMCWEB_LOG_ERROR("DBUS response error: {}", ec.value()); - messages::internalError(asyncResp->res); - return; - } - - auto foundCpuPath = std::ranges::find_if( - subTreePaths, [processorId](const std::string& cpuPath) { - return isProcObjectMatched( - processorId, sdbusplus::message::object_path(cpuPath)); - }); - - if (foundCpuPath == subTreePaths.end()) - { - BMCWEB_LOG_DEBUG("Processor {} not found", processorId); - handler(""); - return; - } - - handler(*foundCpuPath); -} - -inline void getProcessorPaths( - const std::shared_ptr& asyncResp, - const std::string& processorId, - std::function&& handler) -{ - constexpr std::array interfaces = { - "xyz.openbmc_project.Inventory.Item.Cpu"}; - dbus::utility::getSubTreePaths( - "/xyz/openbmc_project/inventory", 0, interfaces, - [asyncResp, processorId, handler{std::move(handler)}]( - const boost::system::error_code& ec, - const std::vector& subTreePaths) { - handleProcessorPaths(asyncResp, processorId, handler, ec, - subTreePaths); - }); -} - -inline void getSubProcessorsCoreHealth( - const std::shared_ptr& asyncResp, - const std::string& service, const std::string& objPath) -{ - dbus::utility::getProperty( - service, objPath, - "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional", - [asyncResp](const boost::system::error_code& ec, bool functional) { - if (ec) - { - if (ec.value() != EBADR) - { - BMCWEB_LOG_ERROR("DBUS response error, ec: {}", ec.value()); - messages::internalError(asyncResp->res); - } - return; - } - - if (!functional) - { - asyncResp->res.jsonValue["Status"]["Health"] = - resource::Health::Critical; - } - }); -} - -inline void afterGetSubProcessorsCorePresent( - const std::shared_ptr& asyncResp, - const boost::system::error_code& ec, bool present) -{ - if (ec) - { - if (ec.value() != EBADR) - { - BMCWEB_LOG_ERROR("DBUS response error for Available {}", - ec.value()); - messages::internalError(asyncResp->res); - } - return; - } - - if (!present) - { - asyncResp->res.jsonValue["Status"]["State"] = resource::State::Absent; - return; - } -} - -inline void afterGetSubProcessorsCoreAvailable( - const std::shared_ptr& asyncResp, - const std::string& service, const std::string& corePath, - const boost::system::error_code& ec, bool available) -{ - if (ec) - { - if (ec.value() != EBADR) - { - BMCWEB_LOG_ERROR("DBUS response error, ec: {}", ec.value()); - messages::internalError(asyncResp->res); - } - return; - } - - if (!available) - { - asyncResp->res.jsonValue["Status"]["State"] = - resource::State::UnavailableOffline; - } - - dbus::utility::getProperty( - service, corePath, "xyz.openbmc_project.Inventory.Item", "Present", - std::bind_front(afterGetSubProcessorsCorePresent, asyncResp)); -} - -inline void getSubProcessorsCoreState( - const std::shared_ptr& asyncResp, - const std::string& service, const std::string& corePath) -{ - dbus::utility::getProperty( - service, corePath, "xyz.openbmc_project.State.Decorator.Availability", - "Available", - std::bind_front(afterGetSubProcessorsCoreAvailable, asyncResp, service, - corePath)); -} - -inline void getEnabledStatus( - const std::shared_ptr& asyncResp, - const std::string& service, const std::string& objPath, - const std::string& interface) -{ - dbus::utility::getProperty( - service, objPath, interface, "Enabled", - [asyncResp](const boost::system::error_code& ec, bool enabled) { - if (ec) - { - if (ec.value() != EBADR) - { - BMCWEB_LOG_ERROR("DBUS response error, ec: {}", ec.value()); - messages::internalError(asyncResp->res); - } - return; - } - - asyncResp->res.jsonValue["Enabled"] = enabled; - }); -} - -inline void getSubProcessorsCoreData( - const std::shared_ptr& asyncResp, - const std::string& processorId, const std::string& coreId, - const std::string& corePath, const dbus::utility::MapperServiceMap& object) -{ - asyncResp->res.addHeader( - boost::beast::http::field::link, - "; rel=describedby"); - asyncResp->res.jsonValue["@odata.type"] = "#Processor.v1_18_0.Processor"; - asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( - "/redfish/v1/Systems/{}/Processors/{}/SubProcessors/{}", - BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId, coreId); - asyncResp->res.jsonValue["Name"] = "SubProcessor"; - asyncResp->res.jsonValue["Id"] = coreId; - - asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; - asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; - - for (const auto& [service, interfaces] : object) - { - for (const auto& intf : interfaces) - { - if (intf == "xyz.openbmc_project.Inventory.Item") - { - name_util::getPrettyName(asyncResp, corePath, service, - "/Name"_json_pointer); - } - else if (intf == "xyz.openbmc_project.Object.Enable") - { - getEnabledStatus(asyncResp, service, corePath, intf); - } - } - - getSubProcessorsCoreState(asyncResp, service, corePath); - getSubProcessorsCoreHealth(asyncResp, service, corePath); - - if constexpr (BMCWEB_HW_ISOLATION) - { - // Check for the hardware status event - hw_isolation_utils::getHwIsolationStatus(asyncResp, corePath); - } - } -} - -inline void handleSubProcessorsSubtree( - const std::shared_ptr& asyncResp, - const std::string& processorId, const std::string& coreId, - const std::function& - callback, - const boost::system::error_code& ec, - const dbus::utility::MapperGetSubTreeResponse& subtree) -{ - if (ec) - { - BMCWEB_LOG_ERROR("DBUS response error, ec: {}", ec.value()); - - // No endpoints property found by mapper - if (ec.value() == boost::system::errc::io_error) - { - messages::resourceNotFound(asyncResp->res, "Processor", - processorId); - return; - } - messages::internalError(asyncResp->res); - return; - } - for (const auto& [corePath, object] : subtree) - { - if (sdbusplus::message::object_path(corePath).filename() == coreId) - { - callback(corePath, object); - return; - } - } - messages::resourceNotFound(asyncResp->res, "Processor", coreId); -} - -inline void getSubProcessorsCoreObject( - const std::shared_ptr& asyncResp, - const std::string& processorId, const std::string& coreId, - const std::string& cpuPath, - std::function&& - callback) -{ - BMCWEB_LOG_DEBUG("Get cores for {}", cpuPath); - - constexpr std::array interface = { - "xyz.openbmc_project.Inventory.Item.CpuCore"}; - dbus::utility::getSubTree( - cpuPath, 0, interface, - [asyncResp, processorId, coreId, callback{std::move(callback)}]( - const boost::system::error_code& ec, - const dbus::utility::MapperGetSubTreeResponse& objects) { - handleSubProcessorsSubtree(asyncResp, processorId, coreId, callback, - ec, objects); - }); -} - -inline void getSubProcessorMembers( - const std::shared_ptr& asyncResp, - const std::string& processorId, const std::string& cpuPath) -{ - if (cpuPath.empty()) - { - BMCWEB_LOG_WARNING("Processor {} not found.", processorId); - messages::resourceNotFound(asyncResp->res, "Processor", processorId); - return; - } - - asyncResp->res.jsonValue["@odata.type"] = - "#ProcessorCollection.ProcessorCollection"; - asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( - "/redfish/v1/Systems/{}/Processors/{}/SubProcessors", - BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId); - asyncResp->res.jsonValue["Name"] = "SubProcessor Collection"; - - collection_util::getCollectionMembers( - asyncResp, - boost::urls::format( - "/redfish/v1/Systems/{}/Processors/{}/SubProcessors", - BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId), - procCoreInterfaces, cpuPath); -} - /** * Request all the properties for the given D-Bus object and fill out the * related entries in the Redfish OperatingConfig response. @@ -1827,188 +1532,4 @@ inline void requestRoutesProcessor(App& app) std::bind_front(handleProcessorPatch, std::ref(app))); } -inline void handleSubProcessorGet( - App& app, const crow::Request& req, - const std::shared_ptr& asyncResp, - const std::string& systemName, const std::string& processorId) -{ - 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; - } - - getProcessorPaths( - asyncResp, processorId, - std::bind_front(getSubProcessorMembers, asyncResp, processorId)); -} - -inline void handleSubProcessorCoreGet( - App& app, const crow::Request& req, - const std::shared_ptr& asyncResp, - const std::string& systemName, const std::string& processorId, - const std::string& coreId) -{ - 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; - } - - getProcessorPaths( - asyncResp, processorId, - [asyncResp, processorId, coreId](const std::string& cpuPath) { - if (cpuPath.empty()) - { - messages::resourceNotFound(asyncResp->res, "Processor", - processorId); - return; - } - getSubProcessorsCoreObject( - asyncResp, processorId, coreId, cpuPath, - std::bind_front(getSubProcessorsCoreData, asyncResp, - processorId, coreId)); - }); -} - -/** - * @brief API used to process the Processor Core "Enabled" member which is - * patched to do appropriate action. - * - * @param[in] asyncResp - The redfish response to return. - * @param[in] procObjPath - The parent processor object path. - * @param[in] coreId - The patched Processor Core resource id. - * @param[in] enabled - The patched "Enabled" member value. - * - * @return The redfish response in the given buffer. - * - * @note - The "Enabled" member of the Processor Core is used to enable - * (aka isolate) or disable (aka deisolate) the resource from the - * system boot so this function will call - * "processHardwareIsolationReq" function which is used to handle the - * resource isolation request. - * - The "Enabled" member of the Processor Core is mapped with - * "xyz.openbmc_project.Object.Enable::Enabled" dbus property. - */ -inline void patchCpuCoreMemberEnabled( - const std::shared_ptr& resp, - const std::string& procObjPath, const std::string& coreId, - const bool enabled) -{ - redfish::hw_isolation_utils::processHardwareIsolationReq( - resp, "Core", coreId, enabled, - std::vector(procCoreInterfaces.begin(), - procCoreInterfaces.end()), - procObjPath); -} - -/** - * @brief API used to process the Processor Core members which are tried to - * patch. - * - * @param[in] req - The redfish patched request to identify the patched - * members - * @param[in] asyncResp - The redfish response to return. - * @param[in] processorId - The patched Core Processor resource id (unused - * now) - * @param[in] coreId - The patched Processor Core resource id. - * - * @return The redfish response in the given buffer. - * - * @note This function will call the appropriate function to handle the - * patched members of the Processor Core. - */ -inline void patchCpuCoreMembers( - App& app, const crow::Request& req, - const std::shared_ptr& asyncResp, - const std::string& systemName, const std::string& processorId, - const std::string& coreId) -{ - 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 enabled; - - if (!json_util::readJsonPatch(req, asyncResp->res, "Enabled", enabled)) - { - return; - } - - getProcessorPaths( - asyncResp, processorId, - [asyncResp, coreId, enabled](const std::string& cpuPath) { - // Handle patched Enabled Redfish property - if (enabled.has_value()) - { - patchCpuCoreMemberEnabled(asyncResp, cpuPath, coreId, *enabled); - } - }); -} - -inline void requestRoutesSubProcessors(App& app) -{ - BMCWEB_ROUTE(app, - "/redfish/v1/Systems//Processors//SubProcessors") - .privileges(redfish::privileges::getProcessorCollection) - .methods(boost::beast::http::verb::get)( - std::bind_front(handleSubProcessorGet, std::ref(app))); - - BMCWEB_ROUTE( - app, "/redfish/v1/Systems//Processors//SubProcessors/") - .privileges(redfish::privileges::getProcessor) - .methods(boost::beast::http::verb::get)( - std::bind_front(handleSubProcessorCoreGet, std::ref(app))); - - BMCWEB_ROUTE( - app, "/redfish/v1/Systems//Processors//SubProcessors/") - .privileges(redfish::privileges::patchProcessor) - .methods(boost::beast::http::verb::patch)( - std::bind_front(patchCpuCoreMembers, std::ref(app))); -} - } // namespace redfish diff --git a/redfish-core/lib/processor_core.hpp b/redfish-core/lib/processor_core.hpp new file mode 100644 index 000000000..8b2290827 --- /dev/null +++ b/redfish-core/lib/processor_core.hpp @@ -0,0 +1,596 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright OpenBMC Authors +// SPDX-FileCopyrightText: Copyright 2018 Intel Corporation +#pragma once + +#include "bmcweb_config.h" + +#include "app.hpp" +#include "async_resp.hpp" +#include "dbus_utility.hpp" +#include "error_messages.hpp" +#include "generated/enums/resource.hpp" +#include "http_request.hpp" +#include "human_sort.hpp" +#include "logging.hpp" +#include "processor.hpp" +#include "query.hpp" +#include "registries/privilege_registry.hpp" +#include "utils/hw_isolation.hpp" +#include "utils/json_utils.hpp" +#include "utils/name_utils.hpp" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace redfish +{ + +// Interfaces which imply a D-Bus object represents a Processor Core +constexpr std::array procCoreInterfaces = { + "xyz.openbmc_project.Inventory.Item.CpuCore"}; + +inline void handleProcessorPaths( + const std::shared_ptr& asyncResp, + const std::string& processorId, + const std::function& handler, + const boost::system::error_code& ec, + const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) +{ + if (ec) + { + // No processor objects found by mapper + if (ec.value() == boost::system::errc::io_error) + { + BMCWEB_LOG_DEBUG("No processors found"); + handler(""); + return; + } + + BMCWEB_LOG_ERROR("DBUS response error: {}", ec.value()); + messages::internalError(asyncResp->res); + return; + } + + auto foundCpuPath = std::ranges::find_if( + subTreePaths, [processorId](const std::string& cpuPath) { + return isProcObjectMatched( + processorId, sdbusplus::message::object_path(cpuPath)); + }); + + if (foundCpuPath == subTreePaths.end()) + { + BMCWEB_LOG_DEBUG("Processor {} not found", processorId); + handler(""); + return; + } + + handler(*foundCpuPath); +} + +inline void getProcessorPaths( + const std::shared_ptr& asyncResp, + const std::string& processorId, + std::function&& handler) +{ + constexpr std::array interfaces = { + "xyz.openbmc_project.Inventory.Item.Cpu"}; + dbus::utility::getSubTreePaths( + "/xyz/openbmc_project/inventory", 0, interfaces, + [asyncResp, processorId, handler{std::move(handler)}]( + const boost::system::error_code& ec, + const std::vector& subTreePaths) { + handleProcessorPaths(asyncResp, processorId, handler, ec, + subTreePaths); + }); +} + +inline void handleSubProcessorCoreHead( + crow::App& app, const crow::Request& req, + const std::shared_ptr& asyncResp, + const std::string& /* systemName */, const std::string& /* processorId */, + const std::string& /* coreId */) +{ + if (!redfish::setUpRedfishRoute(app, req, asyncResp)) + { + return; + } + asyncResp->res.addHeader( + boost::beast::http::field::link, + "; rel=describedby"); +} + +inline void getSubProcessorCoreHealth( + const std::shared_ptr& asyncResp, + const std::string& service, const std::string& objPath) +{ + dbus::utility::getProperty( + service, objPath, + "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional", + [asyncResp](const boost::system::error_code& ec, bool functional) { + if (ec) + { + if (ec.value() != EBADR) + { + BMCWEB_LOG_ERROR("DBUS response error, ec: {}", ec.value()); + messages::internalError(asyncResp->res); + } + return; + } + + if (!functional) + { + asyncResp->res.jsonValue["Status"]["Health"] = + resource::Health::Critical; + } + }); +} + +inline void afterGetSubProcessorCorePresent( + const std::shared_ptr& asyncResp, + const boost::system::error_code& ec, bool present) +{ + if (ec) + { + if (ec.value() != EBADR) + { + BMCWEB_LOG_ERROR("DBUS response error for Available {}", + ec.value()); + messages::internalError(asyncResp->res); + } + return; + } + + if (!present) + { + asyncResp->res.jsonValue["Status"]["State"] = resource::State::Absent; + return; + } +} + +inline void afterGetSubProcessorCoreAvailable( + const std::shared_ptr& asyncResp, + const std::string& service, const std::string& corePath, + const boost::system::error_code& ec, bool available) +{ + if (ec) + { + if (ec.value() != EBADR) + { + BMCWEB_LOG_ERROR("DBUS response error, ec: {}", ec.value()); + messages::internalError(asyncResp->res); + } + return; + } + + if (!available) + { + asyncResp->res.jsonValue["Status"]["State"] = + resource::State::UnavailableOffline; + } + + dbus::utility::getProperty( + service, corePath, "xyz.openbmc_project.Inventory.Item", "Present", + std::bind_front(afterGetSubProcessorCorePresent, asyncResp)); +} + +inline void getSubProcessorCoreState( + const std::shared_ptr& asyncResp, + const std::string& service, const std::string& corePath) +{ + dbus::utility::getProperty( + service, corePath, "xyz.openbmc_project.State.Decorator.Availability", + "Available", + std::bind_front(afterGetSubProcessorCoreAvailable, asyncResp, service, + corePath)); +} + +inline void getEnabledStatus( + const std::shared_ptr& asyncResp, + const std::string& service, const std::string& objPath, + const std::string& interface) +{ + dbus::utility::getProperty( + service, objPath, interface, "Enabled", + [asyncResp](const boost::system::error_code& ec, bool enabled) { + if (ec) + { + if (ec.value() != EBADR) + { + BMCWEB_LOG_ERROR("DBUS response error, ec: {}", ec.value()); + messages::internalError(asyncResp->res); + } + return; + } + + asyncResp->res.jsonValue["Enabled"] = enabled; + }); +} + +inline void getSubProcessorCoreData( + const std::shared_ptr& asyncResp, + const std::string& systemName, const std::string& processorId, + const std::string& coreId, const std::string& corePath, + const dbus::utility::MapperServiceMap& object) +{ + asyncResp->res.addHeader( + boost::beast::http::field::link, + "; rel=describedby"); + asyncResp->res.jsonValue["@odata.type"] = "#Processor.v1_18_0.Processor"; + asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( + "/redfish/v1/Systems/{}/Processors/{}/SubProcessors/{}", systemName, + processorId, coreId); + asyncResp->res.jsonValue["Name"] = "SubProcessor"; + asyncResp->res.jsonValue["Id"] = coreId; + + asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled; + asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK; + + for (const auto& [service, interfaces] : object) + { + for (const auto& intf : interfaces) + { + if (intf == "xyz.openbmc_project.Inventory.Item") + { + name_util::getPrettyName(asyncResp, corePath, service, + "/Name"_json_pointer); + } + else if (intf == "xyz.openbmc_project.Object.Enable") + { + getEnabledStatus(asyncResp, service, corePath, intf); + } + } + + getSubProcessorCoreState(asyncResp, service, corePath); + getSubProcessorCoreHealth(asyncResp, service, corePath); + } + + if constexpr (BMCWEB_HW_ISOLATION) + { + // Check for the hardware status event + hw_isolation_utils::getHwIsolationStatus(asyncResp, corePath); + } +} + +inline void doHandleSubProcessorCoreGet( + const std::shared_ptr& asyncResp, + const std::string& systemName, const std::string& processorId, + const std::string& coreId, const boost::system::error_code& ec, + const dbus::utility::MapperGetSubTreeResponse& coreSubTree) +{ + if (ec) + { + if (ec.value() == boost::system::errc::io_error) + { + BMCWEB_LOG_WARNING("Processor {} not found.", processorId); + messages::resourceNotFound(asyncResp->res, "Processor", + processorId); + return; + } + BMCWEB_LOG_ERROR("DBUS response error {}", ec.value()); + messages::internalError(asyncResp->res); + return; + } + + for (const auto& [corePath, object] : coreSubTree) + { + if (sdbusplus::message::object_path(corePath).filename() == coreId) + { + getSubProcessorCoreData(asyncResp, systemName, processorId, coreId, + corePath, object); + return; + } + } + + BMCWEB_LOG_WARNING("Core {} not found.", coreId); + messages::resourceNotFound(asyncResp->res, "Processor", coreId); +} + +inline void handleSubProcessorCoreGet( + App& app, const crow::Request& req, + const std::shared_ptr& asyncResp, + const std::string& systemName, const std::string& processorId, + const std::string& coreId) +{ + 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; + } + + getProcessorPaths( + asyncResp, processorId, + [asyncResp, systemName, processorId, + coreId](const std::string& cpuPath) { + if (cpuPath.empty()) + { + messages::resourceNotFound(asyncResp->res, "Processor", + processorId); + return; + } + dbus::utility::getAssociatedSubTree( + cpuPath + "/containing", + sdbusplus::message::object_path( + "/xyz/openbmc_project/inventory"), + 0, procCoreInterfaces, + std::bind_front(doHandleSubProcessorCoreGet, asyncResp, + systemName, processorId, coreId)); + }); +} + +inline void handleSubProcessorCollectionHead( + crow::App& app, const crow::Request& req, + const std::shared_ptr& asyncResp, + const std::string& systemName, const std::string& /* processorId */) +{ + 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; + } + + asyncResp->res.addHeader( + boost::beast::http::field::link, + "; rel=describedby"); +} + +inline void doHandleSubProcessorCollectionGet( + const std::shared_ptr& asyncResp, + const std::string& systemName, const std::string& processorId, + const boost::system::error_code& ec, + const dbus::utility::MapperGetSubTreePathsResponse& coreSubTreePaths) +{ + if (ec) + { + if (ec.value() != boost::system::errc::io_error) + { + BMCWEB_LOG_ERROR("DBUS response error {}", ec.value()); + messages::internalError(asyncResp->res); + return; + } + BMCWEB_LOG_WARNING("Processor {} not found.", processorId); + messages::resourceNotFound(asyncResp->res, "Processor", processorId); + return; + } + + asyncResp->res.addHeader( + boost::beast::http::field::link, + "; rel=describedby"); + + asyncResp->res.jsonValue["@odata.type"] = + "#ProcessorCollection.ProcessorCollection"; + asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( + "/redfish/v1/Systems/{}/Processors/{}/SubProcessors", + BMCWEB_REDFISH_SYSTEM_URI_NAME, processorId); + asyncResp->res.jsonValue["Name"] = "SubProcessor Collection"; + + asyncResp->res.jsonValue["Members"] = nlohmann::json::array(); + + std::vector coreIdNames; + for (const std::string& corePath : coreSubTreePaths) + { + std::string coreId = + sdbusplus::message::object_path(corePath).filename(); + if (!coreId.empty()) + { + coreIdNames.emplace_back(std::move(coreId)); + } + } + + std::ranges::sort(coreIdNames, AlphanumLess()); + + nlohmann::json& members = asyncResp->res.jsonValue["Members"]; + for (const std::string& coreId : coreIdNames) + { + nlohmann::json item; + item["@odata.id"] = boost::urls::format( + "/redfish/v1/Systems/{}/Processors/{}/SubProcessors/{}", systemName, + processorId, coreId); + members.emplace_back(std::move(item)); + } + asyncResp->res.jsonValue["Members@odata.count"] = members.size(); +} + +inline void handleSubProcessorCollectionGet( + App& app, const crow::Request& req, + const std::shared_ptr& asyncResp, + const std::string& systemName, const std::string& processorId) +{ + 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; + } + + getProcessorPaths( + asyncResp, processorId, + [asyncResp, systemName, processorId](const std::string& cpuPath) { + dbus::utility::getAssociatedSubTreePaths( + cpuPath + "/containing", + sdbusplus::message::object_path( + "/xyz/openbmc_project/inventory"), + 0, procCoreInterfaces, + std::bind_front(doHandleSubProcessorCollectionGet, asyncResp, + systemName, processorId)); + }); +} + +/** + * @brief API used to process the Processor Core "Enabled" member which is + * patched to do appropriate action. + * + * @param[in] asyncResp - The redfish response to return. + * @param[in] procObjPath - The parent processor object path. + * @param[in] coreId - The patched Processor Core resource id. + * @param[in] enabled - The patched "Enabled" member value. + * + * @return The redfish response in the given buffer. + * + * @note - The "Enabled" member of the Processor Core is used to enable + * (aka isolate) or disable (aka deisolate) the resource from the + * system boot so this function will call + * "processHardwareIsolationReq" function which is used to handle the + * resource isolation request. + * - The "Enabled" member of the Processor Core is mapped with + * "xyz.openbmc_project.Object.Enable::Enabled" dbus property. + */ +inline void patchCpuCoreMemberEnabled( + const std::shared_ptr& resp, + const std::string& procObjPath, const std::string& coreId, + const bool enabled) +{ + redfish::hw_isolation_utils::processHardwareIsolationReq( + resp, "Core", coreId, enabled, + std::vector(procCoreInterfaces.begin(), + procCoreInterfaces.end()), + procObjPath); +} + +/** + * @brief API used to process the Processor Core members which are tried to + * patch. + * + * @param[in] req - The redfish patched request to identify the patched + * members + * @param[in] asyncResp - The redfish response to return. + * @param[in] processorId - The patched Core Processor resource id (unused + * now) + * @param[in] coreId - The patched Processor Core resource id. + * + * @return The redfish response in the given buffer. + * + * @note This function will call the appropriate function to handle the + * patched members of the Processor Core. + */ +inline void patchCpuCoreMembers( + App& app, const crow::Request& req, + const std::shared_ptr& asyncResp, + const std::string& systemName, const std::string& processorId, + const std::string& coreId) +{ + 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 enabled; + + if (!json_util::readJsonPatch(req, asyncResp->res, "Enabled", enabled)) + { + return; + } + + getProcessorPaths( + asyncResp, processorId, + [asyncResp, coreId, enabled](const std::string& cpuPath) { + // Handle patched Enabled Redfish property + if (enabled.has_value()) + { + patchCpuCoreMemberEnabled(asyncResp, cpuPath, coreId, *enabled); + } + }); +} + +inline void requestRoutesSubProcessors(App& app) +{ + BMCWEB_ROUTE( + app, "/redfish/v1/Systems//Processors//SubProcessors//") + .privileges(redfish::privileges::headProcessor) + .methods(boost::beast::http::verb::head)( + std::bind_front(handleSubProcessorCoreHead, std::ref(app))); + + BMCWEB_ROUTE( + app, "/redfish/v1/Systems//Processors//SubProcessors//") + .privileges(redfish::privileges::getProcessor) + .methods(boost::beast::http::verb::get)( + std::bind_front(handleSubProcessorCoreGet, std::ref(app))); + + BMCWEB_ROUTE(app, + "/redfish/v1/Systems//Processors//SubProcessors/") + .privileges(redfish::privileges::headProcessorCollection) + .methods(boost::beast::http::verb::head)( + std::bind_front(handleSubProcessorCollectionHead, std::ref(app))); + + BMCWEB_ROUTE(app, + "/redfish/v1/Systems//Processors//SubProcessors/") + .privileges(redfish::privileges::getProcessorCollection) + .methods(boost::beast::http::verb::get)( + std::bind_front(handleSubProcessorCollectionGet, std::ref(app))); +} + +} // namespace redfish diff --git a/redfish-core/src/redfish.cpp b/redfish-core/src/redfish.cpp index 7b189ab14..ba0309ea9 100644 --- a/redfish-core/src/redfish.cpp +++ b/redfish-core/src/redfish.cpp @@ -42,6 +42,7 @@ #include "power_subsystem.hpp" #include "power_supply.hpp" #include "processor.hpp" +#include "processor_core.hpp" #include "redfish_sessions.hpp" #include "redfish_v1.hpp" #include "roles.hpp"