* 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
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();
new_node = true;
}
+ ExpectFlow* last = nullptr;
if (!new_node)
{
// Requests will be rejected if the snort_protocol_id doesn't
// these fields are const after initialization
const FlowKey* key;
- Session* session;
BitOp* bitop;
FlowHAState* ha_state;
FlowStash* stash;
// these fields are always set; not zeroed
Flow* prev, * next;
+ Session* session;
Inspector* ssn_client;
Inspector* ssn_server;
{
void* key = hash_table->push(flow);
flow->key = (FlowKey*)key;
+ ++flows_allocated;
}
unsigned FlowCache::get_count()
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);
flow->term();
else
flow->reset();
- link_uni(flow);
}
+ link_uni(flow);
if ( flow->session && flow->pkt_type != key->pkt_type )
flow->term();
}
while ( Flow* flow = (Flow*)hash_table->pop() )
- flow->term();
+ delete flow;
return retired;
}
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);
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;
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
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()
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;
}
//-------------------------------------------------------------------------
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()
{
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
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;
if ( !want_flow(type, p) )
return true;
- flow = cache->get(&key);
+ flow = cache->allocate(&key);
if ( !flow )
return true;
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);
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
flow->prev->next = flow->next;
flow->next = flow->prev = nullptr;
--count;
-
}
snort::Flow* get_oldest_uni()
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; }