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
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 \
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++)
{
FR_USER = 0,
FR_SYSTEM,
- FR_IDLE
+ FR_WALL
};
static inline uint64_t get_microseconds(struct timeval t)
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,
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();
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();
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);
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();
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);
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;
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;
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);
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();
// 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;
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()
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
}
}
-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();
}
#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:
#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;
+ }
+}
#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
+++ /dev/null
-//--------------------------------------------------------------------------
-// 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);
-}
-
+++ /dev/null
-//--------------------------------------------------------------------------
-// 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
-
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++ )
PegCount pc;
double d;
const char* s;
+ std::vector<PegCount>* ipc;
};
enum FormatterType : uint8_t
FT_UNSET,
FT_PEG_COUNT,
FT_DOUBLE,
- FT_STRING
+ FT_STRING,
+ FT_IDX_PEG_COUNT
};
class PerfFormatter
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();
{ "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",
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));
void PerfMonitor::tterm()
{
- perf_flow = nullptr;
perf_flow_ip = nullptr;
perf_event = nullptr;
#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;
+++ /dev/null
-add_cpputest(perf_monitor_test perf_monitor)
-
+++ /dev/null
-
-AM_DEFAULT_SOURCE_EXT = .cc
-
-check_PROGRAMS = \
-perf_montor_test.cc
-
-TESTS = $(check_PROGRAMS)
-
-perf_monitor_test_LDADD = ../util_math.o
-
+++ /dev/null
-//--------------------------------------------------------------------------
-// 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);
-}
-
}
LogStat(field_names[i][j].c_str(), values[i][j].d, fh);
break;
+
case FT_PEG_COUNT:
if( !head && values[i][j].pc != 0 )
{
}
LogCount(field_names[i][j].c_str(), values[i][j].pc, fh);
break;
+
case FT_STRING:
if( values[i][j].s )
{
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;
}
"--------------------------------------------------\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;
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();