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