]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2086 in SNORT/snort3 from ~PUNEETKU/snort3:pm_shell_cmd to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Thu, 9 Apr 2020 03:43:45 +0000 (03:43 +0000)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Thu, 9 Apr 2020 03:43:45 +0000 (03:43 +0000)
Squashed commit of the following:

commit 2b6c7588e78aac9e3a0a31b0b1571095b25c80ad
Author: Puneeth Kumar C V <puneetku@cisco.com>
Date:   Sun Mar 15 22:52:53 2020 -0400

    perf_monitor: Enable or disable flow-ip-profiling using shell commands

src/network_inspectors/perf_monitor/perf_module.cc
src/network_inspectors/perf_monitor/perf_module.h
src/network_inspectors/perf_monitor/perf_monitor.cc
src/network_inspectors/perf_monitor/perf_monitor.h [new file with mode: 0644]
src/network_inspectors/perf_monitor/perf_tracker.cc
src/network_inspectors/perf_monitor/perf_tracker.h

index 4b215808c46ab375575f3ceb2466dfd00b3ba720..37296417d12062ac012842ebdd6da117f0faa377 100644 (file)
 #include "config.h"
 #endif
 
-#ifdef HAVE_FLATBUFFERS
-#define FLATBUFFERS_ENUM " | flatbuffers"
-#else
-#define FLATBUFFERS_ENUM
-#endif
-
 #include "perf_module.h"
 
+#include <lua.hpp>
+
 #include "log/messages.h"
+#include "main/analyzer_command.h"
 #include "main/snort.h"
 #include "managers/module_manager.h"
 
+#include "perf_monitor.h"
 #include "perf_pegs.h"
 #include "perf_reload_tuner.h"
 
+#ifdef HAVE_FLATBUFFERS
+#define FLATBUFFERS_ENUM " | flatbuffers"
+#else
+#define FLATBUFFERS_ENUM
+#endif
+
 using namespace snort;
 
 //-------------------------------------------------------------------------
