summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac7
-rw-r--r--extensions/openpower-pels/log_id.cpp97
-rw-r--r--extensions/openpower-pels/log_id.hpp47
-rw-r--r--extensions/openpower-pels/openpower-pels.mk2
-rw-r--r--extensions/openpower-pels/paths.cpp23
-rw-r--r--extensions/openpower-pels/paths.hpp15
-rw-r--r--test/openpower-pels/Makefile.include10
-rw-r--r--test/openpower-pels/log_id_test.cpp42
-rw-r--r--test/openpower-pels/paths.cpp26
9 files changed, 269 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 27175a5..ead0a07 100644
--- a/configure.ac
+++ b/configure.ac
@@ -150,6 +150,13 @@ AC_DEFINE(SYSTEMD_INTERFACE, "org.freedesktop.systemd1.Manager", [systemd interf
AC_ARG_ENABLE([openpower-pel-extension],
AS_HELP_STRING([--enable-openpower-pel-extension], [Create PELs])
)
+
+AC_ARG_VAR(EXTENSION_PERSIST_DIR, [Base directory for extension persistent data])
+AS_IF([test "x$EXTENSION_PERSIST_DIR" == "x"], \
+ [EXTENSION_PERSIST_DIR="/var/lib/phosphor-logging/extensions"])
+AC_DEFINE_UNQUOTED([EXTENSION_PERSIST_DIR], ["$EXTENSION_PERSIST_DIR"], \
+ [Base directory for extension persistent data])
+
AM_CONDITIONAL([ENABLE_PEL_EXTENSION], [test "x$enable_openpower_pel_extension" == "xyes"])
AC_CONFIG_HEADERS([config.h])
diff --git a/extensions/openpower-pels/log_id.cpp b/extensions/openpower-pels/log_id.cpp
new file mode 100644
index 0000000..cbe1247
--- /dev/null
+++ b/extensions/openpower-pels/log_id.cpp
@@ -0,0 +1,97 @@
+#include "log_id.hpp"
+
+#include "paths.hpp"
+
+#include <chrono>
+#include <filesystem>
+#include <fstream>
+#include <phosphor-logging/log.hpp>
+
+namespace openpower
+{
+namespace pels
+{
+
+namespace fs = std::filesystem;
+using namespace phosphor::logging;
+
+constexpr uint32_t startingLogID = 1;
+constexpr uint32_t bmcLogIDPrefix = 0x50000000;
+
+namespace detail
+{
+
+uint32_t addLogIDPrefix(uint32_t id)
+{
+ // If redundant BMCs are ever a thing, may need a different prefix.
+ return (id & 0x00FFFFFF) | bmcLogIDPrefix;
+}
+
+uint32_t getTimeBasedLogID()
+{
+ using namespace std::chrono;
+
+ // Use 3 bytes of the nanosecond count since the epoch.
+ uint32_t id =
+ duration_cast<nanoseconds>(system_clock::now().time_since_epoch())
+ .count();
+
+ return addLogIDPrefix(id);
+}
+
+} // namespace detail
+
+uint32_t generatePELID()
+{
+ // Note: there isn't a need to be thread safe.
+
+ static std::string idFilename;
+ if (idFilename.empty())
+ {
+ idFilename = getPELIDFile();
+ }
+
+ uint32_t id = 0;
+
+ if (!fs::exists(idFilename))
+ {
+ auto path = fs::path(idFilename).parent_path();
+ if (!fs::exists(path))
+ {
+ fs::create_directories(path);
+ }
+
+ id = startingLogID;
+ }
+ else
+ {
+ std::ifstream idFile{idFilename};
+ idFile >> id;
+ if (idFile.fail())
+ {
+ // Just make up an ID
+ log<level::ERR>("Unable to read PEL ID File!");
+ return detail::getTimeBasedLogID();
+ }
+ }
+
+ // Wrapping shouldn't be a problem, but check anyway
+ if (id == 0x00FFFFFF)
+ {
+ id = startingLogID;
+ }
+
+ std::ofstream idFile{idFilename};
+ idFile << (id + 1);
+ if (idFile.fail())
+ {
+ // Just make up an ID so we don't reuse one next time
+ log<level::ERR>("Unable to write PEL ID File!");
+ return detail::getTimeBasedLogID();
+ }
+
+ return detail::addLogIDPrefix(id);
+}
+
+} // namespace pels
+} // namespace openpower
diff --git a/extensions/openpower-pels/log_id.hpp b/extensions/openpower-pels/log_id.hpp
new file mode 100644
index 0000000..21f04eb
--- /dev/null
+++ b/extensions/openpower-pels/log_id.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <cstdint>
+
+namespace openpower
+{
+namespace pels
+{
+
+namespace detail
+{
+
+/**
+ * @brief Adds the 1 byte log creator prefix to the log ID
+ *
+ * @param[in] id - the ID to add it to
+ *
+ * @return - the full log ID
+ */
+uint32_t addLogIDPrefix(uint32_t id);
+
+/**
+ * @brief Generates a PEL ID based on the current time.
+ *
+ * Used for error scenarios where the normal method doesn't
+ * work in order to get a unique ID still.
+ *
+ * @return A unique log ID.
+ */
+uint32_t getTimeBasedLogID();
+
+} // namespace detail
+
+/**
+ * @brief Generates a unique PEL log entry ID every time
+ * it is called.
+ *
+ * This ID is used at offset 0x2C in the Private Header
+ * section of a PEL. For single BMC systems, it must
+ * start with 0x50.
+ *
+ * @return uint32_t - The log ID
+ */
+uint32_t generatePELID();
+
+} // namespace pels
+} // namespace openpower
diff --git a/extensions/openpower-pels/openpower-pels.mk b/extensions/openpower-pels/openpower-pels.mk
index cc933f9..2cc2393 100644
--- a/extensions/openpower-pels/openpower-pels.mk
+++ b/extensions/openpower-pels/openpower-pels.mk
@@ -1,6 +1,8 @@
phosphor_log_manager_SOURCES += \
extensions/openpower-pels/bcd_time.cpp \
extensions/openpower-pels/entry_points.cpp \
+ extensions/openpower-pels/log_id.cpp \
extensions/openpower-pels/manager.cpp \
+ extensions/openpower-pels/paths.cpp \
extensions/openpower-pels/private_header.cpp \
extensions/openpower-pels/user_header.cpp
diff --git a/extensions/openpower-pels/paths.cpp b/extensions/openpower-pels/paths.cpp
new file mode 100644
index 0000000..dab73c9
--- /dev/null
+++ b/extensions/openpower-pels/paths.cpp
@@ -0,0 +1,23 @@
+#include "config.h"
+
+#include "paths.hpp"
+
+#include <filesystem>
+
+namespace openpower
+{
+namespace pels
+{
+
+namespace fs = std::filesystem;
+
+fs::path getPELIDFile()
+{
+ fs::path logIDPath{EXTENSION_PERSIST_DIR};
+ logIDPath /= fs::path{"pels"} / fs::path{"pelID"};
+ return logIDPath;
+}
+
+} // namespace pels
+
+} // namespace openpower
diff --git a/extensions/openpower-pels/paths.hpp b/extensions/openpower-pels/paths.hpp
new file mode 100644
index 0000000..334165c
--- /dev/null
+++ b/extensions/openpower-pels/paths.hpp
@@ -0,0 +1,15 @@
+#pragma once
+#include <filesystem>
+
+namespace openpower
+{
+namespace pels
+{
+
+/**
+ * @brief Returns the path to the PEL ID file
+ */
+std::filesystem::path getPELIDFile();
+
+} // namespace pels
+} // namespace openpower
diff --git a/test/openpower-pels/Makefile.include b/test/openpower-pels/Makefile.include
index f860db2..0e0257c 100644
--- a/test/openpower-pels/Makefile.include
+++ b/test/openpower-pels/Makefile.include
@@ -3,6 +3,7 @@ TESTS += $(check_PROGRAMS)
check_PROGRAMS += \
additional_data_test \
bcd_time_test \
+ log_id_test \
private_header_test \
section_header_test \
stream_test \
@@ -58,3 +59,12 @@ user_header_test_LDADD = \
$(test_ldadd) \
$(pel_objects)
user_header_test_LDFLAGS = $(test_ldflags)
+
+log_id_test_SOURCES = \
+ %reldir%/log_id_test.cpp %reldir%/paths.cpp
+log_id_test_CPPFLAGS = $(test_cppflags)
+log_id_test_CXXFLAGS = $(test_cxxflags)
+log_id_test_LDADD = \
+ $(test_ldadd) \
+ $(top_builddir)/extensions/openpower-pels/log_id.o
+log_id_test_LDFLAGS = $(test_ldflags)
diff --git a/test/openpower-pels/log_id_test.cpp b/test/openpower-pels/log_id_test.cpp
new file mode 100644
index 0000000..e5f2632
--- /dev/null
+++ b/test/openpower-pels/log_id_test.cpp
@@ -0,0 +1,42 @@
+#include "extensions/openpower-pels/log_id.hpp"
+#include "extensions/openpower-pels/paths.hpp"
+
+#include <arpa/inet.h>
+
+#include <filesystem>
+
+#include <gtest/gtest.h>
+
+using namespace openpower::pels;
+namespace fs = std::filesystem;
+
+TEST(LogIdTest, TimeBasedIDTest)
+{
+ uint32_t lastID = 0;
+ for (int i = 0; i < 10; i++)
+ {
+ auto id = detail::getTimeBasedLogID();
+
+ EXPECT_EQ(id & 0xFF000000, 0x50000000);
+ EXPECT_NE(id, lastID);
+ lastID = id;
+ }
+}
+
+TEST(LogIdTest, IDTest)
+{
+ EXPECT_EQ(generatePELID(), 0x50000001);
+ EXPECT_EQ(generatePELID(), 0x50000002);
+ EXPECT_EQ(generatePELID(), 0x50000003);
+ EXPECT_EQ(generatePELID(), 0x50000004);
+ EXPECT_EQ(generatePELID(), 0x50000005);
+ EXPECT_EQ(generatePELID(), 0x50000006);
+
+ auto backingFile = getPELIDFile();
+ fs::remove(backingFile);
+ EXPECT_EQ(generatePELID(), 0x50000001);
+ EXPECT_EQ(generatePELID(), 0x50000002);
+ EXPECT_EQ(generatePELID(), 0x50000003);
+
+ fs::remove_all(fs::path{backingFile}.parent_path());
+}
diff --git a/test/openpower-pels/paths.cpp b/test/openpower-pels/paths.cpp
new file mode 100644
index 0000000..464b92c
--- /dev/null
+++ b/test/openpower-pels/paths.cpp
@@ -0,0 +1,26 @@
+#include "extensions/openpower-pels/paths.hpp"
+
+#include <filesystem>
+
+namespace openpower
+{
+namespace pels
+{
+
+// Use paths that work in unit tests.
+
+std::filesystem::path getPELIDFile()
+{
+ static std::string idFile;
+
+ if (idFile.empty())
+ {
+ char templ[] = "/tmp/logidtestXXXXXX";
+ std::filesystem::path dir = mkdtemp(templ);
+ idFile = dir / "logid";
+ }
+ return idFile;
+}
+
+} // namespace pels
+} // namespace openpower
OpenPOWER on IntegriCloud