]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
refactored FlowTracker into c++. added PegCount vector type to PerfFormatter. removed...
authorCarter Waxman <cwaxman@cisco.com>
Fri, 8 Apr 2016 20:55:20 +0000 (16:55 -0400)
committerCarter Waxman <cwaxman@cisco.com>
Fri, 8 Apr 2016 20:55:20 +0000 (16:55 -0400)
20 files changed:
src/network_inspectors/perf_monitor/CMakeLists.txt
src/network_inspectors/perf_monitor/Makefile.am
src/network_inspectors/perf_monitor/base_tracker.cc
src/network_inspectors/perf_monitor/cpu_tracker.cc
src/network_inspectors/perf_monitor/csv_formatter.cc
src/network_inspectors/perf_monitor/flow_ip_tracker.cc
src/network_inspectors/perf_monitor/flow_ip_tracker.h
src/network_inspectors/perf_monitor/flow_tracker.cc
src/network_inspectors/perf_monitor/flow_tracker.h
src/network_inspectors/perf_monitor/perf_flow.cc [deleted file]
src/network_inspectors/perf_monitor/perf_flow.h [deleted file]
src/network_inspectors/perf_monitor/perf_formatter.cc
src/network_inspectors/perf_monitor/perf_formatter.h
src/network_inspectors/perf_monitor/perf_module.cc
src/network_inspectors/perf_monitor/perf_monitor.cc
src/network_inspectors/perf_monitor/perf_monitor.h
src/network_inspectors/perf_monitor/test/CMakeLists.txt [deleted file]
src/network_inspectors/perf_monitor/test/Makefile.am [deleted file]
src/network_inspectors/perf_monitor/test/perf_monitor_test.cc [deleted file]
src/network_inspectors/perf_monitor/text_formatter.cc

