]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #811 in SNORT/snort3 from stream_underflow3 to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Tue, 14 Feb 2017 20:53:05 +0000 (15:53 -0500)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Tue, 14 Feb 2017 20:53:05 +0000 (15:53 -0500)
Squashed commit of the following:

commit 69d72bc0e02c334b8929f03e6a9085daf19a5473
Author: Steve Chew <stechew@cisco.com>
Date:   Thu Feb 9 11:59:27 2017 -0500

    Fix Stream TCP counter underflow bug and handle max and instant stats.

25 files changed:
src/file_api/file_module.cc
src/file_api/file_module.h
src/flow/flow.h
src/flow/session.h
src/framework/counts.h
src/framework/module.cc
src/framework/module.h
src/host_tracker/host_cache_module.cc
src/host_tracker/host_cache_module.h
src/main/snort_module.cc
src/managers/module_manager.cc
src/network_inspectors/perf_monitor/base_tracker.cc
src/network_inspectors/perf_monitor/flow_ip_tracker.h
src/protocols/packet_manager.cc
src/stream/base/stream_module.cc
src/stream/base/stream_module.h
src/stream/icmp/icmp_module.cc
src/stream/icmp/icmp_module.h
src/stream/ip/ip_module.cc
src/stream/ip/ip_module.h
src/stream/ip/ip_session.cc
src/stream/tcp/stream_tcp.h
src/stream/tcp/tcp_module.cc
src/stream/tcp/tcp_module.h
src/stream/tcp/tcp_session.cc

index 93034732e233faaf28b435e0cfbc2a20ffb55a6b..f73164189ed82a0833024aaf6f30aa2b98dd0f9c 100644 (file)
@@ -196,10 +196,10 @@ const PegInfo* FileIdModule::get_pegs() const
 PegCount* FileIdModule::get_counts() const
 { return (PegCount*)&file_counts; }
 
-void FileIdModule::sum_stats()
+void FileIdModule::sum_stats(bool accumulate_now_stats)
 {
     file_stats_sum();
-    Module::sum_stats();
+    Module::sum_stats(accumulate_now_stats);
 }
 
 bool FileIdModule::set(const char*, Value& v, SnortConfig*)
index 6e185c83e32e908fc5e592b35ec9e132335e9566..b9ef58aac5511f206a013bf789312c899fe527a6 100644 (file)
@@ -45,7 +45,7 @@ public:
     const PegInfo* get_pegs() const override;
     PegCount* get_counts() const override;
 
-    void sum_stats() override;
+    void sum_stats(bool) override;
 
     void load_config(FileConfig*& dst);
 
index 922ea5be7442614d8cc512b4c3662d132019d754..814d1636b54f834453e86cc3ce3a3f7893861abd 100644 (file)
@@ -48,6 +48,7 @@
 #define SSNFLAG_COUNTED_INITIALIZE  0x00000100
 #define SSNFLAG_COUNTED_ESTABLISH   0x00000200
 #define SSNFLAG_COUNTED_CLOSING     0x00000400
+#define SSNFLAG_COUNTED_CLOSED      0x00000800
 
 #define SSNFLAG_TIMEDOUT            0x00001000
 #define SSNFLAG_PRUNED              0x00002000
index e9935a95015f818ce7a16244662e6bd526ad0697..6f3afdbebd3c8448b95764c4a18474d4b4e4ce97 100644 (file)
@@ -94,6 +94,16 @@ public:
     PegCount timeouts; \
     PegCount prunes
 
+#define SESSION_STAT_TYPES \
+    CountType sessions = CountType::SUM; \
+    CountType max = CountType::MAX; \
+    CountType created = CountType::SUM; \
+    CountType released = CountType::SUM; \
+    CountType timeouts = CountType::SUM; \
+    CountType prunes = CountType::SUM
+
+// FIXIT-M The calculation for max sessions is incorrect since the sessions
+//         value is reset to zero after writing it out to the now file.
 #define SESSION_STATS_ADD(stats) \
     { \
         stats.sessions++; \
index ae606ed3c87fc252b12937d971cfc893ca262a49..bc1c389572eb4f107723af7bc72f62db9a3c518d 100644 (file)
@@ -40,6 +40,13 @@ struct PegInfo
     const char* help;
 };
 
