xref: /openbmc/pldm/common/flight_recorder.hpp (revision ca1998f3)
1 #pragma once
2 
3 #include <config.h>
4 
5 #include <common/utils.hpp>
6 
7 #include <fstream>
8 #include <iomanip>
9 #include <iostream>
10 #include <vector>
11 namespace pldm
12 {
13 namespace flightrecorder
14 {
15 
16 using ReqOrResponse = bool;
17 using FlightRecorderData = std::vector<uint8_t>;
18 using FlightRecorderTimeStamp = std::string;
19 using FlightRecorderRecord =
20     std::tuple<FlightRecorderTimeStamp, ReqOrResponse, FlightRecorderData>;
21 using FlightRecorderCassette = std::vector<FlightRecorderRecord>;
22 static constexpr auto flightRecorderDumpPath = "/tmp/pldm_flight_recorder";
23 
24 /** @class FlightRecorder
25  *
26  *  The class for implementing the PLDM flight recorder logic. This class
27  *  handles the insertion of the data into the recorder and also provides
28  *  API's to dump the flight recorder into a file.
29  */
30 
31 class FlightRecorder
32 {
33   private:
34     FlightRecorder() : index(0)
35     {
36         flightRecorderPolicy = FLIGHT_RECORDER_MAX_ENTRIES ? true : false;
37         if (flightRecorderPolicy)
38         {
39             tapeRecorder = FlightRecorderCassette(FLIGHT_RECORDER_MAX_ENTRIES);
40         }
41     }
42 
43   protected:
44     int index;
45     FlightRecorderCassette tapeRecorder;
46     bool flightRecorderPolicy;
47 
48   public:
49     FlightRecorder(const FlightRecorder&) = delete;
50     FlightRecorder(FlightRecorder&&) = delete;
51     FlightRecorder& operator=(const FlightRecorder&) = delete;
52     FlightRecorder& operator=(FlightRecorder&&) = delete;
53     ~FlightRecorder() = default;
54 
55     static FlightRecorder& GetInstance()
56     {
57         static FlightRecorder flightRecorder;
58         return flightRecorder;
59     }
60 
61     /** @brief Add records to the flightRecorder
62      *
63      *  @param[in] buffer  - The request/respose byte buffer
64      *  @param[in] isRequest - bool that captures if it is a request message or
65      *                         a response message
66      *
67      *  @return void
68      */
69     void saveRecord(const FlightRecorderData& buffer, ReqOrResponse isRequest)
70     {
71         // if the flight recorder policy is enabled, then only insert the
72         // messages into the flight recorder, if not this function will be just
73         // a no-op
74         if (flightRecorderPolicy)
75         {
76             int currentIndex = index++;
77             tapeRecorder[currentIndex] = std::make_tuple(
78                 pldm::utils::getCurrentSystemTime(), isRequest, buffer);
79             index =
80                 (currentIndex == FLIGHT_RECORDER_MAX_ENTRIES - 1) ? 0 : index;
81         }
82     }
83 
84     /** @brief play flight recorder
85      *
86      *  @return void
87      */
88 
89     void playRecorder()
90     {
91         if (flightRecorderPolicy)
92         {
93             std::ofstream recorderOutputFile(flightRecorderDumpPath);
94             std::cout << "Dumping the flight recorder into : "
95                       << flightRecorderDumpPath << "\n";
96 
97             for (const auto& message : tapeRecorder)
98             {
99                 recorderOutputFile << std::get<FlightRecorderTimeStamp>(message)
100                                    << " : ";
101                 if (std::get<ReqOrResponse>(message))
102                 {
103                     recorderOutputFile << "Tx : \n";
104                 }
105                 else
106                 {
107                     recorderOutputFile << "Rx : \n";
108                 }
109                 for (const auto& word : std::get<FlightRecorderData>(message))
110                 {
111                     recorderOutputFile << std::setfill('0') << std::setw(2)
112                                        << std::hex << (unsigned)word << " ";
113                 }
114                 recorderOutputFile << std::endl;
115             }
116             recorderOutputFile.close();
117         }
118         else
119         {
120             std::cerr << "Fight recorder policy is disabled\n";
121         }
122     }
123 };
124 
125 } // namespace flightrecorder
126 } // namespace pldm
127