@@ -98,6 +102,127 @@ static const Parameter s_params[] =
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
+class PerfMonFlowIPDebug : public AnalyzerCommand
+{
+public:
+    PerfMonFlowIPDebug(PerfConstraints* cs, bool en, PerfMonitor* pm) :
+        enable(en), constraints(cs), perf_monitor(pm) { }
+    ~PerfMonFlowIPDebug() override
+    { perf_monitor->swap_constraints(constraints); }
+
+    bool execute(Analyzer&, void**) override;
+    const char* stringify() override { return "FLOW_IP_PROFILING"; }
+
+private:
+    bool enable;
+    PerfConstraints* constraints;
+    PerfMonitor* perf_monitor;
+};
+
+static const Parameter flow_ip_profiling_params[] =
+{
+    { "seconds", Parameter::PT_INT, "1:max32", nullptr,
+      "report interval" },
+
+    { "packets", Parameter::PT_INT, "0:max32", nullptr,
+      "minimum packets to report" },
+
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+bool PerfMonFlowIPDebug::execute(Analyzer&, void**)
+{
+    if (enable)
+        perf_monitor->enable_profiling(constraints);
+    else
+        perf_monitor->disable_profiling(constraints);
+
+    return true;
+}
+
+static int enable_flow_ip_profiling(lua_State* L)
+{
+    PerfMonitor* perf_monitor =
+        (PerfMonitor*)InspectorManager::get_inspector(PERF_NAME, true);
+
+    if (!perf_monitor)
+    {
+        LogMessage("perf_monitor is not configured, "
+            "flow ip profiling cannot be enabled.\n");
+        return 0;
+    }
+
+    auto* new_constraints = new PerfConstraints(true, luaL_optint(L, 1, 0),
+        luaL_optint(L, 2, 0));
+
+    main_broadcast_command(new PerfMonFlowIPDebug(new_constraints, true, perf_monitor),
+        true);
+
+    LogMessage("Enabling flow ip profiling with sample interval %d packet count %d\n",
+        new_constraints->sample_interval, new_constraints->pkt_cnt);
+
+    return 0;
+}
+
+static int disable_flow_ip_profiling(lua_State*)
+{
+    PerfMonitor* perf_monitor =
+        (PerfMonitor*)InspectorManager::get_inspector(PERF_NAME, true);
+
+    if (!perf_monitor)
+    {
+        LogMessage("Attempting to disable flow ip profiling when "
+            "perf_monitor is not configured\n");
+        return 0;
+    }
+
+    if (!perf_monitor->is_flow_ip_enabled())
+    {
+        LogMessage("Attempting to disable flow ip profiling when "
+            "it is not running\n");
+        return 0;
+    }
+
+    auto* new_constraints = perf_monitor->get_original_constraints();
+
+    main_broadcast_command(new PerfMonFlowIPDebug(new_constraints, false, perf_monitor),
+        true);
+
+    LogMessage("Disabling flow ip profiling\n");
+
+    return 0;
+}
+
+static int show_flow_ip_profiling(lua_State*)
+{
+    bool status = false;
+
+    PerfMonitor* perf_monitor = (PerfMonitor*)InspectorManager::get_inspector(PERF_NAME, true);
+
+    if (perf_monitor)
+        status = perf_monitor->is_flow_ip_enabled();
+    else
+        LogMessage("perf_monitor is not configured\n");
+
+    LogMessage("Snort flow ip profiling is %s\n", status ? "enabled" : "disabled");
+
+    return 0;
+}
+
+static const Command perf_module_cmds[] =
+{
+    { "enable_flow_ip_profiling", enable_flow_ip_profiling,
+      flow_ip_profiling_params, "enable statistics on host pairs" },
+
+    { "disable_flow_ip_profiling", disable_flow_ip_profiling,
+      nullptr, "disable statistics on host pairs" },
+
+    { "show_flow_ip_profiling", show_flow_ip_profiling,
+      nullptr, "show status of statistics on host pairs" },
+
+    { nullptr, nullptr, nullptr, nullptr }
+};
+
 //-------------------------------------------------------------------------
 // perf attributes
 //-------------------------------------------------------------------------
@@ -224,6 +349,11 @@ bool PerfMonModule::end(const char* fqn, int idx, SnortConfig* sc)
 PerfConfig* PerfMonModule::get_config()
 {
     PerfConfig* tmp = config;
+
+    tmp->constraints->flow_ip_enabled = config->perf_flags & PERF_FLOWIP;
+    tmp->constraints->sample_interval = config->sample_interval;
+    tmp->constraints->pkt_cnt = config->pkt_cnt;
+
     config = nullptr;
     return tmp;
 }
@@ -234,6 +364,9 @@ const PegInfo* PerfMonModule::get_pegs() const
 PegCount* PerfMonModule::get_counts() const
 { return (PegCount*)&pmstats; }
 
+const Command* PerfMonModule::get_commands() const
+{ return perf_module_cmds; }
+
 void ModuleConfig::set_name(const std::string& name)
 { this->name = name; }
 
index 1bcd8f13956d62400abc804a1519724c658245ec..02f446a130af509ed71b88ba208897f8760f2db8 100644 (file)
@@ -76,6 +76,17 @@ private:
     std::unordered_map<std::string, bool> peg_names;
 };
 
+struct PerfConstraints
+{
+    bool flow_ip_enabled = false;
+    unsigned sample_interval = 0;
+    uint32_t pkt_cnt = 0;
+
+    PerfConstraints() = default;
+    PerfConstraints(bool en, unsigned interval, uint32_t cnt) :
+        flow_ip_enabled(en), sample_interval(interval), pkt_cnt(cnt) { }
+};
+
 struct PerfConfig
 {
     int perf_flags = 0;
@@ -88,6 +99,10 @@ struct PerfConfig
     PerfOutput output = PerfOutput::TO_FILE;
     std::vector<ModuleConfig> modules;
     std::vector<snort::Module*> mods_to_prep;
+    PerfConstraints* constraints;
+
+    PerfConfig() { constraints = new PerfConstraints; } 
+    ~PerfConfig() { delete constraints; }
 
     bool resolve();
 };
@@ -99,6 +114,7 @@ public:
     PerfMonModule();
     ~PerfMonModule() override;
 
+    const snort::Command* get_commands() const override;
     bool set(const char*, snort::Value&, snort::SnortConfig*) override;
     bool begin(const char*, int, snort::SnortConfig*) override;
     bool end(const char*, int, snort::SnortConfig*) override;
index 8c038418f6a8e6831a5a895b9ba18aeb2cfa3ef3..d18ffdddd7a94b8b918af3f7f907890aedf921ad 100644 (file)
 #include "config.h"
 #endif
 
+#include "perf_monitor.h"
+
 #include "framework/data_bus.h"
 #include "hash/hash_defs.h"
 #include "hash/xhash.h"
 #include "log/messages.h"
