]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1735 in SNORT/snort3 from ~DAVMCPHE/snort3:flow_object_allocation...
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 8 Oct 2019 18:17:05 +0000 (14:17 -0400)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 8 Oct 2019 18:17:05 +0000 (14:17 -0400)
Squashed commit of the following:

commit 3b8ffbfb453e155f805ec859198ca08b945d0cdf
Author: davis mcpherson <davmcphe.cisco.com>
Date:   Wed Sep 4 10:57:08 2019 -0400

    flow: patch to allocate Flow objects individually on demand. Once allocated the Flow objects are reused until snort exits or reload changes the max_flows setting

src/flow/expect_cache.cc
src/flow/flow.h
src/flow/flow_cache.cc
src/flow/flow_cache.h
src/flow/flow_control.cc
src/flow/flow_control.h
src/flow/flow_uni_list.h
src/flow/test/flow_control_test.cc

index 1bc043e64bf8104b47ab7c8e9de7d5084f8cd335..73e12bb69f06b42f1c20e8901c0852becf6eaf87 100644 (file)
@@ -323,10 +323,8 @@ ExpectCache::~ExpectCache()
  * snort_protocol_id and associated data is not stored.
  *
  */
-int ExpectCache::add_flow(const Packet *ctrlPkt,
-    PktType type, IpProtocol ip_proto,
-    const SfIp* cliIP, uint16_t cliPort,
-    const SfIp* srvIP, uint16_t srvPort,
+int ExpectCache::add_flow(const Packet *ctrlPkt, PktType type, IpProtocol ip_proto,
+    const SfIp* cliIP, uint16_t cliPort, const SfIp* srvIP, uint16_t srvPort,
     char direction, FlowData* fd, SnortProtocolId snort_protocol_id)
 {
     /* Just pull the VLAN ID, MPLS ID, and Address Space ID from the
@@ -339,11 +337,8 @@ int ExpectCache::add_flow(const Packet *ctrlPkt,
     bool reversed_key = key.init(type, ip_proto, cliIP, cliPort, srvIP, srvPort,
             vlanId, mplsId, addressSpaceId);
 
-    ExpectNode* node;
-    ExpectFlow* last;
     bool new_node = false;
-
-    node = (ExpectNode*) hash_table->get(&key, &new_node);
+    ExpectNode* node = (ExpectNode*) hash_table->get(&key, &new_node);
     if (!node)
     {
         prune();
@@ -365,6 +360,7 @@ int ExpectCache::add_flow(const Packet *ctrlPkt,
         new_node = true;
     }
 
+    ExpectFlow* last = nullptr;
     if (!new_node)
     {
         // Requests will be rejected if the snort_protocol_id doesn't
index 86a8765ca928b67e9929c3c7dab583560a3db6fe..218dfbb5002bede64d73b341a7011445e3d580d4 100644 (file)
@@ -346,7 +346,6 @@ public:  // FIXIT-M privatize if possible
 
     // these fields are const after initialization
     const FlowKey* key;
-    Session* session;
     BitOp* bitop;
     FlowHAState* ha_state;
     FlowStash* stash;
@@ -356,6 +355,7 @@ public:  // FIXIT-M privatize if possible
 
     // these fields are always set; not zeroed
     Flow* prev, * next;
+    Session* session;
     Inspector* ssn_client;
     Inspector* ssn_server;
 
index 28f332fa442f9f8ac8d5afbe68fad17677a250a1..785668c49f93f599800512b8a796e811aaef6772 100644 (file)
@@ -70,6 +70,7 @@ void FlowCache::push(Flow* flow)
 {
     void* key = hash_table->push(flow);
     flow->key = (FlowKey*)key;
+    ++flows_allocated;
 }
 
 unsigned FlowCache::get_count()
@@ -110,14 +111,19 @@ void FlowCache::unlink_uni(Flow* flow)
         uni_flows->unlink_uni(flow);
 }
 
-Flow* FlowCache::get(const FlowKey* key)
+Flow* FlowCache::allocate(const FlowKey* key)
 {
     time_t timestamp = packet_time();
     Flow* flow = (Flow*)hash_table->get(key);
 
     if ( !flow )
     {
-        if ( !prune_stale(timestamp, nullptr) )
+        if ( flows_allocated < config.max_flows )
+        {
+            Flow* new_flow = new Flow;
+            push(new_flow);
+        }
+        else if ( !prune_stale(timestamp, nullptr) )
         {
             if ( !prune_unis(key->pkt_type) )
                 prune_excess(nullptr);
@@ -130,9 +136,9 @@ Flow* FlowCache::get(const FlowKey* key)
             flow->term();
         else
             flow->reset();
-        link_uni(flow);
     }
 
+    link_uni(flow);
     if ( flow->session && flow->pkt_type != key->pkt_type )
         flow->term();
 
@@ -369,7 +375,7 @@ unsigned FlowCache::purge()
     }
 
     while ( Flow* flow = (Flow*)hash_table->pop() )
-        flow->term();
+        delete flow;
 
     return retired;
 }
index b0393ee9851d7ee68b8b33997f801252dea6e73b..2a37d99e217a413fb114e0e0fd2e42124c2023f4 100644 (file)
@@ -48,13 +48,10 @@ public:
     FlowCache(const FlowCache&) = delete;
     FlowCache& operator=(const FlowCache&) = delete;
 
-    void push(snort::Flow*);
-
     snort::Flow* find(const snort::FlowKey*);
-    snort::Flow* get(const snort::FlowKey*);
+    snort::Flow* allocate(const snort::FlowKey*);
 
     int release(snort::Flow*, PruneReason = PruneReason::NONE, bool do_cleanup = true);
-
     unsigned prune_stale(uint32_t thetime, const snort::Flow* save_me);
     unsigned prune_excess(const snort::Flow* save_me);
     bool prune_one(PruneReason, bool do_cleanup);
@@ -78,9 +75,11 @@ public:
     void unlink_uni(snort::Flow*);
 
 private:
+    void push(snort::Flow*);
     void link_uni(snort::Flow*);
     int remove(snort::Flow*);
     int retire(snort::Flow*);
+    unsigned prune_unis(PktType);
 
 private:
     static const unsigned cleanup_flows = 1;
@@ -88,12 +87,11 @@ private:
     uint32_t flags;
 
     class ZHash* hash_table;
+    unsigned flows_allocated = 0;
     FlowUniList* uni_flows;
     FlowUniList* uni_ip_flows;
 
-    //snort::Flow* uni_head_ip, *uni_tail_ip, *uni_head_nonip, *uni_tail_nonip;
     PruneStats prune_stats;
-    unsigned prune_unis(PktType);
 };
 #endif
 
index d814d9d798b2d54cedd083c7712dad4b8fcf4412..9a4b4477f11eb35530b006b841a0cdd49f98e2d6 100644 (file)
@@ -47,11 +47,6 @@ using namespace snort;
 FlowControl::FlowControl(const FlowCacheConfig& fc)
 {
     cache = new FlowCache(fc);
-
-    mem = (Flow*)snort_calloc(fc.max_flows, sizeof(Flow));
-
-    for ( unsigned i = 0; i < fc.max_flows; ++i )
-        cache->push(mem + i);
 }
 
 FlowControl::~FlowControl()
@@ -69,25 +64,18 @@ FlowControl::~FlowControl()
 
 PegCount FlowControl::get_total_prunes() const
 {
-    auto cache = get_cache();
-    return cache ? cache->get_total_prunes() : 0;
+    return cache->get_total_prunes();
 }
 
 PegCount FlowControl::get_prunes(PruneReason reason) const
 {
-    auto cache = get_cache();
-    return cache ? cache->get_prunes(reason) : 0;
+    return cache->get_prunes(reason);
 }
 
 void FlowControl::clear_counts()
 {
-    for ( int i = 0; i < to_utype(PktType::MAX); ++i )
-    {
-        if ( cache )
-            cache->reset_stats();
-
-        num_flows = 0;
-    }
+    cache->reset_stats();
+    num_flows = 0;
 }
 
 //-------------------------------------------------------------------------
@@ -96,65 +84,41 @@ void FlowControl::clear_counts()
 
 Flow* FlowControl::find_flow(const FlowKey* key)
 {
-    if ( auto cache = get_cache() )
-        return cache->find(key);
-
-    return nullptr;
+    return cache->find(key);
 }
 
 Flow* FlowControl::new_flow(const FlowKey* key)
 {
-    if ( auto cache = get_cache() )
-        return cache->get(key);
-
-    return nullptr;
+    return cache->allocate(key);
 }
 
-// FIXIT-L cache* can be put in flow so that lookups by
-// packet type are obviated for existing / initialized flows
 void FlowControl::delete_flow(const FlowKey* key)
 {
-    FlowCache* cache = get_cache();
-
-    if ( !cache )
-        return;
-
     if ( auto flow = cache->find(key) )
         cache->release(flow, PruneReason::HA);
 }
 
 void FlowControl::delete_flow(Flow* flow, PruneReason reason)
 {
-    if ( auto cache = get_cache() )
-        cache->release(flow, reason);
+    cache->release(flow, reason);
 }
 
 void FlowControl::purge_flows ()
 {
-    if ( auto cache = get_cache() )
-        cache->purge();
+    cache->purge();
 }
 
 // hole for memory manager/prune handler
 bool FlowControl::prune_one(PruneReason reason, bool do_cleanup)
 {
-    auto cache = get_cache();
-    return cache ? cache->prune_one(reason, do_cleanup) : false;
+    return cache->prune_one(reason, do_cleanup);
 }
 
 void FlowControl::timeout_flows(time_t cur_time)
 {
-    if ( types.empty() )
-        return;
-
     ActiveSuspendContext act_susp;
-    FlowCache* fc = get_cache();
-
-    if ( ++next >= types.size() )
-        next = 0;
 
-    if ( fc )
-        fc->timeout(1, cur_time);
+    cache->timeout(1, cur_time);
 }
 
 void FlowControl::preemptive_cleanup()
@@ -341,8 +305,7 @@ void FlowControl::init_proto(PktType type, InspectSsnFunc get_ssn)
 {
     assert(get_ssn);
 
-    proto[to_utype(type)].get_ssn = get_ssn;
-    types.emplace_back(type);
+    get_proto_session[to_utype(type)] = get_ssn;
 }
 
 // FIXIT-P apply more filtering logic here, eg require_3whs
@@ -367,7 +330,7 @@ static bool want_flow(PktType type, Packet* p)
 
 bool FlowControl::process(PktType type, Packet* p, bool* new_flow)
 {
-    if ( !proto[to_utype(type)].get_ssn )
+    if ( !get_proto_session[to_utype(type)] )
         return false;
 
     FlowKey key;
@@ -386,7 +349,7 @@ bool FlowControl::process(PktType type, Packet* p, bool* new_flow)
             if ( !want_flow(type, p) )
                 return true;
 
-            flow = cache->get(&key);
+            flow = cache->allocate(&key);
 
             if ( !flow )
                 return true;
@@ -399,7 +362,7 @@ bool FlowControl::process(PktType type, Packet* p, bool* new_flow)
     if ( !flow->session )
     {
         flow->init(type);
-        flow->session = proto[to_utype(type)].get_ssn(flow);
+        flow->session = get_proto_session[to_utype(type)](flow);
     }
 
     num_flows += process(flow, p);
index 825733ff9ada726eaec9db16b3d728e003a0d1f9..0bc1fd92de1aaf3c2e2782c4912971b53cde53b9 100644 (file)
@@ -95,31 +95,17 @@ public:
     void clear_counts();
 
 private:
-    FlowCache* get_cache()
-    { return cache; }
-
-    const FlowCache* get_cache() const
-    { return cache; }
-
     void set_key(snort::FlowKey*, snort::Packet*);
-
     unsigned process(snort::Flow*, snort::Packet*);
     void preemptive_cleanup();
 
 private:
-    struct
-    {
-        snort::InspectSsnFunc get_ssn = nullptr;
-    } proto[to_utype(PktType::MAX)];
-
+    snort::InspectSsnFunc get_proto_session[to_utype(PktType::MAX)] = {};
     PegCount num_flows = 0;
     FlowCache* cache = nullptr;
     snort::Flow* mem = nullptr;
     class ExpectCache* exp_cache = nullptr;
     PktType last_pkt_type = PktType::NONE;
-
-    std::vector<PktType> types;
-    unsigned next = 0;
 };
 
 #endif
index fd04f747d9a38eaf6402695d912bf5a17e7bde20..75718fa960e05088ca2f0d1e295f7217c11c0cc8 100644 (file)
@@ -61,7 +61,6 @@ public:
         flow->prev->next = flow->next;
         flow->next = flow->prev = nullptr;
         --count;
-
     }
 
     snort::Flow* get_oldest_uni()
index 5b5050c21890118303291957a9815992e3039a77..5d51af82380dcebc45c519ae806053f928e38bdd 100644 (file)
@@ -70,7 +70,7 @@ DetectionEngine::~DetectionEngine() = default;
 ExpectCache::~ExpectCache() = default;
 unsigned FlowCache::purge() { return 1; }
 Flow* FlowCache::find(const FlowKey*) { return nullptr; }
-Flow* FlowCache::get(const FlowKey*) { return nullptr; }
+Flow* FlowCache::allocate(const FlowKey*) { return nullptr; }
 void FlowCache::push(Flow*) { }
 bool FlowCache::prune_one(PruneReason, bool) { return true; }
 unsigned FlowCache::timeout(unsigned, time_t) { return 1; }