Add RDE discovery- Negotiate and medium params
Google-Bug-Id: 321094056
Change-Id: If405b07f98442119e0481adcfe26229835c11965
Signed-off-by: Harsh Tyagi <harshtya@google.com>
diff --git a/interface/pldm_interface.cpp b/interface/pldm_interface.cpp
index 33e88ec..5912746 100644
--- a/interface/pldm_interface.cpp
+++ b/interface/pldm_interface.cpp
@@ -16,11 +16,12 @@
size_t reqMsgLen)
{
struct sockaddr_mctp addr;
+ memset(&addr, 0, sizeof(addr));
addr.smctp_family = AF_MCTP;
addr.smctp_network = networkId;
addr.smctp_addr.s_addr = eid;
addr.smctp_type = MCTP_MSG_TYPE_PLDM;
- addr.smctp_tag = DESTINATION_MCTP_TAG_OWNER;
+ addr.smctp_tag = MCTP_TAG_OWNER;
int rc =
sendto(mctpFd, reinterpret_cast<const uint8_t*>(pldmReqMsg), reqMsgLen,
diff --git a/meson.build b/meson.build
index 6ab0761..ce77f2a 100644
--- a/meson.build
+++ b/meson.build
@@ -7,14 +7,16 @@
'c_std=c18',
])
-sources = [
- 'rded.cpp',
+lib_sources = [
'interface/pldm_interface.cpp',
'interface/pldm_rde.cpp',
'util/matcher/rde_match_handler.cpp',
'util/state_machine/discovery/base/base_disc_state_machine.cpp',
+ 'util/state_machine/discovery/rde/rde_disc_state_machine.cpp',
]
+all_sources = ['rded.cpp'] + lib_sources
+
cpp = meson.get_compiler('cpp')
phosphor_dbus_interfaces = dependency('phosphor-dbus-interfaces')
sdbusplus = dependency('sdbusplus')
@@ -83,12 +85,7 @@
rded_lib = static_library(
'rded_lib',
- [
- 'interface/pldm_interface.cpp',
- 'interface/pldm_rde.cpp',
- 'util/matcher/rde_match_handler.cpp',
- 'util/state_machine/discovery/base/base_disc_state_machine.cpp'
- ],
+ lib_sources,
include_directories: headers,
implicit_include_directories: false,
dependencies: deps)
@@ -104,7 +101,7 @@
executable(
'rded',
- sources,
+ all_sources,
implicit_include_directories: false,
dependencies: deps,
install: true,
diff --git a/rded.cpp b/rded.cpp
index 75b78d3..e0d8135 100644
--- a/rded.cpp
+++ b/rded.cpp
@@ -48,6 +48,7 @@
return -1;
}
+ ASSERT_MIN_MCTP_RETRIES(MAX_RETRIES_MCTP_SOCK_FAILURE);
RdeMatchHandler matcher(fd);
matcher.triggerMatcher();
stdplus::print(stderr, "RDE Reactor stopped...\n");
diff --git a/tests/discovery/rde/rde_disc_state_machine_test.cpp b/tests/discovery/rde/rde_disc_state_machine_test.cpp
new file mode 100644
index 0000000..dd1c14e
--- /dev/null
+++ b/tests/discovery/rde/rde_disc_state_machine_test.cpp
@@ -0,0 +1,90 @@
+#include "libpldm/base.h"
+
+#include "tests/pldm_interface_mock.hpp"
+#include "util/state_machine/discovery/rde/rde_disc_state_machine.hpp"
+
+#include <stdplus/print.hpp>
+
+#include <memory>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using ::testing::_;
+using ::testing::Return;
+
+constexpr int testFd = 3;
+constexpr int testNetId = 6;
+constexpr std::string testDeviceId = "1_1_3_1";
+
+class RdeDiscoveryTest : public ::testing::Test
+{
+ protected:
+ std::shared_ptr<MockPldmInterface> mockInterface =
+ std::make_shared<MockPldmInterface>();
+};
+
+TEST_F(RdeDiscoveryTest, StateMachineRunSuccess)
+{
+ std::unique_ptr<RdeDiscoveryStateMachine> stateMachineRde =
+ std::make_unique<RdeDiscoveryStateMachine>(testFd, testDeviceId,
+ testNetId, mockInterface);
+
+ EXPECT_CALL(*mockInterface, pldmSendAtNetwork(_, _, _, _, _))
+ .WillOnce(
+ Return(PLDM_REQUESTER_SUCCESS)) // send for Negotiate Redfish Params
+ .WillOnce(Return(PLDM_REQUESTER_SUCCESS)); // send for Medium Params
+
+ EXPECT_CALL(*mockInterface, pldmRecvAtNetwork(_, _, _, _, _, _))
+ .WillOnce(Return(
+ PLDM_REQUESTER_SUCCESS)) // receive for Negotiate Redfish Params
+ .WillOnce(Return(PLDM_REQUESTER_SUCCESS)); // receive for Medium Params
+ OperationStatus status = stateMachineRde.get()->run();
+ stdplus::println(stderr, "Status: {}", static_cast<int>(status));
+ // All invocations tested with success code (State machine runs fine)
+ EXPECT_EQ(status, OperationStatus::Success);
+}
+
+TEST_F(RdeDiscoveryTest, StateMachineRunReceiveFails)
+{
+ // Fails at the first receive and hence discovery should fail and no more
+ // calls to be made to the interface
+ std::unique_ptr<RdeDiscoveryStateMachine> stateMachineRde =
+ std::make_unique<RdeDiscoveryStateMachine>(testFd, testDeviceId,
+ testNetId, mockInterface);
+
+ EXPECT_CALL(*mockInterface, pldmSendAtNetwork(_, _, _, _, _))
+ .WillOnce(Return(PLDM_REQUESTER_SUCCESS)); // send for Negotiate Redfish
+
+ EXPECT_CALL(*mockInterface, pldmRecvAtNetwork(_, _, _, _, _, _))
+ .WillOnce(Return(
+ PLDM_REQUESTER_RESP_MSG_TOO_SMALL)); // receive fails for negotiate
+ // redfish params
+
+ // Since negotiate redfish params fail hence next command not invoked
+ OperationStatus status = stateMachineRde.get()->run();
+ stdplus::println(stderr, "Status: {}", static_cast<int>(status));
+
+ // Receive failure - hence discovery fails
+ EXPECT_EQ(status, OperationStatus::PldmRecvFailure);
+}
+
+TEST_F(RdeDiscoveryTest, StateMachineRunSendFails)
+{
+ // Fails at the first send and hence discovery should fail and no more
+ // calls to be made to the interface
+ std::unique_ptr<RdeDiscoveryStateMachine> stateMachineRde =
+ std::make_unique<RdeDiscoveryStateMachine>(testFd, testDeviceId,
+ testNetId, mockInterface);
+
+ // send for Negotiate Redfish Params fails
+ EXPECT_CALL(*mockInterface, pldmSendAtNetwork(_, _, _, _, _))
+ .WillOnce(Return(PLDM_REQUESTER_SEND_FAIL));
+
+ // No receiveFrom calls are expected as it failed on first send
+ OperationStatus status = stateMachineRde.get()->run();
+ stdplus::println(stderr, "Status: {}", static_cast<int>(status));
+
+ // Send failure - hence discovery fails
+ EXPECT_EQ(status, OperationStatus::PldmSendFailure);
+}
diff --git a/tests/meson.build b/tests/meson.build
index cd2ed39..969f642 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -21,7 +21,8 @@
tests = [
'mctp_setup_test',
- 'discovery/base/base_disc_state_machine_test'
+ 'discovery/base/base_disc_state_machine_test',
+ 'discovery/rde/rde_disc_state_machine_test'
]
foreach t : tests
diff --git a/util/common.hpp b/util/common.hpp
index 7bea407..9d365b9 100644
--- a/util/common.hpp
+++ b/util/common.hpp
@@ -4,10 +4,12 @@
#include <string>
#include <unordered_set>
-#define PLDM_RDE 0x06
#define PLDM_MAX_REQUEST_BYTES 2048
#define MAX_RETRIES_FOR_REQUEST 500
-#define MAX_RETRIES_MCTP_SOCK_FAILURE 5
+
+#define MAX_RETRIES_MCTP_SOCK_FAILURE 3 // should be always >= 1
+#define ASSERT_MIN_MCTP_RETRIES(value) assert((value) >= 1)
+
#define MAX_LOOP_ITERATION_STATE_MACHINE 50
#define DEFAULT_INITIAL_VAL 0
diff --git a/util/matcher/rde_match_handler.cpp b/util/matcher/rde_match_handler.cpp
index e9bd55d..1d072e9 100644
--- a/util/matcher/rde_match_handler.cpp
+++ b/util/matcher/rde_match_handler.cpp
@@ -12,7 +12,9 @@
using ChangedPropertiesType = std::vector<std::pair<std::string, DbusVariant>>;
RdeMatchHandler::RdeMatchHandler(int socketFd) : fd(socketFd)
-{}
+{
+ pldmInterface = std::make_shared<PldmInterface>();
+}
RdeMatchHandler::~RdeMatchHandler()
{}
@@ -20,19 +22,71 @@
int RdeMatchHandler::initiateDiscovery(const int& fd, const std::string& udevId,
const int& netId)
{
- int rc = 0;
// Begin Base Discovery
stdplus::print(stderr, "Initiating PLDM Discovery...\n");
- // TODO(@harshtya): Add discovery calls
- // TODO(@harshtya): Remove the log below after discovery calls
- stdplus::print(stderr, "Call arguments: {}, {}, {}\n", fd, udevId, netId);
- if (rc)
+ std::unique_ptr<BaseDiscoveryStateMachine> stateMachineBase =
+ std::make_unique<BaseDiscoveryStateMachine>(fd, udevId, netId,
+ pldmInterface);
+
+ int rc = 0;
+ for (int retryCounter = 0; retryCounter < MAX_RETRIES_MCTP_SOCK_FAILURE;
+ retryCounter++)
{
- stdplus::print(stderr,
- "Failure in Base Discovery with error code: {}\n", rc);
- return rc;
+ rc = static_cast<int>(stateMachineBase->run());
+ if (rc == 0)
+ {
+ break; // Successfully completed state machine run
+ }
+ if (retryCounter == (MAX_RETRIES_MCTP_SOCK_FAILURE - 1))
+ {
+ stdplus::println(stderr,
+ "Initial base discovery failed with all retries.");
+ return rc;
+ }
+ stdplus::println(stderr,
+ "Initial Base Discovery failed."
+ "Retrying with retryCounter: {}",
+ (retryCounter + 1));
}
+
+ this->deviceToBaseStateMap.emplace(udevId, std::move(stateMachineBase));
+ if constexpr (DEBUG)
+ {
+ this->deviceToBaseStateMap[udevId]->printState();
+ }
+
+ std::unique_ptr<RdeDiscoveryStateMachine> stateMachineRde =
+ std::make_unique<RdeDiscoveryStateMachine>(fd, udevId, netId,
+ pldmInterface);
+
+ for (int retryCounter = 0; retryCounter < MAX_RETRIES_MCTP_SOCK_FAILURE;
+ retryCounter++)
+ {
+ rc = static_cast<int>(stateMachineRde->run());
+ if (rc == 0)
+ {
+ break; // Successfully completed state machine run
+ }
+
+ if (retryCounter == (MAX_RETRIES_MCTP_SOCK_FAILURE - 1))
+ {
+ stdplus::println(stderr,
+ "Initial RDE discovery failed with all retries.");
+ return rc;
+ }
+ stdplus::println(stderr,
+ "Initial RDE discovery failed."
+ "Retrying with retryCounter: {}",
+ (retryCounter + 1));
+ }
+
+ this->deviceToRdeStateMap.emplace(udevId, std::move(stateMachineRde));
+ if constexpr (DEBUG)
+ {
+ this->deviceToRdeStateMap[udevId]->printState();
+ }
+
return rc;
}
@@ -159,7 +213,7 @@
continue;
}
- if (DEBUG)
+ if constexpr (DEBUG)
{
stdplus::print(stderr, "New device detected: {}\n",
std::string(changedObject));
@@ -188,7 +242,8 @@
return;
}
- // TODO(@harshtya): Call RDE Setup here
+ rdeSetup(fd, objectServer, std::string(changedObject), port, udevId,
+ vendorId, prefixPath);
}
});
}
@@ -216,7 +271,7 @@
if (it != objectPathToDeviceIdMap.end())
{
cleanupMctpLink(it->second);
- // TODO (@harshtya): clean up the Rde device from maps
+ cleanupDiscoveryStates(it->second);
// TODO (@harshtya): clean up the dictionaries
objectPathToDeviceIdMap.erase(std::string(changedObject));
deviceToNetIdMap.erase(it->second);
@@ -234,7 +289,18 @@
objectServer.add_manager("/xyz/openbmc_project/rde_devices");
std::string prefixPath = "/xyz/openbmc_project/rde_devices/";
- // TODO(@harshtya): Add scan for existing devices
+ try
+ {
+ scanForExistingDevices(this->fd, objectServer, prefixPath, systemBus);
+ }
+ catch (const std::exception& e)
+ {
+ // skip scan and wait for new device detection
+ stdplus::println(
+ stderr,
+ "Some exception occured while scanning for existing rde devices {}",
+ e.what());
+ }
// Initialize the match handler for interfacesAdded
auto matchAdd =
@@ -257,7 +323,7 @@
int netId = setupOnePort(port, udevId); // MCTP Setup
deviceToNetIdMap.emplace(udevId, netId);
int rc = initiateDiscovery(fd, udevId, netId);
- if (rc)
+ if (rc != 0)
{
stdplus::print(stderr,
"PLDM/RDE Discovery failed for device: {}"
@@ -268,7 +334,7 @@
std::string objectPath = std::format("{}{}", prefixPath, udevId);
- if (DEBUG)
+ if constexpr (DEBUG)
{
stdplus::print(stderr, "Creating object path for RDE Operation: {}\n ",
objectPath);
@@ -283,10 +349,27 @@
iface->register_property("UDEVID", udevId,
sdbusplus::asio::PropertyPermission::readOnly);
- // TODO(@harshtya): Add RDE OPeration Handler Dbus method
+ // TODO(@harshtya): Add RDE Operation Handler Dbus method
iface->initialize();
deviceToDbusIntfMap.emplace(std::string(changedObject), iface);
objectPathToDeviceIdMap.emplace(std::string(changedObject), udevId);
return 0;
}
+
+void RdeMatchHandler::cleanupDiscoveryStates(const std::string& udevId)
+{
+ // Remove Base discovery state if exists
+ auto it = deviceToBaseStateMap.find(udevId);
+ if (it != deviceToBaseStateMap.end())
+ {
+ deviceToBaseStateMap.erase(udevId);
+ }
+
+ // Remove RDE discovery state if exists
+ it = deviceToRdeStateMap.find(udevId);
+ if (it != deviceToRdeStateMap.end())
+ {
+ deviceToRdeStateMap.erase(udevId);
+ }
+}
diff --git a/util/matcher/rde_match_handler.hpp b/util/matcher/rde_match_handler.hpp
index 84d284f..afd865f 100644
--- a/util/matcher/rde_match_handler.hpp
+++ b/util/matcher/rde_match_handler.hpp
@@ -1,6 +1,10 @@
#ifndef RDE_MATCH_HANDLER_HPP
#define RDE_MATCH_HANDLER_HPP
+#include "util/state_machine/discovery/base/base_disc_state_machine.hpp"
+#include "util/state_machine/discovery/rde/rde_disc_state_machine.hpp"
+#include "util/state_machine/state_machine_factory.hpp"
+
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/asio/property.hpp>
@@ -33,6 +37,11 @@
std::unordered_map<std::string, std::string> objectPathToDeviceIdMap;
+ std::unordered_map<std::string, std::unique_ptr<StateMachineFactory>>
+ deviceToBaseStateMap;
+
+ std::unordered_map<std::string, std::unique_ptr<StateMachineFactory>>
+ deviceToRdeStateMap;
/**
* @brief Scans for existing USB devices in the Entity Manager that can be
* RDE Devices as soon as the RDE Daemon boots up
@@ -109,5 +118,14 @@
const std::string& changedObject, const std::string& port,
const std::string& udevId, const std::string& vendorId,
const std::string& prefixPath);
+
+ /**
+ * @brief Cleans up the objects of State Machine when device is removed
+ *
+ * @param[in] udevId - Unique udev identifier for the device removed
+ */
+ void cleanupDiscoveryStates(const std::string& udevId);
+
+ std::shared_ptr<PldmInterface> pldmInterface;
};
#endif // RDE_MATCH_HANDLER_HPP
diff --git a/util/resource_id_mapper.hpp b/util/resource_id_mapper.hpp
index 4ddf223..e56dff3 100644
--- a/util/resource_id_mapper.hpp
+++ b/util/resource_id_mapper.hpp
@@ -202,7 +202,7 @@
auto it = resourceIdMap.find(uri);
if (it != resourceIdMap.end())
{
- if (DEBUG)
+ if constexpr (DEBUG)
{
stdplus::print(stderr, "Resource id found: {}\n",
std::to_string(it->second));
diff --git a/util/state_machine/discovery/base/base_disc_state_machine.cpp b/util/state_machine/discovery/base/base_disc_state_machine.cpp
index 23973d2..9700150 100644
--- a/util/state_machine/discovery/base/base_disc_state_machine.cpp
+++ b/util/state_machine/discovery/base/base_disc_state_machine.cpp
@@ -8,7 +8,7 @@
BaseDiscoveryStateMachine::BaseDiscoveryStateMachine(
int fd, const std::string& deviceName, int netId,
- std::shared_ptr<PldmInterface> pldmInterface) :
+ const std::shared_ptr<PldmInterface>& pldmInterface) :
fd(fd),
deviceName(deviceName), netId(netId), pldmInterface(pldmInterface)
{
diff --git a/util/state_machine/discovery/base/base_disc_state_machine.hpp b/util/state_machine/discovery/base/base_disc_state_machine.hpp
index d773fcc..7d15984 100644
--- a/util/state_machine/discovery/base/base_disc_state_machine.hpp
+++ b/util/state_machine/discovery/base/base_disc_state_machine.hpp
@@ -28,8 +28,9 @@
class BaseDiscoveryStateMachine : public StateMachineFactory
{
public:
- BaseDiscoveryStateMachine(int fd, const std::string& deviceName, int netId,
- std::shared_ptr<PldmInterface> pldmInterface);
+ BaseDiscoveryStateMachine(
+ int fd, const std::string& deviceName, int netId,
+ const std::shared_ptr<PldmInterface>& pldmInterface);
OperationStatus run() override;
diff --git a/util/state_machine/discovery/rde/rde_disc_state_machine.cpp b/util/state_machine/discovery/rde/rde_disc_state_machine.cpp
new file mode 100644
index 0000000..2126635
--- /dev/null
+++ b/util/state_machine/discovery/rde/rde_disc_state_machine.cpp
@@ -0,0 +1,293 @@
+#include "rde_disc_state_machine.hpp"
+
+#include "libpldm/base.h"
+#include "libpldm/pldm.h"
+
+#include "interface/pldm_interface.hpp"
+
+#include <common.hpp>
+#include <stdplus/print.hpp>
+
+#include <cstdint>
+#include <iostream>
+#include <optional>
+#include <set>
+#include <unordered_map>
+
+std::unordered_map<uint8_t, int> rdeCommandRequestSize = {
+ {PLDM_NEGOTIATE_REDFISH_PARAMETERS, 3},
+ {PLDM_NEGOTIATE_MEDIUM_PARAMETERS, 4},
+ {PLDM_GET_SCHEMA_DICTIONARY, 5},
+ {PLDM_RDE_MULTIPART_RECEIVE, 7}};
+
+RdeDiscoveryStateMachine::RdeDiscoveryStateMachine(
+ int fd, const std::string& deviceName, int netId,
+ const std::shared_ptr<PldmInterface>& pldmInterface) :
+ fd(fd),
+ deviceName(deviceName), netId(netId), pldmInterface(pldmInterface)
+{
+ this->initialized = true;
+ this->requesterStatus = StateMachineStatus::NoPendingAction;
+ this->eid = DEST_EID;
+ this->instanceId = INSTANCE_ID;
+ this->mcFeatures = {.value = 102};
+}
+
+OperationStatus RdeDiscoveryStateMachine::run()
+{
+ stdplus::println("Triggering RDE discovery...");
+ if (!this->initialized &&
+ (this->requesterStatus != StateMachineStatus::NoPendingAction))
+ {
+ return OperationStatus::StateMachineInitializationError;
+ }
+
+ this->nextCommand = PLDM_NEGOTIATE_REDFISH_PARAMETERS;
+ this->requesterStatus = StateMachineStatus::ReadyToPickNextRequest;
+
+ for (int retryCounter = 0; retryCounter < RDE_REQUEST_RETRIES;
+ retryCounter++)
+ {
+ if (this->requesterStatus == StateMachineStatus::NoPendingAction)
+ {
+
+ stdplus::println(stderr,
+ "RDE Negotiate discovery successfully completed!");
+ break;
+ }
+ OperationStatus status = triggerNextCommand();
+ if (status != OperationStatus::Success)
+ {
+ stdplus::println(
+ stderr, "RDE discovery failed at command: {} with status: {}",
+ std::to_string(this->nextCommand), static_cast<int>(status));
+ return status;
+ }
+ }
+
+ return OperationStatus::Success;
+}
+
+OperationStatus RdeDiscoveryStateMachine::triggerNextCommand()
+{
+ switch (this->nextCommand)
+ {
+ case PLDM_NEGOTIATE_REDFISH_PARAMETERS:
+ {
+ return processNegotiateRedfishParametersRequest();
+ }
+ case PLDM_NEGOTIATE_MEDIUM_PARAMETERS:
+ {
+ return processNegotiateMediumParameters();
+ }
+
+ default:
+ return OperationStatus::OperationFailure;
+ }
+ return OperationStatus::Success;
+}
+
+OperationStatus RdeDiscoveryStateMachine::pushCommandResponse(
+ const struct pldm_msg* respMsg, size_t respSize)
+{
+ switch (this->nextCommand)
+ {
+ case PLDM_NEGOTIATE_REDFISH_PARAMETERS:
+ {
+ uint8_t completionCode = DEFAULT_INITIAL_VAL;
+ int rc = decode_negotiate_redfish_parameters_resp(
+ respMsg, respSize - sizeof(struct pldm_msg_hdr),
+ &completionCode, &(this->rdeDeviceInfo));
+ if ((rc != 0) || (completionCode != 0))
+ {
+ this->requesterStatus = StateMachineStatus::RequestFailed;
+ stdplus::println(
+ stderr,
+ "Negotiate redfish parameters response decode failed with "
+ "rc: {} and completion code:",
+ rc, completionCode);
+ return OperationStatus::IncorrectResponseMsg;
+ }
+ this->nextCommand = PLDM_NEGOTIATE_MEDIUM_PARAMETERS;
+ this->requesterStatus = StateMachineStatus::ReadyToPickNextRequest;
+ return OperationStatus::Success;
+ }
+ case PLDM_NEGOTIATE_MEDIUM_PARAMETERS:
+ {
+ uint8_t completionCode = DEFAULT_INITIAL_VAL;
+ uint32_t maxDeviceTransferSize = DEFAULT_INITIAL_VAL;
+ int rc = decode_negotiate_medium_parameters_resp(
+ respMsg, respSize - sizeof(struct pldm_msg_hdr),
+ &completionCode, &maxDeviceTransferSize);
+ if ((rc != 0) || (completionCode != 0))
+ {
+ this->requesterStatus = StateMachineStatus::RequestFailed;
+ stdplus::println(
+ stderr,
+ "Negotiate medium parameters response decode failed with "
+ "rc: {} and completion code:",
+ rc, completionCode);
+ return OperationStatus::IncorrectResponseMsg;
+ }
+ this->rdeDeviceInfo.device_maximum_transfer_chunk_size =
+ maxDeviceTransferSize;
+
+ this->negotiatedTransferSize =
+ (maxDeviceTransferSize >
+ RdeDiscoveryStateMachine::mcTransferSize)
+ ? RdeDiscoveryStateMachine::mcTransferSize
+ : maxDeviceTransferSize;
+
+ this->nextCommand =
+ static_cast<int>(OperationStatus::NoNextCommandFound);
+ this->requesterStatus = StateMachineStatus::NoPendingAction;
+ return OperationStatus::Success;
+ }
+ default:
+ return OperationStatus::OperationFailure;
+ }
+}
+
+OperationStatus
+ RdeDiscoveryStateMachine::processNegotiateRedfishParametersRequest()
+{
+ stdplus::println(stderr, "Trigerring negotiate redfish params...");
+ int requestBytes = rdeCommandRequestSize[PLDM_NEGOTIATE_REDFISH_PARAMETERS];
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + requestBytes);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ int rc = encode_negotiate_redfish_parameters_req(
+ this->instanceId, RdeDiscoveryStateMachine::mcConcurrency,
+ &(this->mcFeatures), request);
+ if (rc)
+ {
+ stdplus::println(
+ stderr,
+ "Encoding Negotiate Redfish Params request failed in RDE discovery"
+ "with rc: {}",
+ rc);
+ return OperationStatus::EncodingRequestFailure;
+ }
+
+ if (pldmInterface->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) + RDE_NEGOTIATE_REDFISH_PARAMS_RESP_SIZE, 0);
+ uint8_t* responseMsg = response.data();
+ size_t responseMsgSize = response.size();
+ auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg);
+
+ if (pldmInterface->pldmRecvAtNetwork(this->eid, this->netId, this->fd,
+ this->instanceId, &responseMsg,
+ &responseMsgSize))
+ {
+ this->requesterStatus = StateMachineStatus::RequestFailed;
+ return OperationStatus::PldmRecvFailure;
+ }
+
+ stdplus::println(stderr,
+ "Pushing Response for RDE_NEGOTIATE_REDFISH_PARAMS...");
+ OperationStatus status = pushCommandResponse(responsePtr, responseMsgSize);
+ if (status != OperationStatus::Success)
+ {
+ stdplus::println(stderr,
+ "Failed to push response for Negotiate Redfish"
+ " Params in RDE discovery with status: {}",
+ static_cast<int>(status));
+ }
+ return status;
+}
+
+OperationStatus RdeDiscoveryStateMachine::processNegotiateMediumParameters()
+{
+ stdplus::println(stderr, "Trigerring negotiate medium params...");
+ int requestBytes = rdeCommandRequestSize[PLDM_NEGOTIATE_MEDIUM_PARAMETERS];
+ std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + requestBytes);
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+ int rc = encode_negotiate_medium_parameters_req(
+ this->instanceId, RdeDiscoveryStateMachine::mcTransferSize, request);
+ if (rc)
+ {
+ stdplus::println(
+ stderr,
+ "Encoding Negotiate Medium Params request failed in RDE discovery"
+ "with rc: {}",
+ rc);
+ return OperationStatus::EncodingRequestFailure;
+ }
+
+ if (pldmInterface->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) + RDE_NEGOTIATE_REDFISH_MEDIUM_PARAMS_RESP_SIZE,
+ 0);
+ uint8_t* responseMsg = response.data();
+ size_t responseMsgSize = response.size();
+ auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg);
+ if (pldmInterface->pldmRecvAtNetwork(this->eid, this->netId, this->fd,
+ this->instanceId, &responseMsg,
+ &responseMsgSize))
+ {
+ this->requesterStatus = StateMachineStatus::RequestFailed;
+ return OperationStatus::PldmRecvFailure;
+ }
+ stdplus::println(stderr,
+ "Pushing Response for RDE_NEGOTIATE_MED_PARAMS...");
+ OperationStatus status = pushCommandResponse(responsePtr, responseMsgSize);
+ if (status != OperationStatus::Success)
+ {
+ stdplus::println(stderr,
+ "Failed to push response for RDE Negotiate "
+ "Medium in RDE discovery with rc: {}",
+ static_cast<int>(status));
+ }
+ return status;
+}
+
+void RdeDiscoveryStateMachine::printState()
+{
+ stdplus::println(stderr,
+ "====================================================");
+ stdplus::println(stderr, "***RDE Negotiate/Medium Parameters Begins***");
+ stdplus::println(stderr,
+ "====================================================");
+
+ stdplus::println(stderr, "MC Concurrency: {}",
+ RdeDiscoveryStateMachine::mcConcurrency);
+
+ stdplus::println(stderr, "MC Transfer Size: {}",
+ RdeDiscoveryStateMachine::mcTransferSize);
+
+ stdplus::println(stderr, "RDE device Concurrency: {}",
+ this->rdeDeviceInfo.device_concurrency);
+
+ stdplus::println(stderr, "RDE device Device Capabilities Flag: {} ",
+ this->rdeDeviceInfo.device_capabilities_flag.byte);
+
+ stdplus::println(stderr, "RDE device Device Feature Support: {}",
+ this->rdeDeviceInfo.device_feature_support.value);
+
+ stdplus::println(stderr, "RDE device Device Configuration Signature: {}",
+ this->rdeDeviceInfo.device_configuration_signature);
+
+ stdplus::println(
+ stderr, "RDE device Device Provider Name (Eid): {}",
+ this->rdeDeviceInfo.device_provider_name.string_length_bytes);
+
+ stdplus::println(stderr, "Negotiated Transfer Size (Medium Parameters): {}",
+ this->negotiatedTransferSize);
+
+ stdplus::println(stderr,
+ "====================================================");
+ stdplus::println(stderr, "***RDE Negotiate/Medium Parameters Ends***");
+ stdplus::println(stderr,
+ "====================================================");
+}
diff --git a/util/state_machine/discovery/rde/rde_disc_state_machine.hpp b/util/state_machine/discovery/rde/rde_disc_state_machine.hpp
new file mode 100644
index 0000000..58bc8fa
--- /dev/null
+++ b/util/state_machine/discovery/rde/rde_disc_state_machine.hpp
@@ -0,0 +1,76 @@
+#ifndef RDE_DISC_STATE_MACHINE_HPP
+#define RDE_DISC_STATE_MACHINE_HPP
+
+#include "common.hpp"
+#include "interface/pldm_rde.hpp"
+#include "pldm_interface.hpp"
+#include "state_machine_factory.hpp"
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#define RDE_REQUEST_RETRIES 50
+#define RDE_NEGOTIATE_REDFISH_PARAMS_RESP_SIZE 12
+#define RDE_NEGOTIATE_REDFISH_MEDIUM_PARAMS_RESP_SIZE 6
+#define RDE_GET_DICT_SCHEMA_RESP_SIZE 6
+#define MC_CONCURRENCY 3
+#define INITIAL_TRANSFER_HANDLE 0x00
+#define DICTIONARY_EXTRACTION_RETRIES 3
+
+class RdeDiscoveryStateMachine : public StateMachineFactory
+{
+ public:
+ static constexpr uint8_t mcConcurrency = MC_CONCURRENCY;
+ static constexpr uint32_t mcTransferSize = PLDM_MAX_REQUEST_BYTES;
+
+ RdeDiscoveryStateMachine(
+ int fd, const std::string& deviceName, int netId,
+ const std::shared_ptr<PldmInterface>& pldmInterface);
+
+ OperationStatus run() override;
+
+ OperationStatus triggerNextCommand() override;
+
+ OperationStatus pushCommandResponse(const struct pldm_msg* respMsg,
+ size_t respSize) override;
+
+ void printState() override;
+
+ class Context
+ {
+ public:
+ Context();
+
+ private:
+ bool initialized;
+ int nextCommand;
+ int requesterStatus;
+ bool contextStatus;
+ };
+
+ private:
+ OperationStatus processNegotiateRedfishParametersRequest();
+ OperationStatus processNegotiateMediumParameters();
+ OperationStatus processGetSchemaDictionary();
+ OperationStatus processGetMultipart();
+
+ int fd;
+ std::string deviceName;
+ int netId;
+ uint8_t eid;
+ int instanceId;
+
+ // Store all the contexts
+ bitfield16_t mcFeatures;
+ pldm_rde_device_info rdeDeviceInfo;
+ uint32_t negotiatedTransferSize;
+
+ bool initialized;
+ int nextCommand;
+ StateMachineStatus requesterStatus;
+ std::vector<Context> contexts;
+
+ std::shared_ptr<PldmInterface> pldmInterface;
+};
+#endif // RDE_DISC_STATE_MACHINE_HPP