+enum CountType
+{
+    SUM,   // Tracks cumulative total number of items seen.
+    NOW,   // Gives snapshot of current number of items.
+    MAX,   // Tracks maximum value seen.
+};
+
 SO_PUBLIC extern const struct PegInfo simple_pegs[];
 
 #define array_size(a) (sizeof(a)/sizeof(a[0]))
index 134ae02f57e196fd3210789d6e75000a173ecf02..790662343aa68183b402416da4d76950fb3d157f 100644 (file)
@@ -84,7 +84,7 @@ bool Module::set(const char*, Value& v, SnortConfig*)
     return true;
 }
 
-void Module::sum_stats()
+void Module::sum_stats_helper(bool accumulate_now_stats, const CountType* const count_types)
 {
     if ( num_counts < 0 )
         reset_stats();
@@ -97,18 +97,45 @@ void Module::sum_stats()
     if ( global_stats() )
     {
         for ( int i = 0; i < num_counts; i++ )
-            counts[i] = p[i];
+            set_peg_count(i, p[i]);
     }
     else
     {
         for ( int i = 0; i < num_counts; i++ )
         {
-            counts[i] += p[i];
-            p[i] = 0;
+            if(count_types)
+            {
+                switch (count_types[i])
+                {
+                case CountType::SUM:
+                    add_peg_count(i, p[i]);
+                    p[i] = 0;
+                    break;
+
+                case CountType::NOW:
+                    if(accumulate_now_stats)
+                        add_peg_count(i, p[i]);
+                    break;
+
+                case CountType::MAX:
+                    set_max_peg_count(i, p[i]);
+                    break;
+                }
+            }
+            else
+            {
+                add_peg_count(i, p[i]);
+                p[i] = 0;
+            }
         }
     }
 }
 
