]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3787: flow_cache: Prune multiple flows
authorShanmugam S (shanms) <shanms@cisco.com>
Fri, 24 Mar 2023 08:10:12 +0000 (08:10 +0000)
committerShanmugam S (shanms) <shanms@cisco.com>
Fri, 24 Mar 2023 08:10:12 +0000 (08:10 +0000)
Merge in SNORT/snort3 from ~KBHANDAN/snort3:prune_multiple to master

Squashed commit of the following:

commit 2851a29722b096be89b291dc8d2e88dd0764510b
Author: Kaushal Bhandankar <kbhandan@cisco.com>
Date:   Thu Mar 23 01:28:22 2023 +0530

    flow_cache: Prune multiple flows

src/flow/flow_cache.cc
src/flow/flow_cache.h
src/flow/flow_config.h
src/flow/flow_control.cc
src/flow/flow_control.h
src/flow/test/flow_control_test.cc
src/stream/base/stream_module.cc
src/stream/stream.cc

index bdadac13dd9ec68b0077ab7444574d5ca49bf9c9..39fbce6417a781325dfc857da84b94d5fce2938c 100644 (file)
@@ -354,8 +354,7 @@ unsigned FlowCache::prune_excess(const Flow* save_me)
 
         if (!pruned and hash_table->get_num_nodes() > max_cap)
         {
-            prune_one(PruneReason::EXCESS, true);
-            ++pruned;
+            pruned += prune_multiple(PruneReason::EXCESS, true);
         }
     }
 
@@ -381,6 +380,21 @@ bool FlowCache::prune_one(PruneReason reason, bool do_cleanup)
     return true;
 }
 
+unsigned FlowCache::prune_multiple(PruneReason reason, bool do_cleanup)
+{
+    unsigned pruned = 0;
+    // so we don't prune the current flow (assume current == MRU)
+    if ( hash_table->get_num_nodes() <= 1 )
+        return 0;
+
+    for (pruned = 0; pruned < config.prune_flows && prune_one(reason, do_cleanup); pruned++);
+
+    if ( PacketTracer::is_active() and pruned )
+        PacketTracer::log("Flow: Pruned memcap %u flows\n", pruned);
+
+    return pruned;
+}
+
 unsigned FlowCache::timeout(unsigned num_flows, time_t thetime)
 {
     ActiveSuspendContext act_susp(Active::ASP_TIMEOUT);
index 10d4cafec7adae7e1b69becfb4ed26e76ad69a0c..a3eb84c6df53b8c0bed6d174820cc4cef35746d1 100644 (file)
@@ -61,6 +61,7 @@ public:
     bool prune_one(PruneReason, bool do_cleanup);
     unsigned timeout(unsigned num_flows, time_t cur_time);
     unsigned delete_flows(unsigned num_to_delete);
+    unsigned prune_multiple(PruneReason, bool do_cleanup);
 
     unsigned purge();
     unsigned get_count();
index b76b87d24a7172e4d8b2b881046ffe1c8d5ef81b..13dd833a964359ac066708392a69adc9639fd20f 100644 (file)
@@ -34,6 +34,7 @@ struct FlowCacheConfig
     unsigned max_flows = 0;
     unsigned pruning_timeout = 0;
     FlowTypeConfig proto[to_utype(PktType::MAX)];
+    unsigned prune_flows = 0;
 };
 
 #endif
index 0a6d3ebf5912275e10403d98c26e53e9b73265f6..ede0570175761bcad9314f9d61e323dfcf2e29b1 100644 (file)
@@ -127,6 +127,9 @@ unsigned FlowControl::delete_flows(unsigned num_to_delete)
 bool FlowControl::prune_one(PruneReason reason, bool do_cleanup)
 { return cache->prune_one(reason, do_cleanup); }
 
+unsigned FlowControl::prune_multiple(PruneReason reason, bool do_cleanup)
+{ return cache->prune_multiple(reason, do_cleanup); }
+
 void FlowControl::timeout_flows(unsigned max, time_t cur_time)
 {
     cache->timeout(max, cur_time);
index f2b4152c8986f60223da926c548b9abdbb30520b..500d9f5a8b54ab63e516e374750fe5caad4a27b6 100644 (file)
@@ -70,6 +70,7 @@ public:
     void timeout_flows(unsigned int, time_t cur_time);
     void check_expected_flow(snort::Flow*, snort::Packet*);
     bool is_expected(snort::Packet*);
+    unsigned prune_multiple(PruneReason, bool do_cleanup);
 
     int add_expected_ignore(
         const snort::Packet* ctrlPkt, PktType, IpProtocol,
index 27abccf577ff52dfe918c2dbcb183117369ed0e3..8d4bcba5744cc900cdf98c69c2d5f4fcc530564f 100644 (file)
@@ -79,6 +79,7 @@ Flow* FlowCache::find(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::prune_multiple(PruneReason , bool) { return 0; }
 unsigned FlowCache::delete_flows(unsigned) { return 0; }
 unsigned FlowCache::timeout(unsigned, time_t) { return 1; }
 size_t FlowCache::uni_flows_size() const { return 0; }
index 6a2a508a2fad7d53b2c3bef9453cf0af21867c59..ddd85b5d4cac4e2222dad98bc619949d746137bc 100644 (file)
@@ -85,6 +85,9 @@ static const Parameter s_params[] =
     { "max_flows", Parameter::PT_INT, "2:max32", "476288",
       "maximum simultaneous flows tracked before pruning" },
 
+    { "prune_flows", Parameter::PT_INT, "1:max32", "10",
+      "maximum flows to prune at one time" },
+
     { "pruning_timeout", Parameter::PT_INT, "1:max32", "30",
       "minimum inactive time before being eligible for pruning" },
 
@@ -178,6 +181,11 @@ bool StreamModule::set(const char* fqn, Value& v, SnortConfig* c)
         config.flow_cache_cfg.max_flows = v.get_uint32();
         return true;
     }
+    else if ( v.is("prune_flows") )
+    {
+        config.flow_cache_cfg.prune_flows = v.get_uint32();
+        return true;
+    }
     else if ( v.is("pruning_timeout") )
     {
         config.flow_cache_cfg.pruning_timeout = v.get_uint32();
@@ -343,6 +351,7 @@ void StreamModuleConfig::show() const
     ConfigLogger::log_value("max_flows", flow_cache_cfg.max_flows);
     ConfigLogger::log_value("max_aux_ip", SnortConfig::get_conf()->max_aux_ip);
     ConfigLogger::log_value("pruning_timeout", flow_cache_cfg.pruning_timeout);
+    ConfigLogger::log_value("prune_flows", flow_cache_cfg.prune_flows);
 
     for (int i = to_utype(PktType::IP); i < to_utype(PktType::PDU); ++i)
     {
index 68116b52421b1c5f966890bddf86758285a9a4a9..9d5a828f5ab4eb9c8c7716967873cacaa4b2d0b8 100644 (file)
@@ -388,7 +388,7 @@ bool Stream::prune_flows()
     if ( !flow_con )
         return false;
 
-    return flow_con->prune_one(PruneReason::MEMCAP, false);
+    return flow_con->prune_multiple(PruneReason::MEMCAP, false);
 }
 
 //-------------------------------------------------------------------------