-#include "managers/inspector_manager.h"
+#include "main/analyzer_command.h"
+#include "main/thread.h"
 #include "profiler/profiler.h"
 #include "protocols/packet.h"
 
-#include "base_tracker.h"
-#include "cpu_tracker.h"
-#include "flow_ip_tracker.h"
-#include "flow_tracker.h"
-#include "perf_module.h"
-
-
 #ifdef UNIT_TEST
 #include "catch/snort_catch.h"
 #endif
@@ -55,35 +51,12 @@ THREAD_LOCAL ProfileStats perfmonStats;
 static THREAD_LOCAL std::vector<PerfTracker*>* trackers;
 static THREAD_LOCAL FlowIPTracker* flow_ip_tracker = nullptr;
 
+static THREAD_LOCAL PerfConstraints* t_constraints;
+
 //-------------------------------------------------------------------------
 // class stuff
 //-------------------------------------------------------------------------
 
-class FlowIPDataHandler;
-class PerfMonitor : public Inspector
-{
-public:
-    PerfMonitor(PerfConfig*);
-    ~PerfMonitor() override { delete config;}
-
-    bool configure(SnortConfig*) override;
-    void show(SnortConfig*) override;
-
-    void eval(Packet*) override;
-    bool ready_to_process(Packet* p);
-
-    void tinit() override;
-    void tterm() override;
-
-    void rotate();
-
-    FlowIPTracker* get_flow_ip();
-
-private:
-    PerfConfig* const config;
-    void disable_tracker(size_t);
-};
-
 class PerfIdleHandler : public DataHandler
 {
 public:
@@ -118,6 +91,11 @@ public:
 
     void handle(DataEvent&, Flow* flow) override
     {
+        FlowIPTracker* tracker = perf_monitor.get_flow_ip();
+
+        if (!tracker)
+            return;
+
         FlowState state = SFS_STATE_MAX;
 
         if ( flow->pkt_type == PktType::UDP )
@@ -135,9 +113,7 @@ public:
         if ( state == SFS_STATE_MAX )
             return;
 
-        FlowIPTracker* tracker = perf_monitor.get_flow_ip();
-        if (tracker)
-            tracker->update_state(&flow->client_ip, &flow->server_ip, state);
+        tracker->update_state(&flow->client_ip, &flow->server_ip, state);
     }
 
 private:
@@ -222,9 +198,7 @@ bool PerfMonitor::configure(SnortConfig* sc)
 {
     new PerfIdleHandler(*this, sc);
     new PerfRotateHandler(*this, sc);
-
-    if ( config->perf_flags & PERF_FLOWIP )
-        new FlowIPDataHandler(*this, sc);
+    new FlowIPDataHandler(*this, sc);
 
     return config->resolve();
 }
@@ -233,17 +207,17 @@ void PerfMonitor::tinit()
 {
     trackers = new std::vector<PerfTracker*>();
 
+    t_constraints = config->constraints;
+
     if (config->perf_flags & PERF_BASE)
         trackers->emplace_back(new BaseTracker(config));
 
     if (config->perf_flags & PERF_FLOW)
         trackers->emplace_back(new FlowTracker(config));
 
+    flow_ip_tracker = new FlowIPTracker(config);
     if (config->perf_flags & PERF_FLOWIP)
-    {
-        flow_ip_tracker = new FlowIPTracker(config);
         trackers->emplace_back(flow_ip_tracker);
-    }
 
     if (config->perf_flags & PERF_CPU )
         trackers->emplace_back(new CPUTracker(config));
@@ -260,23 +234,31 @@ void PerfMonitor::tinit()
 
 bool PerfMonReloadTuner::tinit()
 {
-    if (flow_ip_tracker)
+    PerfMonitor* pm = (PerfMonitor*)InspectorManager::get_inspector(PERF_NAME, true);
+    auto* new_constraints = pm->get_constraints();
+
+    if (new_constraints->flow_ip_enabled)
+    {
+        pm->enable_profiling(new_constraints);
         return flow_ip_tracker->initialize(memcap);
+    }
     else
-        return false;
+        pm->disable_profiling(new_constraints);
+
+    return false;
 }
 
 bool PerfMonReloadTuner::tune_resources(unsigned work_limit)
 {
-    if (flow_ip_tracker)
+    if (t_constraints->flow_ip_enabled)
     {
         unsigned num_freed = 0;
         int result = flow_ip_tracker->get_ip_map()->tune_memory_resources(work_limit, num_freed);
         pmstats.flow_tracker_reload_deletes += num_freed;
         return (result == HASH_OK);
     }
-    else
-        return true;
+
+    return true;
 }
 
 void PerfMonitor::tterm()
@@ -288,11 +270,17 @@ void PerfMonitor::tterm()
             auto back = trackers->back();
             if ( config->perf_flags & PERF_SUMMARY )
                 back->process(true);
+            if (back == flow_ip_tracker)
+                flow_ip_tracker = nullptr;
             delete back;
             trackers->pop_back();
         }
         delete trackers;
-        flow_ip_tracker = nullptr;
+        if (flow_ip_tracker)
+        {
+            delete flow_ip_tracker;
+            flow_ip_tracker = nullptr;
+        }
     }
 }
 
