| #include "base_disc_state_machine.hpp" |
| |
| #include "libpldm/base.h" |
| #include "libpldm/pldm.h" |
| |
| #include "interface/pldm_interface.hpp" |
| |
| #include <stdplus/print.hpp> |
| #include <util/common.hpp> |
| |
| BaseDiscoveryStateMachine::BaseDiscoveryStateMachine( |
| int fd, const std::string& deviceName, int netId) : |
| fd(fd), |
| deviceName(deviceName), netId(netId) |
| { |
| stdplus::print(stderr, "Initializing base discovery state machine...\n"); |
| this->initialized = true; |
| this->requesterStatus = StateMachineStatus::NoPendingAction; |
| this->eid = DEST_EID; |
| this->instanceId = INSTANCE_ID; // TODO(@harshtya): Make this dynamic |
| } |
| |
| OperationStatus BaseDiscoveryStateMachine::run() |
| { |
| stdplus::print(stderr, "Triggering PLDM Base discovery for device {}...\n", |
| this->deviceName); |
| if (!this->initialized && |
| this->requesterStatus != StateMachineStatus::NoPendingAction) |
| { |
| return OperationStatus::StateMachineInitializationError; |
| } |
| |
| // Setting up the initial command set |
| this->nextCommand = PLDM_GET_TID; |
| this->requesterStatus = StateMachineStatus::ReadyToPickNextRequest; |
| for (int processCounter = 0; processCounter < BASE_REQUEST_RETRIES; |
| processCounter++) |
| { |
| if (this->requesterStatus == StateMachineStatus::NoPendingAction) |
| { |
| stdplus::print(stderr, "Base discovery successfully completed\n"); |
| break; |
| } |
| OperationStatus status = triggerNextCommand(); |
| if (status != OperationStatus::Success) |
| { |
| stdplus::print(stderr, |
| "Base discovery failed at command {} with " |
| "status: {}\n", |
| std::to_string(this->nextCommand), |
| static_cast<int>(status)); |
| return status; |
| } |
| |
| if (processCounter == (BASE_REQUEST_RETRIES - 1)) |
| { |
| stdplus::print(stderr, "Base discovery failed due infinite loop\n"); |
| return OperationStatus::OperationFailure; |
| } |
| } |
| return OperationStatus::Success; |
| } |
| |
| OperationStatus BaseDiscoveryStateMachine::triggerNextCommand() |
| { |
| switch (this->nextCommand) |
| { |
| case PLDM_GET_TID: |
| return processGetTidRequest(); |
| case PLDM_GET_PLDM_TYPES: |
| return processGetPldmTypesRequest(); |
| case PLDM_GET_PLDM_VERSION: |
| return processGetPldmVersionRequest(); |
| case PLDM_GET_PLDM_COMMANDS: |
| return processGetPldmCommandsRequest(); |
| default: |
| return OperationStatus::NoNextCommandFound; |
| } |
| return OperationStatus::Success; |
| } |
| |
| OperationStatus BaseDiscoveryStateMachine::processGetTidRequest() |
| { |
| std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + |
| baseCommandRequestSize.at(PLDM_GET_TID)); |
| auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| |
| int rc = encode_get_tid_req(this->instanceId, request); |
| if (rc) |
| { |
| stdplus::print( |
| stderr, |
| "Encoding TID request failed in base discovery with rc: {} for " |
| "device {}\n", |
| rc, this->deviceName); |
| return OperationStatus::EncodingRequestFailure; |
| } |
| |
| if (pldmSendAtNetwork(this->eid, this->netId, this->fd, requestMsg.data(), |
| requestMsg.size())) |
| { |
| this->requesterStatus = StateMachineStatus::RequestFailed; |
| return OperationStatus::PldmSendFailure; |
| } |
| std::vector<uint8_t> response( |
| sizeof(pldm_msg_hdr) + PLDM_GET_TID_RESP_BYTES, 0); |
| uint8_t* responseMsg = response.data(); |
| size_t responseMsgSize = sizeof(pldm_msg_hdr) + PLDM_GET_TID_RESP_BYTES; |
| auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg); |
| |
| if (pldmRecvAtNetwork(this->eid, this->netId, this->fd, this->instanceId, |
| &responseMsg, &responseMsgSize)) |
| { |
| this->requesterStatus = StateMachineStatus::RequestFailed; |
| return OperationStatus::PldmRecvFailure; |
| } |
| |
| stdplus::print(stderr, "Pushing response for GET_TID for device {}\n", |
| this->deviceName); |
| OperationStatus status = pushCommandResponse(responsePtr, responseMsgSize); |
| if (status != OperationStatus::Success) |
| { |
| stdplus::print(stderr, |
| "Failed to push response for Get TID in base " |
| "discovery with status: {} for device: {}\n", |
| static_cast<int>(status), this->deviceName); |
| } |
| return status; |
| } |
| |
| OperationStatus BaseDiscoveryStateMachine::processGetPldmTypesRequest() |
| { |
| std::vector<uint8_t> requestMsg( |
| sizeof(pldm_msg_hdr) + baseCommandRequestSize.at(PLDM_GET_PLDM_TYPES)); |
| auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| |
| int rc = encode_get_types_req(this->instanceId, request); |
| if (rc) |
| { |
| stdplus::print( |
| stderr, |
| "Encoding PLDM Types request failed in base discovery with rc: {} " |
| "for device {}\n", |
| rc, this->deviceName); |
| return OperationStatus::EncodingRequestFailure; |
| } |
| |
| if (pldmSendAtNetwork(this->eid, this->netId, this->fd, requestMsg.data(), |
| requestMsg.size())) |
| { |
| this->requesterStatus = StateMachineStatus::RequestFailed; |
| return OperationStatus::PldmSendFailure; |
| } |
| std::vector<uint8_t> response( |
| sizeof(pldm_msg_hdr) + PLDM_GET_TYPES_RESP_BYTES, 0); |
| uint8_t* responseMsg = response.data(); |
| size_t responseMsgSize = response.size(); |
| auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg); |
| |
| if (pldmRecvAtNetwork(this->eid, this->netId, this->fd, this->instanceId, |
| &responseMsg, &responseMsgSize)) |
| { |
| this->requesterStatus = StateMachineStatus::RequestFailed; |
| return OperationStatus::PldmRecvFailure; |
| } |
| stdplus::print(stderr, |
| "Pushing response for GET_PLDM_TYPES for device: " |
| "{}\n", |
| this->deviceName); |
| OperationStatus status = pushCommandResponse(responsePtr, responseMsgSize); |
| if (status != OperationStatus::Success) |
| { |
| stdplus::print(stderr, |
| "Failed to push response for Get PLDM TYPES in base " |
| "discovery with status: {} for device: {}\n", |
| static_cast<int>(status), this->deviceName); |
| } |
| return status; |
| } |
| |
| OperationStatus BaseDiscoveryStateMachine::processGetPldmVersionRequest() |
| { |
| std::vector<uint8_t> requestMsg( |
| sizeof(pldm_msg_hdr) + |
| baseCommandRequestSize.at(PLDM_GET_PLDM_VERSION)); |
| auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| |
| int rc = encode_get_version_req(this->instanceId, /*transfer_handle=*/0, |
| PLDM_GET_FIRSTPART, this->commandPldmType, |
| request); |
| if (rc) |
| { |
| stdplus::print( |
| stderr, |
| "Encoding PLDM Version request failed in base discovery with rc: " |
| "{} for device {} and pldmType: {}\n", |
| rc, this->deviceName, std::to_string(this->commandPldmType)); |
| return OperationStatus::EncodingRequestFailure; |
| } |
| |
| if (pldmSendAtNetwork(this->eid, this->netId, this->fd, requestMsg.data(), |
| requestMsg.size())) |
| { |
| this->requesterStatus = StateMachineStatus::RequestFailed; |
| return OperationStatus::PldmSendFailure; |
| } |
| |
| std::vector<uint8_t> response( |
| sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_RESP_BYTES, 0); |
| uint8_t* responseMsg = response.data(); |
| size_t responseMsgSize = response.size(); |
| auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg); |
| |
| if (pldmRecvAtNetwork(this->eid, this->netId, this->fd, this->instanceId, |
| &responseMsg, &responseMsgSize)) |
| { |
| this->requesterStatus = StateMachineStatus::RequestFailed; |
| return OperationStatus::PldmRecvFailure; |
| } |
| stdplus::print(stderr, |
| "Pushing response for GET_PLDM_VERSION for device: " |
| "{} with pldmType: {}\n", |
| this->deviceName, std::to_string(this->commandPldmType)); |
| OperationStatus status = pushCommandResponse(responsePtr, responseMsgSize); |
| if (status != OperationStatus::Success) |
| { |
| stdplus::print(stderr, |
| "Failed to push response for Get PLDM Version in base " |
| "discovery with status: {} for device: {} for pldm Type:" |
| " {}\n", |
| static_cast<int>(status), this->deviceName, |
| std::to_string(this->commandPldmType)); |
| } |
| return status; |
| } |
| |
| OperationStatus BaseDiscoveryStateMachine::processGetPldmCommandsRequest() |
| { |
| std::vector<uint8_t> requestMsg( |
| sizeof(pldm_msg_hdr) + |
| baseCommandRequestSize.at(PLDM_GET_PLDM_COMMANDS)); |
| auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); |
| |
| int rc = encode_get_commands_req(this->instanceId, this->commandPldmType, |
| this->pldmVersions[this->commandPldmType], |
| request); |
| if (rc) |
| { |
| stdplus::print( |
| stderr, |
| "Encoding PLDM Commands request failed in base discovery with rc: " |
| "{} for device {} and pldmType: {}\n", |
| rc, this->deviceName, std::to_string(this->commandPldmType)); |
| return OperationStatus::EncodingRequestFailure; |
| } |
| |
| if (pldmSendAtNetwork(this->eid, this->netId, this->fd, requestMsg.data(), |
| requestMsg.size())) |
| { |
| this->requesterStatus = StateMachineStatus::RequestFailed; |
| return OperationStatus::PldmSendFailure; |
| } |
| std::vector<uint8_t> response( |
| sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_RESP_BYTES, 0); |
| uint8_t* responseMsg = response.data(); |
| size_t responseMsgSize = response.size(); |
| auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg); |
| |
| if (pldmRecvAtNetwork(this->eid, this->netId, this->fd, this->instanceId, |
| &responseMsg, &responseMsgSize)) |
| { |
| this->requesterStatus = StateMachineStatus::RequestFailed; |
| return OperationStatus::PldmRecvFailure; |
| } |
| |
| stdplus::print(stderr, |
| "Pushing response for GET_PLDM_COMMANDS for device: " |
| "{} with pldmType: {}\n", |
| this->deviceName, std::to_string(this->commandPldmType)); |
| OperationStatus status = pushCommandResponse(responsePtr, responseMsgSize); |
| if (status != OperationStatus::Success) |
| { |
| stdplus::print(stderr, |
| "Failed to push response for Get PLDM Command in base " |
| "discovery with status: {} for device: {} for pldm Type:" |
| " {}\n", |
| static_cast<int>(status), this->deviceName, |
| std::to_string(this->commandPldmType)); |
| } |
| return status; |
| } |
| |
| OperationStatus BaseDiscoveryStateMachine::pushCommandResponse( |
| [[maybe_unused]] struct pldm_msg* respMsg, [[maybe_unused]] size_t respSize) |
| { |
| // TODO(@harshtya): Implement pushCommandResponse |
| return OperationStatus::Success; |
| } |
| |
| void BaseDiscoveryStateMachine::printState() |
| { |
| // TODO(@harshtya): Implement state print for debug |
| } |