index 17f95727ea32c74da13070d897488245bc02ad04..8730050f38e453fb63dbf022c88fbdfea88c755d 100644 (file)
@@ -11,8 +11,6 @@ add_library ( perf_monitor STATIC
     flow_tracker.h
     flow_ip_tracker.cc
     flow_ip_tracker.h
-    perf_flow.cc
-    perf_flow.h
     perf_formatter.cc
     perf_formatter.h
     perf_module.cc
index cda600c5e1b75c3e9d1a8611d43b0e1976ef805a..73efbd19a8abb1088fd89ae4afd00bbdfcf7d50d 100644 (file)
@@ -8,7 +8,6 @@ cpu_tracker.cc cpu_tracker.h \
 flow_tracker.cc flow_tracker.h \
 flow_ip_tracker.cc flow_ip_tracker.h \
 event_tracker.cc event_tracker.h \
-perf_flow.cc perf_flow.h \
 perf_formatter.cc perf_formatter.h \
 perf_monitor.cc perf_monitor.h \
 perf_module.cc perf_module.h \
index e951d9682edd844d0fa915958d8be62244352e27..55700a9abc16c85f788b8914d05b523912a134ad 100644 (file)
@@ -55,7 +55,7 @@ void BaseTracker::process(bool summary)
     for (unsigned i = 0; i < config->modules.size(); i++)
     {
         Module* m = config->modules.at(i);
-        vector<unsigned> idxs = config->mod_peg_idxs.at(i);
+        vector<unsigned> idxs = config->mod_peg_idxs[i];
         PegCount* pegs = m->get_counts();
 
         for (unsigned j = 0; j < idxs.size(); j++)
index 6ed2bf5389c83b54ba99f2e179635c63f2d143d1..3ac4a041a70480debe9a2e3f3aad5c1b42bc46ea 100644 (file)
@@ -40,7 +40,7 @@ enum CPUFieldRef
 {
     FR_USER = 0,
     FR_SYSTEM,
-    FR_IDLE
+    FR_WALL
 };
 
 static inline uint64_t get_microseconds(struct timeval t)
@@ -55,7 +55,7 @@ CPUTracker::CPUTracker(PerfConfig *perf) :
     formatter->register_section("cpu");
     formatter->register_field("user");
     formatter->register_field("system");
-    formatter->register_field("idle");    
+    formatter->register_field("wall");    
 }
 
 void CPUTracker::get_clocks(struct timeval& user_time,
@@ -104,18 +104,14 @@ void CPUTracker::process(bool)
 
     get_times(user, system, wall);
 
-    auto delt_user = user - last_ut;
-    auto delt_system = system - last_st;
-    auto delt_wall = wall - last_wt;
-    auto delt_idle = delt_wall - delt_system - delt_user;
+    formatter->set_field(0, FR_USER, user - last_ut);
+    formatter->set_field(0, FR_SYSTEM, system - last_st);
+    formatter->set_field(0, FR_WALL, wall - last_wt);
 
     last_ut = user;
     last_st = system;
     last_wt = wall;
 
-    formatter->set_field(0, FR_USER, (double) delt_user / delt_wall * 100);
-    formatter->set_field(0, FR_SYSTEM, (double) delt_system / delt_wall * 100);
-    formatter->set_field(0, FR_IDLE, (double) delt_idle / delt_wall * 100);
 
     formatter->write(fh, cur_time);
     formatter->clear();
@@ -173,10 +169,10 @@ TEST_CASE("Timeval to scalar", "[cpu_tracker]")
 TEST_CASE("csv", "[cpu_tracker]")
 {
     const char* cooked =
-    "#timestamp,cpu.user,cpu.system,cpu.idle\n"
-    "1234567890,23.0769,38.4615,38.4615\n"
-    "1234567890,0,0,100\n"
-    "1234567890,23.0769,38.4615,38.4615\n";
+    "#timestamp,cpu.user,cpu.system,cpu.wall\n"
+    "1234567890,2100000,3200000,8500000\n"
+    "1234567890,0,0,500000\n"
+    "1234567890,2100000,3200000,8500000\n";
 
     FILE* f = tmpfile();
 
@@ -186,21 +182,21 @@ TEST_CASE("csv", "[cpu_tracker]")
 
     tracker.reset();
     tracker.user.tv_sec = 2;
-    tracker.user.tv_usec = 1000000;
+    tracker.user.tv_usec = 100000;
     tracker.sys.tv_sec = 3;
-    tracker.sys.tv_usec = 2000000;
+    tracker.sys.tv_usec = 200000;
     tracker.wall.tv_sec = 8;
-    tracker.wall.tv_usec = 5000000;
+    tracker.wall.tv_usec = 500000;
     tracker.process(false);
     tracker.wall.tv_sec = 9;
     tracker.wall.tv_usec = 0;
     tracker.process(false);
     tracker.user.tv_sec = 4;
-    tracker.user.tv_usec = 2000000;
+    tracker.user.tv_usec = 200000;
     tracker.sys.tv_sec = 6;
-    tracker.sys.tv_usec = 4000000;
+    tracker.sys.tv_usec = 400000;
     tracker.wall.tv_sec = 17;
-    tracker.wall.tv_usec = 5000000;
+    tracker.wall.tv_usec = 500000;
     tracker.process(false);
 
     long int size = ftell(f);
@@ -220,9 +216,9 @@ TEST_CASE("text", "[cpu_tracker]")
     const char* cooked =
     "--------------------------------------------------\n"
     "cpu\n"
-    "                     user: 23.0769\n"
-    "                   system: 38.4615\n"
-    "                     idle: 38.4615\n";
+    "                     user: 2100000\n"
+    "                   system: 3200000\n"
+    "                     wall: 8500000\n";
 
     FILE* f = tmpfile();
 
@@ -232,11 +228,11 @@ TEST_CASE("text", "[cpu_tracker]")
 
     tracker.reset();
     tracker.user.tv_sec = 2;
-    tracker.user.tv_usec = 1000000;
+    tracker.user.tv_usec = 100000;
     tracker.sys.tv_sec = 3;
-    tracker.sys.tv_usec = 2000000;
+    tracker.sys.tv_usec = 200000;
     tracker.wall.tv_sec = 8;
-    tracker.wall.tv_usec = 5000000;
+    tracker.wall.tv_usec = 500000;
     tracker.process(false);
 
     auto size = ftell(f);
index 1174b10c18b790a8e49d6cb3587ff19c33e25652..34061b367a0dfd22cfd2168dbdef8b1da0ab5f67 100644 (file)
@@ -75,13 +75,33 @@ void CSVFormatter::write(FILE* fh, time_t timestamp)
                 case FT_DOUBLE:
                     fprintf(fh, ",%g", values[i][j].d);
                     break;
+
                 case FT_PEG_COUNT:
                     fprintf(fh, ",%" PRIu64, values[i][j].pc);
                     break;
+
                 case FT_STRING:
                     fprintf(fh, ",%s", values[i][j].s ?
                         values[i][j].s : "");
                     break;
+
+                case FT_IDX_PEG_COUNT:
+                {
+                    std::ostringstream ss;
+                    PegCount size = 0;
+
+                    for( PegCount pc : *values[i][j].ipc )
+                    {
+                        if( pc )
+                        {
+                            ss << "," << pc;
+                            size++;
+                        }
+                    }
+                    fprintf(fh, ",%" PRIu64 "%s", size, ss.str().c_str());
+                    break;
+                }
+
                 case FT_UNSET:
                     fputs(",0", fh);
                     break; 
@@ -97,9 +117,9 @@ void CSVFormatter::write(FILE* fh, time_t timestamp)
 TEST_CASE("csv output", "[CSVFormatter]")
 {
     const char* cooked =
-        "#timestamp,name.one,name.two,other.three,other.four,other.five\n"
-        "1234567890,0,1,2,34.5678,hellothere\n"
-        "2345678901,0,0,0,0,\n";
+        "#timestamp,name.one,name.two,other.three,other.four,other.five,other.kvp\n"
+        "1234567890,0,1,2,34.5678,hellothere,3,50,60,70\n"
+        "2345678901,0,0,0,0,,0\n";
     
     FILE* fh = tmpfile();
     CSVFormatter f;
@@ -111,6 +131,7 @@ TEST_CASE("csv output", "[CSVFormatter]")
     f.register_field("three");
     f.register_field("four");
     f.register_field("five");
+    f.register_field("kvp");
     f.finalize_fields(fh);
 
     f.set_field(0, 0, (PegCount)0);
@@ -118,6 +139,13 @@ TEST_CASE("csv output", "[CSVFormatter]")
     f.set_field(1, 0, (PegCount)2);
     f.set_field(1, 1, 34.5678);
     f.set_field(1, 2, "hellothere");
+    
+    std::vector<PegCount> kvp;
+    kvp.push_back(50);
+    kvp.push_back(60);
+    kvp.push_back(70);
+    f.set_field(1, 3, &kvp);
+
     f.write(fh, (time_t)1234567890);
 
     f.clear();
index 3ca8d38714e41b35b53bfc8b90de59a2c5edca40..22d4528cee208687966d666bfd2b939b61eb2823 100644 (file)
@@ -19,7 +19,6 @@
 // flow_ip_tracker.cc author Carter Waxman <cwaxman@cisco.com>
 
 #include "flow_ip_tracker.h"
-#include "perf_flow.h"
 #include "perf_module.h"
 
 #include "sfip/sf_ip.h"
 
 #define FLIP_FILE (PERF_NAME "_flow_ip.csv")
 
+enum FlowIpRef
+{
+    FR_REMAIN = 0,
+    FR_IP_A,
+    FR_IP_B,
+    FR_TCP_PACKS_A_B,
+    FR_TCP_BYTES_A_B,
+    FR_TCP_PACKS_B_A,
+    FR_TCP_BYTES_B_A,
+    FR_UDP_PACKS_A_B,
+    FR_UDP_BYTES_A_B,
+    FR_UDP_PACKS_B_A,
+    FR_UDP_BYTES_B_A,
+    FR_OTHER_PACKS_A_B,
+    FR_OTHER_BYTES_A_B,
+    FR_OTHER_PACKS_B_A,
+    FR_OTHER_BYTES_B_A,
+    FR_TCP_EST,
+    FR_TCP_CLOSED,
+    FR_UDP_CREATED
+};
+
 struct FlowStateKey
 {
     sfip_t ipA;
@@ -76,7 +97,25 @@ FlowStateValue* FlowIPTracker::find_stats(const sfip_t* src_addr, const sfip_t*
 FlowIPTracker::FlowIPTracker(PerfConfig* perf) : PerfTracker(perf,
         perf->output == PERF_FILE ? FLIP_FILE : nullptr)
 {
-
+    formatter->register_section("flow_ip");
+    formatter->register_field("remaining");
+    formatter->register_field("ip_a");
+    formatter->register_field("ip_b");
+    formatter->register_field("tcp_packets_a_b");
+    formatter->register_field("tcp_bytes_a_b");
+    formatter->register_field("tcp_packets_b_a");
+    formatter->register_field("tcp_bytes_b_a");
+    formatter->register_field("udp_packets_a_b");
+    formatter->register_field("udp_bytes_a_b");
+    formatter->register_field("udp_packets_b_a");
+    formatter->register_field("udp_bytes_b_a");
+    formatter->register_field("other_packets_a_b");
+    formatter->register_field("other_bytes_a_b");
+    formatter->register_field("other_packets_b_a");
+    formatter->register_field("other_bytes_b_a");
+    formatter->register_field("tcp_established");
+    formatter->register_field("tcp_closed");
+    formatter->register_field("udp_created");
 }
 
 FlowIPTracker::~FlowIPTracker()
@@ -99,7 +138,7 @@ void FlowIPTracker::reset()
         if (!ipMap)
             FatalError("Unable to allocate memory for FlowIP stats\n"); //FIXIT-H this should all
                                                                         // occur at thread init
-
+        formatter->finalize_fields(fh);
         first = false;
     }
     else
@@ -143,79 +182,57 @@ void FlowIPTracker::update(Packet* p)
     }
 }
 
-void FlowIPTracker::display_stats()
-{
-    SFXHASH_NODE* node;
-    uint64_t total = 0;
-
-    LogMessage(fh, "\n");
-    LogMessage(fh, "\n");
-    LogMessage(fh, "IP Flows (%d unique IP pairs)\n", sfxhash_count(ipMap));
-    LogMessage(fh, "---------------\n");
-    for (node = sfxhash_findfirst(ipMap); node; node = sfxhash_findnext(ipMap))
-    {
-        char ipA[41], ipB[41];
-
-        FlowStateKey* key = (FlowStateKey*)node->key;
-        FlowStateValue* stats = (FlowStateValue*)node->data;
-
-        sfip_raw_ntop(key->ipA.family, key->ipA.ip32, ipA, sizeof(ipA));
-        sfip_raw_ntop(key->ipB.family, key->ipB.ip32, ipB, sizeof(ipB));
-        LogMessage(fh, "[%s <-> %s]: " STDu64 " bytes in " STDu64 " packets (%u, %u, %u)\n", ipA, ipB,
-            stats->total_bytes, stats->total_packets,
-            stats->state_changes[SFS_STATE_TCP_ESTABLISHED],
-            stats->state_changes[SFS_STATE_TCP_CLOSED], stats->state_changes[SFS_STATE_UDP_CREATED]);
-        total += stats->total_packets;
-    }
-    LogMessage(fh, "Classified " STDu64 " packets.\n", total);
-}
-
-void FlowIPTracker::write_stats()
+void FlowIPTracker::process(bool)
 {
-    SFXHASH_NODE* node;
+    PegCount remaining = sfxhash_count(ipMap) - 1;
 
-    if (!fh)
-        return;
-
-    fprintf(fh, "%lu,%u,", (unsigned long)cur_time, sfxhash_count(ipMap));
-    for (node = sfxhash_findfirst(ipMap); node; node = sfxhash_findnext(ipMap))
+    for (auto node = sfxhash_findfirst(ipMap); node; node = sfxhash_findnext(ipMap))
     {
-        char ipA[41], ipB[41];
+        char ip_a[41], ip_b[41];
 
         FlowStateKey* key = (FlowStateKey*)node->key;
         FlowStateValue* stats = (FlowStateValue*)node->data;
 
-        sfip_raw_ntop(key->ipA.family, key->ipA.ip32, ipA, sizeof(ipA));
-        sfip_raw_ntop(key->ipB.family, key->ipB.ip32, ipB, sizeof(ipB));
-        fprintf(fh, "%s,%s," CSVu64 CSVu64 CSVu64 CSVu64 CSVu64 CSVu64 CSVu64
-            CSVu64 CSVu64 CSVu64 CSVu64 CSVu64 "%u,%u,%u\n",
-            ipA, ipB,
-            stats->traffic_stats[SFS_TYPE_TCP].packets_a_to_b,
-            stats->traffic_stats[SFS_TYPE_TCP].bytes_a_to_b,
-            stats->traffic_stats[SFS_TYPE_TCP].packets_b_to_a,
-            stats->traffic_stats[SFS_TYPE_TCP].bytes_b_to_a,
-            stats->traffic_stats[SFS_TYPE_UDP].packets_a_to_b,
-            stats->traffic_stats[SFS_TYPE_UDP].bytes_a_to_b,
-            stats->traffic_stats[SFS_TYPE_UDP].packets_b_to_a,
-            stats->traffic_stats[SFS_TYPE_UDP].bytes_b_to_a,
-            stats->traffic_stats[SFS_TYPE_OTHER].packets_a_to_b,
-            stats->traffic_stats[SFS_TYPE_OTHER].bytes_a_to_b,
-            stats->traffic_stats[SFS_TYPE_OTHER].packets_b_to_a,
-            stats->traffic_stats[SFS_TYPE_OTHER].bytes_b_to_a,
-            stats->state_changes[SFS_STATE_TCP_ESTABLISHED],
-            stats->state_changes[SFS_STATE_TCP_CLOSED],
-            stats->state_changes[SFS_STATE_UDP_CREATED]);
+        sfip_raw_ntop(key->ipA.family, key->ipA.ip32, ip_a, sizeof(ip_a));
+        sfip_raw_ntop(key->ipB.family, key->ipB.ip32, ip_b, sizeof(ip_b));
+        formatter->set_field(0, FR_REMAIN, remaining--);
+        formatter->set_field(0, FR_IP_A, ip_a);
+        formatter->set_field(0, FR_IP_B, ip_b);
+        formatter->set_field(0, FR_TCP_PACKS_A_B,
+            stats->traffic_stats[SFS_TYPE_TCP].packets_a_to_b);
+        formatter->set_field(0, FR_TCP_BYTES_A_B,
+            stats->traffic_stats[SFS_TYPE_TCP].bytes_a_to_b);
+        formatter->set_field(0, FR_TCP_PACKS_B_A,
+            stats->traffic_stats[SFS_TYPE_TCP].packets_b_to_a);
+        formatter->set_field(0, FR_TCP_BYTES_B_A,
+            stats->traffic_stats[SFS_TYPE_TCP].bytes_b_to_a);
+        formatter->set_field(0, FR_UDP_PACKS_A_B,
+            stats->traffic_stats[SFS_TYPE_UDP].packets_a_to_b);
+        formatter->set_field(0, FR_UDP_BYTES_A_B,
+            stats->traffic_stats[SFS_TYPE_UDP].bytes_a_to_b);
+        formatter->set_field(0, FR_UDP_PACKS_B_A,
+            stats->traffic_stats[SFS_TYPE_UDP].packets_b_to_a);
+        formatter->set_field(0, FR_UDP_BYTES_B_A,
+            stats->traffic_stats[SFS_TYPE_UDP].bytes_b_to_a);
+        formatter->set_field(0, FR_OTHER_PACKS_A_B,
+            stats->traffic_stats[SFS_TYPE_OTHER].packets_a_to_b);
+        formatter->set_field(0, FR_OTHER_BYTES_A_B,
+            stats->traffic_stats[SFS_TYPE_OTHER].bytes_a_to_b);
+        formatter->set_field(0, FR_OTHER_PACKS_B_A,
+            stats->traffic_stats[SFS_TYPE_OTHER].packets_b_to_a);
+        formatter->set_field(0, FR_OTHER_BYTES_B_A,
+            stats->traffic_stats[SFS_TYPE_OTHER].bytes_b_to_a);
+        formatter->set_field(0, FR_TCP_EST,
+            (PegCount) stats->state_changes[SFS_STATE_TCP_ESTABLISHED]);
+        formatter->set_field(0, FR_TCP_CLOSED,
+            (PegCount) stats->state_changes[SFS_STATE_TCP_CLOSED]);
+        formatter->set_field(0, FR_UDP_CREATED,
+            (PegCount) stats->state_changes[SFS_STATE_UDP_CREATED]);
+        
+        formatter->write(fh, cur_time);
+        formatter->clear();
     }
 
-    fflush(fh);
-}
-
-void FlowIPTracker::process(bool)
-{
-    
-    formatter->write(fh, cur_time);
-    formatter->clear();
-
     if ( !(config->perf_flags & PERF_SUMMARY) )
         reset();
 }
index c56ad51b11924e08ee4661502d001a1aa152b032..c97fedcb6005357dfca5614e5a4395285a88f670 100644 (file)
 #define FLOW_IP_TRACKER_H
 
 #include "perf_tracker.h"
-#include "perf_flow.h"
 #include "hash/sfxhash.h"
 
+enum FlowState
+{
+    SFS_STATE_TCP_ESTABLISHED = 0,
+    SFS_STATE_TCP_CLOSED,
+    SFS_STATE_UDP_CREATED,
+    SFS_STATE_MAX
+};
+
+enum FlowType
+{
+    SFS_TYPE_TCP = 0,
+    SFS_TYPE_UDP,
+    SFS_TYPE_OTHER,
+    SFS_TYPE_MAX
+};
+
+struct TrafficStats
+{
+    uint64_t packets_a_to_b;
+    uint64_t bytes_a_to_b;
+    uint64_t packets_b_to_a;
+    uint64_t bytes_b_to_a;
+};
+
+struct FlowStateValue
+{
+    TrafficStats traffic_stats[SFS_TYPE_MAX];
+    uint64_t total_packets;
+    uint64_t total_bytes;
+    uint32_t state_changes[SFS_STATE_MAX];
+};
+
 class FlowIPTracker : public PerfTracker
 {
 public:
index 29a8ca670bf091b2c187afe5dbfe864469332e58..232ef1fa7ebe028c8b29bb5d659d7e32f0c84a11 100644 (file)
 #include "flow_tracker.h"
 #include "perf_module.h"
 
+#include "protocols/icmp4.h"
 #include "utils/util.h"
 
 #define FLOW_FILE (PERF_NAME "_flow.csv")
 
-THREAD_LOCAL FlowTracker* perf_flow;
+#define MAX_PKT_LEN  9000
+
+enum FlowSecRef
+{
+    SR_FLOW,
+    SR_TCP,
+    SR_UDP,
+    SR_ICMP
+};
+
+enum FlowFieldRef
+{
+    FR_BYTE_TOTAL = 0,
+    FR_PKT_LEN_CNT,
+    FR_PKT_LEN_OVER,
+};
+
+enum FlowProtoFieldRef
+{
+    FR_SRC_BYTES = 0,
+    FR_DST_BYTES,
+    FR_HIGH_BYTES,
+};
+
+enum FlowIcmpFieldRef
+{
+    FR_ICMP_TYPE_BYTES = 0
+};
 
 FlowTracker::FlowTracker(PerfConfig* perf) : PerfTracker(perf,
-        perf->output == PERF_FILE ? FLOW_FILE : nullptr) { }
+        perf->output == PERF_FILE ? FLOW_FILE : nullptr)
+{
+    pkt_len_cnt.resize( MAX_PKT_LEN + 1 );
+    tcp.src.resize( config->flow_max_port_to_track + 1, 0 );
+    tcp.dst.resize( config->flow_max_port_to_track + 1, 0 );
+    udp.src.resize( config->flow_max_port_to_track + 1, 0 );
+    udp.dst.resize( config->flow_max_port_to_track + 1, 0 );
+    type_icmp.resize( (1 << sizeof(icmp::IcmpType)) + 1, 0 );
+
+    formatter->register_section("flow");
+    formatter->register_field("byte_total");
+    formatter->register_field("packets_by_bytes");
+    formatter->register_field("oversized_packets");
+
+    formatter->register_section("flow_tcp");
+    formatter->register_field("bytes_by_source");
+    formatter->register_field("bytes_by_dest");
+    formatter->register_field("high_port_bytes");
+
+    formatter->register_section("flow_udp");
+    formatter->register_field("bytes_by_source");
+    formatter->register_field("bytes_by_dest");
+    formatter->register_field("high_port_bytes");
+
+    formatter->register_section("flow_icmp");
+    formatter->register_field("bytes_by_type");
+}
 
-FlowTracker::~FlowTracker()
+void FlowTracker::reset()
 {
-    if (stats.pkt_len_cnt)
-    {
-        free(stats.pkt_len_cnt);
-        stats.pkt_len_cnt = nullptr;
-    }
+    formatter->finalize_fields(fh);
+}
 
-    if (stats.port_tcp_src)
+void FlowTracker::update(Packet* p)
+{
+    if (!p->is_rebuilt())
     {
-        free(stats.port_tcp_src);
-        stats.port_tcp_src = nullptr;
-    }
+        auto len = p->pkth->caplen;
 
-    if (stats.port_tcp_dst)
-    {
-        free(stats.port_tcp_dst);
-        stats.port_tcp_dst = nullptr;
-    }
+        if (p->ptrs.tcph)
+            update_transport_flows(p->ptrs.sp, p->ptrs.dp,
+                tcp, len);
+        
+        else if (p->ptrs.udph)
+            update_transport_flows(p->ptrs.sp, p->ptrs.dp,
+                udp, len);
 
-    if (stats.port_udp_src)
-    {
-        free(stats.port_udp_src);
-        stats.port_udp_src = nullptr;
-    }
+        else if (p->ptrs.icmph)
+            type_icmp[p->ptrs.icmph->type] += len;
 
-    if (stats.port_udp_dst)
-    {
-        free(stats.port_udp_dst);
-        stats.port_udp_dst = nullptr;
-    }
+        if (len <= MAX_PKT_LEN)
+            pkt_len_cnt[len]++;
+        else
+            pkt_len_oversize_cnt++;
 
-    if (stats.type_icmp)
-    {
-        free(stats.type_icmp);
-        stats.type_icmp = nullptr;
+        byte_total += len;
     }
 }
 
-void FlowTracker::reset()
+void FlowTracker::process(bool)
 {
-    static THREAD_LOCAL bool first = true;
+    formatter->set_field(SR_FLOW, FR_BYTE_TOTAL, byte_total);
+    formatter->set_field(SR_FLOW, FR_PKT_LEN_CNT, &pkt_len_cnt);
+    formatter->set_field(SR_FLOW, FR_PKT_LEN_OVER, pkt_len_oversize_cnt);
 
-    if (first)
-    {
-        stats.pkt_len_cnt = (uint64_t*)SnortAlloc(sizeof(uint64_t) * (MAX_PKT_LEN + 2));
-        stats.port_tcp_src = (uint64_t*)SnortAlloc(sizeof(uint64_t) * (MAX_PORT+1));
-        stats.port_tcp_dst = (uint64_t*)SnortAlloc(sizeof(uint64_t) * (MAX_PORT+1));
-        stats.port_udp_src = (uint64_t*)SnortAlloc(sizeof(uint64_t) * (MAX_PORT+1));
-        stats.port_udp_dst = (uint64_t*)SnortAlloc(sizeof(uint64_t) * (MAX_PORT+1));
-        stats.type_icmp = (uint64_t*)SnortAlloc(sizeof(uint64_t) * 256);
+    formatter->set_field(SR_TCP, FR_SRC_BYTES, &tcp.src);
+    formatter->set_field(SR_TCP, FR_DST_BYTES, &tcp.dst);
+    formatter->set_field(SR_TCP, FR_HIGH_BYTES, tcp.high);
+    
+    formatter->set_field(SR_UDP, FR_SRC_BYTES, &udp.src);
+    formatter->set_field(SR_UDP, FR_DST_BYTES, &udp.dst);
+    formatter->set_field(SR_UDP, FR_HIGH_BYTES, udp.high);
 
-        if ( config->format == PERF_CSV )
-            log_flow_perf_header(fh);
+    formatter->set_field(SR_ICMP, FR_ICMP_TYPE_BYTES, &type_icmp);
 
-        first = false;
-    }
-    else
-    {
-        memset(stats.pkt_len_cnt, 0, sizeof(uint64_t) * (MAX_PKT_LEN + 2));
-        memset(stats.port_tcp_src, 0, sizeof(uint64_t) * (MAX_PORT+1));
-        memset(stats.port_tcp_dst, 0, sizeof(uint64_t) * (MAX_PORT+1));
-        memset(stats.port_udp_src, 0, sizeof(uint64_t) * (MAX_PORT+1));
-        memset(stats.port_udp_dst, 0, sizeof(uint64_t) * (MAX_PORT+1));
-        memset(stats.type_icmp, 0, sizeof(uint64_t) * 256);
-    }
+    formatter->write(fh, cur_time);
+    formatter->clear();
 
-    stats.pkt_total = 0;
-    stats.byte_total = 0;
+    byte_total = 0;
 
-    stats.port_tcp_high=0;
-    stats.port_tcp_total=0;
+    memset(&pkt_len_cnt[0], 0, pkt_len_cnt.size() * sizeof(PegCount));
+    pkt_len_oversize_cnt = 0;
 
-    stats.port_udp_high=0;
-    stats.port_udp_total=0;
+    memset(&tcp.src[0], 0, tcp.src.size() * sizeof(PegCount));
+    memset(&tcp.dst[0], 0, tcp.dst.size() * sizeof(PegCount));
+    tcp.high = 0;
 
-    stats.type_icmp_total = 0;
+    memset(&udp.src[0], 0, udp.src.size() * sizeof(PegCount));
+    memset(&udp.dst[0], 0, udp.dst.size() * sizeof(PegCount));
+    udp.high = 0;
+    
+    memset(&type_icmp[0], 0, type_icmp.size() * sizeof(PegCount));
 }
 
-void FlowTracker::update(Packet* p)
+void FlowTracker::update_transport_flows(int sport, int dport,
+    FlowProto& proto, int len)
 {
-    if (!p->is_rebuilt())
-        update_flow_stats(&stats, p);
-}
+    if (sport <= config->flow_max_port_to_track &&
+        dport > config->flow_max_port_to_track)
+    {
+        proto.src[sport] += len;
+    }
 
-void FlowTracker::process(bool)
-{
-    process_flow_stats(&stats, fh, config->format, cur_time);
+    else if (dport <= config->flow_max_port_to_track &&
+        sport > config->flow_max_port_to_track)
+    {
+        proto.dst[dport] += len;
+    }
 
-    if (!(config->perf_flags & PERF_SUMMARY))
-        reset();
-}
+    else if (sport <= config->flow_max_port_to_track &&
+        dport <= config->flow_max_port_to_track)
+    {
+        proto.src[sport] += len;
+        proto.dst[dport] += len;
+    }
 
+    else
+    {
+        proto.high += len;
+    }
+}
index ce5c03b40fce602423116db3e2f09aae3ded5a40..f5c5527cf0cf3b3c0a96acccc663ff3b42fbbfe8 100644 (file)
 
 #include "perf_tracker.h"
 
+struct FlowProto
+{
+    std::vector<PegCount> src;
+    std::vector<PegCount> dst;
+    PegCount high;
+};
+
 class FlowTracker : public PerfTracker
 {
 public:
-    RawFlowStats stats;
-
     FlowTracker(PerfConfig* perf);
-    ~FlowTracker();
 
     void reset() override;
     void update(Packet*) override;
     void process(bool) override;
+
+private:
+    PegCount byte_total = 0;
+
+    std::vector<PegCount> pkt_len_cnt;
+    PegCount pkt_len_oversize_cnt = 0;
+
+    FlowProto udp;
+    FlowProto tcp;
+
+    std::vector<PegCount> type_icmp;
+
+    void update_transport_flows(int sport, int dport,
+        FlowProto& proto, int len);
 };
 
-extern THREAD_LOCAL FlowTracker* perf_flow;
 #endif
 
diff --git a/src/network_inspectors/perf_monitor/perf_flow.cc b/src/network_inspectors/perf_monitor/perf_flow.cc
deleted file mode 100644 (file)
index fd63820..0000000
+++ /dev/null
@@ -1,569 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2016 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2002-2013 Sourcefire, Inc.
-//
-// 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.
-//--------------------------------------------------------------------------
-/*
-** authors:
-** Marc Norton <mnorton@sourcefire.com>
-** Dan Roelker <droelker@sourcefire.com>
-**
-** NOTES
-**   4.10.02 - Initial Checkin.  Norton
-**   5.5.02  - Changed output format and added output structure for
-**             easy stat printing. Roelker
-**   5.29.02 - Added ICMP traffic stats and overall protocol flow
-**             stats. Roelker
-**  DESCRIPTION
-**    The following subroutines track eand analyze the traffic flow
-**  statistics.
-**
-**   PacketLen vs Packet Count
-**   TCP-Port vs Packet Count
-**   UDP-Port vs Packet Count
-**   TCP High<->High Port Count
-**   UDP High<->High Port Count
-*/
-
-#include "perf_flow.h"
-
-#include <time.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "main/snort_types.h"
-#include "perf_module.h"
-#include "perf_monitor.h"
-#include "protocols/icmp4.h"
-#include "sfip/sf_ip.h"
-#include "utils/util.h"
-
-static void display_flow_stats(FlowStats* flow_stats, FILE*);
-static void write_flow_stats(FlowStats*, FILE*);
-
-static int update_tcp_flow_stats(RawFlowStats* raw_stats, int sport, int dport, int len)
-{
-    /*
-    ** Track how much data on each port, and hihg<-> high port data
-    */
-    /*
-    if( sport < raw_stats->maxPortToTrack )
-    {
-        raw_stats->port_tcp_src  [ sport ]+= len;
-    }
-
-    if( dport < raw_stats->maxPortToTrack )
-    {
-        raw_stats->port_tcp_dst  [ dport ]+= len;
-    }
-
-    if( sport > 1023 && dport > 1023 )
-    {
-        raw_stats->port_tcp_high += len;
-    }
-    */
-
-    if ( sport <  1024 && dport > 1023 ) //raw_stats->maxPortToTrack )
-    {
-        raw_stats->port_tcp_src  [ sport ]+= len;
-    }
-    else if ( dport < 1024 && sport > 1023 ) //raw_stats->maxPortToTrack )
-    {
-        raw_stats->port_tcp_dst  [ dport ]+= len;
-    }
-    else if ( sport < 1023 && dport < 1023 )
-    {
-        raw_stats->port_tcp_src  [ sport ]+= len;
-        raw_stats->port_tcp_dst  [ dport ]+= len;
-    }
-    else if ( sport > 1023 && dport > 1023 )
-    {
-        raw_stats->port_tcp_src  [ sport ]+= len;
-        raw_stats->port_tcp_dst  [ dport ]+= len;
-
-        raw_stats->port_tcp_high += len;
-    }
-
-    raw_stats->port_tcp_total += len;
-
-    return 0;
-}
-
-static int update_udp_flow_stats(RawFlowStats* raw_stats, int sport, int dport, int len)
-{
-    /*
-     * Track how much data on each port, and hihg<-> high port data
-     */
-    if ( sport <  1024 && dport > 1023 ) //raw_stats->maxPortToTrack )
-    {
-        raw_stats->port_udp_src  [ sport ]+= len;
-    }
-    else if ( dport < 1024 && sport > 1023 ) //raw_stats->maxPortToTrack )
-    {
-        raw_stats->port_udp_dst  [ dport ]+= len;
-    }
-    else if ( sport < 1023 && dport < 1023 )
-    {
-        raw_stats->port_udp_src  [ sport ]+= len;
-        raw_stats->port_udp_dst  [ dport ]+= len;
-    }
-    else if ( sport > 1023 && dport > 1023 )
-    {
-        raw_stats->port_udp_src  [ sport ]+= len;
-        raw_stats->port_udp_dst  [ dport ]+= len;
-
-        raw_stats->port_udp_high += len;
-    }
-
-    raw_stats->port_udp_total += len;
-
-    return 0;
-}
-
-static int update_icmp_flow_stats(RawFlowStats* raw_stats, int type, int len)
-{
-    if (type < 256)
-    {
-        raw_stats->type_icmp[type] += len;
-    }
-
-    raw_stats->type_icmp_total += len;
-
-    return 0;
-}
-
-void update_flow_stats(RawFlowStats* raw_stats, Packet* p)
-{
-    uint32_t len = p->pkth->caplen;
-
-    if (p->ptrs.tcph)
-        update_tcp_flow_stats(raw_stats, p->ptrs.sp, p->ptrs.dp, len);
-    else if (p->ptrs.udph)
-        update_udp_flow_stats(raw_stats, p->ptrs.sp, p->ptrs.dp, len);
-    else if (p->ptrs.icmph)
-        update_icmp_flow_stats(raw_stats, p->ptrs.icmph->type, len);
-
-    // Track how many packets of each length
-    if (len <= MAX_PKT_LEN)
-        raw_stats->pkt_len_cnt[len]++;
-    else
-        raw_stats->pkt_len_cnt[MAX_PKT_LEN+1]++;
-
-    raw_stats->pkt_total++;
-    raw_stats->byte_total += len;
-}
-
-void process_flow_stats(RawFlowStats* raw_stats, FILE* fh, PerfFormat format, time_t time)
-{
-    static THREAD_LOCAL FlowStats flow_stats;
-    int i;
-    double rate, srate, drate, tot_perc;
-    uint64_t tot;
-
-    memset(&flow_stats, 0x00, sizeof(flow_stats));
-
-    /*
-    **  Calculate the percentage of TCP, UDP and ICMP
-    **  and other traffic that consisted in the stream.
-    */
-    if (raw_stats->byte_total != 0)
-    {
-        flow_stats.traffic_tcp = 100.0 * (double)(raw_stats->port_tcp_total) /
-            (double)(raw_stats->byte_total);
-        flow_stats.traffic_udp = 100.0 * (double)(raw_stats->port_udp_total) /
-            (double)(raw_stats->byte_total);
-        flow_stats.traffic_icmp = 100.0 * (double)(raw_stats->type_icmp_total) /
-            (double)(raw_stats->byte_total);
-        flow_stats.traffic_other = 100.0 *
-            (double)((double)raw_stats->byte_total -
-            ((double)raw_stats->port_tcp_total +
-            (double)raw_stats->port_udp_total +
-            (double)raw_stats->type_icmp_total)) / (double)raw_stats->byte_total;
-    }
-    else
-    {
-        flow_stats.traffic_tcp = 0;
-        flow_stats.traffic_udp = 0;
-        flow_stats.traffic_icmp = 0;
-        flow_stats.traffic_other = 0;
-    }
-
-    /*
-    **  Calculate Packet percent of total pkt length
-    **  distribution.
-    */
-    for (i=1; i<MAX_PKT_LEN + 2; i++)
-    {
-        if ( !raw_stats->pkt_len_cnt[i]  )
-            continue;
-
-        rate =  100.0 * (double)(raw_stats->pkt_len_cnt[i]) /
-            (double)(raw_stats->pkt_total);
-
-        if (rate >= 0.1)
-        {
-            flow_stats.pkt_len_percent[i] = rate;
-            flow_stats.pkt_len_percent_count++;
-        }
-        else
-        {
-            flow_stats.pkt_len_percent[i] = 0;
-        }
-    }
-
-    /*
-    **  Calculate TCP port distribution by src, dst and
-    **  total percentage.
-    */
-    for (i = 0; i < perfmon_config->flow_max_port_to_track; i++)
-    {
-        tot = raw_stats->port_tcp_src[i]+raw_stats->port_tcp_dst[i];
-        if (!tot)
-        {
-            flow_stats.port_flow_tcp.tot_perc[i] = 0;
-            continue;
-        }
-
-        tot_perc = 100.0 * tot / raw_stats->port_tcp_total;
-
-        if (tot_perc >= 0.1)
-        {
-            srate =  100.0 * (double)(raw_stats->port_tcp_src[i]) / tot;
-            drate =  100.0 * (double)(raw_stats->port_tcp_dst[i]) / tot;
-
-            flow_stats.port_flow_tcp.tot_perc[i]    = tot_perc;
-            flow_stats.port_flow_tcp.sport_rate[i] = srate;
-            flow_stats.port_flow_tcp.dport_rate[i] = drate;
-            flow_stats.port_flow_tcp_count++;
-        }
-        else
-        {
-            flow_stats.port_flow_tcp.tot_perc[i] = 0;
-        }
-    }
-
-    if (raw_stats->port_tcp_total > 0)
-        flow_stats.port_flow_high_tcp = 100.0 * raw_stats->port_tcp_high / raw_stats->port_tcp_total;
-    else
-        flow_stats.port_flow_high_tcp = 0;
-
-    /*
-    **  Calculate UDP port processing based on src, dst and
-    **  total distributions.
-    */
-    for (i = 0; i < perfmon_config->flow_max_port_to_track; i++)
-    {
-        tot = raw_stats->port_udp_src[i]+raw_stats->port_udp_dst[i];
-        if (!tot)
-        {
-            flow_stats.port_flow_udp.tot_perc[i] = 0;
-            continue;
-        }
-
-        tot_perc= 100.0 * tot / raw_stats->port_udp_total;
-
-        if (tot_perc >= 0.1)
-        {
-            srate =  100.0 * (double)(raw_stats->port_udp_src[i]) / tot;
-            drate =  100.0 * (double)(raw_stats->port_udp_dst[i]) / tot;
-
-            flow_stats.port_flow_udp.tot_perc[i]    = tot_perc;
-            flow_stats.port_flow_udp.sport_rate[i] = srate;
-            flow_stats.port_flow_udp.dport_rate[i] = drate;
-            flow_stats.port_flow_udp_count++;
-        }
-        else
-        {
-            flow_stats.port_flow_udp.tot_perc[i] = 0;
-        }
-    }
-
-    if (raw_stats->port_udp_total > 0)
-        flow_stats.port_flow_high_udp = 100.0 * raw_stats->port_udp_high / raw_stats->port_udp_total;
-    else
-        flow_stats.port_flow_high_udp = 0;
-
-    /*
-    **  Calculate ICMP statistics
-    */
-    for (i=0; i<256; i++)
-    {
-        tot = raw_stats->type_icmp[i];
-        if (!tot)
-        {
-            flow_stats.flow_icmp.tot_perc[i] = 0;
-            continue;
-        }
-
-        tot_perc= 100.0 * tot / raw_stats->type_icmp_total;
-
-        if (tot_perc >= 0.1)
-        {
-            flow_stats.flow_icmp.tot_perc[i]  = tot_perc;
-            flow_stats.flow_icmp_count++;
-        }
-        else
-        {
-            flow_stats.flow_icmp.tot_perc[i] = 0;
-        }
-    }
-
-    flow_stats.time = time;
-
-    if (format == PERF_TEXT)
-        display_flow_stats(&flow_stats, fh);
-
-    else if (format == PERF_CSV)
-        write_flow_stats(&flow_stats, fh);
-}
-
-static void display_flow_stats(FlowStats* flow_stats, FILE* fh)
-{
-    int i;
-
-    LogMessage(fh, "\n");
-    LogMessage(fh, "=========================================\n");
-    LogMessage(fh, "Protocol Byte Flows\n");
-    LogMessage(fh, "=========================================\n");
-    LogMessage(fh, "Protocol    %%Total\n");
-    LogMessage(fh, "------------------\n");
-    LogMessage(fh, "     TCP    %6.2f\n", flow_stats->traffic_tcp);
-    LogMessage(fh, "     UDP    %6.2f\n", flow_stats->traffic_udp);
-    LogMessage(fh, "    ICMP    %6.2f\n", flow_stats->traffic_icmp);
-    LogMessage(fh, "   Other    %6.2f\n", flow_stats->traffic_other);
-
-    LogMessage(fh, "\n");
-    LogMessage(fh, "=========================================\n");
-    LogMessage(fh, "Packet Length Flows\n");
-    LogMessage(fh, "=========================================\n");
-    LogMessage(fh, "Bytes    %%Total\n");
-    LogMessage(fh, "---------------\n");
-    for (i = 1; i < MAX_PKT_LEN + 1; i++)
-    {
-        if (flow_stats->pkt_len_percent[i] < 0.1)
-            continue;
-
-        LogMessage(fh, " %4d    %6.2f\n", i, flow_stats->pkt_len_percent[i]);
-    }
-
-    if (flow_stats->pkt_len_percent[MAX_PKT_LEN + 1] >= 0.1)
-        LogMessage(fh, ">%4d %6.2f%%\n", MAX_PKT_LEN, flow_stats->pkt_len_percent[MAX_PKT_LEN +
-            1]);
-
-    LogMessage(fh, "\n");
-    LogMessage(fh, "=========================================\n");
-    LogMessage(fh, "TCP Port Flows : %.2f%% of Total\n", flow_stats->traffic_tcp);
-    LogMessage(fh, "=========================================\n");
-    if (flow_stats->port_flow_tcp_count || (flow_stats->port_flow_high_tcp >= 0.1))
-    {
-        if (flow_stats->port_flow_tcp_count)
-        {
-            LogMessage(fh, "Port   %%Total     %%Src     %%Dst\n");
-            LogMessage(fh, "-------------------------------\n");
-            for (i = 0; i <= MAX_PORT; i++)
-            {
-                if (flow_stats->port_flow_tcp.tot_perc[i])
-                {
-                    LogMessage(fh, "%4d   %6.2f   %6.2f   %6.2f\n",
-                        i, flow_stats->port_flow_tcp.tot_perc[i],
-                        flow_stats->port_flow_tcp.sport_rate[i],
-                        flow_stats->port_flow_tcp.dport_rate[i]);
-                }
-            }
-        }
-
-        if (flow_stats->port_flow_high_tcp >= 0.1)
-        {
-            if (flow_stats->port_flow_tcp_count)
-                LogMessage(fh, "\n");
-
-            LogMessage(fh, "High<->High: %.2f%%\n", flow_stats->port_flow_high_tcp);
-        }
-    }
-    else
-    {
-        LogMessage(fh, "N/A\n");
-    }
-
-    LogMessage(fh, "\n");
-    LogMessage(fh, "=========================================\n");
-    LogMessage(fh, "UDP Port Flows : %.2f%% of Total\n", flow_stats->traffic_udp);
-    LogMessage(fh, "=========================================\n");
-    if (flow_stats->port_flow_udp_count || (flow_stats->port_flow_high_udp >= 0.1))
-    {
-        if (flow_stats->port_flow_udp_count)
-        {
-            LogMessage(fh, "Port   %%Total     %%Src     %%Dst\n");
-            LogMessage(fh, "-------------------------------\n");
-            for (i = 0; i <= MAX_PORT; i++)
-            {
-                if (flow_stats->port_flow_udp.tot_perc[i])
-                {
-                    LogMessage(fh, "%4d   %6.2f   %6.2f   %6.2f\n",
-                        i, flow_stats->port_flow_udp.tot_perc[i],
-                        flow_stats->port_flow_udp.sport_rate[i],
-                        flow_stats->port_flow_udp.dport_rate[i]);
-                }
-            }
-        }
-
-        if (flow_stats->port_flow_high_udp >= 0.1)
-        {
-            if (flow_stats->port_flow_udp_count)
-                LogMessage(fh, "\n");
-
-            LogMessage(fh, "High<->High: %.2f%%\n", flow_stats->port_flow_high_udp);
-        }
-    }
-    else
-    {
-        LogMessage(fh, "N/A\n");
-    }
-
-    LogMessage(fh, "\n");
-    LogMessage(fh, "=========================================\n");
-    LogMessage(fh, "ICMP Type Flows : %.2f%% of Total\n", flow_stats->traffic_icmp);
-    LogMessage(fh, "=========================================\n");
-    if (flow_stats->flow_icmp_count)
-    {
-        LogMessage(fh, "Type     %%Total\n");
-        LogMessage(fh, "---------------\n");
-        for (i = 0; i < 256; i++)
-        {
-            if (flow_stats->flow_icmp.tot_perc[i])
-            {
-                LogMessage(fh, " %3d     %6.2f\n",
-                    i, flow_stats->flow_icmp.tot_perc[i]);
-            }
-        }
-    }
-    else
-    {
-        LogMessage(fh, "N/A\n");
-    }
-
-    LogMessage(fh, "\n");
-}
-
-static void write_flow_stats(FlowStats* flow_stats, FILE* fh)
-{
-    int i;
-
-    if (!fh)
-        return;
-
-    fprintf(fh, "%ld,", (long)flow_stats->time);
-
-    fprintf(fh, "%.2f,%.2f,%.2f,%.2f,",
-        flow_stats->traffic_tcp,
-        flow_stats->traffic_udp,
-        flow_stats->traffic_icmp,
-        flow_stats->traffic_other);
-
-    fprintf(fh, "%d,", flow_stats->pkt_len_percent_count);
-    for (i = 1; i < MAX_PKT_LEN + 2; i++)
-    {
-        if (flow_stats->pkt_len_percent[i])
-            fprintf(fh, "%d,%.2f,", i, flow_stats->pkt_len_percent[i]);
-    }
-
-    fprintf(fh, "%d,", flow_stats->port_flow_tcp_count);
-    for (i = 0; i <= MAX_PORT; i++)
-    {
-        if (flow_stats->port_flow_tcp.tot_perc[i])
-        {
-            fprintf(fh, "%d,%.2f,%.2f,%.2f,",
-                i, flow_stats->port_flow_tcp.tot_perc[i],
-                flow_stats->port_flow_tcp.sport_rate[i],
-                flow_stats->port_flow_tcp.dport_rate[i]);
-        }
-    }
-
-    fprintf(fh, "%.2f,", flow_stats->port_flow_high_tcp);
-
-    fprintf(fh, "%d,", flow_stats->port_flow_udp_count);
-    for (i = 0; i <= MAX_PORT; i++)
-    {
-        if (flow_stats->port_flow_udp.tot_perc[i])
-        {
-            fprintf(fh, "%d,%.2f,%.2f,%.2f,",
-                i, flow_stats->port_flow_udp.tot_perc[i],
-                flow_stats->port_flow_udp.sport_rate[i],
-                flow_stats->port_flow_udp.dport_rate[i]);
-        }
-    }
-
-    fprintf(fh, "%.2f,", flow_stats->port_flow_high_udp);
-
-    fprintf(fh, "%d,", flow_stats->flow_icmp_count);
-    for (i = 0; i < 256; i++)
-    {
-        if (flow_stats->flow_icmp.tot_perc[i])
-            fprintf(fh, "%d,%.2f,", i, flow_stats->flow_icmp.tot_perc[i]);
-    }
-
-    fprintf(fh, "\n");
-    fflush(fh);
-}
-
-// IMPORTANT - whatever changes you make here, please be sure
-// they correspond to the WriteFlowStats() above!
-void log_flow_perf_header(FILE* fh)
-{
-    if (!fh)
-        return;
-
-    fprintf(fh,
-        "#%s,%s,%s,%s,%s,",
-        "time",
-        "traffic_tcp",
-        "traffic_udp",
-        "traffic_icmp",
-        "traffic_other");
-
-    // Byte flows
-    fprintf(fh,
-        "%s,%s,",
-        "pkt_len_percentCount",
-        "(pktLen,pkt_len_percent)*pkt_len_percentCount");
-
-    // TCP flows
-    fprintf(fh,
-        "%s,%s,%s,",
-        "port_flow_tcp_count",
-        "(port,port_flow_tcp.tot_perc,port_flow_tcp.sport_rate,port_flow_tcp.dport_rate)*port_flow_tcp_count",
-        "port_flow_high_tcp");
-
-    // UDP flows
-    fprintf(fh,
-        "%s,%s,%s,",
-        "port_flow_udp_count",
-        "(port,port_flow_udp.tot_perc,port_flow_udp.sport_rate,port_flow_udp.dport_rate)*port_flow_udp_count",
-        "port_flow_high_udp");
-
-    // ICMP flows
-    fprintf(fh,
-        "%s,%s,",
-        "flow_icmp_count",
-        "(type,flow_icmp.tot_perc)*flow_icmp_count");
-
-    fprintf(fh, "\n");
-    fflush(fh);
-}
-
diff --git a/src/network_inspectors/perf_monitor/perf_flow.h b/src/network_inspectors/perf_monitor/perf_flow.h
deleted file mode 100644 (file)
index b6bcbae..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2016 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2002-2013 Sourcefire, Inc.
-//
-// 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.
-//--------------------------------------------------------------------------
-/*
-** Marc Norton <mnorton@sourcefire.com>
-** Dan Roelker <droelker@sourcefire.com>
-**
-*/
-
-#ifndef PERF_FLOW_H
-#define PERF_FLOW_H
-
-#include "perf_module.h"
-#include "main/snort_types.h"
-#include "hash/sfxhash.h"
-#include "sfip/sfip_t.h"
-#include "protocols/packet.h"
-
-#define MAX_PKT_LEN  9000
-#define MAX_PORT     UINT16_MAX
-
-enum FlowType
-{
-    SFS_TYPE_TCP = 0,
-    SFS_TYPE_UDP,
-    SFS_TYPE_OTHER,
-    SFS_TYPE_MAX
-};
-
-enum FlowState
-{
-    SFS_STATE_TCP_ESTABLISHED = 0,
-    SFS_STATE_TCP_CLOSED,
-    SFS_STATE_UDP_CREATED,
-    SFS_STATE_MAX
-};
-
-struct PortFlow
-{
-    double tot_perc[MAX_PORT+1];
-    double sport_rate[MAX_PORT+1];
-    double dport_rate[MAX_PORT+1];
-};
-
-struct IcmpFlow
-{
-    double tot_perc[256];
-    int display[256];
-};
-
-/* Raw flow statistics */
-struct RawFlowStats
-{
-    time_t time;
-    uint64_t* pkt_len_cnt;
-    uint64_t pkt_total;
-
-    uint64_t byte_total;
-
-    uint64_t* pkt_len_percent;
-
-    uint64_t* port_tcp_src;
-    uint64_t* port_tcp_dst;
-    uint64_t* port_udp_src;
-    uint64_t* port_udp_dst;
-
-    uint64_t* type_icmp;
-
-    uint64_t port_tcp_high;
-    uint64_t port_tcp_total;
-
-    uint64_t port_udp_high;
-    uint64_t port_udp_total;
-
-    uint64_t type_icmp_total;
-};
-
-/* Processed flow statistics */
-struct FlowStats
-{
-    time_t time;
-    double pkt_len_percent[MAX_PKT_LEN + 2];
-    int pkt_len_percent_count;
-
-    double traffic_tcp;
-    double traffic_udp;
-    double traffic_icmp;
-    double traffic_other;
-
-    PortFlow port_flow_tcp;
-    double port_flow_high_tcp;
-    int port_flow_tcp_count;
-
-    PortFlow port_flow_udp;
-    double port_flow_high_udp;
-    int port_flow_udp_count;
-
-    IcmpFlow flow_icmp;
-    int flow_icmp_count;
-};
-
-struct TrafficStats
-{
-    uint64_t packets_a_to_b;
-    uint64_t bytes_a_to_b;
-    uint64_t packets_b_to_a;
-    uint64_t bytes_b_to_a;
-};
-
-struct FlowStateValue
-{
-    TrafficStats traffic_stats[SFS_TYPE_MAX];
-    uint64_t total_packets;
-    uint64_t total_bytes;
-    uint32_t state_changes[SFS_STATE_MAX];
-};
-
-/*
-**  Functions for the performance functions to call
-*/
-void update_flow_stats(RawFlowStats*, Packet*);
-void process_flow_stats(RawFlowStats*, FILE*, PerfFormat, time_t);
-void free_flow_stats(RawFlowStats*);
-void log_flow_perf_header(FILE*);
-
-#endif
-
index 6cf99d38c475c64f6db0ca71ebe918139dd378ac..5d8cc340be0618da4ef809e4469748b6e1cffbc5 100644 (file)
@@ -65,6 +65,16 @@ void PerfFormatter::set_field(unsigned section, unsigned field, const char* val)
     types[section][field] = FT_STRING;
 }
 
+void PerfFormatter::set_field(unsigned section, unsigned field,
+    vector<PegCount>* val)
+{
+    FormatterValue fv;
+
+    fv.ipc = val;
+    values[section][field] = fv;
+    types[section][field] = FT_IDX_PEG_COUNT;
+}
+
 void PerfFormatter::clear()
 {
     for( unsigned i = 0; i < types.size(); i++ )
index cf22709ac18f8a72f08a8dfafe6eb590cce4887a..7c80fedc05b6ae731f65c18c597ba1985e9952ac 100644 (file)
@@ -31,6 +31,7 @@ union FormatterValue
     PegCount pc;
     double d;
     const char* s;
+    std::vector<PegCount>* ipc;
 };
 
 enum FormatterType : uint8_t
@@ -38,7 +39,8 @@ enum FormatterType : uint8_t
     FT_UNSET,
     FT_PEG_COUNT,
     FT_DOUBLE,
-    FT_STRING
+    FT_STRING,
+    FT_IDX_PEG_COUNT
 };
 
 class PerfFormatter
