diff options
-rw-r--r-- | extensions/openpower-pels/host_notifier.cpp | 28 | ||||
-rw-r--r-- | extensions/openpower-pels/host_notifier.hpp | 5 | ||||
-rw-r--r-- | test/openpower-pels/host_notifier_test.cpp | 124 | ||||
-rw-r--r-- | test/openpower-pels/pel_utils.hpp | 4 |
4 files changed, 155 insertions, 6 deletions
diff --git a/extensions/openpower-pels/host_notifier.cpp b/extensions/openpower-pels/host_notifier.cpp index ec5db41..2956b66 100644 --- a/extensions/openpower-pels/host_notifier.cpp +++ b/extensions/openpower-pels/host_notifier.cpp @@ -76,6 +76,34 @@ bool HostNotifier::addPELToQueue(const PEL& pel) bool HostNotifier::enqueueRequired(uint32_t id) const { bool required = true; + Repository::LogID i{Repository::LogID::Pel{id}}; + + if (auto attributes = _repo.getPELAttributes(i); attributes) + { + auto a = attributes.value().get(); + + if ((a.hostState == TransmissionState::acked) || + (a.hostState == TransmissionState::badPEL)) + { + required = false; + } + else if (a.actionFlags.test(hiddenFlagBit) && + (a.hmcState == TransmissionState::acked)) + { + required = false; + } + else if (a.actionFlags.test(dontReportToHostFlagBit)) + { + required = false; + } + } + else + { + using namespace phosphor::logging; + log<level::ERR>("Host Enqueue: Unable to find PEL ID in repository", + entry("PEL_ID=0x%X", id)); + required = false; + } return required; } diff --git a/extensions/openpower-pels/host_notifier.hpp b/extensions/openpower-pels/host_notifier.hpp index ee1ba0c..19ed64d 100644 --- a/extensions/openpower-pels/host_notifier.hpp +++ b/extensions/openpower-pels/host_notifier.hpp @@ -54,6 +54,11 @@ class HostNotifier * @brief Specifies if the PEL needs to go onto the queue to be * set to the host. * + * Only returns false if: + * - Already acked by the host (or they didn't like it) + * - Hidden and the HMC already got it + * - The 'do not report to host' bit is set + * * @param[in] id - The PEL ID * * @return bool - If enqueue is required diff --git a/test/openpower-pels/host_notifier_test.cpp b/test/openpower-pels/host_notifier_test.cpp index 2d50dcf..2f2e1f0 100644 --- a/test/openpower-pels/host_notifier_test.cpp +++ b/test/openpower-pels/host_notifier_test.cpp @@ -38,6 +38,20 @@ const size_t actionFlags1Offset = 67; class HostNotifierTest : public CleanPELFiles { + public: + HostNotifierTest() + { + auto r = sd_event_default(&event); + EXPECT_TRUE(r >= 0); + } + + ~HostNotifierTest() + { + sd_event_unref(event); + } + + protected: + sd_event* event; }; /** @@ -100,6 +114,112 @@ TEST_F(HostNotifierTest, TestHostStateChange) EXPECT_FALSE(called); } +// Test dealing with how acked PELs are put on the +// notification queue. +TEST_F(HostNotifierTest, TestPolicyAckedPEL) +{ + Repository repo{repoPath}; + MockDataInterface dataIface; + + std::unique_ptr<HostInterface> hostIface = + std::make_unique<MockHostInterface>(event, dataIface); + + HostNotifier notifier{repo, dataIface, std::move(hostIface)}; + + auto pel = makePEL(); + repo.add(pel); + + // This is required + EXPECT_TRUE(notifier.enqueueRequired(pel->id())); + + // Not in the repo + EXPECT_FALSE(notifier.enqueueRequired(42)); + + // Now set this PEL to host acked + repo.setPELHostTransState(pel->id(), TransmissionState::acked); + + // Since it's acked, doesn't need to be enqueued or transmitted + EXPECT_FALSE(notifier.enqueueRequired(pel->id())); +} + +// Test the 'don't report' PEL flag +TEST_F(HostNotifierTest, TestPolicyDontReport) +{ + Repository repo{repoPath}; + MockDataInterface dataIface; + + std::unique_ptr<HostInterface> hostIface = + std::make_unique<MockHostInterface>(event, dataIface); + + HostNotifier notifier{repo, dataIface, std::move(hostIface)}; + + // dontReportToHostFlagBit + auto pel = makePEL(0x1000); + + // Double check the action flag is still set + std::bitset<16> actionFlags = pel->userHeader().actionFlags(); + EXPECT_TRUE(actionFlags.test(dontReportToHostFlagBit)); + + repo.add(pel); + + // Don't need to send this to the host + EXPECT_FALSE(notifier.enqueueRequired(pel->id())); +} + +// Test that hidden PELs need notification when there +// is no HMC. +TEST_F(HostNotifierTest, TestPolicyHiddenNoHMC) +{ + Repository repo{repoPath}; + MockDataInterface dataIface; + + std::unique_ptr<HostInterface> hostIface = + std::make_unique<MockHostInterface>(event, dataIface); + + HostNotifier notifier{repo, dataIface, std::move(hostIface)}; + + // hiddenFlagBit + auto pel = makePEL(0x4000); + + // Double check the action flag is still set + std::bitset<16> actionFlags = pel->userHeader().actionFlags(); + EXPECT_TRUE(actionFlags.test(hiddenFlagBit)); + + repo.add(pel); + + // Still need to enqueue this + EXPECT_TRUE(notifier.enqueueRequired(pel->id())); +} + +// Don't need to enqueue a hidden log already acked by the HMC +TEST_F(HostNotifierTest, TestPolicyHiddenWithHMCAcked) +{ + Repository repo{repoPath}; + MockDataInterface dataIface; + + std::unique_ptr<HostInterface> hostIface = + std::make_unique<MockHostInterface>(event, dataIface); + + HostNotifier notifier{repo, dataIface, std::move(hostIface)}; + + // hiddenFlagBit + auto pel = makePEL(0x4000); + + // Double check the action flag is still set + std::bitset<16> actionFlags = pel->userHeader().actionFlags(); + EXPECT_TRUE(actionFlags.test(hiddenFlagBit)); + + repo.add(pel); + + // No HMC yet, so required + EXPECT_TRUE(notifier.enqueueRequired(pel->id())); + + repo.setPELHMCTransState(pel->id(), TransmissionState::acked); + + // Not required anymore + EXPECT_FALSE(notifier.enqueueRequired(pel->id())); +} + // Test that PELs are enqueued on startup TEST_F(HostNotifierTest, TestStartup) { @@ -113,10 +233,6 @@ TEST_F(HostNotifierTest, TestStartup) repo.add(pel); } - sd_event* event = nullptr; - auto r = sd_event_default(&event); - ASSERT_TRUE(r >= 0); - std::unique_ptr<HostInterface> hostIface = std::make_unique<MockHostInterface>(event, dataIface); diff --git a/test/openpower-pels/pel_utils.hpp b/test/openpower-pels/pel_utils.hpp index 78c6401..fae62cd 100644 --- a/test/openpower-pels/pel_utils.hpp +++ b/test/openpower-pels/pel_utils.hpp @@ -29,14 +29,14 @@ class CleanLogID : public ::testing::Test class CleanPELFiles : public ::testing::Test { protected: - static void SetUpTestCase() + void SetUp() override { pelIDFile = openpower::pels::getPELIDFile(); repoPath = openpower::pels::getPELRepoPath(); registryPath = openpower::pels::getMessageRegistryPath(); } - static void TearDownTestCase() + void TearDown() override { std::filesystem::remove_all( std::filesystem::path{pelIDFile}.parent_path()); |