| Manojkiran Eda | ef77305 | 2021-07-29 09:29:28 +0530 | [diff] [blame] | 1 | #pragma once | 
|  | 2 |  | 
| Manojkiran Eda | ef77305 | 2021-07-29 09:29:28 +0530 | [diff] [blame] | 3 | #include <common/utils.hpp> | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 4 | #include <phosphor-logging/lg2.hpp> | 
| Manojkiran Eda | ef77305 | 2021-07-29 09:29:28 +0530 | [diff] [blame] | 5 |  | 
|  | 6 | #include <fstream> | 
|  | 7 | #include <iomanip> | 
|  | 8 | #include <iostream> | 
|  | 9 | #include <vector> | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 10 |  | 
|  | 11 | PHOSPHOR_LOG2_USING; | 
|  | 12 |  | 
| Manojkiran Eda | ef77305 | 2021-07-29 09:29:28 +0530 | [diff] [blame] | 13 | namespace pldm | 
|  | 14 | { | 
|  | 15 | namespace flightrecorder | 
|  | 16 | { | 
| Manojkiran Eda | ef77305 | 2021-07-29 09:29:28 +0530 | [diff] [blame] | 17 | using ReqOrResponse = bool; | 
|  | 18 | using FlightRecorderData = std::vector<uint8_t>; | 
|  | 19 | using FlightRecorderTimeStamp = std::string; | 
|  | 20 | using FlightRecorderRecord = | 
|  | 21 | std::tuple<FlightRecorderTimeStamp, ReqOrResponse, FlightRecorderData>; | 
|  | 22 | using FlightRecorderCassette = std::vector<FlightRecorderRecord>; | 
|  | 23 | static constexpr auto flightRecorderDumpPath = "/tmp/pldm_flight_recorder"; | 
|  | 24 |  | 
|  | 25 | /** @class FlightRecorder | 
|  | 26 | * | 
|  | 27 | *  The class for implementing the PLDM flight recorder logic. This class | 
|  | 28 | *  handles the insertion of the data into the recorder and also provides | 
|  | 29 | *  API's to dump the flight recorder into a file. | 
|  | 30 | */ | 
|  | 31 |  | 
|  | 32 | class FlightRecorder | 
|  | 33 | { | 
|  | 34 | private: | 
|  | 35 | FlightRecorder() : index(0) | 
|  | 36 | { | 
| Manojkiran Eda | ef77305 | 2021-07-29 09:29:28 +0530 | [diff] [blame] | 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); | 
| Patrick Williams | 6da4f91 | 2023-05-10 07:50:53 -0500 | [diff] [blame] | 80 | index = (currentIndex == FLIGHT_RECORDER_MAX_ENTRIES - 1) ? 0 | 
|  | 81 | : index; | 
| Manojkiran Eda | ef77305 | 2021-07-29 09:29:28 +0530 | [diff] [blame] | 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); | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 95 | info("Dumping the flight recorder into : {DUMP_PATH}", "DUMP_PATH", | 
|  | 96 | flightRecorderDumpPath); | 
| Manojkiran Eda | ef77305 | 2021-07-29 09:29:28 +0530 | [diff] [blame] | 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 | { | 
| Riya Dixit | 49cfb13 | 2023-03-02 04:26:53 -0600 | [diff] [blame] | 120 | error("Fight recorder policy is disabled"); | 
| Manojkiran Eda | ef77305 | 2021-07-29 09:29:28 +0530 | [diff] [blame] | 121 | } | 
|  | 122 | } | 
|  | 123 | }; | 
|  | 124 |  | 
|  | 125 | } // namespace flightrecorder | 
|  | 126 | } // namespace pldm |