blob: 7a6e2df1a004cfddfaaf2332fe5607b0d29e5d4b [file] [log] [blame]
Tom Joseph07181f52016-08-08 08:17:08 -05001#include "command_table.hpp"
2
3#include <iomanip>
4#include <iostream>
5
Tom Joseph07181f52016-08-08 08:17:08 -05006#include "message_handler.hpp"
Tom Joseph1efcb492017-01-31 16:56:47 +05307#include "message_parsers.hpp"
Tom Joseph07181f52016-08-08 08:17:08 -05008#include "sessions_manager.hpp"
9
10namespace command
11{
12
13void Table::registerCommand(CommandID inCommand, std::unique_ptr<Entry>&& entry)
14{
Feist, Jamesbd45aae2017-10-26 15:06:13 -070015 auto& command = commandTable[inCommand.command];
16
17 if (command)
18 {
19 std::cout << "I> Already Registered, Skipping " << std::hex
20 << inCommand.command << "\n";
21 return;
22 }
23
Tom Joseph07181f52016-08-08 08:17:08 -050024 std::cout << "I> Registering Command" << std::hex
25 << inCommand.command << "\n";
26
Feist, Jamesbd45aae2017-10-26 15:06:13 -070027 command = std::move(entry);
Tom Joseph07181f52016-08-08 08:17:08 -050028}
29
30std::vector<uint8_t> Table::executeCommand(uint32_t inCommand,
31 std::vector<uint8_t>& commandData,
32 const message::Handler& handler)
33{
34 using namespace std::chrono_literals;
35
36 std::vector<uint8_t> response;
37
38 auto iterator = commandTable.find(inCommand);
39
40 if (iterator == commandTable.end())
41 {
42 std::cerr << "E> Table:: Command Not found: 0x" << std::hex << inCommand
43 << "\n";
44
45 response.resize(1);
46 response[0] = IPMI_CC_INVALID;
47 }
48 else
49 {
50 auto start = std::chrono::steady_clock::now();
51
52 response = iterator->second->executeCommand(commandData, handler);
53
54 auto end = std::chrono::steady_clock::now();
55
56 auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>
57 (end - start);
58
59 // If command time execution time exceeds 2 seconds, log a time
60 // exceeded message
61 if (elapsedSeconds > 2s)
62 {
63 std::cerr << "E> IPMI command timed out:Elapsed time = "
64 << elapsedSeconds.count() << "s" << "\n";
65 }
66 }
67 return response;
68}
69
70std::vector<uint8_t> NetIpmidEntry::executeCommand(
71 std::vector<uint8_t>& commandData,
72 const message::Handler& handler)
73{
74 std::vector<uint8_t> errResponse;
75
76 // Check if the command qualifies to be run prior to establishing a session
77 if (!sessionless && (handler.sessionID == session::SESSION_ZERO))
78 {
79 errResponse.resize(1);
80 errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
81 std::cerr << "E> Table::Not enough privileges for command 0x"
82 << std::hex << command.command << "\n";
83 return errResponse;
84 }
85
86 return functor(commandData, handler);
87}
88
Tom606e8cb2016-12-02 13:36:14 +053089std::vector<uint8_t> ProviderIpmidEntry::executeCommand(
90 std::vector<uint8_t>& commandData,
91 const message::Handler& handler)
92{
Tom Joseph1efcb492017-01-31 16:56:47 +053093 std::vector<uint8_t> response(message::parser::MAX_PAYLOAD_SIZE - 1);
Feist, Jamesbd45aae2017-10-26 15:06:13 -070094 size_t respSize = commandData.size();
Tom606e8cb2016-12-02 13:36:14 +053095
96 ipmi_ret_t ipmiRC = functor(0, 0,
97 reinterpret_cast<void*>(commandData.data()),
98 reinterpret_cast<void*>(response.data() + 1),
99 &respSize, NULL);
100
101 /*
102 * respSize gets you the size of the response data for the IPMI command. The
103 * first byte in a response to the IPMI command is the Completion Code.
104 * So we are inserting completion code as the first byte and incrementing
105 * the response payload size by the size of the completion code.
106 */
107 response[0] = ipmiRC;
108 response.resize(respSize + sizeof(ipmi_ret_t));
109
110 return response;
111}
112
Tom Joseph07181f52016-08-08 08:17:08 -0500113} // namespace command