+void Module::sum_stats(bool)
+{
+    sum_stats_helper(false, nullptr);
+}
+
 void Module::show_interval_stats(IndexVec& peg_idxs, FILE* fh)
 {
     if ( num_counts > 0 )
@@ -123,16 +150,19 @@ void Module::show_stats()
 
 void Module::reset_stats()
 {
-    num_counts = 0;
-    const PegInfo* pegs = get_pegs();
+    if( num_counts <= 0 )
+    {
+        num_counts = 0;
+        const PegInfo* pegs = get_pegs();
 
-    if ( !pegs )
-        return;
+        if ( !pegs )
+            return;
 
-    while ( pegs[num_counts].name )
-        ++num_counts;
+        while ( pegs[num_counts].name )
+            ++num_counts;
 
-    counts.resize(num_counts);
+        counts.resize(num_counts);
+    }
 
     for ( int i = 0; i < num_counts; i++ )
         counts[i] = 0;
index 07c32ac22123c40418c3481b29589d9f5dd6f955..ef9f4b42c911acf49c96bbe8b8794ab216ebddd3 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <string>
 #include <vector>
+#include <assert.h>
 
 #include "framework/counts.h"
 #include "framework/parameter.h"
@@ -148,7 +149,7 @@ public:
     virtual bool global_stats() const
     { return false; }
 
-    virtual void sum_stats();
+    virtual void sum_stats(bool accumulate_now_stats);
     virtual void show_interval_stats(IndexVec&, FILE*);
     virtual void show_stats();
     virtual void reset_stats();
@@ -163,12 +164,15 @@ protected:
     Module(const char* name, const char* help, const Parameter*,
         bool is_list = false, Trace* = nullptr);
 
+    void sum_stats_helper(bool accumulate_now_stats, 
+        const CountType* const count_types);
+
 private:
     friend class ModuleManager;
     void init(const char*, const char* = nullptr);
 
     std::vector<PegCount> counts;
-    int num_counts;
+    int num_counts = -1;
 
     const char* name;
     const char* help;
@@ -179,6 +183,25 @@ private:
     int table_level = 0;
 
     Trace* trace;
+
+    void set_peg_count(int index, PegCount value)
+    {
+        assert(index < num_counts);
+        counts[index] = value;
+    }
+
+    void set_max_peg_count(int index, PegCount value)
+    {
+        assert(index < num_counts);
+        if(value > counts[index])
+            counts[index] = value;
+    }
+
+    void add_peg_count(int index, PegCount value)
+    {
+        assert(index < num_counts);
+        counts[index] += value;
+    }
 };
 
 #endif
index 2bc4c5845a8677a4eb291f86ad8bbeed063f67a4..12b901a524615ca1ee18f31717ed379ad52bb7ef 100644 (file)
@@ -66,9 +66,9 @@ const PegInfo* HostCacheModule::get_pegs() const
 PegCount* HostCacheModule::get_counts() const
 { return (PegCount*)host_cache.get_counts(); }
 
-void HostCacheModule::sum_stats()
+void HostCacheModule::sum_stats(bool accumulate_now_stats)
 {
     host_cache.lock();
-    Module::sum_stats();
+    Module::sum_stats(accumulate_now_stats);
     host_cache.unlock();
 }
index 1b663c91354da6f1697bcacbb90718f1e153df00..f249077ddac8f1d1ab539e0905f9b846ab989268 100644 (file)
@@ -42,7 +42,7 @@ public:
     const PegInfo* get_pegs() const override;
     PegCount* get_counts() const override;
 
-    void sum_stats() override;
+    void sum_stats(bool) override;
 
 private:
     static const Parameter host_cache_params[];
index 498e4d9b4095cbc30948f63bc7e746a5358e8a8a..35a8bb193c976d3acd8e8dda4ca64f61ef2cad0d 100644 (file)
@@ -513,7 +513,7 @@ public:
     bool global_stats() const override
     { return true; }
 
-    void sum_stats() override
+    void sum_stats(bool) override
     { }  // accumulate externally
 
 private:
index bed9f93802d56de746898f8c58b73faec4ba716b..1b52a60c020c206c2a2427c340d98bf538a7d718 100644 (file)
@@ -1267,7 +1267,7 @@ void ModuleManager::accumulate(SnortConfig*)
     for ( auto p : s_modules )
     {
         std::lock_guard<std::mutex> lock(stats_mutex);
-        p->mod->sum_stats();
+        p->mod->sum_stats(true);
     }
     std::lock_guard<std::mutex> lock(stats_mutex);
     pc_sum();
index 370915014987d2ec620dea1a27af005b21cf161e..fbc726fb29608e811558b4ab90c964f811c96453 100644 (file)
@@ -55,7 +55,7 @@ void BaseTracker::process(bool summary)
 
     for ( auto const& m : config->modules )
         if (!summary)
-            m->sum_stats();
+            m->sum_stats(false);
 }
 
 #ifdef UNIT_TEST
@@ -77,9 +77,9 @@ public:
 
     PegCount* get_counts() const override { return counts; }
 
-    void sum_stats() override {}
+    void sum_stats(bool) override {}
 
-    void real_sum_stats() { Module::sum_stats(); }
+    void real_sum_stats() { Module::sum_stats(false); }
 
 private:
     PegCount* counts;
index f1cbc43fc2f25cb5b91929162bca10fd10006a0c..8bb8967ce0307cc05c0e966d125b50957f2e8b92 100644 (file)
@@ -42,10 +42,10 @@ enum FlowType
 
 struct TrafficStats
 {
-    uint64_t packets_a_to_b;
-    uint64_t bytes_a_to_b;
-    uint64_t packets_b_to_a;
-    uint64_t bytes_b_to_a;
+    PegCount  packets_a_to_b;
+    PegCount  bytes_a_to_b;
+    PegCount  packets_b_to_a;
+    PegCount  bytes_b_to_a;
 };
 
 struct FlowStateValue
index 2d6704893a4550840c1708201dc2d4bd3b5ba5f7..2e02e86dd043a0e5209f980ca9a10afcf3fed915 100644 (file)
@@ -817,7 +817,7 @@ void PacketManager::encode_set_dst_mac(uint8_t* mac)
 uint8_t* PacketManager::encode_get_dst_mac()
 { return dst_mac; }
 
