blob: c0d4eba662f3ecc84c787d0b9d2215819ffe1fc2 [file] [edit]
#include "helper/discovery/rde_discovery.hpp"
#include "libpldm/base.h"
#include "libpldm/pldm.h"
#include "libpldm/pldm_rde.h"
#include "libpldm/requester/pldm_rde_requester.h"
#include "libpldm/utils.h"
#include "helper/common.hpp"
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>
std::unordered_map<std::string, int> managerCtxCounter;
std::unordered_map<std::string,
std::unique_ptr<struct pldm_rde_requester_manager>>
managers;
std::vector<struct pldm_rde_requester_context> rdeContexts;
// This map will store dictionaries for each of the RDE Devices separately
std::unordered_map<std::string,
std::unordered_map<uint32_t, std::vector<uint8_t>>>
dictionaryDeviceMap;
std::unordered_map<std::string,
std::unordered_map<uint32_t, std::tuple<uint8_t, uint8_t>>>
dictionaryMetaDeviceMap;
int rdeContextCounter = 0;
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}};
void cleanupRdeDiscAtExit()
{
managerCtxCounter.clear();
managers.clear();
rdeContexts.clear();
dictionaryDeviceMap.clear();
dictionaryMetaDeviceMap.clear();
rdeCommandRequestSize.clear();
}
int printRDENegotiateContext(struct pldm_rde_requester_manager* mgr)
{
std::cerr << "====================================================\n";
std::cerr << "***RDE Negotiate/Medium Parameters Begins***\n";
std::cerr << "====================================================\n";
std::cerr << "MC Concurrency: " << std::to_string(mgr->mc_concurrency)
<< "\n";
std::cerr << "MC Transfer Size: " << std::to_string(mgr->mc_transfer_size)
<< "\n";
std::cerr << "miniBMC Concurrency: "
<< std::to_string(mgr->device.device_concurrency) << "\n";
std::cerr << "miniBMC Device Capabilities Flag: "
<< std::to_string(mgr->device.device_capabilities_flag.byte)
<< "\n";
std::cerr << "miniBMC Device Feature Support: "
<< std::to_string(mgr->device.device_feature_support.value)
<< "\n";
std::cerr << "miniBMC Device Configuration Signature: "
<< std::to_string(mgr->device.device_configuration_signature)
<< "\n";
std::cerr << "miniBMC Device Provider Name (Eid): "
<< std::to_string(
mgr->device.device_provider_name.string_length_bytes)
<< "\n";
std::cerr << "Device max buffer size: "
<< std::to_string(mgr->device.device_maximum_transfer_chunk_size)
<< std::endl;
std::cerr << "Negotiated Transfer Size (Medium Parameters): "
<< std::to_string(mgr->negotiated_transfer_size) << "\n";
std::cerr << "====================================================\n";
std::cerr << "***RDE Negotiate/Medium Parameters Ends***\n";
std::cerr << "====================================================\n";
return 0;
}
// Removes manager for rde device
void removeManagerForRdeDevice(const std::string& rdeDevice)
{
auto it = managers.find(rdeDevice);
if (it != managers.end())
{
managers.erase(rdeDevice);
}
}
// Callback function to allocate memory to contexts and keep them in an array
struct pldm_rde_requester_context*
allocateMemoryToContexts(uint8_t numberOfContexts)
{
int end = rdeContextCounter + numberOfContexts;
for (; rdeContextCounter < end; rdeContextCounter++)
{
struct pldm_rde_requester_context currentCtx = {};
if (pldm_rde_create_context(&currentCtx))
{
return nullptr;
}
rdeContexts.emplace_back(currentCtx);
}
return &rdeContexts[rdeContextCounter - 1];
}
void freeMemory(void* context)
{
free(context);
}
void cleanupDictionaries(const std::string& rdeDeviceId)
{
std::cerr << "Dict size before cleanup" << dictionaryDeviceMap.size()
<< std::endl;
dictionaryDeviceMap.erase(rdeDeviceId);
dictionaryMetaDeviceMap.erase(rdeDeviceId);
std::cerr << "Dict size after cleanup" << dictionaryDeviceMap.size()
<< std::endl;
}
int initManager(const std::string& rdeDeviceId, int netId)
{
// TODO(@harshtya): Cleanup memory when device is removed.
uint8_t mcConcurrency = 3;
uint32_t mcTransferSize = PLDM_MAX_REQUEST_BYTES;
std::unique_ptr<bitfield16_t> mcFeatures = std::make_unique<bitfield16_t>();
mcFeatures->value = 102; // Fixed for now
std::cout << "Initializing RDE Manager...\n";
std::unique_ptr<struct pldm_rde_requester_manager> manager =
std::make_unique<struct pldm_rde_requester_manager>();
managerCtxCounter.insert({rdeDeviceId, rdeContextCounter});
int rc = pldm_rde_init_context(
rdeDeviceId.c_str(), netId, manager.get(), mcConcurrency,
mcTransferSize, mcFeatures.get(), allocateMemoryToContexts, freeMemory);
if (rc)
{
std::cerr
<< "RDE Discovery failed due to context initialization error: "
<< rc << "\n";
return rc;
}
// remove if exists and then emplace
removeManagerForRdeDevice(rdeDeviceId);
managers.emplace(rdeDeviceId, std::move(manager));
return PLDM_RDE_REQUESTER_SUCCESS;
}
/**
* @param[in] manager - Rde manager for the device
* @param[in] resourceIds - List of dictionary schema resource IDs
* @return 0 on success, non zero error code on failure.
*/
static int setResourcesIdsInManager(struct pldm_rde_requester_manager* manager,
std::vector<uint32_t>& resourceIds)
{
return pldm_rde_set_resources_in_context(manager, resourceIds.size(),
resourceIds.data());
}
int getRdeContextForRdeDevice(const std::string& rdeDevice)
{
auto it = managerCtxCounter.find(rdeDevice);
if (it != managerCtxCounter.end())
{
return it->second;
}
return -1;
}
std::optional<struct pldm_rde_requester_manager*>
getManagerForRdeDevice(const std::string& rdeDevice)
{
auto it = managers.find(rdeDevice);
if (it != managers.end())
{
return it->second.get();
}
return std::nullopt;
}
int processNegotiateRedfishParametersRequest(
int fd, uint8_t eid, int instanceId,
struct pldm_rde_requester_manager* manager,
struct pldm_rde_requester_context* ctx,
const std::vector<uint8_t>& requestMsg)
{
ctx->context_status = CONTEXT_BUSY;
ctx->requester_status = PLDM_RDE_REQUESTER_WAITING_FOR_RESPONSE;
int rc = pldm_send_at_network(eid, manager->net_id, fd, requestMsg.data(),
requestMsg.size());
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
return PLDM_RDE_REQUESTER_SEND_FAIL;
}
std::vector<uint8_t> response(sizeof(pldm_msg_hdr) + PLDM_MAX_REQUEST_BYTES,
0);
uint8_t* responseMsg = response.data();
size_t responseMsgSize = response.size();
auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg);
rc = pldm_recv_at_network(eid, fd, instanceId, &responseMsg,
&responseMsgSize, manager->net_id);
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
return PLDM_RDE_REQUESTER_RECV_FAIL;
}
std::cerr << "Pushing Response for Negotiate Redfish Parameters...\n";
rc = pldm_rde_discovery_push_response(manager, ctx, responsePtr,
responseMsgSize);
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
std::cerr << "Saving RDE Disc. Response Failed..." << std::endl;
return PLDM_RDE_REQUESTER_NOT_RESP_MSG;
}
return PLDM_BASE_REQUESTER_SUCCESS;
}
int processNegotiateMediumParametersRequest(
int fd, uint8_t eid, int instanceId,
struct pldm_rde_requester_manager* manager,
struct pldm_rde_requester_context* ctx,
const std::vector<uint8_t>& requestMsg)
{
ctx->context_status = CONTEXT_BUSY;
ctx->requester_status = PLDM_RDE_REQUESTER_WAITING_FOR_RESPONSE;
int rc = pldm_send_at_network(eid, manager->net_id, fd, requestMsg.data(),
requestMsg.size());
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
return PLDM_RDE_REQUESTER_SEND_FAIL;
}
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 = sizeof(pldm_msg_hdr) +
RDE_NEGOTIATE_REDFISH_MEDIUM_PARAMS_RESP_SIZE;
auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg);
rc = pldm_recv_at_network(eid, fd, instanceId, &responseMsg,
&responseMsgSize, manager->net_id);
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
return PLDM_RDE_REQUESTER_RECV_FAIL;
}
std::cerr << "Pushing Response for Negotiate Medium Parameters...\n";
rc = pldm_rde_discovery_push_response(manager, ctx, responsePtr,
responseMsgSize);
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
std::cerr << "Saving RDE Disc. (Med) Response Failed..." << std::endl;
return PLDM_RDE_REQUESTER_NOT_RESP_MSG;
}
return PLDM_RDE_REQUESTER_SUCCESS;
}
std::optional<std::unordered_map<uint32_t, std::vector<uint8_t>>*>
getDictionaryMap(const std::string& rdeDevice)
{
if (DEBUG)
{
std::cerr << "Searching dict for: " << rdeDevice
<< "with length: " << std::to_string(rdeDevice.length())
<< "\n";
}
auto it = dictionaryDeviceMap.find(rdeDevice);
if (it != dictionaryDeviceMap.end())
{
return &(it->second);
}
return std::nullopt;
}
int verifyChecksumForMultipartRecv(const std::vector<uint8_t>& payload)
{
uint32_t payloadLength = payload.size();
auto calculatedChecksum = crc32(&(payload.front()), payloadLength - 4);
uint8_t byte0 = payload[payloadLength - 4];
uint8_t byte1 = payload[payloadLength - 3];
uint8_t byte2 = payload[payloadLength - 2];
uint8_t byte3 = payload[payloadLength - 1];
uint32_t checksumReceived = byte0 | byte1 << 8 | byte2 << 16 | byte3 << 24;
if (calculatedChecksum == checksumReceived)
{
if (DEBUG)
{
std::cerr << "For RDE Op: Checksum Verified, Calculated Checksum: "
<< std::to_string(calculatedChecksum)
<< " , Received Checksum: "
<< std::to_string(checksumReceived) << std::endl;
}
return PLDM_RDE_REQUESTER_SUCCESS;
}
std::cerr
<< "Checksum mismatch for request id/resource id in multipart receive"
<< std::endl;
return PLDM_RDE_REQUESTER_RECV_FAIL;
}
void getDictMultipartResponseHandler(struct pldm_rde_requester_manager* manager,
struct pldm_rde_requester_context* ctx,
uint8_t** payload, uint32_t payloadLength,
bool hasChecksum)
{
uint8_t resourceIdIndex = ctx->current_pdr_resource->resource_id_index;
uint32_t resourceId = manager->resource_ids[resourceIdIndex];
if (DEBUG)
{
std::cerr << "Resource id pushing in dictionary...\t"
<< std::to_string(resourceIdIndex)
<< " and Resource id: " << std::to_string(resourceId) << "\n";
}
std::string device_id = std::string(manager->device_name);
std::unordered_map<uint32_t, std::vector<uint8_t>>* dictionaryRidMap;
std::optional<std::unordered_map<uint32_t, std::vector<uint8_t>>*>
dictionaryRidMapOpt = getDictionaryMap(device_id);
if (dictionaryRidMapOpt.has_value())
{
dictionaryRidMap = dictionaryRidMapOpt.value();
std::cout << dictionaryRidMap->size();
}
else
{
std::cerr << "Unable to fetch dictionary from map while storing\n";
return;
}
auto it = dictionaryRidMap->find(resourceId);
std::vector<uint8_t>* dictionary;
if (it != dictionaryRidMap->end())
{
dictionary = &(it->second);
dictionary->insert(it->second.end(), *payload,
(*payload) + payloadLength);
}
else
{
(*dictionaryRidMap)[resourceId] =
std::vector<uint8_t>(*payload, *payload + payloadLength);
dictionary = &(*dictionaryRidMap)[resourceId];
}
if (DEBUG)
{
std::cerr << "Payload Length inside creating map for resource id << "
<< std::to_string(
ctx->current_pdr_resource->resource_id_index)
<< ": " << payloadLength << "\n";
}
if (hasChecksum)
{
int rc = verifyChecksumForMultipartRecv(*dictionary);
if (rc)
{
std::cerr << "Checksum verification for dictionary failed\n";
}
else
{
if (DEBUG)
{
std::cerr << "Checksum verified delteing last 4 payload\n";
}
dictionary->erase(dictionary->begin() + (dictionary->size() - 4),
dictionary->end());
}
}
}
void responseHandlerCallback(struct pldm_rde_requester_manager* manager,
struct pldm_rde_requester_context* ctx,
uint8_t** payload, uint32_t payloadLength,
bool hasChecksum)
{
switch (ctx->next_command)
{
case PLDM_RDE_MULTIPART_RECEIVE:
getDictMultipartResponseHandler(manager, ctx, payload,
payloadLength, hasChecksum);
break;
default:
break; // No Op for other commands- Can add functionalities later
}
}
int processGetNextDictionarySchema(int fd, uint8_t eid, int instanceId,
struct pldm_rde_requester_manager* manager,
struct pldm_rde_requester_context* ctx,
const std::vector<uint8_t>& requestMsg)
{
ctx->context_status = CONTEXT_BUSY;
ctx->requester_status = PLDM_RDE_REQUESTER_WAITING_FOR_RESPONSE;
int rc = pldm_send_at_network(eid, manager->net_id, fd, requestMsg.data(),
requestMsg.size());
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
return PLDM_RDE_REQUESTER_SEND_FAIL;
}
std::vector<uint8_t> response(
sizeof(pldm_msg_hdr) + RDE_GET_DICT_SCHEMA_RESP_SIZE, 0);
uint8_t* responseMsg = response.data();
size_t responseMsgSize = sizeof(pldm_msg_hdr) +
RDE_GET_DICT_SCHEMA_RESP_SIZE;
auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg);
rc = pldm_recv_at_network(eid, fd, instanceId, &responseMsg,
&responseMsgSize, manager->net_id);
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
return PLDM_RDE_REQUESTER_RECV_FAIL;
}
rc = pldm_rde_push_get_dictionary_response(
manager, ctx, responsePtr, responseMsgSize, responseHandlerCallback);
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
std::cerr << "Saving Dictionary Response Failed..." << std::endl;
return PLDM_RDE_REQUESTER_NOT_RESP_MSG;
}
return PLDM_RDE_REQUESTER_SUCCESS;
}
int processRdeMultipartReceive(int fd, uint8_t eid, int instanceId,
struct pldm_rde_requester_manager* manager,
struct pldm_rde_requester_context* ctx,
const std::vector<uint8_t>& requestMsg)
{
ctx->context_status = CONTEXT_BUSY;
ctx->requester_status = PLDM_RDE_REQUESTER_WAITING_FOR_RESPONSE;
int rc = pldm_send_at_network(eid, manager->net_id, fd, requestMsg.data(),
requestMsg.size());
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
return PLDM_RDE_REQUESTER_SEND_FAIL;
}
std::vector<uint8_t> response(
sizeof(pldm_msg_hdr) + manager->negotiated_transfer_size, 0);
uint8_t* responseMsg = response.data();
size_t responseMsgSize = sizeof(pldm_msg_hdr) +
manager->negotiated_transfer_size;
auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsg);
rc = pldm_recv_at_network(eid, fd, instanceId, &responseMsg,
&responseMsgSize, manager->net_id);
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
return PLDM_RDE_REQUESTER_RECV_FAIL;
}
if (DEBUG)
{
auto resourceId =
manager->resource_ids[ctx->current_pdr_resource->resource_id_index];
auto transferHandleCurrent = ctx->current_pdr_resource->transfer_handle;
std::cerr
<< "Pushing response for Get Multipart receive for resource id: "
<< std::to_string(resourceId)
<< " and transfer handle: " << std::to_string(transferHandleCurrent)
<< "...\n";
}
rc = pldm_rde_push_get_dictionary_response(
manager, ctx, responsePtr, responseMsgSize, responseHandlerCallback);
if (rc)
{
ctx->requester_status = PLDM_RDE_REQUESTER_REQUEST_FAILED;
ctx->context_status = CONTEXT_FREE;
std::cerr << "Saving Dictionary Response Failed..." << std::endl;
return PLDM_RDE_REQUESTER_NOT_RESP_MSG;
}
return PLDM_RDE_REQUESTER_SUCCESS;
}
int processNextRdeRequest(int fd, uint8_t eid, int instanceId,
struct pldm_rde_requester_manager* manager,
struct pldm_rde_requester_context* ctx,
const std::vector<uint8_t>& requestMsg)
{
switch (ctx->next_command)
{
case PLDM_NEGOTIATE_REDFISH_PARAMETERS:
return processNegotiateRedfishParametersRequest(
fd, eid, instanceId, manager, ctx, requestMsg);
case PLDM_NEGOTIATE_MEDIUM_PARAMETERS:
return processNegotiateMediumParametersRequest(
fd, eid, instanceId, manager, ctx, requestMsg);
case PLDM_GET_SCHEMA_DICTIONARY:
return processGetNextDictionarySchema(fd, eid, instanceId, manager,
ctx, requestMsg);
case PLDM_RDE_MULTIPART_RECEIVE:
return processRdeMultipartReceive(fd, eid, instanceId, manager, ctx,
requestMsg);
default:
return PLDM_RDE_REQUESTER_NOT_PLDM_RDE_MSG;
}
}
int performRdeDiscovery(const std::string& rdeDeviceId, int fd, int netId,
uint8_t destEid, uint8_t instanceId,
uint32_t& negotiatedTransferSize)
{
int rc = initManager(rdeDeviceId, netId);
if (rc)
{
std::cerr << "initManager failed with error: " << rc << "\n";
return rc;
}
int rdeContextIndex = getRdeContextForRdeDevice(rdeDeviceId);
if (rdeContextIndex == -1)
{
std::cerr
<< "Unable to provide base context- Error in RDE discovery\n ";
return -1;
}
struct pldm_rde_requester_context baseContext =
rdeContexts[rdeContextIndex];
rc = pldm_rde_start_discovery(&baseContext);
if (rc)
{
std::cerr << "RDE Discovery failed due to context busy with ec: " << rc
<< "\n";
return -1;
}
std::optional<struct pldm_rde_requester_manager*> managerOpt =
getManagerForRdeDevice(rdeDeviceId);
if (!managerOpt.has_value())
{
std::cerr << "Failure to get RDE Manager for rde device with ec: " << rc
<< "\n";
return -1;
}
struct pldm_rde_requester_manager* manager = managerOpt.value();
int retryCounter = 0;
while (true)
{
int requestBytes;
if (baseContext.requester_status ==
PLDM_RDE_REQUESTER_NO_PENDING_ACTION)
{
break;
}
if (rdeCommandRequestSize.find(baseContext.next_command) !=
rdeCommandRequestSize.end())
{
requestBytes = rdeCommandRequestSize[baseContext.next_command];
}
else
{
requestBytes = PLDM_MAX_REQUEST_BYTES;
}
std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + requestBytes);
auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
std::cout << "Getting next RDE Discovery request...\n";
rc = pldm_rde_get_next_discovery_command(instanceId, manager,
&baseContext, request);
if (rc)
{
std::cerr << "Not a valid request to process\n";
return rc;
}
rc = processNextRdeRequest(fd, destEid, 1, manager, &baseContext,
requestMsg);
if (rc)
{
std::cerr << "Unable to process next rde request: "
<< std::to_string(rc) << "\n";
return rc;
}
retryCounter++;
if (retryCounter > 5)
{
std::cerr << "All process counters exhausted for RDE discovery"
<< std::endl;
rc = -1;
}
}
negotiatedTransferSize = manager->negotiated_transfer_size;
if (DEBUG)
{
printRDENegotiateContext(manager);
}
return rc;
}
int performDictionaryDiscoveryForDevice(
const std::string& rdeDeviceId, int fd, uint8_t destEid, uint8_t instanceId,
std::unordered_map<std::string, uint32_t>& resourceIdMap)
{
std::unordered_map<uint32_t, std::vector<uint8_t>> dictionaryRidMap;
std::unordered_map<uint32_t, std::tuple<uint8_t, uint8_t>>
dictionaryMetaRidMap;
std::vector<uint32_t> schemaResourceIds;
for (const auto& [key, value] : resourceIdMap)
{
// We need to extract just the schema resource IDs. There will be
// multiple resources which share the same schema, but we only need
// the resource ID of the first resource of that schema
// For e.g. We only need resource ID of /redfish/v1/Chassis/Tray i.e.
// 0x00020000 instead of resource ID of /redfish/v1/Chassis/SATA_0 i.e.
// 0x00020001. Here the MSB 0x0002 represents the resource type while
// the LSB 0x0001 represent the resource index. So we exclude the
// resource index
uint32_t schemaResourceId = value & 0xFFFF0000;
auto it = std::find(schemaResourceIds.begin(), schemaResourceIds.end(),
schemaResourceId);
if (it == schemaResourceIds.end())
{
schemaResourceIds.emplace_back(schemaResourceId);
}
}
// Add the annotation dictionary
schemaResourceIds.emplace_back(0xffffffff);
dictionaryDeviceMap.insert({rdeDeviceId, dictionaryRidMap});
// For holding schema initial transfer flags - not being used right now
dictionaryMetaDeviceMap.insert({rdeDeviceId, dictionaryMetaRidMap});
int rdeContextIndex = getRdeContextForRdeDevice(rdeDeviceId);
if (rdeContextIndex == -1)
{
std::cerr << "Unable to provide base context- Error in RDE discovery\n";
return -1;
}
struct pldm_rde_requester_context baseContext =
rdeContexts[rdeContextIndex];
int rc = pldm_rde_init_get_dictionary_schema(&baseContext);
if (rc)
{
std::cerr << "PLDM RDE Init dictionary failed with ec: " << rc << "\n";
return rc;
}
if (DEBUG)
{
std::cerr << "Getting dictionary for context resource id : "
<< std::to_string(
(baseContext.current_pdr_resource)->resource_id_index)
<< "\n";
}
std::optional<struct pldm_rde_requester_manager*> managerOpt =
getManagerForRdeDevice(rdeDeviceId);
if (!managerOpt.has_value())
{
std::cerr << "Failure to get RDE Manager for rde device with ec: " << rc
<< "\n";
return -1;
}
struct pldm_rde_requester_manager* manager = managerOpt.value();
rc = setResourcesIdsInManager(manager, schemaResourceIds);
if (rc)
{
std::cerr
<< "RDE Discovery failed due to failed to set resource IDs in context: "
<< rc << "\n";
return -1;
}
std::cout << "Getting Dictionaries..." << std::endl;
int retryCounter = 0;
while (retryCounter < MAX_RETRIES_FOR_REQUEST)
{
int requestBytes;
if (baseContext.requester_status ==
PLDM_RDE_REQUESTER_NO_PENDING_ACTION)
{
break;
}
if (rdeCommandRequestSize.find(baseContext.next_command) !=
rdeCommandRequestSize.end())
{
requestBytes = rdeCommandRequestSize[baseContext.next_command];
}
else
{
requestBytes = PLDM_MAX_REQUEST_BYTES;
}
std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + requestBytes);
auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
if (baseContext.next_command == PLDM_GET_SCHEMA_DICTIONARY)
{
std::cerr << "Getting dictionary for "
<< manager->resource_ids[baseContext.current_pdr_resource
->resource_id_index]
<< "..." << std::endl;
}
rc = pldm_rde_get_next_dictionary_schema_command(
/*instanceId*/ instanceId, manager, &baseContext, request);
if (rc)
{
std::cerr << "Not a valid request to process\n";
return -1;
}
rc = processNextRdeRequest(fd, destEid, instanceId, manager,
&baseContext, requestMsg);
if (rc)
{
std::cerr << "Unable to process next rde request: "
<< std::to_string(rc) << "\n";
return -1;
}
retryCounter++;
}
return 0;
}
int getRdeFreeContextForRdeDevice(
const std::string& rdeDevice,
struct pldm_rde_requester_context* baseContext)
{
auto it = managerCtxCounter.find(rdeDevice);
if (it != managerCtxCounter.end())
{
*baseContext = rdeContexts[it->second];
if (baseContext->context_status != CONTEXT_FREE)
{
return RDE_CONTEXT_NOT_FREE;
}
return RDE_CONTEXT_FREE;
}
return RDE_NO_CONTEXT_FOUND;
}
int getDictionaryForRidDev(const std::string& rdeDeviceId, uint32_t resourceId,
[[maybe_unused]] uint8_t** dictElem,
[[maybe_unused]] uint32_t* dictLength)
{
std::unordered_map<uint32_t, std::vector<uint8_t>>* dictionaryRidMap;
std::optional<std::unordered_map<uint32_t, std::vector<uint8_t>>*>
dictionaryRidMapOpt = getDictionaryMap(rdeDeviceId);
if (!dictionaryRidMapOpt.has_value())
{
std::cerr << "Unable to fetch dictionary from map while storing\n";
return PLDM_RDE_NO_PDR_RESOURCES_FOUND;
}
dictionaryRidMap = dictionaryRidMapOpt.value();
auto it = dictionaryRidMap->find(resourceId);
if (it != dictionaryRidMap->end())
{
*dictElem = &it->second.front();
*dictLength = it->second.size();
return PLDM_RDE_REQUESTER_SUCCESS;
}
else
{
dictElem = nullptr;
}
return PLDM_RDE_NO_PDR_RESOURCES_FOUND;
}