Reuse MCTP instance IDs for PLDM retries
occ-control will request a new instance ID when it times out waiting for
the PLDM response. Code change will not request a new ID unless the
prior response was received successfully.
Change-Id: I8a3509d7ea583bb706ad2ef41bf90cc5d0f0275b
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/pldm.cpp b/pldm.cpp
index 6e3dfe6..f4a1c73 100644
--- a/pldm.cpp
+++ b/pldm.cpp
@@ -158,24 +158,23 @@
if (sensorEntry != sensorToOCCInstance.end())
{
+ const uint8_t instance = sensorEntry->second;
if (eventState ==
static_cast<EventState>(
PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE))
{
log<level::INFO>(
- fmt::format("PLDM: OCC{} is RUNNING", sensorEntry->second)
- .c_str());
-
+ fmt::format("PLDM: OCC{} is RUNNING", instance).c_str());
callBack(sensorEntry->second, true);
}
else if (eventState ==
static_cast<EventState>(
PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED))
{
- log<level::INFO>(fmt::format("PLDM: OCC{} has now STOPPED",
- sensorEntry->second)
- .c_str());
- callBack(sensorEntry->second, false);
+ log<level::INFO>(
+ fmt::format("PLDM: OCC{} has now STOPPED", instance)
+ .c_str());
+ callBack(instance, false);
}
else if (eventState ==
static_cast<EventState>(
@@ -184,22 +183,21 @@
log<level::INFO>(
fmt::format(
"PLDM: OCC{} has now STOPPED and system is in SAFE MODE",
- sensorEntry->second)
+ instance)
.c_str());
// Setting safe mode true
safeModeCallBack(true);
- callBack(sensorEntry->second, false);
+ callBack(instance, false);
}
else
{
log<level::INFO>(
fmt::format("PLDM: Unexpected PLDM state {} for OCC{}",
- eventState, sensorEntry->second)
+ eventState, instance)
.c_str());
}
-
return;
}
}
@@ -342,10 +340,15 @@
}
std::vector<uint8_t>
- Interface::prepareSetEffecterReq(uint8_t instanceId, EffecterID effecterId,
+ Interface::prepareSetEffecterReq(EffecterID effecterId,
CompositeEffecterCount effecterCount,
uint8_t stateIdPos, uint8_t stateSetValue)
{
+ if (!getMctpInstanceId())
+ {
+ return std::vector<uint8_t>();
+ }
+
std::vector<uint8_t> request(
sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
(effecterCount * sizeof(set_effecter_state_field)));
@@ -366,7 +369,8 @@
}
}
auto rc = encode_set_state_effecter_states_req(
- instanceId, effecterId, effecterCount, stateField.data(), requestMsg);
+ mctpInstance.value(), effecterId, effecterCount, stateField.data(),
+ requestMsg);
if (rc != PLDM_SUCCESS)
{
log<level::ERR>("encode set effecter states request returned error ",
@@ -400,15 +404,10 @@
return;
}
- if (!getMctpInstanceId(mctpInstance))
- {
- return;
- }
-
// Prepare the SetStateEffecterStates request to reset the OCC
auto request = prepareSetEffecterReq(
- mctpInstance, effecterEntry->second, OCCEffecterCount,
- bootRestartPosition, PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET);
+ effecterEntry->second, OCCEffecterCount, bootRestartPosition,
+ PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET);
if (request.empty())
{
@@ -449,14 +448,9 @@
return;
}
- if (!getMctpInstanceId(mctpInstance))
- {
- return;
- }
-
// Prepare the SetStateEffecterStates request to HRESET the SBE
auto request = prepareSetEffecterReq(
- mctpInstance, effecterEntry->second, SBEEffecterCount,
+ effecterEntry->second, SBEEffecterCount,
sbeMaintenanceStatePosition, SBE_RETRY_REQUIRED);
if (request.empty())
@@ -479,23 +473,33 @@
}
}
-bool Interface::getMctpInstanceId(uint8_t& instanceId)
+bool Interface::getMctpInstanceId()
{
- auto& bus = open_power::occ::utils::getBus();
- try
+ if (!mctpInstance)
{
- auto method = bus.new_method_call(
- "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
- "xyz.openbmc_project.PLDM.Requester", "GetInstanceId");
- method.append(mctpEid);
- auto reply = bus.call(method);
- reply.read(instanceId);
- }
- catch (const sdbusplus::exception::exception& e)
- {
- log<level::ERR>(
- fmt::format("pldm: GetInstanceId failed: {}", e.what()).c_str());
- return false;
+ // Request new instance ID
+ auto& bus = open_power::occ::utils::getBus();
+ try
+ {
+ auto method = bus.new_method_call(
+ "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
+ "xyz.openbmc_project.PLDM.Requester", "GetInstanceId");
+ method.append(mctpEid);
+ auto reply = bus.call(method);
+ uint8_t newInstanceId;
+ reply.read(newInstanceId);
+ mctpInstance = newInstanceId;
+ log<level::INFO>(fmt::format("pldm: got new InstanceId: {}",
+ mctpInstance.value())
+ .c_str());
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ log<level::ERR>(
+ fmt::format("pldm: GetInstanceId failed: {}", e.what())
+ .c_str());
+ return false;
+ }
}
return true;
@@ -504,6 +508,12 @@
void Interface::sendPldm(const std::vector<uint8_t>& request,
const uint8_t instance, const bool rspExpected)
{
+ if (!mctpInstance)
+ {
+ log<level::ERR>("sendPldm: No MCTP Instance ID found!");
+ return;
+ }
+
// Connect to MCTP scoket
pldmFd = pldm_open();
auto openErrno = errno;
@@ -527,7 +537,7 @@
log<level::INFO>(
fmt::format(
"sendPldm: calling pldm_send(OCC{}, instance:{}, {} bytes)",
- instance, mctpInstance, request.size())
+ instance, mctpInstance.value(), request.size())
.c_str());
pldmResponseReceived = false;
pldmResponseTimeout = false;
@@ -570,6 +580,11 @@
strerror(sendErrno))
.c_str());
}
+ else
+ {
+ // Not waiting for response, instance ID should be freed
+ mctpInstance = std::nullopt;
+ }
pldmClose();
}
}
@@ -638,15 +653,22 @@
auto pldmIface = static_cast<Interface*>(userData);
+ if (!pldmIface->mctpInstance)
+ {
+ log<level::ERR>(
+ "pldmRspCallback: No outstanding MCTP Instance ID found");
+ return -1;
+ }
+
uint8_t* responseMsg = nullptr;
size_t responseMsgSize{};
log<level::INFO>(
fmt::format("pldmRspCallback: calling pldm_recv() instance:{}",
- pldmIface->mctpInstance)
+ pldmIface->mctpInstance.value())
.c_str());
- auto rc = pldm_recv(mctpEid, fd, pldmIface->mctpInstance, &responseMsg,
- &responseMsgSize);
+ auto rc = pldm_recv(mctpEid, fd, pldmIface->mctpInstance.value(),
+ &responseMsg, &responseMsgSize);
int lastErrno = errno;
if (rc)
{
@@ -657,6 +679,8 @@
.c_str());
return -1;
}
+
+ // We got the response for the PLDM request msg that was sent
log<level::INFO>(
fmt::format("pldmRspCallback: pldm_recv() rsp was {} bytes",
responseMsgSize)
@@ -668,13 +692,13 @@
pldmIface->pldmRspTimer.setEnabled(false);
}
+ // instance ID should be freed
+ pldmIface->mctpInstance = std::nullopt;
+
// Set pointer to autodelete
std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg,
std::free};
- // We've got the response meant for the PLDM request msg that was
- // sent out
- // io.set_enabled(Enabled::Off);
auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
if (response->payload[0] != PLDM_SUCCESS)
{
@@ -732,8 +756,9 @@
else
{
log<level::INFO>(
- fmt::format("pldmRspCallback: OCC{} is not running (state:{})",
- instance, occSensorState)
+ fmt::format(
+ "pldmRspCallback: OCC{} is not running (sensor state:{})",
+ instance, occSensorState)
.c_str());
pldmIface->callBack(instance, false);
}
@@ -744,13 +769,21 @@
std::vector<uint8_t> Interface::encodeGetStateSensorRequest(uint8_t instance,
uint16_t sensorId)
{
+ if (!getMctpInstanceId())
+ {
+ log<level::ERR>(
+ "encodeGetStateSensorRequest: failed to getMctpInstanceId");
+ return std::vector<uint8_t>();
+ }
+
bitfield8_t sRearm = {0};
const size_t msgSize =
sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES;
std::vector<uint8_t> request(msgSize);
+
auto msg = reinterpret_cast<pldm_msg*>(request.data());
- auto msgRc = encode_get_state_sensor_readings_req(mctpInstance, sensorId,
- sRearm, 0, msg);
+ auto msgRc = encode_get_state_sensor_readings_req(mctpInstance.value(),
+ sensorId, sRearm, 0, msg);
if (msgRc != PLDM_SUCCESS)
{
log<level::ERR>(
@@ -800,12 +833,6 @@
instance, entry->first)
.c_str());
- if (!getMctpInstanceId(mctpInstance))
- {
- log<level::ERR>("checkActiveSensor: failed to getMctpInstanceId");
- return;
- }
-
// Encode GetStateSensorReadings PLDM message
auto request = encodeGetStateSensorRequest(instance, entry->first);
if (request.empty())
diff --git a/pldm.hpp b/pldm.hpp
index 40bc78b..3f0c844 100644
--- a/pldm.hpp
+++ b/pldm.hpp
@@ -108,7 +108,6 @@
/** @brief Prepare the request for SetStateEffecterStates command
*
- * @param[in] instanceId - PLDM instanceID
* @param[in] effecterId - the instance effecter ID
* @param[in] effecterCount - compositeEffecterCount for the effecter PDR
* @param[in] stateIdPos - position of the stateSetID
@@ -118,7 +117,7 @@
* HRESET, empty response in the case of failure.
*/
std::vector<uint8_t>
- prepareSetEffecterReq(uint8_t instanceId, EffecterID effecterId,
+ prepareSetEffecterReq(EffecterID effecterId,
CompositeEffecterCount effecterCount,
uint8_t stateIdPos, uint8_t stateSetValue);
@@ -144,6 +143,10 @@
void checkActiveSensor(uint8_t instance);
private:
+ /** @brief MCTP instance number used in PLDM requests
+ */
+ std::optional<uint8_t> mctpInstance;
+
/** @brief Callback handler to be invoked when the state of the OCC
* changes
*/
@@ -222,10 +225,6 @@
/** @brief File descriptor for PLDM messages */
int pldmFd = -1;
- /** @brief MCTP instance number used in PLDM requests
- */
- uint8_t mctpInstance{};
-
/** @brief The response for the PLDM request msg is received flag.
*/
bool pldmResponseReceived = false;
@@ -295,11 +294,9 @@
/** @brief Query PLDM for the MCTP requester instance id
*
- * @param[out] - the instance id
- *
* @return true if the id was found and false if not
*/
- bool getMctpInstanceId(uint8_t& instanceId);
+ bool getMctpInstanceId();
/** @brief Encode a GetStateSensor command into a PLDM request
* @param[in] instance - OCC instance number