From cae1d44c2db44b1c76bc85a45e5577f4fd7eeb59 Mon Sep 17 00:00:00 2001 From: Nikita Kosenkov Date: Tue, 13 Sep 2022 14:31:56 +0300 Subject: bmcweb: Added patch to manage SNMPv2 trap receivers in Redfish --- .../bmcweb/0015-Redfish-Implement-SNMP-Trap.patch | 705 +++++++++++++++++++++ .../recipes-phosphor/interfaces/bmcweb_%.bbappend | 1 + 2 files changed, 706 insertions(+) create mode 100644 meta-ibs/meta-cp2-5422/recipes-phosphor/interfaces/bmcweb/0015-Redfish-Implement-SNMP-Trap.patch diff --git a/meta-ibs/meta-cp2-5422/recipes-phosphor/interfaces/bmcweb/0015-Redfish-Implement-SNMP-Trap.patch b/meta-ibs/meta-cp2-5422/recipes-phosphor/interfaces/bmcweb/0015-Redfish-Implement-SNMP-Trap.patch new file mode 100644 index 0000000000..683075b042 --- /dev/null +++ b/meta-ibs/meta-cp2-5422/recipes-phosphor/interfaces/bmcweb/0015-Redfish-Implement-SNMP-Trap.patch @@ -0,0 +1,705 @@ +From 47ba142a47966b9c679a806468a58e0b434ce915 Mon Sep 17 00:00:00 2001 +From: Nikita Kosenkov +Date: Tue, 13 Sep 2022 13:38:49 +0300 +Subject: [PATCH] Redfish: Implement SNMP Trap + +Implement SNMPTrap in EventDestination of Redfish. We can use +this Redfish interface to add/get/delete the SNMPTrap port and +destination address. When the error log is generated, phosphor-snmp +will send SNMPTrap messages to our configured SNMPTrap destination. + +The MIB is here: +https://github.com/openbmc/phosphor-snmp/blob/master/mibs/NotificationMIB.txt + +Refer: +https://www.dmtf.org/sites/default/files/standards/documents/DSP0268_2019.3.pdf + +SNMPTrap test: Tested ok on the Witherspoon machine. +Steps are as follows: +1. Use this Redfish interface to configure the port and + destination address: + curl -k -H "X-Auth-Token: $token" -X POST https://${bmc}/redfish/v1/EventService/Subscriptions -d '{"Destination": "snmp://192.168.31.89:162", "SubscriptionType": "SNMPTrap", "Protocol": "SNMPv2c"}' +2. Run the SNMPTrap receiver tool in the destination + computer(192.168.31.89),I used iReasoning MIB Browser as the + SNMPTrap receiving tool. +3. Trigger error logs such as power supply AC Lost. We will see + the error log under /xyz/openbmc_project/logging. +4. The SNMPTrap receiver tool in the destination computer received + the SNMPTrap sent by OpenBMC. + +Tested: Validator passes +1. Add snmp client: + curl -k -H "X-Auth-Token: $token" -X POST https://${bmc}/redfish/v1/EventService/Subscriptions -d '{"Destination": "snmp://192.168.31.89:162", "SubscriptionType": "SNMPTrap", "Protocol": "SNMPv2c", "Context": "testContext"}' + { + "@Message.ExtendedInfo": [ + { + "@odata.type": "#Message.v1_0_0.Message", + "Message": "The resource has been created successfully", + "MessageArgs": [], + "MessageId": "Base.1.8.1.Created", + "MessageSeverity": "OK", + "Resolution": "None" + } + ] + } +2. Get snmp trap client configurations: +curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/EventService/Subscriptions/snmp1 +{ + "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp1", + "@odata.type": "#EventDestination.v1_7_0.EventDestination", + "Context": "testContext", + "Destination": "snmp://192.168.31.89:162", + "EventFormatType": "Event", + "Id": "snmp1", + "Name": "Event Destination snmp1", + "Protocol": "SNMPv2c", + "SubscriptionType": "SNMPTrap" +} + +Reboot the BMC, and get the snmp trap client again: +curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/EventService/Subscriptions/snmp1 +{ + "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp1", + "@odata.type": "#EventDestination.v1_7_0.EventDestination", + "Context": "testContext", + "Destination": "snmp://192.168.31.89:162", + "EventFormatType": "Event", + "Id": "snmp1", + "Name": "Event Destination snmp1", + "Protocol": "SNMPv2c", + "SubscriptionType": "SNMPTrap" +} + +3. Delete snmp client: +curl -k -H "X-Auth-Token: $token" -X DELETE https://${bmc}/redfish/v1/EventService/Subscriptions/snmp1 +{ + "@Message.ExtendedInfo": [ + { + "@odata.type": "#Message.v1_1_1.Message", + "Message": "Successfully Completed Request", + "MessageArgs": [], + "MessageId": "Base.1.8.1.Success", + "MessageSeverity": "OK", + "Resolution": "None" + } + ] +} +4. After we have added some SNMP clients using Redfish, we can see them in Dbus +busctl tree xyz.openbmc_project.Network.SNMP +`-/xyz + `-/xyz/openbmc_project + `-/xyz/openbmc_project/network + `-/xyz/openbmc_project/network/snmp + `-/xyz/openbmc_project/network/snmp/manager + |-/xyz/openbmc_project/network/snmp/manager/1 + +busctl introspect xyz.openbmc_project.Network.SNMP +/xyz/openbmc_project/network/snmp/manager/1 xyz.openbmc_project.Network.Client +NAME TYPE SIGNATURE RESULT/VALUE FLAGS +.Address property s "192.168.31.89" emits-change writable +.Port property q 162 emits-change writable + +5. Use "busctl call" add client +busctl call xyz.openbmc_project.Network.SNMP /xyz/openbmc_project/network/snmp/manager xyz.openbmc_project.Network.Client.Create Client sq 192.168.31.90 162 +s "/xyz/openbmc_project/network/snmp/manager/2" + +We will see it use the redfish url: +curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/EventService/Subscriptions/snmp2 +{ + "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp2", + "@odata.type": "#EventDestination.v1_7_0.EventDestination", + "Context": "", + "Destination": "snmp://192.168.31.90:162", + "EventFormatType": "Event", + "Id": "snmp2", + "Name": "Event Destination snmp2", + "Protocol": "SNMPv2c", + "SubscriptionType": "SNMPTrap" +} + +6. Deleting snmp client using "busctl" +First, we use redfish to add some SNMP clients: + curl -k -H "X-Auth-Token: $token" -X POST https://${bmc}/redfish/v1/EventService/Subscriptions -d '{"Destination": "snmp://192.168.31.90:162", "SubscriptionType": "SNMPTrap", "Protocol": "SNMPv2c", "Context": "testContext0"}' + curl -k -H "X-Auth-Token: $token" -X POST https://${bmc}/redfish/v1/EventService/Subscriptions -d '{"Destination": "snmp://192.168.31.91:162", "SubscriptionType": "SNMPTrap", "Protocol": "SNMPv2c", "Context": "testContext1"}' + +Then we can use redfish to get the subscriptions: + curl -k -H "X-Auth-Token: $token" -XGET https://${bmc}/redfish/v1/EventService/Subscriptions + { + "@odata.id": "/redfish/v1/EventService/Subscriptions", + "@odata.type": "#EventDestinationCollection.EventDestinationCollection", + "Members": [ + { + "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp1" + }, + { + "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp2" + } + ], + "Members@odata.count": 2, + "Name": "Event Destination Collections" + } + +Now we use busctl to delete SNMP client 2: + busctl call xyz.openbmc_project.Network.SNMP /xyz/openbmc_project/network/snmp/manager/2 xyz.openbmc_project.Object.Delete Delete + +Then we won't see snmp2 in the subscriptions of redfish: + curl -k -H "X-Auth-Token: $token" -XGET https://${bmc}/redfish/v1/EventService/Subscriptions + { + "@odata.id": "/redfish/v1/EventService/Subscriptions", + "@odata.type": "#EventDestinationCollection.EventDestinationCollection", + "Members": [ + { + "@odata.id": "/redfish/v1/EventService/Subscriptions/snmp1" + } + ], + "Members@odata.count": 1, + "Name": "Event Destination Collections" + } +--- + http/utility.hpp | 8 + + .../include/event_service_manager.hpp | 18 +- + redfish-core/lib/event_service.hpp | 397 +++++++++++++++++- + 3 files changed, 399 insertions(+), 24 deletions(-) + +diff --git a/http/utility.hpp b/http/utility.hpp +index 78570169..e9ab786e 100644 +--- a/http/utility.hpp ++++ b/http/utility.hpp +@@ -723,6 +723,10 @@ inline std::string setProtocolDefaults(const boost::urls::url_view& url) + } + return ""; + } ++ if (url.scheme() == "snmp") ++ { ++ return "snmp"; ++ } + return ""; + } + +@@ -745,6 +749,10 @@ inline uint16_t setPortDefaults(const boost::urls::url_view& url) + { + return 443; + } ++ if (url.scheme() == "snmp") ++ { ++ return 162; ++ } + return 0; + } + +diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp +index b20946a6..636ab5be 100644 +--- a/redfish-core/include/event_service_manager.hpp ++++ b/redfish-core/include/event_service_manager.hpp +@@ -880,6 +880,7 @@ class EventServiceManager + } + + std::string addSubscription(const std::shared_ptr& subValue, ++ const std::string& subscriptionId, + const bool updateFile = true) + { + +@@ -891,12 +892,21 @@ class EventServiceManager + int retry = 3; + while (retry != 0) + { +- id = std::to_string(dist(gen)); +- if (gen.error()) ++ if (subscriptionId.empty()) + { +- retry = 0; +- break; ++ id = std::to_string(dist(gen)); ++ if (gen.error()) ++ { ++ retry = 0; ++ break; ++ } ++ } ++ else ++ { ++ ++ id = subscriptionId; + } ++ + auto inserted = subscriptionsMap.insert(std::pair(id, subValue)); + if (inserted.second) + { +diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp +index 29175abe..bf3bb53a 100644 +--- a/redfish-core/lib/event_service.hpp ++++ b/redfish-core/lib/event_service.hpp +@@ -22,7 +22,9 @@ + #include + #include + #include ++#include + ++#include + #include + + namespace redfish +@@ -45,6 +47,250 @@ static constexpr const std::array supportedResourceTypes = { + + static constexpr const uint8_t maxNoOfSubscriptions = 20; + ++inline void ++ doGetSnmpTrapClientdata(const std::shared_ptr& asyncResp, ++ const std::string& objectPath) ++{ ++ ++ sdbusplus::asio::getAllProperties( ++ *crow::connections::systemBus, ++ "xyz.openbmc_project.Network.SNMP", objectPath, ++ "xyz.openbmc_project.Network.Client", ++ [asyncResp](const boost::system::error_code ec, ++ const dbus::utility::DBusPropertiesMap& propertiesList) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR << "D-Bus response error on GetSubTree " << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ ++ const std::string* address = nullptr; ++ const uint16_t* port = nullptr; ++ ++ const bool success = sdbusplus::unpackPropertiesNoThrow( ++ dbus_utils::UnpackErrorPrinter(), propertiesList, "Address", ++ address, "Port", port); ++ ++ if (!success) ++ { ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ ++ if (address != nullptr && port != nullptr) ++ { ++ std::string destination = "snmp://"; ++ destination.append(*address); ++ destination.append(":"); ++ destination.append(std::to_string(*port)); ++ ++ asyncResp->res.jsonValue["Destination"] = std::move(destination); ++ } ++ } ++ ); ++} ++ ++inline void ++ getSnmpTrapClientdata(const std::shared_ptr& asyncResp, ++ const std::string& id, const std::string& objectPath) ++{ ++ asyncResp->res.jsonValue["@odata.type"] = ++ "#EventDestination.v1_7_0.EventDestination"; ++ asyncResp->res.jsonValue["Protocol"] = "SNMPv2c"; ++ asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces( ++ "redfish", "v1", "EventService", "Subscriptions", id); ++ ++ asyncResp->res.jsonValue["Id"] = id; ++ asyncResp->res.jsonValue["Name"] = "Event Destination " + id; ++ ++ asyncResp->res.jsonValue["SubscriptionType"] = "SNMPTrap"; ++ asyncResp->res.jsonValue["EventFormatType"] = "Event"; ++ ++ std::shared_ptr subValue = ++ EventServiceManager::getInstance().getSubscription(id); ++ if (subValue != nullptr) ++ { ++ asyncResp->res.jsonValue["Context"] = subValue->customText; ++ } ++ else ++ { ++ asyncResp->res.jsonValue["Context"] = ""; ++ } ++ ++ doGetSnmpTrapClientdata(asyncResp, objectPath); ++} ++ ++inline void ++ getSnmpTrapClient(const std::shared_ptr& asyncResp, ++ const std::string& id) ++{ ++ crow::connections::systemBus->async_method_call( ++ [asyncResp, id](const boost::system::error_code ec, ++ dbus::utility::ManagedObjectType& resp) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR << "D-Bus response error on GetManagedObjects " ++ << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ ++ for (const auto& objpath : resp) ++ { ++ sdbusplus::message::object_path path(objpath.first); ++ const std::string snmpId = path.filename(); ++ if (snmpId.empty()) ++ { ++ BMCWEB_LOG_ERROR << "The SNMP client ID is wrong"; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ const std::string subscriptionId = "snmp" + snmpId; ++ if (id != subscriptionId) ++ { ++ continue; ++ } ++ ++ getSnmpTrapClientdata(asyncResp, id, objpath.first); ++ return; ++ } ++ ++ messages::resourceNotFound(asyncResp->res, "Subscriptions", id); ++ EventServiceManager::getInstance().deleteSubscription(id); ++ }, ++ "xyz.openbmc_project.Network.SNMP", ++ "/xyz/openbmc_project/network/snmp/manager", ++ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); ++} ++ ++inline void ++ createSnmpTrapClient(const std::shared_ptr& asyncResp, ++ const std::string& host, const uint16_t& snmpTrapPort, ++ const std::shared_ptr& subValue) ++{ ++ crow::connections::systemBus->async_method_call( ++ [asyncResp, subValue](const boost::system::error_code ec, ++ const std::string& dbusSNMPid) { ++ if (ec) ++ { ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ ++ sdbusplus::message::object_path path(dbusSNMPid); ++ const std::string snmpId = path.filename(); ++ if (snmpId.empty()) ++ { ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ ++ const std::string subscriptionId = "snmp" + snmpId; ++ ++ std::string id = EventServiceManager::getInstance().addSubscription( ++ subValue, subscriptionId); ++ ++ if (id.empty()) ++ { ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ ++ asyncResp->res.addHeader("Location", ++ "/redfish/v1/EventService/Subscriptions/" + ++ subscriptionId); ++ messages::created(asyncResp->res); ++ }, ++ "xyz.openbmc_project.Network.SNMP", ++ "/xyz/openbmc_project/network/snmp/manager", ++ "xyz.openbmc_project.Network.Client.Create", "Client", host, ++ snmpTrapPort); ++} ++inline void ++ checkSnmpTrapClient(const std::shared_ptr& asyncResp, ++ const std::string& host, const uint16_t& snmpTrapPort, ++ const std::string& destUrl, ++ const std::shared_ptr& subValue) ++{ ++ crow::connections::systemBus->async_method_call( ++ [asyncResp, host, snmpTrapPort, destUrl, ++ subValue](const boost::system::error_code ec, ++ dbus::utility::ManagedObjectType& resp) { ++ if (ec) ++ { ++ BMCWEB_LOG_ERROR << "D-Bus response error on GetManagedObjects " ++ << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ ++ for (const auto& object : resp) ++ { ++ for (const auto& interface : object.second) ++ { ++ if (interface.first == "xyz.openbmc_project.Network.Client") ++ { ++ std::string address; ++ uint16_t portNum = 0; ++ for (const auto& property : interface.second) ++ { ++ if (property.first == "Address") ++ { ++ const std::string* value = ++ std::get_if(&property.second); ++ if (value == nullptr) ++ { ++ continue; ++ } ++ address = *value; ++ } ++ else if (property.first == "Port") ++ { ++ const uint16_t* value = ++ std::get_if(&property.second); ++ if (value == nullptr) ++ { ++ continue; ++ } ++ portNum = *value; ++ } ++ } ++ ++ if (address == host && portNum == snmpTrapPort) ++ { ++ messages::resourceAlreadyExists( ++ asyncResp->res, ++ "EventDestination.v1_7_0.EventDestination", ++ "Destination", destUrl); ++ return; ++ } ++ } ++ } ++ } ++ // Create the snmp client ++ createSnmpTrapClient(asyncResp, host, snmpTrapPort, subValue); ++ }, ++ "xyz.openbmc_project.Network.SNMP", ++ "/xyz/openbmc_project/network/snmp/manager", ++ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); ++} ++ ++inline void ++ getSnmpSubscriptionList(const std::shared_ptr& asyncResp, ++ const std::string& snmpId, ++ nlohmann::json& memberArray) ++{ ++ const std::string subscriptionId = "snmp" + snmpId; ++ ++ nlohmann::json::object_t member; ++ member["@odata.id"] = crow::utility::urlFromPieces( ++ "redfish", "v1", "EventService", "Subscriptions", subscriptionId); ++ memberArray.push_back(std::move(member)); ++ ++ asyncResp->res.jsonValue["Members@odata.count"] = memberArray.size(); ++} ++ + inline void requestRoutesEventService(App& app) + { + BMCWEB_ROUTE(app, "/redfish/v1/EventService/") +@@ -180,6 +426,59 @@ inline void requestRoutesSubmitTestEvent(App& app) + }); + } + ++inline void doSubscriptionCollection( ++ const boost::system::error_code ec, ++ const std::shared_ptr& asyncResp, ++ dbus::utility::ManagedObjectType& resp) ++{ ++ nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"]; ++ std::vector subscripIds = ++ EventServiceManager::getInstance().getAllIDs(); ++ memberArray = nlohmann::json::array(); ++ ++ for (const std::string& id : subscripIds) ++ { ++ if (!boost::starts_with(id, "snmp")) ++ { ++ nlohmann::json::object_t member; ++ member["@odata.id"] = ++ "/redfish/v1/EventService/Subscriptions/" + id; ++ memberArray.push_back(std::move(member)); ++ } ++ } ++ ++ asyncResp->res.jsonValue["Members@odata.count"] = memberArray.size(); ++ ++ if (ec) ++ { ++ if (ec.value() == EBADR) ++ { ++ // this is an optional process so just return if ++ // it isn't there ++ return; ++ } ++ ++ BMCWEB_LOG_ERROR << "D-Bus response error on GetManagedObjects " << ec; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ ++ for (const std::pair& objpath : resp) ++ { ++ sdbusplus::message::object_path path(objpath.first); ++ const std::string snmpId = path.filename(); ++ if (snmpId.empty()) ++ { ++ BMCWEB_LOG_ERROR << "The SNMP client ID is wrong"; ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ ++ getSnmpSubscriptionList(asyncResp, snmpId, memberArray); ++ } ++} ++ + inline void requestRoutesEventDestinationCollection(App& app) + { + BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/") +@@ -197,21 +496,16 @@ inline void requestRoutesEventDestinationCollection(App& app) + "/redfish/v1/EventService/Subscriptions"; + asyncResp->res.jsonValue["Name"] = "Event Destination Collections"; + +- nlohmann::json& memberArray = asyncResp->res.jsonValue["Members"]; +- +- std::vector subscripIds = +- EventServiceManager::getInstance().getAllIDs(); +- memberArray = nlohmann::json::array(); +- asyncResp->res.jsonValue["Members@odata.count"] = subscripIds.size(); +- +- for (const std::string& id : subscripIds) +- { +- nlohmann::json::object_t member; +- member["@odata.id"] = +- "/redfish/v1/EventService/Subscriptions/" + id; +- memberArray.push_back(std::move(member)); +- } ++ crow::connections::systemBus->async_method_call( ++ [asyncResp](const boost::system::error_code ec, ++ dbus::utility::ManagedObjectType& resp) { ++ doSubscriptionCollection(ec, asyncResp, resp); ++ }, ++ "xyz.openbmc_project.Network.SNMP", ++ "/xyz/openbmc_project/network/snmp/manager", ++ "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); + }); ++ + BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/") + .privileges(redfish::privileges::postEventDestinationCollection) + .methods(boost::beast::http::verb::post)( +@@ -286,7 +580,8 @@ inline void requestRoutesEventDestinationCollection(App& app) + + if (subscriptionType) + { +- if (*subscriptionType != "RedfishEvent") ++ if (*subscriptionType != "RedfishEvent" && ++ (*subscriptionType != "SNMPTrap")) + { + messages::propertyValueNotInList( + asyncResp->res, *subscriptionType, "SubscriptionType"); +@@ -296,10 +591,17 @@ inline void requestRoutesEventDestinationCollection(App& app) + } + else + { +- subValue->subscriptionType = "RedfishEvent"; // Default ++ if (protocol == "SNMPv2c") ++ { ++ subValue->subscriptionType = "SNMPTrap"; ++ } ++ else ++ { ++ subValue->subscriptionType = "RedfishEvent"; // Default ++ } + } + +- if (protocol != "Redfish") ++ if ((protocol != "Redfish") && (protocol != "SNMPv2c")) + { + messages::propertyValueNotInList(asyncResp->res, protocol, + "Protocol"); +@@ -466,8 +768,18 @@ inline void requestRoutesEventDestinationCollection(App& app) + } + } + +- std::string id = +- EventServiceManager::getInstance().addSubscription(subValue); ++ if (protocol == "SNMPv2c") ++ { ++ // Check whether the client already exists ++ checkSnmpTrapClient(asyncResp, host, port, destUrl, subValue); ++ return; ++ } ++ ++ // There is no need to set the default subscriptionId here. ++ const std::string subscriptionId; ++ ++ std::string id = EventServiceManager::getInstance().addSubscription( ++ subValue, subscriptionId); + if (id.empty()) + { + messages::internalError(asyncResp->res); +@@ -492,6 +804,13 @@ inline void requestRoutesEventDestination(App& app) + { + return; + } ++ ++ if (boost::starts_with(param, "snmp")) ++ { ++ getSnmpTrapClient(asyncResp, param); ++ return; ++ } ++ + std::shared_ptr subValue = + EventServiceManager::getInstance().getSubscription(param); + if (subValue == nullptr) +@@ -503,7 +822,7 @@ inline void requestRoutesEventDestination(App& app) + + asyncResp->res.jsonValue["@odata.type"] = + "#EventDestination.v1_7_0.EventDestination"; +- asyncResp->res.jsonValue["Protocol"] = "Redfish"; ++ asyncResp->res.jsonValue["Protocol"] = subValue->protocol; + asyncResp->res.jsonValue["@odata.id"] = + "/redfish/v1/EventService/Subscriptions/" + id; + asyncResp->res.jsonValue["Id"] = id; +@@ -620,6 +939,44 @@ inline void requestRoutesEventDestination(App& app) + { + return; + } ++ ++ if (boost::starts_with(param, "snmp")) ++ { ++ std::string_view snmpTrapId = param; ++ ++ // Erase "snmp" in the request to find the corresponding ++ // dbus snmp client id. For example, the snmpid in the ++ // request is "snmp1", which will be "1" after being erased. ++ snmpTrapId.remove_prefix(4); ++ ++ const std::string snmpPath = ++ "/xyz/openbmc_project/network/snmp/manager/" + ++ std::string(snmpTrapId); ++ ++ crow::connections::systemBus->async_method_call( ++ [asyncResp, param](const boost::system::error_code ec) { ++ if (ec) ++ { ++ // The snmp trap id is incorrect ++ if (ec.value() == EBADR) ++ { ++ messages::resourceNotFound(asyncResp->res, ++ "Subscription", param); ++ return; ++ } ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ messages::success(asyncResp->res); ++ }, ++ "xyz.openbmc_project.Network.SNMP", snmpPath, ++ "xyz.openbmc_project.Object.Delete", "Delete"); ++ ++ EventServiceManager::getInstance().deleteSubscription(param); ++ ++ return; ++ } ++ + if (!EventServiceManager::getInstance().isSubscriptionExist(param)) + { + asyncResp->res.result(boost::beast::http::status::not_found); +-- +2.35.1 + diff --git a/meta-ibs/meta-cp2-5422/recipes-phosphor/interfaces/bmcweb_%.bbappend b/meta-ibs/meta-cp2-5422/recipes-phosphor/interfaces/bmcweb_%.bbappend index 55e0ca2b60..72aa017f07 100644 --- a/meta-ibs/meta-cp2-5422/recipes-phosphor/interfaces/bmcweb_%.bbappend +++ b/meta-ibs/meta-cp2-5422/recipes-phosphor/interfaces/bmcweb_%.bbappend @@ -11,6 +11,7 @@ SRC_URI += "\ file://0012-add-telemetry-hour-data.patch \ file://0013-bugfix-telemetry-circular-buffer.patch \ file://0014-Additional-details-about-errors-when-change-user-pw.patch \ + file://0015-Redfish-Implement-SNMP-Trap.patch \ " #SRC_URI += "\ -- cgit v1.2.3