blob: c0e655a2b1bb7aa1989a5da5371925a808635ab6 [file] [log] [blame]
Tom Joseph07181f52016-08-08 08:17:08 -05001#include "command_table.hpp"
2
Richard Marian Thomaiyar472a37b2018-09-06 07:11:07 +05303#include "main.hpp"
Tom Joseph07181f52016-08-08 08:17:08 -05004#include "message_handler.hpp"
Tom Joseph1efcb492017-01-31 16:56:47 +05305#include "message_parsers.hpp"
Tom Joseph07181f52016-08-08 08:17:08 -05006#include "sessions_manager.hpp"
Nagaraju Goruganti1d9d4162018-03-22 01:27:37 -05007
Patrick Williams75a8d8b2021-09-02 11:30:44 -05008#include <ipmid/types.hpp>
Vernon Mauery66501642018-07-30 09:07:10 -07009#include <main.hpp>
George Liu7b7f25f2022-07-04 17:07:32 +080010#include <phosphor-logging/lg2.hpp>
Vernon Mauery66501642018-07-30 09:07:10 -070011#include <user_channel/user_layer.hpp>
Vernon Mauery9e801a22018-10-12 13:20:49 -070012
George Liubc8958f2022-07-04 09:29:49 +080013#include <iomanip>
14
Tom Joseph07181f52016-08-08 08:17:08 -050015namespace command
16{
17
18void Table::registerCommand(CommandID inCommand, std::unique_ptr<Entry>&& entry)
19{
Feist, Jamesbd45aae2017-10-26 15:06:13 -070020 auto& command = commandTable[inCommand.command];
21
22 if (command)
23 {
George Liu7b7f25f2022-07-04 17:07:32 +080024 lg2::debug("Already Registered: {COMMAND}", "COMMAND",
25 inCommand.command);
Feist, Jamesbd45aae2017-10-26 15:06:13 -070026 return;
27 }
28
Feist, Jamesbd45aae2017-10-26 15:06:13 -070029 command = std::move(entry);
Tom Joseph07181f52016-08-08 08:17:08 -050030}
31
Vernon Mauery8d6f2002018-11-07 09:55:53 -080032void Table::executeCommand(uint32_t inCommand,
33 std::vector<uint8_t>& commandData,
34 std::shared_ptr<message::Handler> handler)
Tom Joseph07181f52016-08-08 08:17:08 -050035{
36 using namespace std::chrono_literals;
37
Tom Joseph07181f52016-08-08 08:17:08 -050038 auto iterator = commandTable.find(inCommand);
39
40 if (iterator == commandTable.end())
41 {
Vernon Mauery66501642018-07-30 09:07:10 -070042 CommandID command(inCommand);
43
Vernon Mauery779e7e12021-06-08 16:24:45 -070044 // Do not forward any session zero commands to ipmid
45 if (handler->sessionID == session::sessionZero)
46 {
George Liu7b7f25f2022-07-04 17:07:32 +080047 lg2::info(
48 "Table: refuse to forward session-zero command: lun: {LUN}, netFn: {NETFN}, command: {COMMAND}",
49 "LUN", command.lun(), "NETFN", command.netFn(), "COMMAND",
50 command.cmd());
Vernon Mauery779e7e12021-06-08 16:24:45 -070051 return;
52 }
Vernon Mauerycfb34ca2021-06-10 15:37:07 -070053 std::shared_ptr<session::Session> session =
Vernon Mauery2085ae02021-06-10 11:51:00 -070054 session::Manager::get().getSession(handler->sessionID);
Vernon Mauerycfb34ca2021-06-10 15:37:07 -070055
56 // Ignore messages that are not part of an active session
57 auto state = static_cast<session::State>(session->state());
58 if (state != session::State::active)
59 {
60 return;
61 }
Vernon Mauery779e7e12021-06-08 16:24:45 -070062
Vernon Mauery66501642018-07-30 09:07:10 -070063 auto bus = getSdBus();
64 // forward the request onto the main ipmi queue
Vernon Mauery8d6f2002018-11-07 09:55:53 -080065 using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t, uint8_t,
66 std::vector<uint8_t>>;
Vernon Mauery66501642018-07-30 09:07:10 -070067 uint8_t lun = command.lun();
68 uint8_t netFn = command.netFn();
69 uint8_t cmd = command.cmd();
Vernon Mauerycfb34ca2021-06-10 15:37:07 -070070
Vernon Mauery66501642018-07-30 09:07:10 -070071 std::map<std::string, ipmi::Value> options = {
Vernon Maueryd92bc322019-03-15 15:24:30 -070072 {"userId", ipmi::Value(static_cast<int>(
73 ipmi::ipmiUserGetUserId(session->userName)))},
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +053074 {"privilege",
75 ipmi::Value(static_cast<int>(session->currentPrivilege()))},
Rajashekar Gade Reddy49a94b22019-11-13 16:46:32 +053076 {"currentSessionId",
77 ipmi::Value(static_cast<uint32_t>(session->getBMCSessionID()))},
Vernon Mauery66501642018-07-30 09:07:10 -070078 };
Vernon Mauery8d6f2002018-11-07 09:55:53 -080079 bus->async_method_call(
80 [handler, this](const boost::system::error_code& ec,
81 const IpmiDbusRspType& response) {
82 if (!ec)
83 {
84 const uint8_t& cc = std::get<3>(response);
85 const std::vector<uint8_t>& responseData =
86 std::get<4>(response);
87 std::vector<uint8_t> payload;
88 payload.reserve(1 + responseData.size());
89 payload.push_back(cc);
90 payload.insert(payload.end(), responseData.begin(),
91 responseData.end());
92 handler->outPayload = std::move(payload);
93 }
94 else
95 {
96 std::vector<uint8_t> payload;
97 payload.push_back(IPMI_CC_UNSPECIFIED_ERROR);
98 handler->outPayload = std::move(payload);
99 }
100 },
101 "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
102 "xyz.openbmc_project.Ipmi.Server", "execute", netFn, lun, cmd,
103 commandData, options);
Tom Joseph07181f52016-08-08 08:17:08 -0500104 }
105 else
106 {
107 auto start = std::chrono::steady_clock::now();
108
Vernon Mauerycfb34ca2021-06-10 15:37:07 -0700109 // Ignore messages that are not part of an active/pre-active session
110 if (handler->sessionID != session::sessionZero)
111 {
112 std::shared_ptr<session::Session> session =
Vernon Mauery2085ae02021-06-10 11:51:00 -0700113 session::Manager::get().getSession(handler->sessionID);
Vernon Mauerycfb34ca2021-06-10 15:37:07 -0700114 auto state = static_cast<session::State>(session->state());
115 if ((state != session::State::setupInProgress) &&
116 (state != session::State::active))
117 {
118 return;
119 }
120 }
121
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800122 handler->outPayload =
123 iterator->second->executeCommand(commandData, handler);
Tom Joseph07181f52016-08-08 08:17:08 -0500124
125 auto end = std::chrono::steady_clock::now();
126
Yong Li899cf5a2020-01-19 13:32:20 +0800127 std::chrono::duration<size_t> elapsedSeconds =
Vernon Mauery9e801a22018-10-12 13:20:49 -0700128 std::chrono::duration_cast<std::chrono::seconds>(end - start);
Tom Joseph07181f52016-08-08 08:17:08 -0500129
130 // If command time execution time exceeds 2 seconds, log a time
131 // exceeded message
132 if (elapsedSeconds > 2s)
133 {
George Liu7b7f25f2022-07-04 17:07:32 +0800134 lg2::error("IPMI command timed out: {DELAY}", "DELAY",
135 elapsedSeconds.count());
Tom Joseph07181f52016-08-08 08:17:08 -0500136 }
137 }
Tom Joseph07181f52016-08-08 08:17:08 -0500138}
139
Vernon Mauery9e801a22018-10-12 13:20:49 -0700140std::vector<uint8_t>
141 NetIpmidEntry::executeCommand(std::vector<uint8_t>& commandData,
Vernon Mauery8d6f2002018-11-07 09:55:53 -0800142 std::shared_ptr<message::Handler> handler)
Tom Joseph07181f52016-08-08 08:17:08 -0500143{
144 std::vector<uint8_t> errResponse;
145
146 // Check if the command qualifies to be run prior to establishing a session
Suryakanth Sekarf8a34fc2019-06-12 20:59:18 +0530147 if (!sessionless && (handler->sessionID == session::sessionZero))
Tom Joseph07181f52016-08-08 08:17:08 -0500148 {
149 errResponse.resize(1);
150 errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
George Liu7b7f25f2022-07-04 17:07:32 +0800151 lg2::info(
152 "Table: Insufficient privilege for command: lun: {LUN}, netFn: {NETFN}, command: {COMMAND}",
153 "LUN", command.lun(), "NETFN", command.netFn(), "COMMAND",
154 command.cmd());
Tom Joseph07181f52016-08-08 08:17:08 -0500155 return errResponse;
156 }
157
Vernon Mauery41ff9b52021-06-11 11:37:40 -0700158 return functor(commandData, handler);
Tom Joseph07181f52016-08-08 08:17:08 -0500159}
160
Tom Joseph07181f52016-08-08 08:17:08 -0500161} // namespace command