-uint64_t PacketManager::get_rebuilt_packet_count()
+PegCount PacketManager::get_rebuilt_packet_count()
 { return total_rebuilt_pkts; }
 
 void PacketManager::encode_set_pkt(Packet* p)
index 3eb0f0bd62c548914395665a6ee8e4a4301095e9..ba8a46264d0d4dfa343b0017c8e7bb3808ef84be 100644 (file)
@@ -142,7 +142,7 @@ bool StreamModule::set(const char* fqn, Value& v, SnortConfig*)
     return true;
 }
 
-void StreamModule::sum_stats()
+void StreamModule::sum_stats(bool)
 { base_sum(); }
 
 void StreamModule::show_stats()
index 7d03a729d668d15bd283718cad25c7007a54b86f..ecc5a89f24adfee38068e5662b29f20de76e7521 100644 (file)
@@ -82,7 +82,7 @@ public:
     ProfileStats* get_profile() const override;
     const StreamModuleConfig* get_data();
 
-    void sum_stats() override;
+    void sum_stats(bool) override;
     void show_stats() override;
     void reset_stats() override;
 
index 725e6cd6d214f708678d71efefe771edbb86d2a9..e6d8c1fcaeb8862a752690397762fe66547da5df 100644 (file)
@@ -93,3 +93,14 @@ const PegInfo* StreamIcmpModule::get_pegs() const
 
 PegCount* StreamIcmpModule::get_counts() const
 { return (PegCount*)&icmpStats; }
+
+void StreamIcmpModule::sum_stats(bool accumulate_now_stats)
+{
+    assert(sizeof(IcmpStats)/sizeof(PegCount) == sizeof(IcmpStatTypes)/sizeof(CountType));
+
+    static const IcmpStatTypes icmp_stat_types;
+    static const CountType* const count_types = (const CountType* const)&icmp_stat_types;
+
+    sum_stats_helper(accumulate_now_stats, count_types);
+}
+
index 70424ca9830fc2f3bc00e932bfb720b313a0a684..7a46665171e5f9e7339ab67b4e663d2d00fb505a 100644 (file)
@@ -35,6 +35,13 @@ struct IcmpStats
     SESSION_STATS;
 };
 
+struct IcmpStatTypes
+{
+    SESSION_STAT_TYPES;
+
+    IcmpStatTypes() {}
+};
+
 //-------------------------------------------------------------------------
 // stream_icmp module
 //-------------------------------------------------------------------------
@@ -55,6 +62,7 @@ public:
     ProfileStats* get_profile(unsigned, const char*&, const char*&) const override;
     const PegInfo* get_pegs() const override;
     PegCount* get_counts() const override;
+    void sum_stats(bool) override;
 
     StreamIcmpConfig* get_data();
 
index 2ebfbe2c33199c0f7347f20ba4dc281ae4157cf6..dedff77b01e4d9a02d15acdefce1d4106997acc9 100644 (file)
@@ -217,3 +217,13 @@ const PegInfo* StreamIpModule::get_pegs() const
 PegCount* StreamIpModule::get_counts() const
 { return (PegCount*)&ip_stats; }
 
+void StreamIpModule::sum_stats(bool accumulate_now_stats)
+{
+    assert(sizeof(IpStats)/sizeof(PegCount) == sizeof(IpStatTypes)/sizeof(CountType));
+
+    static const IpStatTypes ip_stat_types;
+    static const CountType* const count_types = (const CountType* const)&ip_stat_types;
+
+    sum_stats_helper(accumulate_now_stats, count_types);
+}
+
index ae31d519e8b4516fc354b51146f1432fe552b6a1..b78b7368258b0d7c20c973532c934a2e7807146a 100644 (file)
@@ -58,7 +58,7 @@ struct IpStats
 {
     SESSION_STATS;
     PegCount total;             // total_ipfragmented_packets
-    PegCount current;           // iCurrentFrags
+    PegCount current_frags;     // iCurrentFrags
     PegCount max_frags;         // iMaxFrags
     PegCount reassembles;       // total_ipreassembled_packets / iFragFlushes
     PegCount discards;
@@ -78,6 +78,35 @@ struct IpStats
     PegCount fragmented_bytes;  // total_ipfragmented_bytes
 };
 
