Skip to content

Commit

Permalink
Fix oom condition & pldm crash in resetreload path
Browse files Browse the repository at this point in the history
- After the PDR exchange from host post reset reload, bmc
  would start asking for the host sensor states and update
  the dbus objects.
- There was a bug in code where the iterator was crossing
  the end - causing a bad_alloc failure, it is manifested as
  either pldm crash or an oom condition(where the recursion
  is never completed and the stack keeps growing).

Testedby:

1. with the patch on rain139bmc, did 10 power on/offs & also
   reset reload's when host is up and did not see any issue.

Signed-off-by: Manojkiran Eda <[email protected]>
  • Loading branch information
manojkiraneda committed May 10, 2022
1 parent 0f5c59a commit 6aeca8d
Showing 1 changed file with 159 additions and 126 deletions.
285 changes: 159 additions & 126 deletions host-bmc/host_pdr_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ HostPDRHandler::HostPDRHandler(
this->responseReceived = false;
this->mergedHostParents = false;
this->objMapIndex = objPathMap.begin();
this->sensorIndex = stateSensorPDRs.begin();

// After a power off , the remote notes will be deleted
// from the entity association tree, making the nodes point
Expand Down Expand Up @@ -993,169 +994,201 @@ void HostPDRHandler::setHostSensorState()

void HostPDRHandler::_setHostSensorState()
{
uint8_t mctpEid = pldm::utils::readHostEID();
std::vector<uint8_t> stateSensorPDR = *sensorIndex;
auto pdr =
reinterpret_cast<const pldm_state_sensor_pdr*>(stateSensorPDR.data());

if (!pdr)
if (isHostOff)
{
std::cerr << "Failed to get State sensor PDR" << std::endl;
pldm::utils::reportError(
"xyz.openbmc_project.PLDM._setHostSensorState.GetStateSensorPDRFail",
pldm::PelSeverity::ERROR);
std::cerr
<< "set host state sensor begin : Host is off, stopped sending sensor state commands\n";
return;
}

uint16_t sensorId = pdr->sensor_id;

for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
if (sensorIndex != stateSensorPDRs.end())
{
if (terminusHandle == pdr->terminus_handle)
{
if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
{
mctpEid = std::get<1>(terminusInfo);
}
uint8_t mctpEid = pldm::utils::readHostEID();
std::vector<uint8_t> stateSensorPDR = *sensorIndex;
auto pdr = reinterpret_cast<const pldm_state_sensor_pdr*>(
stateSensorPDR.data());

bitfield8_t sensorRearm;
sensorRearm.byte = 0;
uint8_t tid = std::get<0>(terminusInfo);
if (!pdr)
{
std::cerr << "Failed to get State sensor PDR" << std::endl;
pldm::utils::reportError(
"xyz.openbmc_project.PLDM._setHostSensorState.GetStateSensorPDRFail",
pldm::PelSeverity::ERROR);
return;
}

auto instanceId = requester.getInstanceId(mctpEid);
std::vector<uint8_t> requestMsg(
sizeof(pldm_msg_hdr) +
PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
auto rc = encode_get_state_sensor_readings_req(
instanceId, sensorId, sensorRearm, 0, request);
uint16_t sensorId = pdr->sensor_id;

if (rc != PLDM_SUCCESS)
for (const auto& [terminusHandle, terminusInfo] : tlPDRInfo)
{
if (terminusHandle == pdr->terminus_handle)
{
requester.markFree(mctpEid, instanceId);
std::cerr << "Failed to "
"encode_get_state_sensor_readings_req, rc = "
<< rc << " SensorId=" << sensorId << std::endl;
pldm::utils::reportError(
"xyz.openbmc_project.bmc.PLDM._setHostSensorState.EncodeStateSensorFail",
pldm::PelSeverity::ERROR);
return;
}

auto getStateSensorReadingRespHandler = [=,
this](mctp_eid_t /*eid*/,
const pldm_msg*
response,
size_t respMsgLen) {
if (response == nullptr || !respMsgLen)
if (std::get<2>(terminusInfo) == PLDM_TL_PDR_VALID)
{
std::cerr << "Failed to receive response for "
"getStateSensorReading command for sensor id="
<< sensorId << std::endl;
return;
mctpEid = std::get<1>(terminusInfo);
}
std::array<get_sensor_state_field, 8> stateField{};
uint8_t completionCode = 0;
uint8_t comp_sensor_count = 0;

auto rc = decode_get_state_sensor_readings_resp(
response, respMsgLen, &completionCode, &comp_sensor_count,
stateField.data());
bitfield8_t sensorRearm;
sensorRearm.byte = 0;
uint8_t tid = std::get<0>(terminusInfo);

if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
auto instanceId = requester.getInstanceId(mctpEid);
std::vector<uint8_t> requestMsg(
sizeof(pldm_msg_hdr) +
PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES);
auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
auto rc = encode_get_state_sensor_readings_req(
instanceId, sensorId, sensorRearm, 0, request);

if (rc != PLDM_SUCCESS)
{
requester.markFree(mctpEid, instanceId);
std::cerr << "Failed to "
"decode_get_state_sensor_readings_resp, rc = "
<< rc
<< " cc=" << static_cast<unsigned>(completionCode)
<< " SensorId=" << sensorId << std::endl;
"encode_get_state_sensor_readings_req, rc = "
<< rc << " SensorId=" << sensorId << std::endl;
pldm::utils::reportError(
"xyz.openbmc_project.bmc.PLDM._setHostSensorState.EncodeStateSensorFail",
pldm::PelSeverity::ERROR);
return;
}

uint8_t eventState;
uint8_t previousEventState;
uint8_t sensorOffset = comp_sensor_count - 1;

for (size_t i = 0; i < comp_sensor_count; i++)
{
eventState = stateField[i].present_state;
previousEventState = stateField[i].previous_state;

emitStateSensorEventSignal(tid, sensorId, sensorOffset,
eventState, previousEventState);

SensorEntry sensorEntry{tid, sensorId};
auto getStateSensorReadingRespHandler = [=, this](
mctp_eid_t /*eid*/,
const pldm_msg*
response,
size_t respMsgLen) {
if (response == nullptr || !respMsgLen)
{
std::cerr
<< "Failed to receive response for "
"getStateSensorReading command for sensor id="
<< sensorId << std::endl;
if (this->isHostOff)
{
std::cerr
<< "set host state sensor : Host is off, stopped sending sensor state commands\n";
return;
}
if (sensorIndex == stateSensorPDRs.end())
{
return;
}
++sensorIndex;
_setHostSensorState();
}
std::array<get_sensor_state_field, 8> stateField{};
uint8_t completionCode = 0;
uint8_t comp_sensor_count = 0;

pldm::pdr::EntityInfo entityInfo{};
pldm::pdr::CompositeSensorStates compositeSensorStates{};
std::vector<pldm::pdr::StateSetId> stateSetIds{};
auto rc = decode_get_state_sensor_readings_resp(
response, respMsgLen, &completionCode,
&comp_sensor_count, stateField.data());

try
if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
{
std::tie(entityInfo, compositeSensorStates,
stateSetIds) = lookupSensorInfo(sensorEntry);
std::cerr
<< "Failed to "
"decode_get_state_sensor_readings_resp, rc = "
<< rc
<< " cc=" << static_cast<unsigned>(completionCode)
<< " SensorId=" << sensorId << std::endl;
if (sensorIndex == stateSensorPDRs.end())
{
return;
}
++sensorIndex;
_setHostSensorState();
}
catch (const std::out_of_range& e)

uint8_t eventState;
uint8_t previousEventState;
uint8_t sensorOffset = comp_sensor_count - 1;

for (size_t i = 0; i < comp_sensor_count; i++)
{
eventState = stateField[i].present_state;
previousEventState = stateField[i].previous_state;

emitStateSensorEventSignal(tid, sensorId, sensorOffset,
eventState,
previousEventState);

SensorEntry sensorEntry{tid, sensorId};

pldm::pdr::EntityInfo entityInfo{};
pldm::pdr::CompositeSensorStates
compositeSensorStates{};
std::vector<pldm::pdr::StateSetId> stateSetIds{};

try
{
sensorEntry.terminusID = PLDM_TID_RESERVED;
std::tie(entityInfo, compositeSensorStates,
stateSetIds) =
lookupSensorInfo(sensorEntry);
}
catch (const std::out_of_range& e)
{
std::cerr << "No mapping for the events"
<< std::endl;
try
{
sensorEntry.terminusID = PLDM_TID_RESERVED;
std::tie(entityInfo, compositeSensorStates,
stateSetIds) =
lookupSensorInfo(sensorEntry);
}
catch (const std::out_of_range& e)
{
std::cerr << "No mapping for the events"
<< std::endl;
continue;
}
}
}

if (sensorOffset > compositeSensorStates.size())
{
std::cerr
<< " Error Invalid data, Invalid sensor offset,"
<< " SensorId=" << sensorId << std::endl;
return;
}
if (sensorOffset > compositeSensorStates.size())
{
std::cerr
<< " Error Invalid data, Invalid sensor offset,"
<< " SensorId=" << sensorId << std::endl;
return;
}

const auto& possibleStates =
compositeSensorStates[sensorOffset];
if (possibleStates.find(eventState) == possibleStates.end())
const auto& possibleStates =
compositeSensorStates[sensorOffset];
if (possibleStates.find(eventState) ==
possibleStates.end())
{
std::cerr
<< " Error invalid_data, Invalid event state,"
<< " SensorId=" << sensorId << std::endl;
return;
}
const auto& [containerId, entityType, entityInstance] =
entityInfo;
auto stateSetId = stateSetIds[sensorOffset];
pldm::responder::events::StateSensorEntry
stateSensorEntry{containerId, entityType,
entityInstance, sensorOffset,
false, stateSetId};
handleStateSensorEvent(stateSetIds, stateSensorEntry,
eventState);
}
if (sensorIndex == stateSensorPDRs.end())
{
std::cerr << " Error invalid_data, Invalid event state,"
<< " SensorId=" << sensorId << std::endl;
return;
}
const auto& [containerId, entityType, entityInstance] =
entityInfo;
auto stateSetId = stateSetIds[sensorOffset];
pldm::responder::events::StateSensorEntry stateSensorEntry{
containerId, entityType, entityInstance,
sensorOffset, false, stateSetId};
handleStateSensorEvent(stateSetIds, stateSensorEntry,
eventState);
}
if (sensorIndex == stateSensorPDRs.end())
{
sensorIndex = stateSensorPDRs.begin();
std::cout
<< "Completed get_state_sensor_reading commands on all the host sensors\n";
return;
}
sensorIndex++;
_setHostSensorState();
};
++sensorIndex;
_setHostSensorState();
};

rc = handler->registerRequest(
mctpEid, instanceId, PLDM_PLATFORM,
PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
std::move(getStateSensorReadingRespHandler));
rc = handler->registerRequest(
mctpEid, instanceId, PLDM_PLATFORM,
PLDM_GET_STATE_SENSOR_READINGS, std::move(requestMsg),
std::move(getStateSensorReadingRespHandler));

if (rc != PLDM_SUCCESS)
{
std::cerr << " Failed to send request to get State sensor "
"reading on Host,"
<< " SensorId=" << sensorId << std::endl;
if (rc != PLDM_SUCCESS)
{
std::cerr << " Failed to send request to get State sensor "
"reading on Host,"
<< " SensorId=" << sensorId << std::endl;
}
}
}
}
Expand Down

0 comments on commit 6aeca8d

Please sign in to comment.