if (!pruned and hash_table->get_num_nodes() > max_cap)
{
- prune_one(PruneReason::EXCESS, true);
- ++pruned;
+ pruned += prune_multiple(PruneReason::EXCESS, true);
}
}
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);
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();
unsigned max_flows = 0;
unsigned pruning_timeout = 0;
FlowTypeConfig proto[to_utype(PktType::MAX)];
+ unsigned prune_flows = 0;
};
#endif
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);
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,
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; }
{ "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" },
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();
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)
{
if ( !flow_con )
return false;
- return flow_con->prune_one(PruneReason::MEMCAP, false);
+ return flow_con->prune_multiple(PruneReason::MEMCAP, false);
}
//-------------------------------------------------------------------------