#include "protocols/tcp.h"
#include "pub_sub/intrinsic_event_ids.h"
#include "sfip/sf_ip.h"
+#include "time/clock_defs.h"
#include "utils/stats.h"
#include "utils/util.h"
delete bitop;
bitop = nullptr;
filtering_state.clear();
+
+ inspected_packet_count = 0;
+ inspection_duration = 0;
}
void Flow::flush(bool do_cleanup)
disable_inspection();
}
+uint64_t Flow::fetch_add_inspection_duration()
+{
+ if (inspected_packet_count != 0)
+ return get_inspection_duration();
+
+ auto c = DetectionEngine::get_context();
+
+ if (c and c->packet and c->packet->inspection_started_timestamp)
+ {
+ auto packet = c->packet;
+ const auto timestamp = TO_USECS_FROM_EPOCH(SnortClock::now());
+
+ add_inspection_duration(timestamp - packet->inspection_started_timestamp);
+ packet->inspection_started_timestamp = timestamp;
+ }
+
+ return get_inspection_duration();
+}
+
int Flow::set_flow_data(FlowData* fd)
{
if ( !fd ) return -1;
#include "protocols/layer.h"
#include "sfip/sf_ip.h"
#include "target_based/snort_protocols.h"
+#include "time/clock_defs.h"
#define SSNFLAG_SEEN_CLIENT 0x00000001
#define SSNFLAG_SEEN_SENDER 0x00000001
{ return (flow_state <= FlowState::INSPECT) and !is_inspection_disabled(); }
void set_state(FlowState fs)
- { flow_state = fs; }
+ {
+ flow_state = fs;
+ if (fs > FlowState::INSPECT)
+ {
+ inspected_packet_count = flowstats.client_pkts + flowstats.server_pkts;
+ }
+ }
void set_client(Inspector* ins)
{
bool trust_is_deferred() const
{ return deferred_trust.is_deferred(); }
-
+
void set_idle_timeout(unsigned timeout)
- { idle_timeout = timeout; }
+ { idle_timeout = timeout; }
+
+ uint16_t get_inspected_packet_count() const
+ { return inspected_packet_count ? inspected_packet_count : (flowstats.client_pkts + flowstats.server_pkts); }
+
+ void add_inspection_duration(const uint64_t& duration)
+ {
+ if (inspected_packet_count != 0)
+ return;
+
+ inspection_duration += duration;
+ }
+
+ uint64_t get_inspection_duration() const
+ {
+#ifdef USE_TSC_CLOCK
+ return clock_usecs(inspection_duration.load());
+#else
+ return inspection_duration.load();
+#endif
+ }
+
+ uint64_t fetch_add_inspection_duration();
public: // FIXIT-M privatize if possible
// fields are organized by initialization and size to minimize
private:
void clean();
+ std::atomic_ullong inspection_duration{0};
+ uint16_t inspected_packet_count{0};
};
inline void Flow::set_to_client_detection(bool enable)
#include "protocols/ip.h"
#include "protocols/layer.h"
#include "protocols/packet.h"
+#include "time/clock_defs.h"
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness.h>
DetectionEngine::~DetectionEngine() = default;
+Packet test_packet;
+Packet* DetectionEngine::get_current_packet() { return &test_packet; }
+
bool layer::set_outer_ip_api(const Packet* const, ip::IpApi&, int8_t&)
{ return false; }
delete flow;
}
+TEST_GROUP(inspection_time_presence)
+{
+};
+
+TEST(inspection_time_presence, inspection_time_addition)
+{
+ Flow *flow = new Flow;
+
+ flow->flowstats.client_pkts = 3;
+ flow->flowstats.server_pkts = 3;
+
+ flow->add_inspection_duration(2);
+ flow->add_inspection_duration(3);
+
+ CHECK(flow->get_inspection_duration() == 5);
+ CHECK(flow->get_inspected_packet_count() == 6);
+
+ flow->set_state(Flow::FlowState::ALLOW);
+
+ flow->add_inspection_duration(2);
+
+ flow->flowstats.client_pkts = 5;
+ flow->flowstats.server_pkts = 5;
+
+ CHECK(flow->get_inspection_duration() == 5);
+ CHECK(flow->get_inspected_packet_count() == 6);
+
+ delete flow;
+}
+
int main(int argc, char** argv)
{
int return_value = CommandLineTestRunner::RunAllTests(argc, argv);
#include "main/snort_module.h"
#include "main/thread_config.h"
#include "protocols/packet.h"
+#include "profiler/profiler_defs.h"
#include "pub_sub/intrinsic_event_ids.h"
#include "search_engines/search_tool.h"
#include "target_based/snort_protocols.h"
// new it_xxx) is run just once per flow (and all non-flow packets).
void InspectorManager::execute(Packet* p)
{
+ p->inspection_started_timestamp = TO_USECS_FROM_EPOCH(SnortClock::now());
+
if ( trace_enabled(snort_trace, TRACE_INSPECTOR_MANAGER, DEFAULT_TRACE_LOG_LEVEL, p) )
internal_execute<true>(p);
else
internal_execute<false>(p);
+ if ( p->flow )
+ p->flow->add_inspection_duration(TO_USECS_FROM_EPOCH(SnortClock::now()) - p->inspection_started_timestamp);
+
if ( p->flow && ( !p->is_cooked() or p->is_defrag() ) )
ExpectFlow::handle_expected_flows(p);
}
#include "managers/inspector_manager.h"
#include "managers/module_manager.h"
#include "network_inspectors/binder/bind_module.h"
+#include "profiler/rule_profiler_defs.h"
+#include "profiler/time_profiler_defs.h"
#include "search_engines/search_tool.h"
#include "trace/trace.h"
#include "trace/trace_api.h"
THREAD_LOCAL const snort::Trace* snort_trace = nullptr;
+THREAD_LOCAL bool RuleContext::enabled = false;
std::shared_ptr<PolicyTuple> PolicyMap::get_policies(Shell*) { return nullptr; }
void InspectionPolicy::configure() { }
void set_ips_policy(IpsPolicy*) { }
unsigned get_instance_id() { return 0; }
void trace_vprintf(const char*, TraceLevel, const char*, const Packet*, const char*, va_list) { }
+
+THREAD_LOCAL bool TimeProfilerStats::enabled = false;
}
vlan_idx = 0;
filtering_state.clear();
sect = PS_NONE;
+ inspection_started_timestamp = 0;
}
void Packet::release_helpers()
uint64_t user_ips_policy_id;
uint64_t user_network_policy_id;
+ uint64_t inspection_started_timestamp;
+
uint8_t vlan_idx;
uint8_t ts_packet_flags; // FIXIT-M packet flags should always be thread safe
Packet::Packet(bool)
: flow(nullptr), packet_flags(0), xtradata_mask(0), proto_bits(0), alt_dsize(0), num_layers(0),
disable_inspect(true), sect(PS_NONE), active_inst(nullptr), pkth(nullptr), pkt(nullptr), layers(nullptr),
- user_inspection_policy_id(0), user_ips_policy_id(0), user_network_policy_id(0), vlan_idx(0),
+ user_inspection_policy_id(0), user_ips_policy_id(0), user_network_policy_id(0), inspection_started_timestamp(0), vlan_idx(0),
ts_packet_flags(0), allocated(false)
{ }
Packet::~Packet() = default;
#define DURA_ZERO 0
#define TO_TICKS(t) (t)
#define TO_USECS(t) (t)
+#define TO_USECS_FROM_EPOCH(t) (t)
#define TO_NSECS(t) (t)
#define TO_DURATION(v, t) (t)
#define DURA_ZERO Clock::duration::zero()
#define TO_TICKS(t) (t.count())
#define TO_USECS(t) (std::chrono::duration_cast<std::chrono::microseconds>(t).count())
+#define TO_USECS_FROM_EPOCH(t) (TO_USECS(t.time_since_epoch()))
#define TO_NSECS(t) (std::chrono::duration_cast<std::chrono::nanoseconds>(t).count())
#define TO_DURATION(v, t) (std::chrono::duration_cast<decltype(v)>(std::chrono::microseconds(t)))
#endif
void cancel()
{ running = false; }
+ time_point get_start_time() const
+ { return start_time; }
+
private:
duration get_delta() const
{ return Clock::now() - start_time; }