decode/flow: add exception policy stats counters

We will register stats counters for all policies, even though for now
Suri only uses one possible configuration policy at a time. The idea is
that this could change in the near future, so we want to have this
ready.

Task #5816

(cherry picked from commit 657419b53e)
pull/13732/head
Juliana Fajardini 3 years ago
parent b96d03e3d6
commit 6cb9a353ec

@ -317,6 +317,13 @@ the global config is documented.
#decoder-events-prefix: "decoder.event" #decoder-events-prefix: "decoder.event"
# Add stream events as stats. # Add stream events as stats.
#stream-events: false #stream-events: false
# Exception policy stats counters options
# (Note: if exception policy: ignore, counters are not logged)
exception-policy:
#global-stats: true # default: false. True will log stats for all
# valid exception policies
#per-app-proto-errors: false # default: false. True will log errors for
# each app-proto. Warning: VERY verbose
Statistics can be `enabled` or disabled here. Statistics can be `enabled` or disabled here.

@ -4991,6 +4991,11 @@
"memcap": { "memcap": {
"type": "integer" "type": "integer"
}, },
"memcap_exception_policy": {
"description":
"How many times flow memcap exception policy was applied, and which one",
"$ref": "#/$defs/exceptionPolicy"
},
"memuse": { "memuse": {
"type": "integer" "type": "integer"
}, },
@ -5657,6 +5662,35 @@
] ]
} }
} }
},
"exceptionPolicy": {
"type": "object",
"properties": {
"drop_flow": {
"type": "integer",
"minimum": 0
},
"drop_packet": {
"type": "integer",
"minimum": 0
},
"pass_flow": {
"type": "integer",
"minimum": 0
},
"pass_packet": {
"type": "integer",
"minimum": 0
},
"bypass": {
"type": "integer",
"minimum": 0
},
"reject": {
"type": "integer",
"minimum": 0
}
}
} }
} }
} }

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2021 Open Information Security Foundation /* Copyright (C) 2007-2024 Open Information Security Foundation
* *
* You can copy, redistribute or modify this Program under the terms of * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free

@ -76,6 +76,32 @@ extern bool stats_stream_events;
uint8_t decoder_max_layers = PKT_DEFAULT_MAX_DECODED_LAYERS; uint8_t decoder_max_layers = PKT_DEFAULT_MAX_DECODED_LAYERS;
uint16_t packet_alert_max = PACKET_ALERT_MAX; uint16_t packet_alert_max = PACKET_ALERT_MAX;
/* Settings order as in the enum */
// clang-format off
ExceptionPolicyStatsSetts flow_memcap_eps_stats = {
.valid_settings_ids = {
/* EXCEPTION_POLICY_NOT_SET */ false,
/* EXCEPTION_POLICY_AUTO */ false,
/* EXCEPTION_POLICY_PASS_PACKET */ true,
/* EXCEPTION_POLICY_PASS_FLOW */ false,
/* EXCEPTION_POLICY_BYPASS_FLOW */ true,
/* EXCEPTION_POLICY_DROP_PACKET */ false,
/* EXCEPTION_POLICY_DROP_FLOW */ false,
/* EXCEPTION_POLICY_REJECT */ true,
},
.valid_settings_ips = {
/* EXCEPTION_POLICY_NOT_SET */ false,
/* EXCEPTION_POLICY_AUTO */ false,
/* EXCEPTION_POLICY_PASS_PACKET */ true,
/* EXCEPTION_POLICY_PASS_FLOW */ false,
/* EXCEPTION_POLICY_BYPASS_FLOW */ true,
/* EXCEPTION_POLICY_DROP_PACKET */ true,
/* EXCEPTION_POLICY_DROP_FLOW */ false,
/* EXCEPTION_POLICY_REJECT */ true,
},
};
// clang-format on
/** /**
* \brief Initialize PacketAlerts with dynamic alerts array size * \brief Initialize PacketAlerts with dynamic alerts array size
* *
@ -521,6 +547,14 @@ void DecodeUnregisterCounters(void)
SCMutexUnlock(&g_counter_table_mutex); SCMutexUnlock(&g_counter_table_mutex);
} }
static bool IsFlowMemcapExceptionPolicyStatsValid(enum ExceptionPolicy policy)
{
if (EngineModeIsIPS()) {
return flow_memcap_eps_stats.valid_settings_ips[policy];
}
return flow_memcap_eps_stats.valid_settings_ids[policy];
}
void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv) void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
{ {
/* register counters */ /* register counters */
@ -571,6 +605,9 @@ void DecodeRegisterPerfCounters(DecodeThreadVars *dtv, ThreadVars *tv)
dtv->counter_erspan = StatsRegisterMaxCounter("decoder.erspan", tv); dtv->counter_erspan = StatsRegisterMaxCounter("decoder.erspan", tv);
dtv->counter_nsh = StatsRegisterMaxCounter("decoder.nsh", tv); dtv->counter_nsh = StatsRegisterMaxCounter("decoder.nsh", tv);
dtv->counter_flow_memcap = StatsRegisterCounter("flow.memcap", tv); dtv->counter_flow_memcap = StatsRegisterCounter("flow.memcap", tv);
ExceptionPolicySetStatsCounters(tv, &dtv->counter_flow_memcap_eps, &flow_memcap_eps_stats,
FlowGetMemcapExceptionPolicy(), "flow.memcap_exception_policy.",
IsFlowMemcapExceptionPolicyStatsValid);
dtv->counter_tcp_active_sessions = StatsRegisterCounter("tcp.active_sessions", tv); dtv->counter_tcp_active_sessions = StatsRegisterCounter("tcp.active_sessions", tv);
dtv->counter_flow_total = StatsRegisterCounter("flow.total", tv); dtv->counter_flow_total = StatsRegisterCounter("flow.total", tv);