+struct IpStatTypes
+{
+    SESSION_STAT_TYPES;
+    CountType total = CountType::SUM;
+    CountType current_frags = CountType::NOW;
+
+    // FIXIT-M max_frags appears to be unused.
+    CountType max_frags = CountType::SUM;
+
+    CountType reassembles = CountType::SUM;
+    CountType discards = CountType::SUM;
+    CountType frag_timeouts = CountType::SUM;
+    CountType overlaps = CountType::SUM;
+    CountType anomalies = CountType::SUM;
+    CountType alerts = CountType::SUM;
+    CountType drops = CountType::SUM;
+    CountType trackers_created = CountType::SUM;
+    CountType trackers_released = CountType::SUM;
+    CountType trackers_cleared = CountType::SUM;
+    CountType trackers_completed = CountType::SUM;
+    CountType nodes_created = CountType::SUM;
+    CountType nodes_released = CountType::SUM;
+    CountType mem_in_use = CountType::NOW;
+    CountType reassembled_bytes = CountType::SUM;
+    CountType fragmented_bytes = CountType::SUM;
+
+    IpStatTypes() {}
+};
+
 extern const PegInfo ip_pegs[];
 extern THREAD_LOCAL struct IpStats ip_stats;
 extern THREAD_LOCAL ProfileStats ip_perf_stats;
@@ -109,6 +138,7 @@ public:
     ProfileStats* get_profile(unsigned, const char*&, const char*&) const override;
     const PegInfo* get_pegs() const override;
     PegCount* get_counts() const override;
+    void sum_stats(bool) override;
     StreamIpConfig* get_data();
 
     unsigned get_gid() const override
index b8b3238cb22c25c43b032ef0a505d2ce344d6429..b08528e82420f47ca22178736400a8541b9468be 100644 (file)
@@ -128,9 +128,15 @@ IpSession::IpSession(Flow* flow) : Session(flow)
 
 void IpSession::clear()
 {
+    if(tracker.engine)
+    {
+        //  Only decrement if the tracker was not already cleaned up.
+        assert(ip_stats.current_frags);
+        ip_stats.current_frags--;
+    }
+
     IpSessionCleanup(flow, &tracker);
     IpHAManager::process_deletion(flow);
-    ip_stats.current--;
 }
 
 bool IpSession::setup(Packet*)
@@ -141,7 +147,7 @@ bool IpSession::setup(Packet*)
     memset(&tracker, 0, sizeof(tracker));
     SESSION_STATS_ADD(ip_stats);
     ip_stats.trackers_created++;
-    ip_stats.current++;
+    ip_stats.current_frags++;
 
 #ifdef ENABLE_EXPECTED_IP
     if ( Stream::expected_flow(flow, p) )
index d25aa74629189d3488e74853c0d8bfddfe451c43..38b9e5030832e8004c96d0ba026b2f688bd2518d 100644 (file)
 #ifndef STREAM_TCP_H
 #define STREAM_TCP_H
 
-class Flow;
 class Inspector;
 class TcpStreamConfig;
-class Session;
 
-// misc stuff
-Session* get_tcp_session(Flow*);
 TcpStreamConfig* get_tcp_cfg(Inspector*);
 
-void tcp_sinit();
-void tcp_sterm();
-void tcp_sum();
-void tcp_stats();
-void tcp_reset_stats();
-void tcp_show(TcpStreamConfig*);
-
 #endif
 
index 32973bc69a949e3d99814f3261d2a30815aaad66..f7a715b5f52733e9ecbd6fb4555887d687b98418 100644 (file)
@@ -62,8 +62,8 @@ const PegInfo tcp_pegs[] =
     { "rebuilt_bytes", "total rebuilt bytes" },
     { "overlaps", "overlapping segments queued" },
     { "gaps", "missing data between PDUs" },
