Add dictionary class to hold resource dictionaries
Google-Bug-Id: 322198971
Change-Id: I4c931ed1317d5674a330f400b706af9281229b20
Signed-off-by: Harsh Tyagi <harshtya@google.com>
diff --git a/meson.build b/meson.build
index ce77f2a..1505dcd 100644
--- a/meson.build
+++ b/meson.build
@@ -13,6 +13,7 @@
'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',
+ 'util/state_machine/discovery/rde/dictionary.cpp',
]
all_sources = ['rded.cpp'] + lib_sources
diff --git a/tests/discovery/rde/dictionary_test.cpp b/tests/discovery/rde/dictionary_test.cpp
new file mode 100644
index 0000000..824169d
--- /dev/null
+++ b/tests/discovery/rde/dictionary_test.cpp
@@ -0,0 +1,80 @@
+#include "util/state_machine/discovery/rde/dictionary.hpp"
+
+#include <stdplus/print.hpp>
+
+#include <memory>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using ::testing::_;
+using ::testing::Return;
+
+class DictionaryTest : public ::testing::Test
+{
+ protected:
+ uint32_t resourceIdTest = 0x00000;
+ std::unique_ptr<Dictionary> dictionary =
+ std::make_unique<Dictionary>(resourceIdTest);
+};
+
+TEST_F(DictionaryTest, GetDictionaryBytesSuccess)
+{
+ std::vector<uint8_t> payloadPart1 = {0x01, 0x02, 0x03};
+ std::vector<uint8_t> payloadPart2 = {0x04, 0x05};
+ std::vector<uint8_t> payloadPart3 = {0x06, 0x07, 0x08, 0x09};
+
+ std::vector<uint8_t> expectedDictionary = {0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09};
+ OperationStatus status = dictionary->addToDictionaryBytes(
+ std::span<const uint8_t>(payloadPart1.data(), payloadPart1.size()),
+ false);
+ EXPECT_EQ(OperationStatus::Success, status);
+
+ status = dictionary->addToDictionaryBytes(
+ std::span<const uint8_t>(payloadPart2.data(), payloadPart2.size()),
+ false);
+ EXPECT_EQ(OperationStatus::Success, status);
+
+ dictionary->addToDictionaryBytes(
+ std::span<const uint8_t>(payloadPart3.data(), payloadPart3.size()),
+ false);
+ EXPECT_EQ(OperationStatus::Success, status);
+
+ std::span<const uint8_t> resultDictionary =
+ dictionary->getDictionaryBytes();
+ EXPECT_EQ(expectedDictionary, std::vector<uint8_t>(resultDictionary.begin(),
+ resultDictionary.end()));
+}
+
+TEST_F(DictionaryTest, ChecksumFailure)
+{
+ std::vector<uint8_t> payloadPart1 = {0x01, 0x02, 0x03};
+ std::vector<uint8_t> payloadPart2 = {0x04, 0x05, 0x04, 0x05};
+
+ OperationStatus status = dictionary->addToDictionaryBytes(
+ std::span<const uint8_t>(payloadPart1.data(), payloadPart1.size()),
+ false);
+ EXPECT_EQ(OperationStatus::Success, status);
+
+ status = dictionary->addToDictionaryBytes(
+ std::span<const uint8_t>(payloadPart2.data(), payloadPart2.size()),
+ true);
+ EXPECT_EQ(OperationStatus::ChecksumFailure, status);
+}
+
+TEST_F(DictionaryTest, ChecksumSuccess)
+{
+ std::vector<uint8_t> payload = {0x01, 0x02, 0x03, 0x04, 0x05};
+ std::vector<uint8_t> payloadWithChecksum = {0xf4, 0x99, 0x0b, 0x47};
+
+ OperationStatus status = dictionary->addToDictionaryBytes(
+ std::span<const uint8_t>(payload.data(), payload.size()), false);
+ EXPECT_EQ(OperationStatus::Success, status);
+
+ status = dictionary->addToDictionaryBytes(
+ std::span<const uint8_t>(payloadWithChecksum.data(),
+ payloadWithChecksum.size()),
+ true);
+ EXPECT_EQ(OperationStatus::Success, status);
+}
diff --git a/tests/meson.build b/tests/meson.build
index 969f642..2686806 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -22,7 +22,8 @@
tests = [
'mctp_setup_test',
'discovery/base/base_disc_state_machine_test',
- 'discovery/rde/rde_disc_state_machine_test'
+ 'discovery/rde/rde_disc_state_machine_test',
+ 'discovery/rde/dictionary_test',
]
foreach t : tests
diff --git a/util/state_machine/discovery/rde/dictionary.cpp b/util/state_machine/discovery/rde/dictionary.cpp
new file mode 100644
index 0000000..809f4dc
--- /dev/null
+++ b/util/state_machine/discovery/rde/dictionary.cpp
@@ -0,0 +1,119 @@
+#include "dictionary.hpp"
+
+#include "libpldm/utils.h"
+
+#include <stdplus/print.hpp>
+
+Dictionary::Dictionary(uint32_t resourceId) : resourceId(resourceId)
+{}
+
+std::span<const uint8_t> Dictionary::getDictionaryBytes()
+{
+ return dictionary;
+}
+
+OperationStatus
+ Dictionary::addToDictionaryBytes(std::span<const uint8_t> payload,
+ bool hasChecksum)
+{
+ this->dictionary.insert(this->dictionary.end(), payload.begin(),
+ payload.end());
+
+ if (hasChecksum)
+ {
+ OperationStatus checksumVerification = verifyChecksum();
+
+ // remove the checksum bytes from the dictionary
+ this->dictionary.erase(this->dictionary.begin() +
+ (this->dictionary.size() - 4),
+ this->dictionary.end());
+
+ if (checksumVerification == OperationStatus::ChecksumFailure)
+ {
+ return checksumVerification;
+ }
+ }
+ return OperationStatus::Success;
+}
+
+OperationStatus Dictionary::verifyChecksum()
+{
+ uint32_t payloadLength = this->dictionary.size();
+ auto calculatedChecksum =
+ crc32(&(this->dictionary.front()), payloadLength - 4);
+ uint8_t byte0 = this->dictionary[payloadLength - 4];
+ uint8_t byte1 = this->dictionary[payloadLength - 3];
+ uint8_t byte2 = this->dictionary[payloadLength - 2];
+ uint8_t byte3 = this->dictionary[payloadLength - 1];
+
+ uint32_t receivedChecksum =
+ (byte0 | (byte1 << 8) | (byte2 << 16) | (byte3 << 24));
+
+ if (calculatedChecksum == receivedChecksum)
+ {
+ if (DEBUG)
+ {
+ stdplus::println(stderr,
+ "Successfully verified checksum in "
+ "dictionary extraction for resource id: {}"
+ " with calculated checksum: {} and "
+ "received checksum: {}",
+ static_cast<uint32_t>(resourceId),
+ static_cast<uint32_t>(calculatedChecksum),
+ static_cast<uint32_t>(receivedChecksum));
+ }
+ return OperationStatus::Success;
+ }
+ stdplus::println(stderr,
+ "Failed to verify checksum in "
+ "dictionary extraction for resource id: {}"
+ " with calculated checksum: {} and "
+ "received checksum: {}",
+ static_cast<uint32_t>(resourceId),
+ static_cast<uint32_t>(calculatedChecksum),
+ static_cast<uint32_t>(receivedChecksum));
+ return OperationStatus::ChecksumFailure;
+}
+
+// Getters and Setters
+
+uint32_t Dictionary::getResourceId() const
+{
+ return this->resourceId;
+}
+
+// Getter for currentSchemaClass
+uint8_t Dictionary::getCurrentSchemaClass() const
+{
+ return this->currentSchemaClass;
+}
+
+// Setter for currentSchemaClass
+void Dictionary::setCurrentSchemaClass(uint8_t newSchemaClass)
+{
+ this->currentSchemaClass = newSchemaClass;
+}
+
+// Getter for currentTransferHandle
+uint32_t Dictionary::getCurrentTransferHandle() const
+{
+ return this->currentTransferHandle;
+}
+
+// Setter for currentTransferHandle
+void Dictionary::setCurrentTransferHandle(uint32_t newTransferHandle)
+{
+ this->currentTransferHandle = newTransferHandle;
+}
+
+// Getter for currentTransferOperation
+uint8_t Dictionary::getCurrentTransferOperation() const
+{
+ return this->currentTransferOperation;
+}
+
+// Setter for currentTransferOperation
+void Dictionary::setCurrentTransferOperation(uint8_t newTransferOperation)
+{
+ this->currentTransferOperation = newTransferOperation;
+}
diff --git a/util/state_machine/discovery/rde/dictionary.hpp b/util/state_machine/discovery/rde/dictionary.hpp
new file mode 100644
index 0000000..13b248c
--- /dev/null
+++ b/util/state_machine/discovery/rde/dictionary.hpp
@@ -0,0 +1,51 @@
+#include "common.hpp"
+#include "state_machine_factory.hpp"
+
+#include <cstdint>
+#include <optional>
+#include <span>
+#include <vector>
+
+class Dictionary
+{
+ public:
+ Dictionary(uint32_t resourceId);
+
+ /**
+ * @brief Adds bytes to the end of the vector for the dictionary
+ *
+ * @param[in] payload - Bytes to be added
+ * @param[in] payloadLength - Size of the bytes to be added
+ * @param[in] hasChecksum - Contains checksum or not (last 4 bytes are
+ * checksum if it is true)
+ *
+ * @return OperationStatus
+ */
+ OperationStatus addToDictionaryBytes(std::span<const uint8_t> payload,
+ bool hasChecksum);
+
+ // Getters and Setters
+ uint32_t getResourceId() const;
+ std::span<const uint8_t> getDictionaryBytes();
+
+ uint8_t getCurrentSchemaClass() const;
+ void setCurrentSchemaClass(uint8_t newSchemaClass);
+
+ uint32_t getCurrentTransferHandle() const;
+ void setCurrentTransferHandle(uint32_t newTransferHandle);
+
+ uint8_t getCurrentTransferOperation() const;
+ void setCurrentTransferOperation(uint8_t newTransferOperation);
+
+ private:
+ uint32_t resourceId;
+ uint8_t currentSchemaClass;
+ uint32_t currentTransferHandle;
+ uint8_t currentTransferOperation;
+ std::vector<uint8_t> dictionary;
+
+ /**
+ * @brief Verifies checksum of the dictionary
+ */
+ OperationStatus verifyChecksum();
+};
diff --git a/util/state_machine/state_machine_factory.hpp b/util/state_machine/state_machine_factory.hpp
index d00a065..a6e5f77 100644
--- a/util/state_machine/state_machine_factory.hpp
+++ b/util/state_machine/state_machine_factory.hpp
@@ -33,6 +33,7 @@
OperationFailure,
StateMachineInitializationError,
PartialFailure,
+ ChecksumFailure,
};
/**