Change the send Buffer size dynamically
On a Linux system the send buffer size has defaulted
to around 90k, and when a pldm message is sent via
the pldm_send() that is bigger than 90k, we get an error
ENOBUFS (No buffer space avilable).
This commit would dynamically change the socket parameter
(SO_SNDBUF) to set the new maximum socket send buffer size
so that we can successfully send the message.
Tested By:
1. hard coded the current buffer size value to 10 and forced
the buffer size to be increase for mutiple commands & was able
to power on the host with out any problems.
Signed-off-by: Manojkiran Eda <manojkiran.eda@gmail.com>
Change-Id: I5f7a3948ea019b4dc983cf5e1926cfc128c02084
diff --git a/fw-update/test/inventory_manager_test.cpp b/fw-update/test/inventory_manager_test.cpp
index 5b14aac..196cb20 100644
--- a/fw-update/test/inventory_manager_test.cpp
+++ b/fw-update/test/inventory_manager_test.cpp
@@ -17,7 +17,7 @@
event(sdeventplus::Event::get_default()),
dbusImplRequester(pldm::utils::DBusHandler::getBus(),
"/xyz/openbmc_project/pldm"),
- reqHandler(fd, event, dbusImplRequester, false, seconds(1), 2,
+ reqHandler(fd, event, dbusImplRequester, false, 90000, seconds(1), 2,
milliseconds(100)),
inventoryManager(reqHandler, dbusImplRequester, outDescriptorMap,
outComponentInfoMap)
diff --git a/pldmd/pldmd.cpp b/pldmd/pldmd.cpp
index d23acf8..d48844f 100644
--- a/pldmd/pldmd.cpp
+++ b/pldmd/pldmd.cpp
@@ -177,7 +177,19 @@
std::cerr << "Failed to create the socket, RC= " << returnCode << "\n";
exit(EXIT_FAILURE);
}
+ socklen_t optlen;
+ int currentSendbuffSize;
+ // Get Current send buffer size
+ optlen = sizeof(currentSendbuffSize);
+
+ int res = getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, ¤tSendbuffSize,
+ &optlen);
+ if (res == -1)
+ {
+ std::cerr << "Error in obtaining the default send buffer size, Error : "
+ << strerror(errno) << std::endl;
+ }
auto event = Event::get_default();
auto& bus = pldm::utils::DBusHandler::getBus();
sdbusplus::server::manager::manager objManager(
@@ -185,8 +197,9 @@
dbus_api::Requester dbusImplReq(bus, "/xyz/openbmc_project/pldm");
Invoker invoker{};
- requester::Handler<requester::Request> reqHandler(sockfd, event,
- dbusImplReq, verbose);
+ requester::Handler<requester::Request> reqHandler(
+ sockfd, event, dbusImplReq, currentSendbuffSize, verbose);
+
#ifdef LIBPLDMRESPONDER
using namespace pldm::state_sensor;
dbus_api::Host dbusImplHost(bus, "/xyz/openbmc_project/pldm");
@@ -299,8 +312,8 @@
std::unique_ptr<MctpDiscovery> mctpDiscoveryHandler =
std::make_unique<MctpDiscovery>(bus, fwManager.get());
- auto callback = [verbose, &invoker, &reqHandler,
- &fwManager](IO& io, int fd, uint32_t revents) {
+ auto callback = [verbose, &invoker, &reqHandler, currentSendbuffSize,
+ &fwManager](IO& io, int fd, uint32_t revents) mutable {
if (!(revents & EPOLLIN))
{
return;
@@ -366,6 +379,26 @@
msg.msg_iov = iov;
msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
+ if (currentSendbuffSize >= 0 &&
+ (size_t)currentSendbuffSize < (*response).size())
+ {
+ int oldBuffSize = currentSendbuffSize;
+ currentSendbuffSize = (*response).size();
+ int res = setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
+ ¤tSendbuffSize,
+ sizeof(currentSendbuffSize));
+ if (res == -1)
+ {
+ std::cerr
+ << "Responder : Failed to set the new send buffer size [bytes] : "
+ << currentSendbuffSize
+ << " from current size [bytes] : "
+ << oldBuffSize
+ << ", Error : " << strerror(errno)
+ << std::endl;
+ return;
+ }
+ }
int result = sendmsg(fd, &msg, 0);
if (-1 == result)
diff --git a/requester/handler.hpp b/requester/handler.hpp
index 6290526..ff7f33d 100644
--- a/requester/handler.hpp
+++ b/requester/handler.hpp
@@ -9,6 +9,8 @@
#include "pldmd/dbus_impl_requester.hpp"
#include "request.hpp"
+#include <sys/socket.h>
+
#include <function2/function2.hpp>
#include <sdbusplus/timer.hpp>
#include <sdeventplus/event.hpp>
@@ -91,6 +93,7 @@
* @param[in] fd - fd of MCTP communications socket
* @param[in] event - reference to PLDM daemon's main event loop
* @param[in] requester - reference to Requester object
+ * @param[in] currentSendbuffSize - current send buffer size
* @param[in] verbose - verbose tracing flag
* @param[in] instanceIdExpiryInterval - instance ID expiration interval
* @param[in] numRetries - number of request retries
@@ -98,14 +101,15 @@
*/
explicit Handler(
int fd, sdeventplus::Event& event, pldm::dbus_api::Requester& requester,
- bool verbose,
+ int currentSendbuffSize, bool verbose,
std::chrono::seconds instanceIdExpiryInterval =
std::chrono::seconds(INSTANCE_ID_EXPIRATION_INTERVAL),
uint8_t numRetries = static_cast<uint8_t>(NUMBER_OF_REQUEST_RETRIES),
std::chrono::milliseconds responseTimeOut =
std::chrono::milliseconds(RESPONSE_TIME_OUT)) :
fd(fd),
- event(event), requester(requester), verbose(verbose),
+ event(event), requester(requester),
+ currentSendbuffSize(currentSendbuffSize), verbose(verbose),
instanceIdExpiryInterval(instanceIdExpiryInterval),
numRetries(numRetries), responseTimeOut(responseTimeOut)
{}
@@ -165,7 +169,7 @@
auto request = std::make_unique<RequestInterface>(
fd, eid, event, std::move(requestMsg), numRetries, responseTimeOut,
- verbose);
+ currentSendbuffSize, verbose);
auto timer = std::make_unique<phosphor::Timer>(
event.get(), instanceIdExpiryCallBack);
@@ -240,6 +244,7 @@
int fd; //!< file descriptor of MCTP communications socket
sdeventplus::Event& event; //!< reference to PLDM daemon's main event loop
pldm::dbus_api::Requester& requester; //!< reference to Requester object
+ int currentSendbuffSize; //!< current Send Buffer size
bool verbose; //!< verbose tracing flag
std::chrono::seconds
instanceIdExpiryInterval; //!< Instance ID expiration interval
diff --git a/requester/request.hpp b/requester/request.hpp
index 24e6942..2f2470f 100644
--- a/requester/request.hpp
+++ b/requester/request.hpp
@@ -6,6 +6,8 @@
#include "common/types.hpp"
#include "common/utils.hpp"
+#include <sys/socket.h>
+
#include <sdbusplus/timer.hpp>
#include <sdeventplus/event.hpp>
@@ -141,6 +143,7 @@
*
* @param[in] fd - fd of the MCTP communication socket
* @param[in] eid - endpoint ID of the remote MCTP endpoint
+ * @param[in] currrentSendbuffSize - the current send buffer size
* @param[in] event - reference to PLDM daemon's main event loop
* @param[in] requestMsg - PLDM request message
* @param[in] numRetries - number of request retries
@@ -149,16 +152,19 @@
*/
explicit Request(int fd, mctp_eid_t eid, sdeventplus::Event& event,
pldm::Request&& requestMsg, uint8_t numRetries,
- std::chrono::milliseconds timeout, bool verbose) :
+ std::chrono::milliseconds timeout, int currentSendbuffSize,
+ bool verbose) :
RequestRetryTimer(event, numRetries, timeout),
- fd(fd), eid(eid), requestMsg(std::move(requestMsg)), verbose(verbose)
+ fd(fd), eid(eid), requestMsg(std::move(requestMsg)),
+ currentSendbuffSize(currentSendbuffSize), verbose(verbose)
{}
private:
int fd; //!< file descriptor of MCTP communications socket
mctp_eid_t eid; //!< endpoint ID of the remote MCTP endpoint
pldm::Request requestMsg; //!< PLDM request message
- bool verbose; //!< verbose tracing flag
+ mutable int currentSendbuffSize; //!< current Send Buffer size
+ bool verbose; //!< verbose tracing flag
/** @brief Sends the PLDM request message on the socket
*
@@ -170,6 +176,24 @@
{
pldm::utils::printBuffer(pldm::utils::Tx, requestMsg);
}
+ if (currentSendbuffSize >= 0 &&
+ (size_t)currentSendbuffSize < requestMsg.size())
+ {
+ int oldSendbuffSize = currentSendbuffSize;
+ currentSendbuffSize = requestMsg.size();
+ int res =
+ setsockopt(fd, SOL_SOCKET, SO_SNDBUF, ¤tSendbuffSize,
+ sizeof(currentSendbuffSize));
+ if (res == -1)
+ {
+ std::cerr
+ << "Requester : Failed to set the new send buffer size [bytes] : "
+ << currentSendbuffSize
+ << " from current size [bytes]: " << oldSendbuffSize
+ << " , Error : " << strerror(errno) << std::endl;
+ return PLDM_ERROR;
+ }
+ }
auto rc = pldm_send(eid, fd, requestMsg.data(), requestMsg.size());
if (rc < 0)
{
diff --git a/requester/test/handler_test.cpp b/requester/test/handler_test.cpp
index 144e5f5..068aff0 100644
--- a/requester/test/handler_test.cpp
+++ b/requester/test/handler_test.cpp
@@ -74,8 +74,8 @@
TEST_F(HandlerTest, singleRequestResponseScenario)
{
- Handler<NiceMock<MockRequest>> reqHandler(fd, event, dbusImplReq, false,
- seconds(1), 2, milliseconds(100));
+ Handler<NiceMock<MockRequest>> reqHandler(
+ fd, event, dbusImplReq, false, 90000, seconds(1), 2, milliseconds(100));
pldm::Request request{};
auto instanceId = dbusImplReq.getInstanceId(eid);
auto rc = reqHandler.registerRequest(
@@ -96,8 +96,8 @@
TEST_F(HandlerTest, singleRequestInstanceIdTimerExpired)
{
- Handler<NiceMock<MockRequest>> reqHandler(fd, event, dbusImplReq, false,
- seconds(1), 2, milliseconds(100));
+ Handler<NiceMock<MockRequest>> reqHandler(
+ fd, event, dbusImplReq, false, 90000, seconds(1), 2, milliseconds(100));
pldm::Request request{};
auto instanceId = dbusImplReq.getInstanceId(eid);
auto rc = reqHandler.registerRequest(
@@ -116,8 +116,8 @@
TEST_F(HandlerTest, multipleRequestResponseScenario)
{
- Handler<NiceMock<MockRequest>> reqHandler(fd, event, dbusImplReq, false,
- seconds(2), 2, milliseconds(100));
+ Handler<NiceMock<MockRequest>> reqHandler(
+ fd, event, dbusImplReq, false, 90000, seconds(2), 2, milliseconds(100));
pldm::Request request{};
auto instanceId = dbusImplReq.getInstanceId(eid);
auto rc = reqHandler.registerRequest(
@@ -150,4 +150,4 @@
EXPECT_EQ(validResponse, true);
EXPECT_EQ(callbackCount, 2);
EXPECT_EQ(instanceId, dbusImplReq.getInstanceId(eid));
-}
\ No newline at end of file
+}
diff --git a/requester/test/mock_request.hpp b/requester/test/mock_request.hpp
index 355609d..7e6fc41 100644
--- a/requester/test/mock_request.hpp
+++ b/requester/test/mock_request.hpp
@@ -16,7 +16,8 @@
public:
MockRequest(int /*fd*/, mctp_eid_t /*eid*/, sdeventplus::Event& event,
pldm::Request&& /*requestMsg*/, uint8_t numRetries,
- std::chrono::milliseconds responseTimeOut, bool /*verbose*/) :
+ std::chrono::milliseconds responseTimeOut,
+ int /*currentSendbuffSize*/, bool /*verbose*/) :
RequestRetryTimer(event, numRetries, responseTimeOut)
{}
@@ -25,4 +26,4 @@
} // namespace requester
-} // namespace pldm
\ No newline at end of file
+} // namespace pldm
diff --git a/requester/test/request_test.cpp b/requester/test/request_test.cpp
index 5239c12..234ff32 100644
--- a/requester/test/request_test.cpp
+++ b/requester/test/request_test.cpp
@@ -49,7 +49,7 @@
TEST_F(RequestIntfTest, 0Retries100msTimeout)
{
MockRequest request(fd, eid, event, std::move(requestMsg), 0,
- milliseconds(100), false);
+ milliseconds(100), 90000, false);
EXPECT_CALL(request, send())
.Times(Exactly(1))
.WillOnce(Return(PLDM_SUCCESS));
@@ -60,7 +60,7 @@
TEST_F(RequestIntfTest, 2Retries100msTimeout)
{
MockRequest request(fd, eid, event, std::move(requestMsg), 2,
- milliseconds(100), false);
+ milliseconds(100), 90000, false);
// send() is called a total of 3 times, the original plus two retries
EXPECT_CALL(request, send()).Times(3).WillRepeatedly(Return(PLDM_SUCCESS));
auto rc = request.start();
@@ -71,7 +71,7 @@
TEST_F(RequestIntfTest, 9Retries100msTimeoutRequestStoppedAfter1sec)
{
MockRequest request(fd, eid, event, std::move(requestMsg), 9,
- milliseconds(100), false);
+ milliseconds(100), 90000, false);
// send() will be called a total of 10 times, the original plus 9 retries.
// In a ideal scenario send() would have been called 10 times in 1 sec (when
// the timer is stopped) with a timeout of 100ms. Because there are delays
@@ -94,7 +94,7 @@
TEST_F(RequestIntfTest, 2Retries100msTimeoutsendReturnsError)
{
MockRequest request(fd, eid, event, std::move(requestMsg), 2,
- milliseconds(100), false);
+ milliseconds(100), 90000, false);
EXPECT_CALL(request, send()).Times(Exactly(1)).WillOnce(Return(PLDM_ERROR));
auto rc = request.start();
EXPECT_EQ(rc, PLDM_ERROR);