-    { "max_segs", "number of times the maximum queued segment limit was reached" },
-    { "max_bytes", "number of times the maximum queued byte limit was reached" },
+    { "exceeded_max_segs", "number of times the maximum queued segment limit was reached" },
+    { "exceeded_max_bytes", "number of times the maximum queued byte limit was reached" },
     { "internal_events", "135:X events generated" },
     { "client_cleanups", "number of times data from server was flushed when session released" },
     { "server_cleanups", "number of times data from client was flushed when session released" },
@@ -365,3 +365,13 @@ const PegInfo* StreamTcpModule::get_pegs() const
 PegCount* StreamTcpModule::get_counts() const
 { return (PegCount*)&tcpStats; }
 
+void StreamTcpModule::sum_stats(bool accumulate_now_stats)
+{
+    assert(sizeof(TcpStats)/sizeof(PegCount) == sizeof(TcpStatTypes)/sizeof(CountType));
+
+    static const TcpStatTypes tcp_stat_types;
+    static const CountType* const count_types = (const CountType* const)&tcp_stat_types;
+
+    sum_stats_helper(accumulate_now_stats, count_types);
+}
+
index 06b28e00c9d1bac5c786ef37c88cb550c900f4bb..575fca729b587a0fb150f979245fb51541c49eba 100644 (file)
@@ -82,8 +82,8 @@ struct TcpStats
     PegCount rebuilt_bytes;     //total_rebuilt_bytes
     PegCount overlaps;
     PegCount gaps;
-    PegCount max_segs;
-    PegCount max_bytes;
+    PegCount exceeded_max_segs;
+    PegCount exceeded_max_bytes;
     PegCount internalEvents;
     PegCount s5tcp1;
     PegCount s5tcp2;
@@ -93,6 +93,40 @@ struct TcpStats
     PegCount sessions_closing;
 };
 
+struct TcpStatTypes
+{
+    SESSION_STAT_TYPES;
+    CountType resyns = CountType::SUM;
+    CountType discards = CountType::SUM;
+    CountType events = CountType::SUM;
+    CountType sessions_ignored = CountType::SUM;
+    CountType no_pickups = CountType::SUM;
+    CountType sessions_on_syn = CountType::SUM;
+    CountType sessions_on_syn_ack = CountType::SUM;
+    CountType sessions_on_3way = CountType::SUM;
+    CountType sessions_on_data = CountType::SUM;
+    CountType segs_queued = CountType::SUM;
+    CountType segs_released = CountType::SUM;
+    CountType segs_split = CountType::SUM;
+    CountType segs_used = CountType::SUM;
+    CountType rebuilt_packets = CountType::SUM;
+    CountType rebuilt_buffers = CountType::SUM;
+    CountType rebuilt_bytes = CountType::SUM;
+    CountType overlaps = CountType::SUM;
+    CountType gaps = CountType::SUM;
+    CountType exceeded_max_segs = CountType::SUM;
+    CountType exceeded_max_bytes = CountType::SUM;
+    CountType internalEvents = CountType::SUM;
+    CountType s5tcp1 = CountType::SUM;
+    CountType s5tcp2 = CountType::SUM;
+    CountType mem_in_use = CountType::NOW;
+    CountType sessions_initializing = CountType::NOW;
+    CountType sessions_established = CountType::NOW;
+    CountType sessions_closing = CountType::NOW;
+
+    TcpStatTypes() {}
+};
+
 extern THREAD_LOCAL struct TcpStats tcpStats;
 
 inline void inc_tcp_discards()
@@ -130,6 +164,7 @@ public:
     ProfileStats* get_profile(unsigned, const char*&, const char*&) const override;
     const PegInfo* get_pegs() const override;
     PegCount* get_counts() const override;
+    void sum_stats(bool) override;
 
 private:
     TcpStreamConfig* config;
