summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/openpower-pels/host_notifier.cpp28
-rw-r--r--extensions/openpower-pels/host_notifier.hpp5
-rw-r--r--test/openpower-pels/host_notifier_test.cpp124
-rw-r--r--test/openpower-pels/pel_utils.hpp4
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());
OpenPOWER on IntegriCloud