@@ -52,6 +54,7 @@ public:
     virtual void set_field(unsigned, unsigned, PegCount);
     virtual void set_field(unsigned, unsigned, double);
     virtual void set_field(unsigned, unsigned, const char*);
+    virtual void set_field(unsigned, unsigned, std::vector<PegCount>*);
     virtual void write(FILE*, time_t) = 0;
     virtual void clear();
 
index 5994c8a7c5430fe71d7903199a220c14cf608c06..b806e0bcbcdc14e85f09ec3093ac6d59df28f45d 100644 (file)
@@ -68,7 +68,7 @@ static const Parameter s_params[] =
     { "max_file_size", Parameter::PT_INT, "4096:", "1073741824",
       "files will be rolled over if they exceed this size" },
 
-    { "flow_ports", Parameter::PT_INT, "0:", "1023",
+    { "flow_ports", Parameter::PT_INT, "0:65535", "1023",
       "maximum ports to track" },
 
     { "output", Parameter::PT_ENUM, "file | console", "file",
index 8b4d47e7d49f744168430f1135dbf4eae1cb3980..3f301491e2a6fc5b67e75b0023ef37f355bf876e 100644 (file)
@@ -158,7 +158,7 @@ void PerfMonitor::tinit()
         trackers->push_back(new BaseTracker(&config));
 
     if (config.perf_flags & PERF_FLOW)
-        trackers->push_back(perf_flow = new FlowTracker(&config));
+        trackers->push_back(new FlowTracker(&config));
 
     if (config.perf_flags & PERF_FLOWIP)
         trackers->push_back(perf_flow_ip = new FlowIPTracker(&config));
@@ -180,7 +180,6 @@ void PerfMonitor::tinit()
 
 void PerfMonitor::tterm()
 {
-    perf_flow = nullptr;
     perf_flow_ip = nullptr;
     perf_event = nullptr;
 
index 5f793103ff8018e582d06dc9370f35dab365e33c..cd8efa0f9cde134098acec6e652233a798091463 100644 (file)
 
 #include <vector>
 #include "perf_module.h"
-#include "perf_flow.h"
 #include "main/snort_types.h"
 #include "main/snort_debug.h"
 #include "main/thread.h"
 #include "protocols/packet.h"
 #include "utils/stats.h"
 
-
-
 //FIXIT-M: this shouldn't be needed outside of perfmon
 extern PerfConfig* perfmon_config;
 extern THREAD_LOCAL bool perfmon_rotate_perf_file;
diff --git a/src/network_inspectors/perf_monitor/test/CMakeLists.txt b/src/network_inspectors/perf_monitor/test/CMakeLists.txt
deleted file mode 100644 (file)
index a66912f..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-add_cpputest(perf_monitor_test perf_monitor)
-
diff --git a/src/network_inspectors/perf_monitor/test/Makefile.am b/src/network_inspectors/perf_monitor/test/Makefile.am
deleted file mode 100644 (file)
index 9f345a3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-
-AM_DEFAULT_SOURCE_EXT = .cc
-
-check_PROGRAMS = \
-perf_montor_test.cc
-
-TESTS = $(check_PROGRAMS)
-
-perf_monitor_test_LDADD = ../util_math.o
-
diff --git a/src/network_inspectors/perf_monitor/test/perf_monitor_test.cc b/src/network_inspectors/perf_monitor/test/perf_monitor_test.cc
deleted file mode 100644 (file)
index 432b4be..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2015-2016 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_test.cc author Carter Waxman <cwaxman@cisco.com>
-// unit test main
-
-#include <CppUTest/CommandLineTestRunner.h>
-#include <CppUTest/TestHarness.h>
-
-#include "../perf_monitor.h"
-
-TEST_GROUP(perf_monitor_config)
-{
-};
-
-TEST(perf_monitor_config, packets)
-{
-}
-
-int main(int argc, char** argv)
-{
-    return CommandLineTestRunner::RunAllTests(argc, argv);
-}
-
index 1740aecc1897f47e288b9b967648d5c94213590c..97a2f63db3e7f3227bddf5f07737f4d7826196fa 100644 (file)
@@ -62,6 +62,7 @@ void TextFormatter::write(FILE* fh, time_t)
                     }
                     LogStat(field_names[i][j].c_str(), values[i][j].d, fh);
                     break;
+
                 case FT_PEG_COUNT:
                     if( !head && values[i][j].pc != 0 )
                     {
@@ -70,6 +71,7 @@ void TextFormatter::write(FILE* fh, time_t)
                     }
                     LogCount(field_names[i][j].c_str(), values[i][j].pc, fh);
                     break;
+
                 case FT_STRING:
                     if( values[i][j].s )
                     {
@@ -81,6 +83,27 @@ void TextFormatter::write(FILE* fh, time_t)
                         LogValue(field_names[i][j].c_str(), values[i][j].s, fh);
                     }
                     break;
+
+                case FT_IDX_PEG_COUNT:
+                {
+                    vector<PegCount>* vals = values[i][j].ipc;
+                    for( unsigned k = 0; k < vals->size(); k++ )
+                    {
+                        if( !vals->at(k) )
+                            continue;
+
+                        if( !head )
+                        {
+                            LogLabel(section_names[i].c_str(), fh);
+                            head = true;
+                        }
+                        std::ostringstream ss;
+                        ss << field_names[i][j] << "." << k;
+                        LogCount(ss.str().c_str(), vals->at(k), fh);
+                    }
+                    break;
+                }
+
                 case FT_UNSET:
                     break; 
             }
@@ -100,7 +123,13 @@ TEST_CASE("text output", "[TextFormatter]")
         "--------------------------------------------------\n"
         "other\n"
         "                     four: 34.5678\n"
-        "                     five: hellothere\n";
+        "--------------------------------------------------\n"
+        "str\n"
+        "                     five: hellothere\n"
+        "--------------------------------------------------\n"
+        "vec\n"
+        "                 vector.0: 50\n"
+        "                 vector.2: 70\n";
         
     FILE* fh = tmpfile();
     TextFormatter f;
@@ -111,14 +140,24 @@ TEST_CASE("text output", "[TextFormatter]")
     f.register_section("other");
     f.register_field("three");
     f.register_field("four");
+    f.register_section("str");
     f.register_field("five");
+    f.register_section("vec");
+    f.register_field("vector");
     f.finalize_fields(fh);
 
     f.set_field(0, 0, (PegCount)1);
     f.set_field(0, 1, (PegCount)0);
     f.set_field(1, 0, (PegCount)0);
     f.set_field(1, 1, 34.5678);
-    f.set_field(1, 2, "hellothere");
+    f.set_field(2, 0, "hellothere");
+
+    std::vector<PegCount> kvp;
+    kvp.push_back(50);
+    kvp.push_back(0);
+    kvp.push_back(70);
+    f.set_field(3, 0, &kvp);
+    
     f.write(fh, (time_t)1234567890);
 
     f.clear();