blob: f0a8f1772e936729f59a932d9220a3d67ff37f7e [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{
15 std::cout << "I> Registering Command" << std::hex
16 << inCommand.command << "\n";
17
18 commandTable[inCommand.command] = std::move(entry);
19}
20
21std::vector<uint8_t> Table::executeCommand(uint32_t inCommand,
22 std::vector<uint8_t>& commandData,
23 const message::Handler& handler)
24{
25 using namespace std::chrono_literals;
26
27 std::vector<uint8_t> response;
28
29 auto iterator = commandTable.find(inCommand);
30
31 if (iterator == commandTable.end())
32 {
33 std::cerr << "E> Table:: Command Not found: 0x" << std::hex << inCommand
34 << "\n";
35
36 response.resize(1);
37 response[0] = IPMI_CC_INVALID;
38 }
39 else
40 {
41 auto start = std::chrono::steady_clock::now();
42
43 response = iterator->second->executeCommand(commandData, handler);
44
45 auto end = std::chrono::steady_clock::now();
46
47 auto elapsedSeconds = std::chrono::duration_cast<std::chrono::seconds>
48 (end - start);
49
50 // If command time execution time exceeds 2 seconds, log a time
51 // exceeded message
52 if (elapsedSeconds > 2s)
53 {
54 std::cerr << "E> IPMI command timed out:Elapsed time = "
55 << elapsedSeconds.count() << "s" << "\n";
56 }
57 }
58 return response;
59}
60
61std::vector<uint8_t> NetIpmidEntry::executeCommand(
62 std::vector<uint8_t>& commandData,
63 const message::Handler& handler)
64{
65 std::vector<uint8_t> errResponse;
66
67 // Check if the command qualifies to be run prior to establishing a session
68 if (!sessionless && (handler.sessionID == session::SESSION_ZERO))
69 {
70 errResponse.resize(1);
71 errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
72 std::cerr << "E> Table::Not enough privileges for command 0x"
73 << std::hex << command.command << "\n";
74 return errResponse;
75 }
76
77 return functor(commandData, handler);
78}
79
Tom606e8cb2016-12-02 13:36:14 +053080std::vector<uint8_t> ProviderIpmidEntry::executeCommand(
81 std::vector<uint8_t>& commandData,
82 const message::Handler& handler)
83{
Tom Joseph1efcb492017-01-31 16:56:47 +053084 std::vector<uint8_t> response(message::parser::MAX_PAYLOAD_SIZE - 1);
Tom606e8cb2016-12-02 13:36:14 +053085 size_t respSize {};
86
87 ipmi_ret_t ipmiRC = functor(0, 0,
88 reinterpret_cast<void*>(commandData.data()),
89 reinterpret_cast<void*>(response.data() + 1),
90 &respSize, NULL);
91
92 /*
93 * respSize gets you the size of the response data for the IPMI command. The
94 * first byte in a response to the IPMI command is the Completion Code.
95 * So we are inserting completion code as the first byte and incrementing
96 * the response payload size by the size of the completion code.
97 */
98 response[0] = ipmiRC;
99 response.resize(respSize + sizeof(ipmi_ret_t));
100
101 return response;
102}
103
Tom Joseph07181f52016-08-08 08:17:08 -0500104} // namespace command