@@ -303,6 +291,50 @@ void PerfMonitor::rotate()
             disable_tracker(i--);
 }
 
+void PerfMonitor::swap_constraints(PerfConstraints* constraints)
+{
+    PerfConstraints* tmp = config->constraints;
+
+    config->constraints = constraints;
+    delete tmp;
+}
+
+PerfConstraints* PerfMonitor::get_original_constraints()
+{
+    auto* new_constraints = new PerfConstraints(false, config->pkt_cnt,
+        config->sample_interval);
+
+    return new_constraints;
+}
+
+void PerfMonitor::enable_profiling(PerfConstraints* constraints)
+{
+    t_constraints = constraints;
+
+    auto itr = std::find(trackers->begin(), trackers->end(), flow_ip_tracker);
+
+    if (itr != trackers->end())
+        return;
+
+    trackers->emplace_back(flow_ip_tracker);
+
+    if (!flow_ip_tracker->is_open())
+        flow_ip_tracker->open(true);
+}
+
+void PerfMonitor::disable_profiling(PerfConstraints* constraints)
+{
+    t_constraints = constraints;
+
+    auto itr = std::find(trackers->begin(), trackers->end(), flow_ip_tracker);
+
+    if (itr != trackers->end())
+    {
+        trackers->erase(itr);
+        flow_ip_tracker->close();
+    }
+}
+
 void PerfMonitor::eval(Packet* p)
 {
     Profile profile(perfmonStats);
@@ -355,9 +387,9 @@ bool PerfMonitor::ready_to_process(Packet* p)
     if (!sample_time)
         sample_time = cur_time;
 
-    if ( cnt >= config->pkt_cnt )
+    if ( cnt >= t_constraints->pkt_cnt )
     {
-        if ((cur_time - sample_time) >= config->sample_interval)
+        if ((cur_time - sample_time) >= t_constraints->sample_interval)
         {
             if (cnt == 0)
                 for (auto& tracker : *trackers)
@@ -372,7 +404,7 @@ bool PerfMonitor::ready_to_process(Packet* p)
 }
 
 FlowIPTracker* PerfMonitor::get_flow_ip()
-{ return flow_ip_tracker; }
+{ return t_constraints->flow_ip_enabled ? flow_ip_tracker : nullptr; }
 
 //-------------------------------------------------------------------------
 // api stuff
@@ -440,22 +472,24 @@ TEST_CASE("Process timing logic", "[perfmon]")
     DAQ_PktHdr_t pkth;
     p.pkth = &pkth;
 
-    config->pkt_cnt = 0;
-    config->sample_interval = 0;
+    t_constraints = config->constraints;
+
+    t_constraints->pkt_cnt = 0;
+    t_constraints->sample_interval = 0;
     pkth.ts.tv_sec = 0;
     REQUIRE((perfmon.ready_to_process(&p) == true));
     pkth.ts.tv_sec = 1;
     REQUIRE((perfmon.ready_to_process(&p) == true));
 
-    config->pkt_cnt = 2;
-    config->sample_interval = 0;
+    t_constraints->pkt_cnt = 2;
+    t_constraints->sample_interval = 0;
     pkth.ts.tv_sec = 2;
     REQUIRE((perfmon.ready_to_process(&p) == false));
     pkth.ts.tv_sec = 3;
     REQUIRE((perfmon.ready_to_process(&p) == true));
 
-    config->pkt_cnt = 0;
-    config->sample_interval = 2;
+    t_constraints->pkt_cnt = 0;
+    t_constraints->sample_interval = 2;
     pkth.ts.tv_sec = 4;
     REQUIRE((perfmon.ready_to_process(&p) == false));
     pkth.ts.tv_sec = 8;
@@ -463,8 +497,8 @@ TEST_CASE("Process timing logic", "[perfmon]")
     pkth.ts.tv_sec = 10;
     REQUIRE((perfmon.ready_to_process(&p) == true));
 
-    config->pkt_cnt = 5;
-    config->sample_interval = 4;
+    t_constraints->pkt_cnt = 5;
+    t_constraints->sample_interval = 4;
     pkth.ts.tv_sec = 11;
     REQUIRE((perfmon.ready_to_process(&p) == false));
     pkth.ts.tv_sec = 14;
diff --git a/src/network_inspectors/perf_monitor/perf_monitor.h b/src/network_inspectors/perf_monitor/perf_monitor.h
new file mode 100644 (file)
index 0000000..4f8cb3f
--- /dev/null
@@ -0,0 +1,72 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// perf_monitor.h author Puneeth Kumar C V <puneetku@cisco.com>
+
+#ifndef PERF_MONITOR_H
+#define PERF_MONITOR_H
+
+#include "managers/inspector_manager.h"
+#include "protocols/packet.h"
+
+#include "base_tracker.h"
+#include "cpu_tracker.h"
+#include "flow_ip_tracker.h"
+#include "flow_tracker.h"
+#include "perf_module.h"
+
+class FlowIPDataHandler;
+
+class PerfMonitor : public snort::Inspector
+{
+public:
+    PerfMonitor(PerfConfig*);
+    ~PerfMonitor() override { delete config; }
+
+    bool configure(snort::SnortConfig*) override;
+    void show(snort::SnortConfig*) override;
+
+    void eval(snort::Packet*) override;
+    bool ready_to_process(snort::Packet* p);
+
+    void tinit() override;
+    void tterm() override;
+
+    void rotate();
+
+    void swap_constraints(PerfConstraints*);
+    PerfConstraints* get_original_constraints();
+
+    void enable_profiling(PerfConstraints*);
+    void disable_profiling(PerfConstraints*);
+
+    FlowIPTracker* get_flow_ip();
+
+    inline PerfConstraints* get_constraints()
+    { return config->constraints; }
+
+    inline bool is_flow_ip_enabled()
+    { return config->constraints->flow_ip_enabled; }
+
+private:
+    PerfConfig* const config;
+    void disable_tracker(size_t);
+};
+
+#endif
+
index 9e51d5dd0d649e1097d2f4d8318b279bb51f5e1e..cc9efa40940466ac98b0a376d90620f50099a9a8 100644 (file)
@@ -97,6 +97,15 @@ PerfTracker::~PerfTracker()
         fclose(fh);
 }
 
+void PerfTracker::close()
+{
+    if (fh && fh != stdout)
+    {
+        fclose(fh);
+        fh = nullptr;
+    }
+}
+
 bool PerfTracker::open(bool append)
 {
     if (fname.length())
index d27d60a350c3482f07e5a9628131f397f2ba3602..1686287489f865ef178e5a8271f0af61693b5e01 100644 (file)
@@ -51,31 +51,30 @@ struct Packet;
 class PerfTracker
 {
 public:
-    virtual void reset() {}
-
-    virtual void update(snort::Packet*) {}
-    virtual void process(bool /*summary*/) {} // FIXIT-M get rid of this step.
+    virtual ~PerfTracker();
 
-    virtual void update_time(time_t time) final { cur_time = time; }
-    virtual const std::string& get_name() final { return tracker_name; }
+    virtual void reset() { }
+    virtual void process(bool /*summary*/) { } // FIXIT-M get rid of this step.
+    virtual void update(snort::Packet*) { }
+    virtual void update_time(time_t time) { cur_time = time; }
+    virtual const std::string& get_name() { return tracker_name; }
 
-    virtual bool open(bool append) final;
-    virtual bool rotate() final;
-    virtual bool auto_rotate() final;
-
-    virtual ~PerfTracker();
+    bool open(bool append);
+    void close();
+    bool rotate();
+    bool auto_rotate();
+    bool is_open() { return fh != nullptr; }
 
     PerfTracker(const PerfTracker&) = delete;
     PerfTracker& operator=(const PerfTracker&) = delete;
 
 protected:
-    uint64_t max_file_size = 0;
+    PerfTracker(PerfConfig*, const char* tracker_name);
+    virtual void write();
 
+    uint64_t max_file_size = 0;
     PerfFormatter* formatter;
 
-    PerfTracker(PerfConfig*, const char* tracker_name);
-    virtual void write() final;
-
 private:
     std::string fname;
     std::string tracker_name;