index 97cdd846b0ccdd607884a6906bb3a18679133721..0275646fabfb86eb9bbe8bf6cd5583899b0f746e 100644 (file)
@@ -204,9 +204,8 @@ void TcpSession::update_perf_base_state(char newState)
             if ( ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
                 && !( session_flags & SSNFLAG_COUNTED_CLOSING ) )
             {
-                //assert(tcpStats.sessions_initializing);
-                if ( tcpStats.sessions_initializing )  // FIXIT-L eliminate / fix underflow
-                    tcpStats.sessions_initializing--;
+                assert(tcpStats.sessions_initializing);
+                tcpStats.sessions_initializing--;
             }
         }
         break;
@@ -219,7 +218,7 @@ void TcpSession::update_perf_base_state(char newState)
 
             if ( session_flags & SSNFLAG_COUNTED_ESTABLISH )
             {
-                //assert(tcpStats.sessions_established);
+                assert(tcpStats.sessions_established);
                 tcpStats.sessions_established--;
 
                 if (perfmon_config  && (perfmon_config->perf_flags & PERF_FLOWIP))
@@ -228,34 +227,36 @@ void TcpSession::update_perf_base_state(char newState)
             }
             else if ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
             {
-                //assert(tcpStats.sessions_initializing);
-                if ( tcpStats.sessions_initializing )  // FIXIT-L eliminate / fix underflow
-                    tcpStats.sessions_initializing--;
+                assert(tcpStats.sessions_initializing);
+                tcpStats.sessions_initializing--;
             }
         }
         break;
 
     case TcpStreamTracker::TCP_CLOSED:
-        if ( session_flags & SSNFLAG_COUNTED_CLOSING )
-        {
-            //assert(tcpStats.sessions_closing);
-            tcpStats.sessions_closing--;
-        }
-        else if ( session_flags & SSNFLAG_COUNTED_ESTABLISH )
+        if ( !( session_flags & SSNFLAG_COUNTED_CLOSED ) )
         {
-            //assert(tcpStats.sessions_established);
-            if ( tcpStats.sessions_established )  // FIXIT-L eliminate / fix underflow
+            session_flags |= SSNFLAG_COUNTED_CLOSED;
+
+            if ( session_flags & SSNFLAG_COUNTED_CLOSING )
+            {
+                assert(tcpStats.sessions_closing);
+                tcpStats.sessions_closing--;
+            }
+            else if ( session_flags & SSNFLAG_COUNTED_ESTABLISH )
+            {
+                assert(tcpStats.sessions_established);
                 tcpStats.sessions_established--;
 
-            if ( perfmon_config && ( perfmon_config->perf_flags & PERF_FLOWIP ) )
-                perf_flow_ip->update_state(&flow->client_ip,
-                    &flow->server_ip, SFS_STATE_TCP_CLOSED);
-        }
-        else if ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
-        {
-            //assert(tcpStats.sessions_initializing);
-            if ( tcpStats.sessions_initializing )  // FIXIT-L eliminate / fix underflow
+                if ( perfmon_config && ( perfmon_config->perf_flags & PERF_FLOWIP ) )
+                    perf_flow_ip->update_state(&flow->client_ip,
+                        &flow->server_ip, SFS_STATE_TCP_CLOSED);
+            }
+            else if ( session_flags & SSNFLAG_COUNTED_INITIALIZE )
+            {
+                assert(tcpStats.sessions_initializing);
                 tcpStats.sessions_initializing--;
+            }
         }
         break;
 
@@ -298,7 +299,7 @@ bool TcpSession::flow_exceeds_config_thresholds(TcpSegmentDescriptor& tsd)
     if ( config->max_queued_bytes
         && ( listener->reassembler->get_seg_bytes_total() > config->max_queued_bytes ) )
     {
-        tcpStats.max_bytes++;
+        tcpStats.exceeded_max_bytes++;
         // FIXIT-H add one alert per flow per above
         return true;
     }
@@ -306,7 +307,7 @@ bool TcpSession::flow_exceeds_config_thresholds(TcpSegmentDescriptor& tsd)
     if ( config->max_queued_segs
         && ( listener->reassembler->get_seg_count() + 1 > config->max_queued_segs ) )
     {
-        tcpStats.max_segs++;
+        tcpStats.exceeded_max_segs++;
         // FIXIT-H add one alert per flow per above
         return true;
     }