In-Memory FlightRecorder support for pldmd

pldm daemon in BMC can act both as a requester and
responder, and it is capable of talking to any device
that talks pldm spec.

With the rapid increase in the number of commands supported
by pldmd, and also with the async request/response support
enabled, its becomes extremely tough to debug the failures
in the communication.

And most of times, the essential information that is needed
to debug are the last few commands that BMC pldm responded to.
So this commit is an attempt to bring in an in-memory flight
recorder that could save the last 10(can be configurable)
pldm transactions in a circular buffer, and dumps the contents
of it into a file when it receives a SIGUR1 signal.

Resolves openbmc/pldm#24

Tested By :

1. Power on host
2. In the middle of poweron, send the SIGUSR1 signal to pldmd

root@rain118bmc:/tmp# kill -10 836
Received SIGUR1(10) Signal interrupt
root@rain118bmc:/tmp# Dumping the flight recorder into /tmp/pldm_flight_recorder

3. Make sure pldmd is not killed and does the rest of the power on
  operation.

4. check the contents of /tmp/pldm_flight_recorder
root@p10bmc:~# cat /tmp/pldm_flight_recorder
UTC Nov 05 / 11:27:25.334606 : Tx :
0a 3f 0d 00
UTC Nov 05 / 11:27:26.292988 : Rx :
09 01 8b 3f 0d 00 00 7b 1e 00 50 00
UTC Nov 05 / 11:27:26.296915 : Tx :
0b 3f 0d 00
UTC Nov 05 / 11:27:27.250999 : Rx :
09 01 8c 3f 0d 00 00 7c 1e 00 50 00
UTC Nov 05 / 11:27:27.254762 : Tx :
0c 3f 0d 00
UTC Nov 05 / 11:27:28.212168 : Rx :
09 01 8d 3f 0d 00 00 7d 1e 00 50 00
UTC Nov 05 / 11:27:28.216086 : Tx :
0d 3f 0d 00
UTC Nov 05 / 11:27:29.171228 : Rx :
09 01 8e 3f 0d 00 00 7e 1e 00 50 00
UTC Nov 05 / 11:27:29.175143 : Tx :
0e 3f 0d 00
UTC Nov 05 / 11:27:25.330716 : Rx :
09 01 8a 3f 0d 00 00 7a 1e 00 50 00

5. Configure with -Dflightrecorder-max-entries=0
root@p10bmc:~# kill -10 21847
Received SIGUR1(10) Signal interrupt
Fight recorder policy is disabled

Signed-off-by: Manojkiran Eda <manojkiran.eda@gmail.com>
Change-Id: I4e9c828f4ada9f1db6bf3a9b68c16e71b6e5d8f0
diff --git a/pldmd/pldmd.cpp b/pldmd/pldmd.cpp
index d48844f..d64751d 100644
--- a/pldmd/pldmd.cpp
+++ b/pldmd/pldmd.cpp
@@ -3,6 +3,7 @@
 #include "libpldm/pdr.h"
 #include "libpldm/platform.h"
 
+#include "common/flight_recorder.hpp"
 #include "common/utils.hpp"
 #include "dbus_impl_requester.hpp"
 #include "fw-update/manager.hpp"
@@ -22,6 +23,8 @@
 
 #include <sdeventplus/event.hpp>
 #include <sdeventplus/source/io.hpp>
+#include <sdeventplus/source/signal.hpp>
+#include <stdplus/signal.hpp>
 
 #include <cstdio>
 #include <cstring>
@@ -62,6 +65,17 @@
 using namespace sdeventplus::source;
 using namespace pldm::responder;
 using namespace pldm::utils;
+using sdeventplus::source::Signal;
+using namespace pldm::flightrecorder;
+
+void interruptFlightRecorderCallBack(Signal& /*signal*/,
+                                     const struct signalfd_siginfo*)
+{
+    std::cerr << "\nReceived SIGUR1(10) Signal interrupt\n";
+
+    // obtain the flight recorder instance and dump the recorder
+    FlightRecorder::GetInstance().playRecorder();
+}
 
 static std::optional<Response>
     processRxMsg(const std::vector<uint8_t>& requestMsg, Invoker& invoker,
@@ -350,6 +364,7 @@
                 fd, static_cast<void*>(requestMsg.data()), peekedLength, 0);
             if (recvDataLength == peekedLength)
             {
+                FlightRecorder::GetInstance().saveRecord(requestMsg, false);
                 if (verbose)
                 {
                     printBuffer(Rx, requestMsg);
@@ -366,6 +381,8 @@
                                                  reqHandler, fwManager.get());
                     if (response.has_value())
                     {
+                        FlightRecorder::GetInstance().saveRecord(*response,
+                                                                 true);
                         if (verbose)
                         {
                             printBuffer(Tx, *response);
@@ -429,6 +446,9 @@
         hostPDRHandler->setHostFirmwareCondition();
     }
 #endif
+    stdplus::signal::block(SIGUSR1);
+    sdeventplus::source::Signal sigUsr1(
+        event, SIGUSR1, std::bind_front(&interruptFlightRecorderCallBack));
     returnCode = event.loop();
 
     if (shutdown(sockfd, SHUT_RDWR))