xref: /openbmc/pldm/common/flight_recorder.hpp (revision 7b017268)
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 
37         flightRecorderPolicy = FLIGHT_RECORDER_MAX_ENTRIES ? true : false;
38         if (flightRecorderPolicy)
39         {
40             tapeRecorder = FlightRecorderCassette(FLIGHT_RECORDER_MAX_ENTRIES);
41         }
42     }
43 
44   protected:
45     int index;
46     FlightRecorderCassette tapeRecorder;
47     bool flightRecorderPolicy;
48 
49   public:
50     FlightRecorder(const FlightRecorder&) = delete;
51     FlightRecorder(FlightRecorder&&) = delete;
52     FlightRecorder& operator=(const FlightRecorder&) = delete;
53     FlightRecorder& operator=(FlightRecorder&&) = delete;
54     ~FlightRecorder() = default;
55 
56     static FlightRecorder& GetInstance()
57     {
58         static FlightRecorder flightRecorder;
59         return flightRecorder;
60     }
61 
62     /** @brief Add records to the flightRecorder
63      *
64      *  @param[in] buffer  - The request/respose byte buffer
65      *  @param[in] isRequest - bool that captures if it is a request message or
66      *                         a response message
67      *
68      *  @return void
69      */
70     void saveRecord(const FlightRecorderData& buffer, ReqOrResponse isRequest)
71     {
72         // if the flight recorder policy is enabled, then only insert the
73         // messages into the flight recorder, if not this function will be just
74         // a no-op
75         if (flightRecorderPolicy)
76         {
77             int currentIndex = index++;
78             tapeRecorder[currentIndex] = std::make_tuple(
79                 pldm::utils::getCurrentSystemTime(), isRequest, buffer);
80             index =
81                 (currentIndex == FLIGHT_RECORDER_MAX_ENTRIES - 1) ? 0 : index;
82         }
83     }
84 
85     /** @brief play flight recorder
86      *
87      *  @return void
88      */
89 
90     void playRecorder()
91     {
92         if (flightRecorderPolicy)
93         {
94             std::ofstream recorderOutputFile(flightRecorderDumpPath);
95             std::cout << "Dumping the flight recorder into : "
96                       << flightRecorderDumpPath << "\n";
97 
98             for (const auto& message : tapeRecorder)
99             {
100                 recorderOutputFile << std::get<FlightRecorderTimeStamp>(message)
101                                    << " : ";
102                 if (std::get<ReqOrResponse>(message))
103                 {
104                     recorderOutputFile << "Tx : \n";
105                 }
106                 else
107                 {
108                     recorderOutputFile << "Rx : \n";
109                 }
110                 for (const auto& word : std::get<FlightRecorderData>(message))
111                 {
112                     recorderOutputFile << std::setfill('0') << std::setw(2)
113                                        << std::hex << (unsigned)word << " ";
114                 }
115                 recorderOutputFile << std::endl;
116             }
117             recorderOutputFile.close();
118         }
119         else
120         {
121             std::cerr << "Fight recorder policy is disabled\n";
122         }
123     }
124 };
125 
126 } // namespace flightrecorder
127 } // namespace pldm
128