]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3278] Added configurable PerfMonMgr singleton
authorThomas Markwalder <tmark@isc.org>
Wed, 20 Mar 2024 14:47:42 +0000 (10:47 -0400)
committerThomas Markwalder <tmark@isc.org>
Tue, 26 Mar 2024 19:33:28 +0000 (19:33 +0000)
load() now creates PerfMonMgr singleton and invokes it's configure() function.

src/hooks/dhcp/perfmon/monitored_duration.*
    DurationKey::getMessageTypeLabel(uint16_t family, uint16_t msg_type)  - new function
    Translates DHCP_NOTYPE/DHCPV6_NOTYPE to "*"

src/hooks/dhcp/perfmon/perfmon_callouts.cc
    Added PerfMonMgr singleton
    int load(LibraryHandle& handle)  - creates singleton and parses configuration

src/hooks/dhcp/perfmon/perfmon_config.cc
 DurationKeyParser::getMessageNameType4(const std::string& name)
 DurationKeyParser::getMessageNameType6(const std::string& name) - map "*" to NOTYPE
     static std::map<std::string, uint16_t> name_type_map = {

src/hooks/dhcp/perfmon/tests/duration_key_parser_unittests.cc
    TEST_F(DurationKeyParserTest, validScenarios4) - verify "*" message type parses

src/hooks/dhcp/perfmon/libloadtests/load_unload_unittests.cc
    Updated to pass in a valid configuration on load test.

src/hooks/dhcp/perfmon/libloadtests/load_unload_unittests.cc
src/hooks/dhcp/perfmon/monitored_duration.cc
src/hooks/dhcp/perfmon/monitored_duration.h
src/hooks/dhcp/perfmon/perfmon_callouts.cc
src/hooks/dhcp/perfmon/perfmon_config.cc
src/hooks/dhcp/perfmon/perfmon_config.h
src/hooks/dhcp/perfmon/tests/duration_key_parser_unittests.cc
src/hooks/dhcp/perfmon/tests/perfmon_mgr_unittests.cc

index 31d8cd28e573854714814147443db252c70e3e73..92792d26a6ded5ed623449cbd6f987e7000e2a77 100644 (file)
@@ -42,16 +42,42 @@ public:
     virtual ~PerfMonLibLoadTest() {
         unloadLibraries();
     }
+
+    /// @brief Creates a valid set configuration parameters valid for the library.
+    virtual isc::data::ElementPtr validConfigParams() {
+        std::string valid_config =
+            R"({
+                    "enable-monitoring" : true,
+                    "interval-width-secs" : 5,
+                    "stats-mgr-reporting"  : true,
+                    "alarm-report-secs" : 600,
+                    "alarms": [{
+                            "duration-key": {
+                                "query-type" : "*",
+                                "response-type" : "*",
+                                "start-event" : "socket-received",
+                                "stop-event" : "buffer-read",
+                                "subnet-id" : 70
+                                },
+                            "enable-alarm" : true,
+                            "high-water-ms" : 500,
+                            "low-water-ms" : 25
+                        }]
+                })";
+
+        // Convert JSON texts to Element map.
+        return (Element::fromJSON(valid_config));
+    }
 };
 
 // Simple V4 test that checks the library can be loaded and unloaded several times.
 TEST_F(PerfMonLibLoadTest, validLoad4) {
-    validDaemonTest("kea-dhcp4");
+    validDaemonTest("kea-dhcp4", AF_INET, valid_params_);
 }
 
 // Simple V6 test that checks the library can be loaded and unloaded several times.
 TEST_F(PerfMonLibLoadTest, validLoad6) {
-    validDaemonTest("kea-dhcp6", AF_INET6);
+    validDaemonTest("kea-dhcp6", AF_INET6, valid_params_);
 }
 
 // Simple test that checks the library cannot by loaded by invalid daemons.
index 230531030973b8209865ba5fc274dee2bc510d4e..d010db106dcd3cc650e792de24d35789cd463e84 100644 (file)
@@ -157,17 +157,21 @@ DurationKey::validateMessagePair(uint16_t family, uint8_t query_type, uint8_t re
 }
 
 std::string
