From: Carter Waxman Date: Fri, 8 Apr 2016 20:55:20 +0000 (-0400) Subject: refactored FlowTracker into c++. added PegCount vector type to PerfFormatter. removed... X-Git-Tag: 3.0.0-233~457^2~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d80b7eb57f06446447a3a9232b8b542eab7a2df5;p=thirdparty%2Fsnort3.git refactored FlowTracker into c++. added PegCount vector type to PerfFormatter. removed unused test directory. removed remainder of legacy code (perf_flow.*) --- diff --git a/src/network_inspectors/perf_monitor/CMakeLists.txt b/src/network_inspectors/perf_monitor/CMakeLists.txt index 17f95727e..8730050f3 100644 --- a/src/network_inspectors/perf_monitor/CMakeLists.txt +++ b/src/network_inspectors/perf_monitor/CMakeLists.txt @@ -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 diff --git a/src/network_inspectors/perf_monitor/Makefile.am b/src/network_inspectors/perf_monitor/Makefile.am index cda600c5e..73efbd19a 100644 --- a/src/network_inspectors/perf_monitor/Makefile.am +++ b/src/network_inspectors/perf_monitor/Makefile.am @@ -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 \ diff --git a/src/network_inspectors/perf_monitor/base_tracker.cc b/src/network_inspectors/perf_monitor/base_tracker.cc index e951d9682..55700a9ab 100644 --- a/src/network_inspectors/perf_monitor/base_tracker.cc +++ b/src/network_inspectors/perf_monitor/base_tracker.cc @@ -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 idxs = config->mod_peg_idxs.at(i); + vector idxs = config->mod_peg_idxs[i]; PegCount* pegs = m->get_counts(); for (unsigned j = 0; j < idxs.size(); j++) diff --git a/src/network_inspectors/perf_monitor/cpu_tracker.cc b/src/network_inspectors/perf_monitor/cpu_tracker.cc index 6ed2bf538..3ac4a041a 100644 --- a/src/network_inspectors/perf_monitor/cpu_tracker.cc +++ b/src/network_inspectors/perf_monitor/cpu_tracker.cc @@ -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); diff --git a/src/network_inspectors/perf_monitor/csv_formatter.cc b/src/network_inspectors/perf_monitor/csv_formatter.cc index 1174b10c1..34061b367 100644 --- a/src/network_inspectors/perf_monitor/csv_formatter.cc +++ b/src/network_inspectors/perf_monitor/csv_formatter.cc @@ -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 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(); diff --git a/src/network_inspectors/perf_monitor/flow_ip_tracker.cc b/src/network_inspectors/perf_monitor/flow_ip_tracker.cc index 3ca8d3871..22d4528ce 100644 --- a/src/network_inspectors/perf_monitor/flow_ip_tracker.cc +++ b/src/network_inspectors/perf_monitor/flow_ip_tracker.cc @@ -19,7 +19,6 @@ // flow_ip_tracker.cc author Carter Waxman #include "flow_ip_tracker.h" -#include "perf_flow.h" #include "perf_module.h" #include "sfip/sf_ip.h" @@ -27,6 +26,28 @@ #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(); } diff --git a/src/network_inspectors/perf_monitor/flow_ip_tracker.h b/src/network_inspectors/perf_monitor/flow_ip_tracker.h index c56ad51b1..c97fedcb6 100644 --- a/src/network_inspectors/perf_monitor/flow_ip_tracker.h +++ b/src/network_inspectors/perf_monitor/flow_ip_tracker.h @@ -22,9 +22,40 @@ #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: diff --git a/src/network_inspectors/perf_monitor/flow_tracker.cc b/src/network_inspectors/perf_monitor/flow_tracker.cc index 29a8ca670..232ef1fa7 100644 --- a/src/network_inspectors/perf_monitor/flow_tracker.cc +++ b/src/network_inspectors/perf_monitor/flow_tracker.cc @@ -21,105 +21,159 @@ #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; + } +} diff --git a/src/network_inspectors/perf_monitor/flow_tracker.h b/src/network_inspectors/perf_monitor/flow_tracker.h index ce5c03b40..f5c5527cf 100644 --- a/src/network_inspectors/perf_monitor/flow_tracker.h +++ b/src/network_inspectors/perf_monitor/flow_tracker.h @@ -23,19 +23,36 @@ #include "perf_tracker.h" +struct FlowProto +{ + std::vector src; + std::vector 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 pkt_len_cnt; + PegCount pkt_len_oversize_cnt = 0; + + FlowProto udp; + FlowProto tcp; + + std::vector 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 index fd6382041..000000000 --- a/src/network_inspectors/perf_monitor/perf_flow.cc +++ /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 -** Dan Roelker -** -** 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 -#include -#include -#include -#include -#include - -#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; ipkt_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 index b6bcbae85..000000000 --- a/src/network_inspectors/perf_monitor/perf_flow.h +++ /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 -** Dan Roelker -** -*/ - -#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 - diff --git a/src/network_inspectors/perf_monitor/perf_formatter.cc b/src/network_inspectors/perf_monitor/perf_formatter.cc index 6cf99d38c..5d8cc340b 100644 --- a/src/network_inspectors/perf_monitor/perf_formatter.cc +++ b/src/network_inspectors/perf_monitor/perf_formatter.cc @@ -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* 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++ ) diff --git a/src/network_inspectors/perf_monitor/perf_formatter.h b/src/network_inspectors/perf_monitor/perf_formatter.h index cf22709ac..7c80fedc0 100644 --- a/src/network_inspectors/perf_monitor/perf_formatter.h +++ b/src/network_inspectors/perf_monitor/perf_formatter.h @@ -31,6 +31,7 @@ union FormatterValue PegCount pc; double d; const char* s; + std::vector* 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*); virtual void write(FILE*, time_t) = 0; virtual void clear(); diff --git a/src/network_inspectors/perf_monitor/perf_module.cc b/src/network_inspectors/perf_monitor/perf_module.cc index 5994c8a7c..b806e0bcb 100644 --- a/src/network_inspectors/perf_monitor/perf_module.cc +++ b/src/network_inspectors/perf_monitor/perf_module.cc @@ -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", diff --git a/src/network_inspectors/perf_monitor/perf_monitor.cc b/src/network_inspectors/perf_monitor/perf_monitor.cc index 8b4d47e7d..3f301491e 100644 --- a/src/network_inspectors/perf_monitor/perf_monitor.cc +++ b/src/network_inspectors/perf_monitor/perf_monitor.cc @@ -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; diff --git a/src/network_inspectors/perf_monitor/perf_monitor.h b/src/network_inspectors/perf_monitor/perf_monitor.h index 5f793103f..cd8efa0f9 100644 --- a/src/network_inspectors/perf_monitor/perf_monitor.h +++ b/src/network_inspectors/perf_monitor/perf_monitor.h @@ -26,15 +26,12 @@ #include #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 index a66912f32..000000000 --- a/src/network_inspectors/perf_monitor/test/CMakeLists.txt +++ /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 index 9f345a38c..000000000 --- a/src/network_inspectors/perf_monitor/test/Makefile.am +++ /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 index 432b4be52..000000000 --- a/src/network_inspectors/perf_monitor/test/perf_monitor_test.cc +++ /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 -// unit test main - -#include -#include - -#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); -} - diff --git a/src/network_inspectors/perf_monitor/text_formatter.cc b/src/network_inspectors/perf_monitor/text_formatter.cc index 1740aecc1..97a2f63db 100644 --- a/src/network_inspectors/perf_monitor/text_formatter.cc +++ b/src/network_inspectors/perf_monitor/text_formatter.cc @@ -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* 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 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();