counts[i] = 0;
}
+PegCount Module::get_global_count(const char* name) const
+{
+ const PegInfo* infos = get_pegs();
+
+ for ( unsigned i = 0; infos[i].name; i++ )
+ {
+ if ( strcmp(name, infos[i].name) == 0 )
+ return counts[i];
+ }
+ assert(false); // wrong name = programmer error
+ return 0;
+}
+
bool Module::verified_begin(const char* fqn, int idx, SnortConfig* c)
{
table_level++;
virtual const PegInfo* get_pegs() const
{ return nullptr; }
+ virtual bool counts_need_prep() const
+ { return false; }
+
+ virtual void prep_counts() { }
+
// counts and profile are thread local
virtual PegCount* get_counts() const
{ return nullptr; }
+ virtual PegCount get_global_count(const char* name) const;
+
virtual int get_num_counts() const
{ return num_counts; }
for ( auto p : s_modules )
{
std::lock_guard<std::mutex> lock(stats_mutex);
+ p->mod->prep_counts();
p->mod->sum_stats(true);
}
std::lock_guard<std::mutex> lock(stats_mutex);
- pc_sum();
}
void ModuleManager::reset_stats(SnortConfig*)
void BaseTracker::process(bool summary)
{
+ for ( Module* mod : config->mods_to_prep )
+ mod->prep_counts();
+
write();
- for ( auto const& mod : config->modules )
+ for ( const ModuleConfig& mod : config->modules )
if ( !summary )
mod.ptr->sum_stats(false);
}
}
for ( auto& mod : modules )
+ {
if ( !mod.resolve() )
return false;
+ if ( mod.ptr->counts_need_prep() )
+ mods_to_prep.push_back(mod.ptr);
+ }
+
return true;
}
PerfFormat format = PerfFormat::CSV;
PerfOutput output = PerfOutput::TO_FILE;
std::vector<ModuleConfig> modules;
+ std::vector<snort::Module*> mods_to_prep;
bool resolve();
};
#include "log/messages.h"
#include "main/snort_config.h"
+#include "active.h"
+#include "sfdaq.h"
#include "sfdaq_config.h"
+#include "trough.h"
using namespace snort;
#define sfdaq_help "configure packet acquisition interface"
+struct DAQStats
+{
+ PegCount pcaps;
+ PegCount received;
+ PegCount analyzed;
+ PegCount dropped;
+ PegCount filtered;
+ PegCount outstanding;
+ PegCount injected;
+ PegCount verdicts[MAX_DAQ_VERDICT];
+ PegCount internal_blacklist;
+ PegCount internal_whitelist;
+ PegCount skipped;
+ PegCount idle;
+ PegCount rx_bytes;
+};
+
+const PegInfo daq_names[] =
+{
+ { CountType::MAX, "pcaps", "total files and interfaces processed" },
+ { CountType::SUM, "received", "total packets received from DAQ" },
+ { CountType::SUM, "analyzed", "total packets analyzed from DAQ" },
+ { CountType::SUM, "dropped", "packets dropped" },
+ { CountType::SUM, "filtered", "packets filtered out" },
+ { CountType::SUM, "outstanding", "packets unprocessed" },
+ { CountType::SUM, "injected", "active responses or replacements" },
+ { CountType::SUM, "allow", "total allow verdicts" },
+ { CountType::SUM, "block", "total block verdicts" },
+ { CountType::SUM, "replace", "total replace verdicts" },
+ { CountType::SUM, "whitelist", "total whitelist verdicts" },
+ { CountType::SUM, "blacklist", "total blacklist verdicts" },
+ { CountType::SUM, "ignore", "total ignore verdicts" },
+ { CountType::SUM, "retry", "total retry verdicts" },
+
+ // FIXIT-L these are not exactly DAQ counts - but they are related
+ { CountType::SUM, "internal_blacklist",
+ "packets blacklisted internally due to lack of DAQ support" },
+ { CountType::SUM, "internal_whitelist",
+ "packets whitelisted internally due to lack of DAQ support" },
+ { CountType::SUM, "skipped", "packets skipped at startup" },
+ { CountType::SUM, "idle", "attempts to acquire from DAQ without available packets" },
+ { CountType::SUM, "rx_bytes", "total bytes received" },
+ { CountType::END, nullptr, nullptr }
+};
+
+static THREAD_LOCAL DAQStats stats;
+
static const Parameter string_list_param[] =
{
{ "str", Parameter::PT_STRING, nullptr, nullptr, "string parameter" },
PegCount* SFDAQModule::get_counts() const
{
- static THREAD_LOCAL DAQStats ds;
+ return (PegCount*) &stats;
+}
+
+static DAQ_Stats_t operator-(const DAQ_Stats_t& left, const DAQ_Stats_t& right)
+{
+ DAQ_Stats_t ret;
+
+ ret.hw_packets_received = left.hw_packets_received - right.hw_packets_received;
+ ret.hw_packets_dropped = left.hw_packets_dropped - right.hw_packets_dropped;
+ ret.packets_received = left.packets_received - right.packets_received;
+ ret.packets_filtered = left.packets_filtered - right.packets_filtered;
+ ret.packets_injected = left.packets_injected - right.packets_injected;
+
+ for ( unsigned i = 0; i < MAX_DAQ_VERDICT; i++ )
+ ret.verdicts[i] = left.verdicts[i] - right.verdicts[i];
+
+ return ret;
+}
+
+void SFDAQModule::prep_counts()
+{
+ static THREAD_LOCAL DAQ_Stats_t sfdaq_stats;
+ static THREAD_LOCAL PegCount last_skipped = 0;
+ static THREAD_LOCAL bool did_init = false;
+
+ if ( !did_init )
+ {
+ memset(&sfdaq_stats, 0, sizeof(DAQ_Stats_t));
+ did_init = true;
+ }
+
+ if ( SFDAQ::get_local_instance() == nullptr )
+ return;
+
+ DAQ_Stats_t new_sfdaq_stats = *SFDAQ::get_stats();
+
+ // must subtract explicitly; can't zero; daq stats are cumulative ...
+ DAQ_Stats_t sfdaq_stats_delta = new_sfdaq_stats - sfdaq_stats;
+
+ uint64_t pkts_out = new_sfdaq_stats.hw_packets_received -
+ new_sfdaq_stats.packets_filtered -
+ new_sfdaq_stats.packets_received;
+
+ stats.pcaps = Trough::get_file_count();
+ stats.received = sfdaq_stats_delta.hw_packets_received;
+ stats.analyzed = sfdaq_stats_delta.packets_received;
+ stats.dropped = sfdaq_stats_delta.hw_packets_dropped;
+ stats.filtered = sfdaq_stats_delta.packets_filtered;
+ stats.outstanding = pkts_out;
+ stats.injected = sfdaq_stats_delta.packets_injected;
+
+ for ( unsigned i = 0; i < MAX_DAQ_VERDICT; i++ )
+ stats.verdicts[i] = sfdaq_stats_delta.verdicts[i];
+
+ stats.internal_blacklist = aux_counts.internal_blacklist;
+ stats.internal_whitelist = aux_counts.internal_whitelist;
+ stats.skipped = SnortConfig::get_conf()->pkt_skip - last_skipped;
+ stats.idle = aux_counts.idle;
+ stats.rx_bytes = aux_counts.rx_bytes;
+
+ memset(&aux_counts, 0, sizeof(AuxCount));
+ last_skipped = stats.skipped;
- get_daq_stats(ds);
- return (PegCount*) &ds;
+ sfdaq_stats = new_sfdaq_stats;
+ for ( unsigned i = 0; i < MAX_DAQ_VERDICT; i++ )
+ sfdaq_stats.verdicts[i] = new_sfdaq_stats.verdicts[i];
}
const PegInfo* get_pegs() const override;
PegCount* get_counts() const override;
+ void prep_counts() override;
+
+ bool counts_need_prep() const override
+ { return true; }
Usage get_usage() const override
{ return GLOBAL; }
#include "detection/detection_engine.h"
#include "file_api/file_stats.h"
#include "filters/sfthreshold.h"
+#include "framework/module.h"
#include "helpers/process.h"
#include "log/messages.h"
#include "main/snort_config.h"
#define STATS_SEPARATOR \
"--------------------------------------------------"
-static DAQ_Stats_t g_daq_stats;
-static AuxCount gaux;
-
-THREAD_LOCAL PacketCount pc;
THREAD_LOCAL AuxCount aux_counts;
+THREAD_LOCAL PacketCount pc;
ProcessCount proc_stats;
PegCount get_packet_number()
struct timeval difftime;
TIMERSUB(&endtime, &starttime, &difftime);
+
uint32_t tmp = (uint32_t)difftime.tv_sec;
uint32_t total_secs = tmp;
if ( total_secs < 1 )
LogMessage("%25.25s: %lu.%lu\n", "seconds",
(unsigned long)difftime.tv_sec, (unsigned long)difftime.tv_usec);
- PegCount num_pkts = g_daq_stats.hw_packets_received;
+ PegCount num_pkts = ModuleManager::get_module("daq")->get_global_count("received");
LogMessage("%25.25s: " STDu64 "\n", "packets", num_pkts);
uint64_t pps = (num_pkts / total_secs);
}
//-------------------------------------------------------------------------
-// FIXIT-L need better encapsulation of these daq counts by their modules
-
-const PegInfo daq_names[] =
-{
- { CountType::SUM, "pcaps", "total files and interfaces processed" },
- { CountType::SUM, "received", "total packets received from DAQ" },
- { CountType::SUM, "analyzed", "total packets analyzed from DAQ" },
- { CountType::SUM, "dropped", "packets dropped" },
- { CountType::SUM, "filtered", "packets filtered out" },
- { CountType::SUM, "outstanding", "packets unprocessed" },
- { CountType::SUM, "injected", "active responses or replacements" },
- { CountType::SUM, "allow", "total allow verdicts" },
- { CountType::SUM, "block", "total block verdicts" },
- { CountType::SUM, "replace", "total replace verdicts" },
- { CountType::SUM, "whitelist", "total whitelist verdicts" },
- { CountType::SUM, "blacklist", "total blacklist verdicts" },
- { CountType::SUM, "ignore", "total ignore verdicts" },
- { CountType::SUM, "retry", "total retry verdicts" },
-
- // FIXIT-L these are not exactly DAQ counts - but they are related
- { CountType::SUM, "internal_blacklist",
- "packets blacklisted internally due to lack of DAQ support" },
- { CountType::SUM, "internal_whitelist",
- "packets whitelisted internally due to lack of DAQ support" },
- { CountType::SUM, "skipped", "packets skipped at startup" },
- { CountType::SUM, "idle", "attempts to acquire from DAQ without available packets" },
- { CountType::SUM, "rx_bytes", "total bytes received" },
- { CountType::END, nullptr, nullptr }
-};
const PegInfo pc_names[] =
{
//-------------------------------------------------------------------------
-void pc_sum()
-{
- // must sum explicitly; can't zero; daq stats are cumulative ...
- const DAQ_Stats_t* daq_stats = SFDAQ::get_stats();
-
- g_daq_stats.hw_packets_received += daq_stats->hw_packets_received;
- g_daq_stats.hw_packets_dropped += daq_stats->hw_packets_dropped;
- g_daq_stats.packets_received += daq_stats->packets_received;
- g_daq_stats.packets_filtered += daq_stats->packets_filtered;
- g_daq_stats.packets_injected += daq_stats->packets_injected;
-
- for ( unsigned i = 0; i < MAX_DAQ_VERDICT; i++ )
- g_daq_stats.verdicts[i] += daq_stats->verdicts[i];
-
- sum_stats((PegCount*)&gaux, (PegCount*)&aux_counts, sizeof(aux_counts)/sizeof(PegCount));
-
- memset(&aux_counts, 0, sizeof(aux_counts));
-}
-
-//-------------------------------------------------------------------------
-
-void get_daq_stats(DAQStats& daq_stats)
-{
- uint64_t pkts_recv = g_daq_stats.hw_packets_received;
- uint64_t pkts_drop = g_daq_stats.hw_packets_dropped;
- uint64_t pkts_inj = g_daq_stats.packets_injected + Active::get_injects();
-
- uint64_t pkts_out = 0;
-
- if ( pkts_recv > g_daq_stats.packets_filtered + g_daq_stats.packets_received )
- pkts_out = pkts_recv - g_daq_stats.packets_filtered - g_daq_stats.packets_received;
-
- daq_stats.pcaps = Trough::get_file_count();
- daq_stats.received = pkts_recv;
- daq_stats.analyzed = g_daq_stats.packets_received;
- daq_stats.dropped = pkts_drop;
- daq_stats.filtered = g_daq_stats.packets_filtered;
- daq_stats.outstanding = pkts_out;
- daq_stats.injected = pkts_inj;
-
- for ( unsigned i = 0; i < MAX_DAQ_VERDICT; i++ )
- daq_stats.verdicts[i] = g_daq_stats.verdicts[i];
-
- daq_stats.internal_blacklist = gaux.internal_blacklist;
- daq_stats.internal_whitelist = gaux.internal_whitelist;
- daq_stats.skipped = SnortConfig::get_conf()->pkt_skip;
- daq_stats.idle = gaux.idle;
- daq_stats.rx_bytes = gaux.rx_bytes;
-}
-
void DropStats()
{
- DAQStats daq_stats;
- get_daq_stats(daq_stats);
-
LogLabel("Packet Statistics");
- show_stats((PegCount*)&daq_stats, daq_names, array_size(daq_names)-1, "daq");
-
+ ModuleManager::get_module("daq")->show_stats();
+
PacketManager::dump_stats();
LogLabel("Module Statistics");
return head;
}
+void show_stats(PegCount* pegs, const PegInfo* info, const char* module_name)
+{
+ bool head = false;
+
+ for ( unsigned i = 0; info->name[i]; ++i )
+ head = show_stat(head, pegs[i], info[i].name, module_name);
+}
+
void show_stats(
PegCount* pegs, const PegInfo* info, unsigned n, const char* module_name)
{
PegCount rx_bytes;
};
-//-------------------------------------------------------------------------
-// FIXIT-L daq stats should be moved to sfdaq
-
-struct DAQStats
-{
- PegCount pcaps;
- PegCount received;
- PegCount analyzed;
- PegCount dropped;
- PegCount filtered;
- PegCount outstanding;
- PegCount injected;
- PegCount verdicts[MAX_DAQ_VERDICT];
- PegCount internal_blacklist;
- PegCount internal_whitelist;
- PegCount skipped;
- PegCount idle;
- PegCount rx_bytes;
-};
-
extern ProcessCount proc_stats;
extern THREAD_LOCAL AuxCount aux_counts;
extern SO_PUBLIC THREAD_LOCAL PacketCount pc;
SO_PUBLIC void LogStat(const char*, uint64_t n, uint64_t tot, FILE* = stdout);
SO_PUBLIC void LogStat(const char*, double, FILE* = stdout);
-void get_daq_stats(DAQStats& daq_stats);
-
void sum_stats(PegCount* sums, PegCount* counts, unsigned n);
+void show_stats(PegCount*, const PegInfo*, const char* module_name = nullptr);
void show_stats(PegCount*, const PegInfo*, unsigned n, const char* module_name = nullptr);
-void show_stats( PegCount*, const PegInfo*, IndexVec&, const char* module_name, FILE*);
+void show_stats(PegCount*, const PegInfo*, IndexVec&, const char* module_name, FILE*);
void show_percent_stats(PegCount*, const char*[], unsigned n, const char* module_name = nullptr);
void sum_stats(SimpleStats* sums, SimpleStats* counts);
double CalcPct(uint64_t, uint64_t);
void DropStats();
-void pc_sum();
void PrintStatistics();
void TimeStart();
void TimeStop();