-DurationKey::getLabel() const {
-    std::ostringstream oss;
-    if (family_ == AF_INET) {
-        oss << (query_type_ == DHCP_NOTYPE ? "NONE" : Pkt4::getName(query_type_)) << "-"
-            << (response_type_ == DHCP_NOTYPE ? "NONE" : Pkt4::getName(response_type_));
-    } else {
-        oss << (query_type_ == DHCPV6_NOTYPE ? "NONE" : Pkt6::getName(query_type_)) << "-"
-            << (response_type_ == DHCPV6_NOTYPE ? "NONE" : Pkt6::getName(response_type_));
+DurationKey::getMessageTypeLabel(uint16_t family, uint16_t msg_type) {
+    if (family == AF_INET) {
+        return (msg_type == DHCP_NOTYPE ? "*" : Pkt4::getName(msg_type));
     }
 
-    oss << "." << start_event_label_ << "-" << stop_event_label_
+    return (msg_type == DHCPV6_NOTYPE ? "*" : Pkt6::getName(msg_type));
+}
+
+std::string
+DurationKey::getLabel() const {
+    std::ostringstream oss;
+    oss << getMessageTypeLabel(family_, query_type_)
+       << "-"
+        << getMessageTypeLabel(family_, response_type_)
+        << "." << start_event_label_ << "-" << stop_event_label_
         << "." << subnet_id_;
 
     return (oss.str());
index 59cc304683f4268abca94bdfa40d7bbd8af1fd8a..1ab40bef63c50d3e5d80edf1d390fc08cfc3082e 100644 (file)
@@ -188,6 +188,15 @@ public:
         return (subnet_id_);
     }
 
+    /// @brief Get a label for a family-specific message type (e.g.
+    ///  "DHCPDISCOVER", "SOLICIT")
+    ///
+    /// @param family Protocol family of the key (AF_INET or AF_INET6)
+    /// @param msg_type numeric message type to translate
+    ///
+    /// @return Text label, for values of DHCP_NOTYPE or DHCPV6_NOTYPE: "*"
+    static std::string getMessageTypeLabel(uint16_t family, uint16_t msg_type);
+
     /// @brief Get a composite label of the member values with text message types.
     ///
     /// The format of the string:
@@ -201,7 +210,7 @@ public:
     ///
     ///     or
     ///
-    ///     "DHCPV6_SOLICIT-DHCPV6_ADVERTISE.socket_received.buffer_read.12"
+    ///     "SOLICIT-ADVERTISE.socket_received.buffer_read.12"
     ///
     /// @endcode
     ///
index 959fd3de2a55be128e0deed0446ec47b6f6d1ca7..49c2452d4e8c55996e7c1e771c4a8c8f6c4cb27e 100644 (file)
 #include <config.h>
 
 #include <perfmon_log.h>
+#include <perfmon_mgr.h>
 #include <cc/command_interpreter.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <hooks/hooks.h>
 #include <process/daemon.h>
 
+namespace isc {
+namespace perfmon {
+
+/// @brief PerfMonMgr singleton
+PerfMonMgrPtr mgr;
+
+} // end of namespace perfmon
+}
+
+using namespace isc::data;
 using namespace isc::dhcp;
 using namespace isc::hooks;
 using namespace isc::log;
@@ -88,24 +99,34 @@ int pkt6_send(CalloutHandle& handle) {
 ///
 /// @param handle library handle
 /// @return 0 when initialization is successful, 1 otherwise
-int load(LibraryHandle& /* handle */) {
-    // Make the hook library not loadable by d2 or ca.
-    uint16_t family = CfgMgr::instance().getFamily();
-    const std::string& proc_name = Daemon::getProcName();
-    if (family == AF_INET) {
-        if (proc_name != "kea-dhcp4") {
-            isc_throw(isc::Unexpected, "Bad process name: " << proc_name
-                      << ", expected kea-dhcp4");
-        }
-    } else {
-        if (proc_name != "kea-dhcp6") {
+int load(LibraryHandle& handle) {
+    try {
+        // Make the hook library only loadable for kea-dhcpX.
+        uint16_t family = CfgMgr::instance().getFamily();
+        const std::string& proc_name = Daemon::getProcName();
+        if (family == AF_INET) {
+            if (proc_name != "kea-dhcp4") {
+                isc_throw(isc::Unexpected, "Bad process name: " << proc_name
+                          << ", expected kea-dhcp4");
+            }
+        } else if (proc_name != "kea-dhcp6") {
             isc_throw(isc::Unexpected, "Bad process name: " << proc_name
                       << ", expected kea-dhcp6");
         }
-    }
 
-    /// @todo register commands
-    /// handle.registerCommandCallout("command-here", handler_here);
+        // Instantiate the manager singleton.
+        mgr.reset(new PerfMonMgr(family));
+
+        // Configure the manager using the hook library's parameters.
+        ConstElementPtr json = handle.getParameters();
+        mgr->configure(json);
+
+        /// @todo register commands
+        /// handle.registerCommandCallout("command-here", handler_here);
+    } catch (const std::exception& ex) {
+        LOG_ERROR(perfmon_logger, PERFMON_INIT_FAILED).arg(ex.what());
+        return (1);
+    }
 
     LOG_INFO(perfmon_logger, PERFMON_INIT_OK);
     return (0);
index 93778abc5933c3412a6aa83a8e34cc73faf80242..04b9755979f77cef1b96ec2ff4273486f06fa984 100644 (file)
@@ -33,6 +33,7 @@ uint16_t
 DurationKeyParser::getMessageNameType4(const std::string& name) {
     static std::map<std::string, uint16_t> name_type_map = {
         {"",                        DHCP_NOTYPE},
+        {"*",                       DHCP_NOTYPE},
         {"DHCPDISCOVER",            DHCPDISCOVER},
         {"DHCPOFFER",               DHCPOFFER},
         {"DHCPREQUEST",             DHCPREQUEST},
@@ -63,6 +64,7 @@ uint16_t
 DurationKeyParser::getMessageNameType6(const std::string& name) {
     static std::map<std::string, uint16_t> name_type_map = {
            {"",                    DHCPV6_NOTYPE},
+           {"*",                   DHCPV6_NOTYPE},
                {"SOLICIT",                         DHCPV6_SOLICIT},
                {"ADVERTISE",                   DHCPV6_ADVERTISE},
                {"REQUEST",                         DHCPV6_REQUEST},
index 1f65c57681f2d84a02ec9b27ac48e9a60133417f..c004d3d92cb293f0c02dda83ddc8fdf9b7f24a26 100644 (file)
@@ -37,7 +37,7 @@ namespace perfmon {
 ///                },
 ///                "enable-alarm" : true,
 ///                "high-water-ms" : 500,
-///                "low-water-ms" : 25,
+///                "low-water-ms" : 25
 ///            },
 ///            ..
 ///            }]
index fb83d53a1cacf44d7f3f340c35c27ea88b75fd02..9abe417dabc0a43fb7ebcf9eceed18cac1a44012 100644 (file)
@@ -165,6 +165,32 @@ TEST_F(DurationKeyParserTest, validScenarios4) {
             })",
             DHCPDISCOVER, DHCPOFFER, "start_here", "stop_there", SUBNET_ID_GLOBAL
         },
+        {
+            // Empty message types should map to DHCP_NOTYPE
+            __LINE__,
+            R"(
+            {
+                "query-type": "",
+                "response-type": "",
+                "start-event": "start_here",
+                "stop-event": "stop_there",
+                "subnet-id": 701
+            })",
+            DHCP_NOTYPE, DHCP_NOTYPE, "start_here", "stop_there", 701
+        },
+        {
+            // "*" message types should map to DHCP_NOTYPE
+            __LINE__,
+            R"(
+            {
+                "query-type": "*",
+                "response-type": "*",
+                "start-event": "start_here",
+                "stop-event": "stop_there",
+                "subnet-id": 701
+            })",
+            DHCP_NOTYPE, DHCP_NOTYPE, "start_here", "stop_there", 701
+        },
     };
 
     testValidScenarios(scenarios, AF_INET);
@@ -386,6 +412,32 @@ TEST_F(DurationKeyParserTest, parseValidScenarios6) {
             })",
             DHCPV6_SOLICIT, DHCPV6_ADVERTISE, "start_here", "stop_there", SUBNET_ID_GLOBAL
         },
+        {
+            // Empty message types should map to DHCPV6_NOTYPE
+            __LINE__,
+            R"(
+            {
+                "query-type": "",
+                "response-type": "",
+                "start-event": "start_here",
+                "stop-event": "stop_there",
+                "subnet-id": 701
+            })",
+            DHCPV6_NOTYPE, DHCPV6_NOTYPE, "start_here", "stop_there", 701
+        },
+        {
+            // "*" message types should map to DHCPV6_NOTYPE
+            __LINE__,
+            R"(
+            {
+                "query-type": "*",
+                "response-type": "*",
+                "start-event": "start_here",
+                "stop-event": "stop_there",
+                "subnet-id": 701
+            })",
+            DHCPV6_NOTYPE, DHCPV6_NOTYPE, "start_here", "stop_there", 701
+        },
     };
 
     testValidScenarios(scenarios, AF_INET6);
index 95167e017228596fb6995d1118f46c83f4d6b35c..443fe7ab4a792177764c15b2028330c6cfdb83b8 100644 (file)
@@ -117,7 +117,8 @@ public:
         EXPECT_EQ(mgr->getAlarmStore()->getFamily(), family_);
         AlarmCollectionPtr alarms = mgr->getAlarmStore()->getAll();
         ASSERT_EQ(alarms->size(), 1);
-        DurationKeyPtr key(new DurationKey(family_, 0, 0, "process-started", "process-completed", 70));
+        DurationKeyPtr key(new DurationKey(family_, 0, 0, "process-started",
+                                           "process-completed", 70));
         AlarmPtr alarm = (*alarms)[0];
         ASSERT_TRUE(alarm);
         EXPECT_EQ(*alarm, *key) << "alarm:" << alarm->getLabel();