Specify PEL callout priority and sort callouts.
Allow the priority to be passed in at creation time by calling the
CALLOUT_PRIORITY keyword. When creating a PEL, callouts will always
be sorted by priority instead of creation time, the order is as follows:
H,M,A,B,C,L.
Signed-off-by: Miguel Gomez <mgomez@mx1.ibm.com>
Change-Id: I84345aaf3fad7b2e4958b698ab761966f499986b
diff --git a/extensions/openpower-pels/callouts.cpp b/extensions/openpower-pels/callouts.cpp
index 2440621..885dda5 100644
--- a/extensions/openpower-pels/callouts.cpp
+++ b/extensions/openpower-pels/callouts.cpp
@@ -61,7 +61,19 @@
using namespace phosphor::logging;
log<level::INFO>("Dropping PEL callout because at max");
}
+
+ // Mapping including the 3 Medium levels as A,B and C
+ const std::map<std::uint8_t, int> priorities = {
+ {'H', 10}, {'M', 9}, {'A', 8}, {'B', 7}, {'C', 6}, {'L', 5}};
+
+ auto sortPriority = [&priorities](const std::unique_ptr<Callout>& p1,
+ const std::unique_ptr<Callout>& p2) {
+ return priorities.at(p1->priority()) > priorities.at(p2->priority());
+ };
+
+ std::sort(_callouts.begin(), _callouts.end(), sortPriority);
}
+
} // namespace src
} // namespace pels
-} // namespace openpower
+} // namespace openpower
\ No newline at end of file
diff --git a/extensions/openpower-pels/src.cpp b/extensions/openpower-pels/src.cpp
index 3fd62e8..643adec 100644
--- a/extensions/openpower-pels/src.cpp
+++ b/extensions/openpower-pels/src.cpp
@@ -748,7 +748,19 @@
getRegistryCallouts(regEntry, additionalData, dataIface);
auto item = additionalData.getValue("CALLOUT_INVENTORY_PATH");
+ auto priority = additionalData.getValue("CALLOUT_PRIORITY");
+ std::optional<CalloutPriority> calloutPriority;
+
+ // Only H, M or L priority values.
+ if (priority && !(*priority).empty())
+ {
+ uint8_t p = (*priority)[0];
+ if (p == 'H' || p == 'M' || p == 'L')
+ {
+ calloutPriority = static_cast<CalloutPriority>(p);
+ }
+ }
// If the first registry callout says to use the passed in inventory
// path to get the location code for a symbolic FRU callout with a
// trusted location code, then do not add the inventory path as a
@@ -759,7 +771,7 @@
if (item && !useInvForSymbolicFRULocCode)
{
- addInventoryCallout(*item, std::nullopt, std::nullopt, dataIface);
+ addInventoryCallout(*item, calloutPriority, std::nullopt, dataIface);
}
addDevicePathCallouts(additionalData, dataIface);
diff --git a/test/openpower-pels/src_callouts_test.cpp b/test/openpower-pels/src_callouts_test.cpp
index b1fe9c4..69c26b8 100644
--- a/test/openpower-pels/src_callouts_test.cpp
+++ b/test/openpower-pels/src_callouts_test.cpp
@@ -120,3 +120,83 @@
EXPECT_EQ(callouts.callouts().size(), maxNumberOfCallouts);
}
+
+TEST(CalloutsTest, TestSortCallouts)
+{
+ Callouts callouts;
+
+ // Add callouts with different priorities to test sorting in descending
+ // order
+
+ auto c0 = std::make_unique<Callout>(CalloutPriority::high, "U1-P1",
+ "1234567", "ABC", "123456789ABC");
+
+ callouts.addCallout(std::move(c0));
+
+ auto c1 = std::make_unique<Callout>(CalloutPriority::medium, "U1-P2",
+ "1234567", "ABCD", "123456789ABC");
+
+ callouts.addCallout(std::move(c1));
+
+ auto c2 = std::make_unique<Callout>(CalloutPriority::low, "U1-P3",
+ "1234567", "ABCDE", "123456789ABC");
+
+ callouts.addCallout(std::move(c2));
+
+ auto c3 = std::make_unique<Callout>(CalloutPriority::high, "U1-P4",
+ "1234567", "ABCDE1", "123456789ABC");
+
+ callouts.addCallout(std::move(c3));
+
+ auto c4 = std::make_unique<Callout>(CalloutPriority::high, "U1-P5",
+ "1234567", "ABCDE2", "123456789ABC");
+
+ callouts.addCallout(std::move(c4));
+
+ auto c5 = std::make_unique<Callout>(CalloutPriority::low, "U1-P6",
+ "1234567", "ABCDE2", "123456789ABC");
+
+ callouts.addCallout(std::move(c5));
+
+ auto c6 = std::make_unique<Callout>(CalloutPriority::medium, "U1-P7",
+ "1234567", "ABCD2", "123456789ABC");
+
+ callouts.addCallout(std::move(c6));
+
+ auto c7 = std::make_unique<Callout>(CalloutPriority::mediumGroupA, "U1-P8",
+ "1234567", "ABCDE3", "123456789ABC");
+
+ callouts.addCallout(std::move(c7));
+
+ auto c8 = std::make_unique<Callout>(CalloutPriority::mediumGroupC, "U1-P9",
+ "1234567", "ABCDE4", "123456789ABC");
+
+ callouts.addCallout(std::move(c8));
+
+ auto c9 = std::make_unique<Callout>(CalloutPriority::low, "U1-P10",
+ "1234567", "ABCDE3", "123456789ABC");
+
+ callouts.addCallout(std::move(c9));
+
+ const auto& calloutObjects = callouts.callouts();
+ EXPECT_EQ(calloutObjects[0]->locationCode(), "U1-P1");
+ EXPECT_EQ(calloutObjects[0]->priority(), 'H');
+ EXPECT_EQ(calloutObjects[1]->locationCode(), "U1-P4");
+ EXPECT_EQ(calloutObjects[1]->priority(), 'H');
+ EXPECT_EQ(calloutObjects[2]->locationCode(), "U1-P5");
+ EXPECT_EQ(calloutObjects[2]->priority(), 'H');
+ EXPECT_EQ(calloutObjects[3]->locationCode(), "U1-P2");
+ EXPECT_EQ(calloutObjects[3]->priority(), 'M');
+ EXPECT_EQ(calloutObjects[4]->locationCode(), "U1-P7");
+ EXPECT_EQ(calloutObjects[4]->priority(), 'M');
+ EXPECT_EQ(calloutObjects[5]->locationCode(), "U1-P8");
+ EXPECT_EQ(calloutObjects[5]->priority(), 'A');
+ EXPECT_EQ(calloutObjects[6]->locationCode(), "U1-P9");
+ EXPECT_EQ(calloutObjects[6]->priority(), 'C');
+ EXPECT_EQ(calloutObjects[7]->locationCode(), "U1-P3");
+ EXPECT_EQ(calloutObjects[7]->priority(), 'L');
+ EXPECT_EQ(calloutObjects[8]->locationCode(), "U1-P6");
+ EXPECT_EQ(calloutObjects[8]->priority(), 'L');
+ EXPECT_EQ(calloutObjects[9]->locationCode(), "U1-P10");
+ EXPECT_EQ(calloutObjects[9]->priority(), 'L');
+}
diff --git a/test/openpower-pels/src_test.cpp b/test/openpower-pels/src_test.cpp
index 1f0db2a..671bd54 100644
--- a/test/openpower-pels/src_test.cpp
+++ b/test/openpower-pels/src_test.cpp
@@ -1265,3 +1265,39 @@
"Failed extracting callout data from JSON: Invalid "
"priority 'X' found in JSON callout");
}
+
+// Test that an inventory path callout can have
+// a different priority than H.
+TEST_F(SRCTest, InventoryCalloutTestPriority)
+{
+ message::Entry entry;
+ entry.src.type = 0xBD;
+ entry.src.reasonCode = 0xABCD;
+ entry.subsystem = 0x42;
+ entry.src.powerFault = false;
+
+ std::vector<std::string> adData{"CALLOUT_INVENTORY_PATH=motherboard",
+ "CALLOUT_PRIORITY=M"};
+ AdditionalData ad{adData};
+ NiceMock<MockDataInterface> dataIface;
+
+ EXPECT_CALL(dataIface, getLocationCode("motherboard"))
+ .WillOnce(Return("UTMS-P1"));
+
+ EXPECT_CALL(dataIface, getHWCalloutFields("motherboard", _, _, _))
+ .Times(1)
+ .WillOnce(DoAll(SetArgReferee<1>("1234567"), SetArgReferee<2>("CCCC"),
+ SetArgReferee<3>("123456789ABC")));
+
+ SRC src{entry, ad, dataIface};
+ EXPECT_TRUE(src.valid());
+
+ ASSERT_TRUE(src.callouts());
+
+ EXPECT_EQ(src.callouts()->callouts().size(), 1);
+
+ auto& callout = src.callouts()->callouts().front();
+
+ EXPECT_EQ(callout->locationCode(), "UTMS-P1");
+ EXPECT_EQ(callout->priority(), 'M');
+}
\ No newline at end of file