blob: cd64c833186effbaf4f9a885b85eec20f2719ffc [file] [edit]
#include "libpldm/pldm_rde.h"
#include "common/utils.hpp"
#include "helper/common.hpp"
#include "helper/discovery/base_discovery.hpp"
#include "helper/discovery/platform_discovery.hpp"
#include "helper/discovery/rde_discovery.hpp"
#include "helper/rde_operation/rde_operation.hpp"
// libbej
#include "libbej/bej_common.h"
#include "libbej/bej_encoder_core.h"
#include "libbej/bej_encoder_json.hpp"
#include <locale.h>
#include <signal.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <boost/asio.hpp>
#include <boost/asio/io_context.hpp>
#include <helper/mctpsetup.hpp>
#include <libbej/bej_decoder_json.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server.hpp>
#include <sdbusplus/unpack_properties.hpp>
#include <sdeventplus/event.hpp>
#include <chrono>
#include <csignal>
#include <cstddef>
#include <iostream>
#include <unordered_map>
#include <vector>
using namespace sdeventplus;
using namespace pldm::utils;
using DbusVariant = std::variant<std::string, uint64_t, uint32_t, uint16_t,
uint8_t, sdbusplus::message::object_path>;
using ChangedPropertiesType = std::vector<std::pair<std::string, DbusVariant>>;
constexpr uint8_t DEST_EID = 9;
// TODO(@harshtya): Change instance id to be dynamic
constexpr uint8_t INSTANCE_ID = 1;
constexpr int SOCKET_TIMEOUT_SECONDS = 8;
constexpr uint32_t annotationDictRid = 0xffffffff;
int fd = -1; // MCTP Socket for RDE communication
boost::asio::io_context io;
std::unordered_map<int, int> retryCounterMap;
std::unordered_map<std::string, int> deviceNetIdMap;
std::unordered_map<std::string,
std::shared_ptr<sdbusplus::asio::dbus_interface>>
dbusIntfMap;
std::unordered_map<std::string, std::string> objectPathDeviceId;
std::unordered_map<std::string, std::unordered_map<std::string, uint32_t>>
rdeResourceIdMap;
struct CacheEntry
{
std::string response;
std::chrono::steady_clock::time_point timestamp;
};
std::unordered_map<std::string, std::unordered_map<std::string, CacheEntry>>
rdeResponseCacheMap;
constexpr int CACHE_EXPIRATION_SECONDS = 300;
static int getResourceIdForUri(std::string& uri, std::string& udevId,
uint32_t& resourceId)
{
if (rdeResourceIdMap.find(udevId) != rdeResourceIdMap.end())
{
std::unordered_map<std::string, uint32_t>::iterator it =
rdeResourceIdMap[udevId].find(uri);
if (it != rdeResourceIdMap[udevId].end())
{
resourceId = it->second;
if (DEBUG)
{
std::cout << "Resource id found: " << std::to_string(it->second)
<< "\n";
}
return 0;
}
}
if ((uri.find("Cables") == std::string::npos) &&
(uri.find("Systems") == std::string::npos))
{
std::cerr << "Resource id not found for uri: " << uri << std::endl;
}
return 1;
}
void cleanupAtExit()
{
// cleans up at daemon termination
fd = 0;
rdeResponseCacheMap.clear();
rdeResourceIdMap.clear();
deviceNetIdMap.clear();
dbusIntfMap.clear();
objectPathDeviceId.clear();
retryCounterMap.clear();
cleanupBaseDiscAtExit();
cleanupRdeDiscAtExit();
cleanupMctpAtExit();
}
void signalHandler(int signal)
{
std::cerr << "Received signal " << signal << ". Cleaning up...\n";
cleanupAtExit();
std::exit(signal);
}
int initiateDiscovery(int fd, std::string udevId, int netId, uint8_t destEid,
uint8_t instanceId)
{
int rc;
// Begin Base Discovery
std::cerr << "Initiating PLDM Discovery...\n";
rc = performBaseDiscovery(udevId, fd, netId, destEid, instanceId);
if (rc)
{
std::cerr << "Failure in Base Discovery with error code: " << rc
<< "\n";
return rc;
}
std::cerr << "Initializing RDE Discovery...\n";
uint32_t negotiatedTransferSize = 0;
rc = performRdeDiscovery(udevId, fd, netId, destEid, instanceId,
negotiatedTransferSize);
if (rc)
{
std::cerr << "Failure in Base Discovery with error code: " << rc
<< "\n";
return rc;
}
std::unordered_map<std::string, uint32_t> resourceIdMap;
rdeResourceIdMap.emplace(std::make_pair(udevId, std::move(resourceIdMap)));
auto it = rdeResourceIdMap.find(udevId);
if (it == rdeResourceIdMap.end())
{
std::cerr << "Failed to find Resource ID map for " << udevId
<< " device" << std::endl;
return -1;
}
std::cerr << "Initializing PDR Discovery...\n";
rc = performPdrDiscovery(udevId, fd, netId, destEid, instanceId,
negotiatedTransferSize, it->second);
if (rc)
{
std::cerr << "Failure in Base Discovery with error code: " << rc
<< "\n";
return rc;
}
rc = performDictionaryDiscoveryForDevice(udevId, fd, destEid, instanceId,
it->second);
if (rc)
{
std::cerr << "Failure in getting dictionaries with error code: " << rc
<< "\n";
return rc;
}
return 0;
}
void getDeviceIdForRemovedDevice(const std::string& objPath,
std::string* deviceId)
{
auto it = objectPathDeviceId.find(objPath);
if (it != objectPathDeviceId.end())
{
*deviceId = it->second;
}
}
/**
* @brief generate operation id
*/
uint16_t generateOperationId()
{
// TODO(@harshtya): Create an operation id generator (Following the spec)
return 32770;
}
/**
* @brief Retry counter tracker
*/
int getCurrentRetryCount(int requestId)
{
auto it = retryCounterMap.find(requestId);
if (it == retryCounterMap.end())
{
retryCounterMap.insert({requestId, 1});
return 1;
}
int retryCount = it->second;
retryCounterMap.insert({requestId, retryCount + 1});
return retryCount + 1;
}
/**
* @brief Removes the query parameters as we do not support expand yet
*/
int removeQueryParams(std::string& uri, std::string_view delimeter)
{
std::string::size_type start = uri.find(delimeter);
int end = uri.length();
if (start == std::string::npos)
{
if (DEBUG)
{
std::cerr << "No query parameters found\n";
}
return 1;
}
uri.erase(start, end - start + 1);
return 0;
}
/**
* @brief Remove any trailing forward slashes in URI
*/
void truncateTrailingFwSlash(std::string& uri)
{
if (uri.back() == '/')
{
uri.pop_back();
}
}
/**
* @brief Checks whether the POST request is an UPDATE request or ACTION
*/
bool isActionOperation(const std::string& uri, std::string& resourceUri)
{
std::string actionString = "/Actions";
size_t index;
if ((index = uri.find(actionString)) != std::string::npos)
{
resourceUri = uri.substr(0, index);
return true;
}
return false;
}
int getSchemaDictionary(void* context, uint32_t resourceId,
const uint8_t** dictionary)
{
int rc;
if (context == nullptr)
{
std::cerr << " null context (deviceIdPtr) resourceId:" << resourceId
<< "\n";
return -1;
}
const std::string* deviceIdPtr = static_cast<const std::string*>(context);
// (TODO) to get rid of this calculation once BMC removes the
// hardcoding of the resource ID mapping.
uint32_t ridSchema = resourceId >> 16 << 16;
uint32_t schemaDictLen = 0;
uint8_t* schemaDict = nullptr;
rc = getDictionaryForRidDev(*deviceIdPtr, ridSchema, &schemaDict,
&schemaDictLen);
if (rc)
{
std::cerr << "Unable to fetch schema dictionary\n";
return rc;
}
*dictionary = (const uint8_t*)schemaDict;
return 0;
}
/**
* Translate BEJ to string
*/
int translateBejToString(uint32_t resourceId, const std::string& deviceId,
std::string* json, uint8_t** payload,
uint32_t payloadLength)
{
int rc;
uint32_t annotationDictLen = 0;
uint8_t* annotationDict = nullptr;
// get_dictioanry_for_rid from particular resource id
rc = getDictionaryForRidDev(deviceId, annotationDictRid, &annotationDict,
&annotationDictLen);
if (rc)
{
std::cerr << "Unable to fetch annotation dictionary\n";
return rc;
}
uint32_t ridSchema = resourceId >> 16 << 16;
uint32_t schemaDictLen = 0;
uint8_t* schemaDict = nullptr;
rc = getDictionaryForRidDev(deviceId, ridSchema, &schemaDict,
&schemaDictLen);
if (rc)
{
std::cerr << "Unable to fetch schema dictionary\n";
return rc;
}
std::span<uint8_t> bejson = std::span{*payload, payloadLength};
BejDictionaries bejDictionaries;
bejDictionaries.schemaDictionary = schemaDict;
bejDictionaries.schemaDictionarySize = schemaDictLen;
bejDictionaries.annotationDictionary = annotationDict;
bejDictionaries.annotationDictionarySize = annotationDictLen;
bejDictionaries.errorDictionary = nullptr;
bejDictionaries.errorDictionarySize = 0;
struct BejNodeDecodeInfo nodeDecodeInfo = {};
nodeDecodeInfo.context = (void*)&deviceId;
nodeDecodeInfo.getSchemaDictionary = &getSchemaDictionary;
if (payloadLength > 0)
{
libbej::BejDecoderJson decoder;
decoder.decode(bejDictionaries, bejson, BEJ_DICTIONARY_START_AT_HEAD,
&nodeDecodeInfo);
*json = decoder.getOutput();
}
else
{
*json = "{\"Status\": \"Completed\"}";
}
return 0;
}
/**
* @brief RDE Operation DBus method handler
*/
std::string
rdeOperation(boost::asio::yield_context yield, int requestId,
uint8_t operationType /* Change to std::string req_type */,
std::string uri, std::string udevid,
std::string reqPayloadJson)
{
struct pldm_rde_requester_context baseContext;
int rc = getRdeFreeContextForRdeDevice(udevid, &baseContext);
if (rc == RDE_NO_CONTEXT_FOUND)
{
std::cerr << "Unable to provide base context- Error in RDE discovery\n";
return "Unsuccessful RDE operation with error code: " +
std::to_string(rc);
}
// if base context is free to execute
if (baseContext.context_status == CONTEXT_BUSY ||
baseContext.context_status == CONTEXT_CONTINUE)
{
auto timer = std::make_shared<boost::asio::steady_timer>(io);
timer->expires_from_now(std::chrono::milliseconds(20));
timer->async_wait(yield);
std::cerr << "Timer expired. RDE Operation failed\n";
int currentRetry = getCurrentRetryCount(requestId);
if (currentRetry > MAX_RETRIES_FOR_REQUEST)
{
retryCounterMap.erase(requestId);
return "Max retries exceeded for request. Abandoning...\n";
}
rdeOperation(yield, requestId, operationType, uri, udevid,
reqPayloadJson);
}
// get manager
std::optional<struct pldm_rde_requester_manager*> managerOpt =
getManagerForRdeDevice(udevid);
if (!managerOpt.has_value())
{
std::cerr
<< "Failed to get manager to perform read request for request id: "
<< std::to_string(requestId) << ", request uri: " << uri
<< ", UDEVID: " << udevid << "\n";
retryCounterMap.erase(requestId);
return "Unsuccessful RDE operation with error code: " +
std::to_string(rc);
}
struct pldm_rde_requester_manager* manager = managerOpt.value();
uint32_t resourceId = 0;
std::string rawUri = uri;
// strip query params - until expand is supported
rc = removeQueryParams(uri, "?");
if (DEBUG && !rc)
{
retryCounterMap.erase(requestId);
std::cerr << "URI after removing query params: " << uri << "\n";
}
truncateTrailingFwSlash(uri);
std::string resource_uri = uri;
bool isAction = isActionOperation(uri, resource_uri);
bool bypassCache = false;
if (isAction)
{
if (int(operationType) != 8)
{
std::cerr << "Action operation with non-POST type: "
<< std::to_string(operationType) << " for URI: " << rawUri
<< "\n";
retryCounterMap.erase(requestId);
return "Unsuccessful RDE operation: Action must be POST for URI: " +
rawUri + "\n";
}
rc = getResourceIdForUri(resource_uri, udevid, resourceId);
if (rc)
{
std::cerr << "Unable to resolve collection for RDE Action request "
<< "with rawUri: " << rawUri << "\n";
retryCounterMap.erase(requestId);
return "Unable to resolve collection for RDE Action request with rc: " +
std::to_string(rc) + "\n";
}
if (uri.find("FetchIdentifyState") != std::string::npos)
{
operationType = PLDM_RDE_OPERATION_READ;
bypassCache = true;
}
else
{
// TODO(@harshtya): Define 6 in PLDM_RDE_OPERATION_TYPES in libpldm
operationType =
PLDM_RDE_OPERATION_ACTION; // This is the operation type for
// ACTION request
}
}
else
{
rc = getResourceIdForUri(uri, udevid, resourceId);
if (rc)
{
if (int(operationType) != 8)
{
if ((uri.find("Cables") == std::string::npos) &&
(uri.find("Systems") == std::string::npos))
{
std::cerr
<< "Unsuccessful RDE operation- no resource id found, rc: " +
std::to_string(rc) + " with URI: " + rawUri +
"\n";
}
retryCounterMap.erase(requestId);
return "Unsuccessful RDE operation with error code: " +
std::to_string(rc) + " with URI: " + rawUri + "\n";
}
else
{
// Create a resource request
std::cerr << "Operation create not supported: " << rawUri
<< "\n";
retryCounterMap.erase(requestId);
return "Create RDE operation not yet supported for " + rawUri +
"\n";
}
}
}
if (operationType == PLDM_RDE_OPERATION_READ && !bypassCache)
{
auto udevIt = rdeResponseCacheMap.find(udevid);
if (udevIt != rdeResponseCacheMap.end())
{
auto uriIt = udevIt->second.find(rawUri);
if (uriIt != udevIt->second.end())
{
auto now = std::chrono::steady_clock::now();
auto duration =
std::chrono::duration<double>(now - uriIt->second.timestamp)
.count();
if (DEBUG)
{
std::cerr << "Cache duration for URI: " << rawUri << " is "
<< duration << " seconds\n";
}
if (duration <= CACHE_EXPIRATION_SECONDS)
{
if (DEBUG)
{
std::cerr
<< "Serving response from cache for URI: " << rawUri
<< "\n";
}
retryCounterMap.erase(requestId);
return uriIt->second.response;
}
else
{
// Cache expired, let's proceed to fetch new one
if (DEBUG)
{
std::cerr << "Cache expired for URI: " << rawUri
<< "\n";
}
udevIt->second.erase(uriIt);
}
}
}
}
uint16_t operation_id = generateOperationId();
for (int retry = 0; retry < MAX_RETRIES_MCTP_SOCK_FAILURE; retry++)
{
rc = executeRdeOperation(fd, DEST_EID, INSTANCE_ID, rawUri, uri, udevid,
operation_id, operationType, requestId,
manager, &baseContext, resourceId,
reqPayloadJson);
if (rc)
{
std::cerr << "Request execution failed: ReqID: "
<< std::to_string(requestId) << ", URI: " << uri << ", "
<< "operation type: " << std::to_string(operationType)
<< " with retry counter: " << (retry + 1) << std::endl;
retryCounterMap.erase(requestId);
cleanupRequestId(requestId, &baseContext);
if (retry == (MAX_RETRIES_MCTP_SOCK_FAILURE - 1))
{
std::cerr << "All retries exhausted for rde execute: " << uri
<< std::endl;
return "Unsuccessful RDE operation with error code: " +
std::to_string(rc);
}
}
else
{
break;
}
}
uint8_t* payload;
uint32_t payloadLength;
rc = getResponseForRequestId(requestId, &payload, &payloadLength);
if (rc)
{
std::cerr << "Unable to fetch response from response map with rc: "
<< rc << " for URI: " << rawUri;
retryCounterMap.erase(requestId);
cleanupRequestId(requestId, &baseContext);
return "Unsuccessful RDE operation with error code: " +
std::to_string(rc);
}
std::string jsonResp;
rc = translateBejToString(resourceId, udevid, &jsonResp, &payload,
payloadLength);
if (rc)
{
std::cerr << "Unable to translate BEJ for URI: " << rawUri << "\n";
jsonResp = "Unsuccessful RDE operation- failed to translate bej";
}
else if (operationType == PLDM_RDE_OPERATION_READ && !bypassCache)
{
CacheEntry entry;
entry.response = jsonResp;
entry.timestamp = std::chrono::steady_clock::now();
rdeResponseCacheMap[udevid][rawUri] = entry;
// Add a cap for max entries per device here to prevent unbounded memory
// growth.
if (rdeResponseCacheMap[udevid].size() >= 100)
{
rdeResponseCacheMap[udevid].clear();
}
}
cleanupRequestId(requestId, &baseContext);
retryCounterMap.erase(requestId);
return jsonResp;
}
void pldmSetup(int& fd, sdbusplus::asio::object_server& objectServer,
std::string changedObject, std::string& port,
std::string& udevid, std::string& vendorId,
std::string& prefixPath)
{
int netId = setupOnePort(port, udevid); // MCTP Setup
if (netId == -1)
{
std::cerr << "Mctp failed udevId: " << udevid << ", " << port << "\n";
return;
}
deviceNetIdMap.insert({udevid, netId});
int rc = 0;
for (int retryCounter = 0; retryCounter < MAX_RETRIES_MCTP_SOCK_FAILURE;
retryCounter++)
{
rc = initiateDiscovery(fd, udevid, netId, DEST_EID, INSTANCE_ID);
if (rc)
{
std::cerr << "PLDM/RDE Discovery failed for device: " << port
<< ", udev: " << udevid
<< "with retry counter:" << (retryCounter + 1)
<< std::endl;
cleanupDictionaries(udevid);
if (retryCounter == (MAX_RETRIES_MCTP_SOCK_FAILURE - 1))
{
std::cerr << "All retries exhausted for discovery for "
<< " udev: " << udevid << std::endl;
return;
}
}
else
{
break;
}
std::cerr << "Retrying discovery again due to failure" << std::endl;
}
if (rc)
{
std::cerr << "PLDM/RDE Discovery failed for device: " << port
<< ", udev: " << udevid << "after all retries" << std::endl;
return;
}
std::string objectPath = prefixPath + udevid;
if (DEBUG)
{
std::cerr << "New object path created: " << objectPath << "\n";
}
std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
objectServer.add_interface(objectPath, "xyz.openbmc_project.RdeDevice");
iface->register_property("VID", vendorId,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("USBPORT", port,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_property("UDEVID", udevid,
sdbusplus::asio::PropertyPermission::readOnly);
iface->register_method("execute_rde", std::move(rdeOperation));
iface->initialize();
dbusIntfMap.insert({std::string(changedObject), iface});
objectPathDeviceId.insert({std::string(changedObject), udevid});
}
int triggerRdeReactor(int fd)
{
/**
* RDE Reactor is responsible to react to a new RDE device whenever Entity
* Manager adds a new object path in its service tree that has the interface
* "xyz.openbmc_project.Configuration.RdeSatelliteController"
*
* The detector code for detecting a RDE Device resides in Entity Manager
*/
boost::asio::io_context io;
std::shared_ptr<sdbusplus::asio::connection> systemBus =
std::make_shared<sdbusplus::asio::connection>(io);
sdbusplus::asio::object_server objectServer(systemBus, true);
objectServer.add_manager("/xyz/openbmc_project/rde_devices");
std::string prefixPath = "/xyz/openbmc_project/rde_devices/";
std::cerr << "Beginning RDE reactor...\n";
// Find the all the object paths that implement interface
// xyz.openbmc_project.Configuration.RdeSatelliteController
// Then, create rde_device dbus object
using propertyMap =
std::vector<std::pair<std::string, std::vector<std::string>>>;
constexpr std::array<std::string_view, 1> interfaces = {
"xyz.openbmc_project.Configuration.RdeSatelliteController"};
using DBusProperties = std::vector<std::pair<std::string, DbusVariant>>;
systemBus->async_method_call_timed(
[&fd, &systemBus, &objectServer, &prefixPath](
const boost::system::error_code& ec,
const std::vector<std::pair<std::string, propertyMap>>& subtree) {
if (ec)
{
std::cerr << "D-Bus error: " << ec << ", " << ec.message() << " \n";
return;
}
if (subtree.empty())
{
std::cerr << "No instances found \n";
return;
}
for (const auto& [objPath, services] : subtree)
{
for (const auto& service : services)
{
systemBus->async_method_call_timed(
[&fd, &objectServer, &prefixPath,
objPath](const boost::system::error_code& ec2,
const DBusProperties& properties) {
if (ec2)
{
std::cerr << "DBUS response error on GetAll: "
<< ec2.message() << " \n";
return;
}
std::string vendorId;
std::string udevid;
std::string port;
const bool success = sdbusplus::unpackPropertiesNoThrow(
[](const sdbusplus::UnpackErrorReason reason,
const std::string& property) {
std::cerr << " Error unpacking the property "
<< property << " reason "
<< static_cast<int>(reason) << " \n";
},
properties, "VID", vendorId, "USBPORT", port, "UDEVID",
udevid);
if (success)
{
if (vendorId.empty() || port.empty() || udevid.empty())
{
std::cerr
<< "Matcher does not have required properties\n";
return;
}
// Do PLDM Setup
pldmSetup(fd, objectServer, std::string(objPath), port,
udevid, vendorId, prefixPath);
}
else
{
std::cerr << "error in parsing properties \n";
}
},
service.first, objPath, "org.freedesktop.DBus.Properties",
"GetAll", /*timeout in usec*/ 90000000,
"xyz.openbmc_project.Configuration.RdeSatelliteController");
}
}
},
"xyz.openbmc_project.ObjectMapper",
"/xyz/openbmc_project/object_mapper",
"xyz.openbmc_project.ObjectMapper", "GetSubTree", /*timeout*/ 90000000,
"/xyz/openbmc_project/inventory", 0, interfaces);
auto matchAdd = std::make_unique<sdbusplus::bus::match_t>(
*systemBus, sdbusplus::bus::match::rules::interfacesAdded(),
[&objectServer, &prefixPath, &systemBus,
&fd](sdbusplus::message_t& reply) {
sdbusplus::message::object_path changedObject;
reply.read(changedObject);
std::vector<std::pair<std::string, ChangedPropertiesType>>
changedInterfaces;
reply.read(changedInterfaces);
std::string vendorId;
std::string udevid;
std::string port;
for (const auto& [changedInterface, changedProps] : changedInterfaces)
{
if (changedInterface !=
"xyz.openbmc_project.Configuration.RdeSatelliteController")
{
continue;
}
if (DEBUG)
{
std::cerr << "DEBUG: Changed object path: "
<< std::string(changedObject) << "\n";
}
for (auto& [key, value] : changedProps)
{
if (key == "VID")
{
vendorId = std::get<std::string>(value);
}
else if (key == "USBPORT")
{
port = std::get<std::string>(value);
}
else if (key == "UDEVID")
{
udevid = std::get<std::string>(value);
}
}
if (vendorId.empty() || port.empty() || udevid.empty())
{
std::cerr << "Matcher does not have required properties\n";
return;
}
pldmSetup(fd, objectServer, std::string(changedObject), port,
udevid, vendorId, prefixPath);
}
});
// Remove object path if the device is removed
auto matchRemove = std::make_unique<sdbusplus::bus::match_t>(
*systemBus, sdbusplus::bus::match::rules::interfacesRemoved(),
[&objectServer](sdbusplus::message_t& reply) {
sdbusplus::message::object_path changedObject;
std::vector<std::string> interfacesRemoved;
reply.read(changedObject, interfacesRemoved);
auto it = dbusIntfMap.find(std::string(changedObject));
if (it != dbusIntfMap.end())
{
std::shared_ptr<sdbusplus::asio::dbus_interface> iface = it->second;
auto removed = objectServer.remove_interface(iface);
std::cout << "Removed RDE Device from tree: " << removed << "\n";
dbusIntfMap.erase(std::string(changedObject));
std::string deviceId;
getDeviceIdForRemovedDevice(std::string(changedObject), &deviceId);
if (!deviceId.empty())
{
cleanupDictionaries(deviceId);
cleanupMctpLink(deviceId);
// Remove the resource ID maps for the rde device
rdeResourceIdMap.erase(deviceId);
rdeResponseCacheMap.erase(deviceId);
}
// TODO (@harshtya): clean up the manager for this object path
// TODO (@harshtya): clean up the dictionaries
}
});
systemBus->request_name("xyz.openbmc_project.rdeoperation");
io.run();
return 0;
}
void setSocketTimeout(int fd, int seconds, int milliseconds)
{
struct timeval tv;
tv.tv_sec = seconds;
tv.tv_usec = milliseconds;
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
}
int main()
{
int rc = 0;
std::atexit(cleanupAtExit);
std::signal(SIGTERM, signalHandler);
std::signal(SIGINT, signalHandler);
std::cerr << "Successfully started the RDE Daemon \n";
std::cerr << "rde_expand_enabled: " << rde_expand_enabled << "\n";
fd = socket(AF_MCTP, SOCK_DGRAM, 0);
if (-1 == fd)
{
std::cerr << "Created socket Failed\n";
return fd;
}
std::cerr << "Socket Created with ID: " << fd << ". Setting timeouts...\n";
setSocketTimeout(fd, /*seconds=*/SOCKET_TIMEOUT_SECONDS,
/*milliseconds=*/0);
socklen_t optlen;
int currentSendbuffSize;
optlen = sizeof(currentSendbuffSize);
int res = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &currentSendbuffSize,
&optlen);
if (res == -1)
{
std::cerr << "Error in obtaining the default send buffer size, Error: "
<< strerror(errno) << std::endl;
return -1;
}
rc = triggerRdeReactor(fd);
if (rc)
{
std::cerr << "Error in RDE reactor \n";
return rc;
}
std::cerr << "RDE Reactor stopped...\n";
// Daemon loop -- Code never reaches here if the reactor is running fine--
auto event = Event::get_default();
rc = event.loop();
if (rc)
{
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}