From b5ca3fdcf15c029e36b05d619752711871bf0e8d Mon Sep 17 00:00:00 2001 From: Jiaqing Zhao Date: Wed, 8 Mar 2023 15:14:58 +0800 Subject: POST EthernetInterfaceCollection for VLAN With EthernetInterface 1.9.0, creation of VLAN interface is done by POST EthernetInterfaceCollection. This patch implements the POST handler to do so. Tested: * With valid RelatedInterfaces and VLANId provided, new VLAN interface is successfully created. * Creating VLAN over another VLAN or non-existent interface returns error. * Creating an existing VLAN returns ResourceAlreadyExists error. * Invalid RelatedInterfaces links are rejected. Change-Id: I6b1064193eccf7ec487b43139a73d9932b6eea84 Signed-off-by: Jiaqing Zhao Signed-off-by: Ed Tanous --- redfish-core/lib/ethernet.hpp | 128 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) (limited to 'redfish-core/lib') diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp index 74f544c9c8..1d2c988c7c 100644 --- a/redfish-core/lib/ethernet.hpp +++ b/redfish-core/lib/ethernet.hpp @@ -1749,6 +1749,50 @@ inline void afterDelete(const std::shared_ptr& asyncResp, messages::internalError(asyncResp->res); } +inline void afterVlanCreate(const std::shared_ptr& asyncResp, + const std::string& parentInterfaceUri, + const std::string& vlanInterface, + const boost::system::error_code& ec, + const sdbusplus::message_t& m + +) +{ + if (ec) + { + const sd_bus_error* dbusError = m.get_error(); + if (dbusError == nullptr) + { + messages::internalError(asyncResp->res); + return; + } + BMCWEB_LOG_DEBUG << "DBus error: " << dbusError->name; + + if (std::string_view( + "xyz.openbmc_project.Common.Error.ResourceNotFound") == + dbusError->name) + { + messages::propertyValueNotInList( + asyncResp->res, parentInterfaceUri, + "Links/RelatedInterfaces/0/@odata.id"); + return; + } + if (std::string_view( + "xyz.openbmc_project.Common.Error.InvalidArgument") == + dbusError->name) + { + messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", + "Id", vlanInterface); + return; + } + messages::internalError(asyncResp->res); + return; + } + + const boost::urls::url vlanInterfaceUri = boost::urls::format( + "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface); + asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); +} + inline void requestEthernetInterfacesRoutes(App& app) { BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") @@ -1798,6 +1842,90 @@ inline void requestEthernetInterfacesRoutes(App& app) }); }); + BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") + .privileges(redfish::privileges::postEthernetInterfaceCollection) + .methods(boost::beast::http::verb::post)( + [&app](const crow::Request& req, + const std::shared_ptr& asyncResp) { + if (!redfish::setUpRedfishRoute(app, req, asyncResp)) + { + return; + } + + bool vlanEnable = false; + uint32_t vlanId = 0; + nlohmann::json::array_t relatedInterfaces; + + if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable", + vlanEnable, "VLAN/VLANId", vlanId, + "Links/RelatedInterfaces", + relatedInterfaces)) + { + return; + } + + if (relatedInterfaces.size() != 1) + { + messages::arraySizeTooLong(asyncResp->res, + "Links/RelatedInterfaces", + relatedInterfaces.size()); + return; + } + + std::string parentInterfaceUri; + if (!json_util::readJson(relatedInterfaces[0], asyncResp->res, + "@odata.id", parentInterfaceUri)) + { + messages::propertyMissing(asyncResp->res, + "Links/RelatedInterfaces/0/@odata.id"); + return; + } + BMCWEB_LOG_INFO << "Parent Interface URI: " << parentInterfaceUri; + + boost::urls::result parsedUri = + boost::urls::parse_relative_ref(parentInterfaceUri); + if (!parsedUri) + { + messages::propertyValueFormatError( + asyncResp->res, parentInterfaceUri, + "Links/RelatedInterfaces/0/@odata.id"); + return; + } + + std::string parentInterface; + if (!crow::utility::readUrlSegments( + *parsedUri, "redfish", "v1", "Managers", "bmc", + "EthernetInterfaces", std::ref(parentInterface))) + { + messages::propertyValueNotInList( + asyncResp->res, parentInterfaceUri, + "Links/RelatedInterfaces/0/@odata.id"); + return; + } + + if (!vlanEnable) + { + // In OpenBMC implementation, VLANEnable cannot be false on + // create + messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable", + "false"); + return; + } + + std::string vlanInterface = parentInterface + "_" + + std::to_string(vlanId); + crow::connections::systemBus->async_method_call( + [asyncResp, parentInterfaceUri, + vlanInterface](const boost::system::error_code& ec, + const sdbusplus::message_t& m) { + afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec, + m); + }, + "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", + "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface, + vlanId); + }); + BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces//") .privileges(redfish::privileges::getEthernetInterface) .methods(boost::beast::http::verb::get)( -- cgit v1.2.3