netipmid: Update netipmid to use ipmid as the main queue
All ipmi processing is now done in the main ipmi queue
(phosphor-host-ipmid) and messages are passed via dbus. This removes the
handler registration for providers and just passes the message along to
the main queue instead of executing the provider in-situ. This makes the
net-ipmid more like the bt-bridge or kcs-bridge that are simple channel
handlers that move messages from a medium to the queue.
Change-Id: Icc9d580fd5546505c95acf0bea47c70e09809b7d
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/command_table.cpp b/command_table.cpp
index d0ef173..e911bc6 100644
--- a/command_table.cpp
+++ b/command_table.cpp
@@ -6,12 +6,23 @@
#include "sessions_manager.hpp"
#include <iomanip>
+#include <main.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
+#include <user_channel/user_layer.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using namespace phosphor::logging;
+namespace ipmi
+{
+using Value = sdbusplus::message::variant<bool, uint8_t, int16_t, uint16_t,
+ int32_t, uint32_t, int64_t, uint64_t,
+ double, std::string>;
+
+} // namespace ipmi
+
namespace command
{
@@ -23,8 +34,7 @@
{
log<level::DEBUG>(
"Already Registered",
- phosphor::logging::entry("SKIPPED_ENTRY=0x%x",
- uint32_t(inCommand.command)));
+ phosphor::logging::entry("SKIPPED_ENTRY=0x%x", inCommand.command));
return;
}
@@ -43,8 +53,52 @@
if (iterator == commandTable.end())
{
- response.resize(1);
- response[0] = IPMI_CC_INVALID;
+ CommandID command(inCommand);
+
+ auto bus = getSdBus();
+ // forward the request onto the main ipmi queue
+ auto method = bus->new_method_call(
+ "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
+ "xyz.openbmc_project.Ipmi.Server", "execute");
+ uint8_t lun = command.lun();
+ uint8_t netFn = command.netFn();
+ uint8_t cmd = command.cmd();
+ std::shared_ptr<session::Session> session =
+ std::get<session::Manager&>(singletonPool)
+ .getSession(handler.sessionID);
+ std::map<std::string, ipmi::Value> options = {
+ {"userId", ipmi::Value(ipmi::ipmiUserGetUserId(session->userName))},
+ {"privilege", ipmi::Value(static_cast<int>(session->curPrivLevel))},
+ };
+ method.append(netFn, lun, cmd, commandData, options);
+ using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t, uint8_t,
+ std::vector<uint8_t>>;
+ IpmiDbusRspType rspTuple;
+ try
+ {
+ auto reply = bus->call(method);
+ reply.read(rspTuple);
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ response.push_back(IPMI_CC_UNSPECIFIED_ERROR);
+ log<level::ERR>("Error sending command to ipmi queue");
+ elog<InternalFailure>();
+ }
+ auto& [rnetFn, rlun, rcmd, cc, responseData] = rspTuple;
+ if (uint8_t(netFn + 1) != rnetFn || rlun != lun || rcmd != cmd)
+ {
+ response.push_back(IPMI_CC_UNSPECIFIED_ERROR);
+ log<level::ERR>("DBus call/response mismatch from ipmi queue");
+ elog<InternalFailure>();
+ }
+ else
+ {
+ response.reserve(1 + responseData.size());
+ response.push_back(cc);
+ response.insert(response.end(), responseData.begin(),
+ responseData.end());
+ }
}
else
{
@@ -80,62 +134,13 @@
errResponse.resize(1);
errResponse[0] = IPMI_CC_INSUFFICIENT_PRIVILEGE;
log<level::INFO>("Table: Insufficient privilege for command",
- entry("LUN=%x", int(command.NetFnLun.lun)),
- entry("NETFN=%x", int(command.NetFnLun.netFn)),
- entry("CMD=%x", command.cmd));
+ entry("LUN=%x", command.lun()),
+ entry("NETFN=%x", command.netFn()),
+ entry("CMD=%x", command.cmd()));
return errResponse;
}
return functor(commandData, handler);
}
-std::vector<uint8_t>
- ProviderIpmidEntry::executeCommand(std::vector<uint8_t>& commandData,
- const message::Handler& handler)
-{
- std::vector<uint8_t> response(message::parser::MAX_PAYLOAD_SIZE - 1);
- size_t respSize = commandData.size();
- ipmi_ret_t ipmiRC = IPMI_CC_UNSPECIFIED_ERROR;
- std::shared_ptr<session::Session> session =
- std::get<session::Manager&>(singletonPool)
- .getSession(handler.sessionID);
-
- if (session->curPrivLevel >= Entry::getPrivilege())
- {
- try
- {
- ipmiRC = functor(0, 0, reinterpret_cast<void*>(commandData.data()),
- reinterpret_cast<void*>(response.data() + 1),
- &respSize, NULL);
- }
- // IPMI command handlers can throw unhandled exceptions, catch those
- // and return sane error code.
- catch (const std::exception& e)
- {
- log<level::ERR>("Table: Unspecified error for command",
- entry("EXCEPTION=%s", e.what()),
- entry("LUN=%x", int(command.NetFnLun.lun)),
- entry("NETFN=%x", int(command.NetFnLun.netFn)),
- entry("CMD=%x", command.cmd));
- respSize = 0;
- // fall through
- }
- }
- else
- {
- respSize = 0;
- ipmiRC = IPMI_CC_INSUFFICIENT_PRIVILEGE;
- }
- /*
- * respSize gets you the size of the response data for the IPMI command. The
- * first byte in a response to the IPMI command is the Completion Code.
- * So we are inserting completion code as the first byte and incrementing
- * the response payload size by the size of the completion code.
- */
- response[0] = ipmiRC;
- response.resize(respSize + sizeof(ipmi_ret_t));
-
- return response;
-}
-
} // namespace command