@ -32,6 +32,7 @@
#include "threadvars.h" #include "threadvars.h"
#include "util-debug.h" #include "util-debug.h"
#include "decode-events.h" #include "decode-events.h"
#include "util-exception-policy-types.h"
#ifdef PROFILING #ifdef PROFILING
#include "flow-worker.h" #include "flow-worker.h"
#include "app-layer-protos.h" #include "app-layer-protos.h"
@ -728,6 +729,7 @@ typedef struct DecodeThreadVars_
uint16_t counter_defrag_max_hit; uint16_t counter_defrag_max_hit;
uint16_t counter_flow_memcap; uint16_t counter_flow_memcap;
ExceptionPolicyCounters counter_flow_memcap_eps;
uint16_t counter_tcp_active_sessions; uint16_t counter_tcp_active_sessions;
uint16_t counter_flow_total; uint16_t counter_flow_total;

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2023 Open Information Security Foundation /* Copyright (C) 2007-2024 Open Information Security Foundation
* *
* You can copy, redistribute or modify this Program under the terms of * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free
@ -641,9 +641,24 @@ static inline Flow *FlowSpareSync(ThreadVars *tv, FlowLookupStruct *fls,
return f; return f;
} }
static inline void NoFlowHandleIPS(Packet *p) static void FlowExceptionPolicyStatsIncr(
ThreadVars *tv, FlowLookupStruct *fls, enum ExceptionPolicy policy)
{
#ifdef UNITTESTS
if (tv == NULL) {
return;
}
#endif
uint16_t id = fls->dtv->counter_flow_memcap_eps.eps_id[policy];
if (likely(id > 0)) {
StatsIncr(tv, id);
}
}
static inline void NoFlowHandleIPS(ThreadVars *tv, FlowLookupStruct *fls, Packet *p)
{ {
ExceptionPolicyApply(p, flow_config.memcap_policy, PKT_DROP_REASON_FLOW_MEMCAP); ExceptionPolicyApply(p, flow_config.memcap_policy, PKT_DROP_REASON_FLOW_MEMCAP);
FlowExceptionPolicyStatsIncr(tv, fls, flow_config.memcap_policy);
} }
/** /**
@ -663,7 +678,7 @@ static Flow *FlowGetNew(ThreadVars *tv, FlowLookupStruct *fls, Packet *p)
const bool emerg = ((SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY) != 0); const bool emerg = ((SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY) != 0);
#ifdef DEBUG #ifdef DEBUG
if (g_eps_flow_memcap != UINT64_MAX && g_eps_flow_memcap == p->pcap_cnt) { if (g_eps_flow_memcap != UINT64_MAX && g_eps_flow_memcap == p->pcap_cnt) {
NoFlowHandleIPS(p); NoFlowHandleIPS(tv, fls, p);
StatsIncr(tv, fls->dtv->counter_flow_memcap); StatsIncr(tv, fls->dtv->counter_flow_memcap);
return NULL; return NULL;
} }
@ -689,7 +704,14 @@ static Flow *FlowGetNew(ThreadVars *tv, FlowLookupStruct *fls, Packet *p)
f = FlowGetUsedFlow(tv, fls->dtv, p->ts); f = FlowGetUsedFlow(tv, fls->dtv, p->ts);
if (f == NULL) { if (f == NULL) {
NoFlowHandleIPS(p); NoFlowHandleIPS(tv, fls, p);
#ifdef UNITTESTS
if (tv != NULL && fls->dtv != NULL) {
#endif
StatsIncr(tv, fls->dtv->counter_flow_memcap);
#ifdef UNITTESTS
}
#endif
return NULL; return NULL;
} }
#ifdef UNITTESTS #ifdef UNITTESTS
@ -714,7 +736,7 @@ static Flow *FlowGetNew(ThreadVars *tv, FlowLookupStruct *fls, Packet *p)
#ifdef UNITTESTS #ifdef UNITTESTS
} }
#endif #endif
NoFlowHandleIPS(p); NoFlowHandleIPS(tv, fls, p);
return NULL; return NULL;
} }

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2013 Open Information Security Foundation /* Copyright (C) 2007-2024 Open Information Security Foundation
* *
* You can copy, redistribute or modify this Program under the terms of * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free
@ -143,6 +143,11 @@ uint64_t FlowGetMemuse(void)
return memusecopy; return memusecopy;
} }
enum ExceptionPolicy FlowGetMemcapExceptionPolicy(void)
{
return flow_config.memcap_policy;
}
void FlowCleanupAppLayer(Flow *f) void FlowCleanupAppLayer(Flow *f)
{ {
if (f == NULL || f->proto == 0) if (f == NULL || f->proto == 0)

@ -1,4 +1,4 @@
/* Copyright (C) 2007-2013 Open Information Security Foundation /* Copyright (C) 2007-2024 Open Information Security Foundation
* *
* You can copy, redistribute or modify this Program under the terms of * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free
@ -30,6 +30,7 @@ typedef struct FlowStorageId FlowStorageId;
#include "decode.h" #include "decode.h"
#include "util-time.h" #include "util-time.h"
#include "util-exception-policy.h" #include "util-exception-policy.h"
#include "util-exception-policy-types.h"
#include "util-var.h" #include "util-var.h"
#include "util-optimize.h" #include "util-optimize.h"
#include "app-layer-protos.h" #include "app-layer-protos.h"
@ -572,6 +573,7 @@ void FlowUpdateState(Flow *f, enum FlowState s);
int FlowSetMemcap(uint64_t size); int FlowSetMemcap(uint64_t size);
uint64_t FlowGetMemcap(void); uint64_t FlowGetMemcap(void);
uint64_t FlowGetMemuse(void); uint64_t FlowGetMemuse(void);
enum ExceptionPolicy FlowGetMemcapExceptionPolicy(void);
FlowStorageId GetFlowBypassInfoID(void); FlowStorageId GetFlowBypassInfoID(void);
void RegisterFlowBypassInfo(void); void RegisterFlowBypassInfo(void);

@ -1,4 +1,4 @@
/* Copyright (C) 2014-2020 Open Information Security Foundation /* Copyright (C) 2014-2024 Open Information Security Foundation
* *
* You can copy, redistribute or modify this Program under the terms of * You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free * the GNU General Public License version 2 as published by the Free

@ -213,6 +213,10 @@ uint16_t g_livedev_mask = 0xffff;
* support */ * support */
bool g_disable_hashing = false; bool g_disable_hashing = false;
/** add per-proto app-layer error counters for exception policies stats? disabled by default */
bool g_stats_eps_per_app_proto_errors = false;
bool g_eps_stats_counters = false;
/** Suricata instance */ /** Suricata instance */
SCInstance suricata; SCInstance suricata;
@ -2712,6 +2716,16 @@ int PostConfLoadedSetup(SCInstance *suri)
and app layer setup. */ and app layer setup. */
FeatureTrackingRegister(); FeatureTrackingRegister();
ConfNode *eps = ConfGetNode("stats.exception-policy");
if (eps != NULL) {
if (ConfNodeChildValueIsTrue(eps, "per-app-proto-errors")) {
g_stats_eps_per_app_proto_errors = true;
}
if (ConfNodeChildValueIsTrue(eps, "global-stats")) {
g_eps_stats_counters = true;
}
}
AppLayerSetup(); AppLayerSetup();
/* Suricata will use this umask if provided. By default it will use the /* Suricata will use this umask if provided. By default it will use the

@ -38,7 +38,7 @@ enum ExceptionPolicy {
/* Max length = possible exception policy scenarios + counter names /* Max length = possible exception policy scenarios + counter names
* + exception policy type. E.g.: * + exception policy type. E.g.:
* "tcp.reassembly_exception_policy.drop_packet" + 1 */ * "tcp.reassembly_exception_policy.drop_packet" + 1 */
#define EXCEPTION_POLICY_COUNTER_MAX_LEN 44 #define EXCEPTION_POLICY_COUNTER_MAX_LEN 45
typedef struct ExceptionPolicyCounters_ { typedef struct ExceptionPolicyCounters_ {
/* Follows enum order */ /* Follows enum order */

@ -30,6 +30,7 @@
enum ExceptionPolicy g_eps_master_switch = EXCEPTION_POLICY_NOT_SET; enum ExceptionPolicy g_eps_master_switch = EXCEPTION_POLICY_NOT_SET;
/** true if exception policy was defined in config */ /** true if exception policy was defined in config */
static bool g_eps_have_exception_policy = false; static bool g_eps_have_exception_policy = false;
extern bool g_eps_stats_counters;
const char *ExceptionPolicyEnumToString(enum ExceptionPolicy policy, bool is_json) const char *ExceptionPolicyEnumToString(enum ExceptionPolicy policy, bool is_json)
{ {
@ -294,6 +295,22 @@ enum ExceptionPolicy ExceptionPolicyMidstreamParse(bool midstream_enabled)
return policy; return policy;
} }
void ExceptionPolicySetStatsCounters(ThreadVars *tv, ExceptionPolicyCounters *counter,
ExceptionPolicyStatsSetts *setting, enum ExceptionPolicy conf_policy,
const char *default_str, bool (*isExceptionPolicyValid)(enum ExceptionPolicy))
{
if (conf_policy != EXCEPTION_POLICY_NOT_SET && g_eps_stats_counters) {
/* set-up policy counters */
for (enum ExceptionPolicy i = EXCEPTION_POLICY_NOT_SET + 1; i < EXCEPTION_POLICY_MAX; i++) {
if (isExceptionPolicyValid(i)) {
snprintf(setting->eps_name[i], sizeof(setting->eps_name[i]), "%s%s", default_str,
ExceptionPolicyEnumToString(i, true));
counter->eps_id[i] = StatsRegisterCounter(setting->eps_name[i], tv);
}
}
}
}
#ifndef DEBUG #ifndef DEBUG
int ExceptionSimulationCommandLineParser(const char *name, const char *arg) int ExceptionSimulationCommandLineParser(const char *name, const char *arg)

@ -31,6 +31,9 @@ void ExceptionPolicyApply(
Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason); Packet *p, enum ExceptionPolicy policy, enum PacketDropReason drop_reason);
enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support_flow); enum ExceptionPolicy ExceptionPolicyParse(const char *option, const bool support_flow);
enum ExceptionPolicy ExceptionPolicyMidstreamParse(bool midstream_enabled); enum ExceptionPolicy ExceptionPolicyMidstreamParse(bool midstream_enabled);
void ExceptionPolicySetStatsCounters(ThreadVars *tv, ExceptionPolicyCounters *counter,
ExceptionPolicyStatsSetts *setting, enum ExceptionPolicy conf_policy,
const char *default_str, bool (*isExceptionPolicyValid)(enum ExceptionPolicy));
extern enum ExceptionPolicy g_eps_master_switch; extern enum ExceptionPolicy g_eps_master_switch;
#ifdef DEBUG #ifdef DEBUG

@ -73,6 +73,11 @@ stats:
#decoder-events-prefix: "decoder.event" #decoder-events-prefix: "decoder.event"
# Add stream events as stats. # Add stream events as stats.
#stream-events: false #stream-events: false
exception-policy:
#global-stats: true # default: false. True will log stats counters
# for each exception policy.
#per-app-proto-errors: false # default: false. True will log errors for
# each app-proto. Warning: VERY verbose
# Plugins -- Experimental -- specify the filename for each plugin shared object # Plugins -- Experimental -- specify the filename for each plugin shared object
plugins: plugins:

Loading…
Cancel
Save