oem-ibm: Call PEL API when host drops event log

When IBM's hypervisor receives an event log (PEL) using the file API, it
may end up discarding it, returning the reason the file was discarded in
the status argument of the file ack command.  It can do this for two
reasons, either it doesn't have any more room to store event logs, or
the event log was malformed.

In these cases, call the HostReject D-Bus method on the PEL daemon so it
can handle it. The code must convert the value of the status returned
into the proper D-Bus enum value.

Without this call, the operating system was missing event logs when
there were floods of them.

Tested:
API was called when system was flooded with event logs, allowing the PEL
daemon to resend them as space opens up.

Change-Id: I9d3acf4e5c5f885934ef96e89ddb93dd8f9c10a3
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/oem/ibm/libpldmresponder/file_io_type_pel.cpp b/oem/ibm/libpldmresponder/file_io_type_pel.cpp
index 15d8281..16ba928 100644
--- a/oem/ibm/libpldmresponder/file_io_type_pel.cpp
+++ b/oem/ibm/libpldmresponder/file_io_type_pel.cpp
@@ -9,6 +9,7 @@
 #include <systemd/sd-bus.h>
 #include <unistd.h>
 
+#include <org/open_power/Logging/PEL/server.hpp>
 #include <phosphor-logging/lg2.hpp>
 #include <sdbusplus/server.hpp>
 #include <xyz/openbmc_project/Logging/Entry/server.hpp>
@@ -26,6 +27,7 @@
 namespace responder
 {
 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
+using namespace sdbusplus::org::open_power::Logging::server;
 
 namespace detail
 {
@@ -219,27 +221,81 @@
     return rc;
 }
 
-int PelHandler::fileAck(uint8_t /*fileStatus*/)
+int PelHandler::fileAck(uint8_t fileStatus)
 {
     static constexpr auto logObjPath = "/xyz/openbmc_project/logging";
     static constexpr auto logInterface = "org.open_power.Logging.PEL";
+    static std::string service;
     auto& bus = pldm::utils::DBusHandler::getBus();
 
-    try
+    if (service.empty())
     {
-        auto service = pldm::utils::DBusHandler().getService(logObjPath,
-                                                             logInterface);
-        auto method = bus.new_method_call(service.c_str(), logObjPath,
-                                          logInterface, "HostAck");
-        method.append(fileHandle);
-        bus.call_noreply(method);
+        try
+        {
+            service = pldm::utils::DBusHandler().getService(logObjPath,
+                                                            logInterface);
+        }
+        catch (const sdbusplus::exception_t& e)
+        {
+            error("Mapper call failed when trying to find logging service "
+                  "to ack PEL ID {FILE_HANDLE} error = {ERR_EXCEP}",
+                  "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e);
+            return PLDM_ERROR;
+        }
     }
-    catch (const std::exception& e)
+
+    if (fileStatus == PLDM_SUCCESS)
     {
-        error(
-            "HostAck D-Bus call failed on PEL ID 0x{FILE_HANDLE}, error ={ERR_EXCEP}",
-            "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e.what());
-        return PLDM_ERROR;
+        try
+        {
+            auto method = bus.new_method_call(service.c_str(), logObjPath,
+                                              logInterface, "HostAck");
+            method.append(fileHandle);
+            bus.call_noreply(method);
+        }
+        catch (const std::exception& e)
+        {
+            error(
+                "HostAck D-Bus call failed on PEL ID {FILE_HANDLE}, error = {ERR_EXCEP}",
+                "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e);
+            return PLDM_ERROR;
+        }
+    }
+    else
+    {
+        PEL::RejectionReason reason{};
+        if (fileStatus == PLDM_FULL_FILE_DISCARDED)
+        {
+            reason = PEL::RejectionReason::HostFull;
+        }
+        else if (fileStatus == PLDM_ERROR_FILE_DISCARDED)
+        {
+            reason = PEL::RejectionReason::BadPEL;
+        }
+        else
+        {
+            error(
+                "Invalid file status {STATUS} in PEL file ack response for PEL {FILE_HANDLE}",
+                "STATUS", lg2::hex, fileStatus, "FILE_HANDLE", lg2::hex,
+                fileHandle);
+            return PLDM_ERROR;
+        }
+
+        try
+        {
+            auto method = bus.new_method_call(service.c_str(), logObjPath,
+                                              logInterface, "HostReject");
+            method.append(fileHandle, reason);
+            bus.call_noreply(method);
+        }
+        catch (const std::exception& e)
+        {
+            error("HostReject D-Bus call failed on PEL ID {FILE_HANDLE}, "
+                  "error = {ERR_EXCEP}, status = {STATUS}",
+                  "FILE_HANDLE", lg2::hex, fileHandle, "ERR_EXCEP", e, "STATUS",
+                  lg2::hex, fileStatus);
+            return PLDM_ERROR;
+        }
     }
 
     return PLDM_SUCCESS;