NVMeContext: Improve encapsulation of state
Consolidate NVMe MI MCTP message exchange and data parsing in the
NVMeContext implementation, and prevent NVMeSensorMain reaching into
internal details of NVMeContext when adding new sensors.
Previously message data parsing was intermixed with the MCTP message
handler implementation. Instead, make the MCTP message handler simply
dispatch the message buffer to the appropriate context instance.
Refactoring the code in this way makes it easier to later extract a base
class from the NVMeContext implementation.
Change-Id: I77bdfb703fd3da43186994d7b306076bd092afcf
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/include/NVMeContext.hpp b/include/NVMeContext.hpp
index f2d804a..7f24e17 100644
--- a/include/NVMeContext.hpp
+++ b/include/NVMeContext.hpp
@@ -8,20 +8,27 @@
#include <memory>
-struct NVMeContext : std::enable_shared_from_this<NVMeContext>
+class NVMeContext : public std::enable_shared_from_this<NVMeContext>
{
+ public:
NVMeContext(boost::asio::io_service& io, int rootBus);
virtual ~NVMeContext();
- void pollNVMeDevices();
- void close();
+ void addSensor(std::shared_ptr<NVMeSensor> sensor);
+ virtual void pollNVMeDevices();
+ virtual void close();
+ virtual void readAndProcessNVMeSensor();
+ virtual void processResponse(void* msg, size_t len);
+ private:
boost::asio::deadline_timer scanTimer;
int rootBus; // Root bus for this drive
boost::asio::deadline_timer mctpResponseTimer;
boost::asio::ip::tcp::socket nvmeSlaveSocket;
std::list<std::shared_ptr<NVMeSensor>> sensors; // used as a poll queue
+
+ void readResponse();
};
using NVMEMap = boost::container::flat_map<int, std::shared_ptr<NVMeContext>>;
diff --git a/src/NVMeContext.cpp b/src/NVMeContext.cpp
index c421d1f..36be841 100644
--- a/src/NVMeContext.cpp
+++ b/src/NVMeContext.cpp
@@ -107,6 +107,27 @@
} // namespace nvmeMCTP
+static void rxMessage(uint8_t eid, void*, void* msg, size_t len)
+{
+ int inFd = mctp_smbus_get_in_fd(nvmeMCTP::smbus);
+ int rootBus = nvmeMCTP::getRootBus(inFd);
+
+ NVMEMap& nvmeMap = getNVMEMap();
+ auto findMap = nvmeMap.find(rootBus);
+ if (findMap == nvmeMap.end())
+ {
+ std::cerr << "Unable to lookup root bus " << rootBus << "\n";
+ return;
+ }
+
+ if (debug)
+ {
+ std::cout << "Eid from the received messaged: " << eid << "\n";
+ }
+
+ findMap->second->processResponse(msg, len);
+}
+
static int verifyIntegrity(uint8_t* msg, size_t len)
{
uint32_t msgIntegrity = {0};
@@ -143,23 +164,11 @@
return reading;
}
-static void rxMessage(uint8_t eid, void*, void* msg, size_t len)
+void NVMeContext::processResponse(void* msg, size_t len)
{
struct nvme_mi_msg_response_header header
{};
- int inFd = mctp_smbus_get_in_fd(nvmeMCTP::smbus);
- int rootBus = nvmeMCTP::getRootBus(inFd);
-
- NVMEMap& nvmeMap = getNVMEMap();
- auto findMap = nvmeMap.find(rootBus);
- if (findMap == nvmeMap.end())
- {
- std::cerr << "Unable to lookup root bus " << rootBus << "\n";
- return;
- }
- std::shared_ptr<NVMeContext>& self = findMap->second;
-
if (msg == nullptr)
{
std::cerr << "Bad message received\n";
@@ -172,11 +181,6 @@
return;
}
- if (debug)
- {
- std::cout << "Eid from the received messaged: " << eid << "\n";
- }
-
uint8_t* messageData = static_cast<uint8_t*>(msg);
if ((*messageData & NVME_MI_MESSAGE_TYPE_MASK) != NVME_MI_MESSAGE_TYPE)
@@ -229,7 +233,7 @@
return;
}
- std::shared_ptr<NVMeSensor> sensorInfo = self->sensors.front();
+ std::shared_ptr<NVMeSensor> sensorInfo = sensors.front();
if (debug)
{
std::cout << "Temperature Reading: "
@@ -254,10 +258,10 @@
}
// move to back of scan queue
- self->sensors.pop_front();
- self->sensors.emplace_back(sensorInfo);
+ sensors.pop_front();
+ sensors.emplace_back(sensorInfo);
- self->mctpResponseTimer.cancel();
+ mctpResponseTimer.cancel();
}
static int nvmeMessageTransmit(mctp& mctp, nvme_mi_msg_request& req)
@@ -310,26 +314,24 @@
return mctp_message_tx(&mctp, 0, messageBuf.data(), msgSize);
}
-static void readResponse(const std::shared_ptr<NVMeContext>& nvmeDevice)
+void NVMeContext::readResponse()
{
- nvmeDevice->nvmeSlaveSocket.async_wait(
+ nvmeSlaveSocket.async_wait(
boost::asio::ip::tcp::socket::wait_error,
- [nvmeDevice](const boost::system::error_code errorCode) {
+ [this](const boost::system::error_code errorCode) {
if (errorCode)
{
return;
}
- mctp_smbus_set_in_fd(nvmeMCTP::smbus,
- nvmeMCTP::getInFd(nvmeDevice->rootBus));
+ mctp_smbus_set_in_fd(nvmeMCTP::smbus, nvmeMCTP::getInFd(rootBus));
// through libmctp this will invoke rxMessage
mctp_smbus_read(nvmeMCTP::smbus);
});
}
-static void
- readAndProcessNVMeSensor(const std::shared_ptr<NVMeContext>& nvmeDevice)
+void NVMeContext::readAndProcessNVMeSensor()
{
struct nvme_mi_msg_request requestMsg = {};
requestMsg.header.opcode = NVME_MI_OPCODE_HEALTH_STATUS_POLL;
@@ -338,19 +340,19 @@
int mctpResponseTimeout = 1;
- if (nvmeDevice->sensors.empty())
+ if (sensors.empty())
{
return;
}
- std::shared_ptr<NVMeSensor>& sensor = nvmeDevice->sensors.front();
+ std::shared_ptr<NVMeSensor>& sensor = sensors.front();
// setup the timeout timer
- nvmeDevice->mctpResponseTimer.expires_from_now(
+ mctpResponseTimer.expires_from_now(
boost::posix_time::seconds(mctpResponseTimeout));
- nvmeDevice->mctpResponseTimer.async_wait(
- [sensor, nvmeDevice](const boost::system::error_code errorCode) {
+ mctpResponseTimer.async_wait(
+ [sensor, this](const boost::system::error_code errorCode) {
if (errorCode)
{
// timer cancelled successfully
@@ -360,18 +362,18 @@
sensor->incrementError();
// cycle it back
- nvmeDevice->sensors.pop_front();
- nvmeDevice->sensors.emplace_back(sensor);
+ sensors.pop_front();
+ sensors.emplace_back(sensor);
- nvmeDevice->nvmeSlaveSocket.cancel();
+ nvmeSlaveSocket.cancel();
});
- readResponse(nvmeDevice);
+ readResponse();
if (debug)
{
std::cout << "Sending message to read data from Drive on bus: "
- << sensor->bus << " , rootBus: " << nvmeDevice->rootBus
+ << sensor->bus << " , rootBus: " << rootBus
<< " device: " << sensor->name << "\n";
}
@@ -407,7 +409,7 @@
}
else
{
- readAndProcessNVMeSensor(self);
+ self->readAndProcessNVMeSensor();
}
self->pollNVMeDevices();
@@ -422,6 +424,11 @@
nvmeMCTP::closeInFd(rootBus);
}
+void NVMeContext::addSensor(std::shared_ptr<NVMeSensor> sensor)
+{
+ sensors.emplace_back(sensor);
+}
+
NVMeContext::~NVMeContext()
{
close();
diff --git a/src/NVMeSensorMain.cpp b/src/NVMeSensorMain.cpp
index 4c6804e..d744ece 100644
--- a/src/NVMeSensorMain.cpp
+++ b/src/NVMeSensorMain.cpp
@@ -136,7 +136,7 @@
objectServer, io, dbusConnection, sensorName,
std::move(sensorThresholds), interfacePath, busNumber);
- context->sensors.emplace_back(sensorPtr);
+ context->addSensor(sensorPtr);
}
for (const auto& [_, context] : nvmeDeviceMap)
{