]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #349 in SNORT/snort3 from ~JOCORNET/snort3:flowcache_cleanup to...
authorRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 18 Mar 2016 14:51:41 +0000 (10:51 -0400)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 18 Mar 2016 14:51:41 +0000 (10:51 -0400)
Squashed commit of the following:

commit 2fca1612227942961bf4323b542d19f888fb511e
Author: Joel Cornett <joel.cornett@gmail.com>
Date:   Fri Mar 18 10:42:57 2016 -0400

    moved flag_context to helpers/

commit 2f63f3bc1fc3b0f34ca3901631238f74cb5fd8fc
Author: Joel Cornett <joel.cornett@gmail.com>
Date:   Thu Mar 17 17:35:24 2016 -0400

    moved stuff around

commit e7b40f23a6d260aa1e0c1329ea83933d99a42544
Author: Joel Cornett <joel.cornett@gmail.com>
Date:   Thu Mar 17 17:23:55 2016 -0400

    fixed include

commit 07526b2908250c5c17ff0eeef0878bc4ec2c5258
Author: Joel Cornett <joel.cornett@gmail.com>
Date:   Thu Mar 17 16:26:56 2016 -0400

    fixed zero initialization of PruneStats

commit 18ab473322799d2d881e86bb96539f0b43bc8496
Author: Joel Cornett <joel.cornett@gmail.com>
Date:   Thu Mar 17 14:52:40 2016 -0400

    updated cleanup_flows calculation

commit 47d1baeb2b604fa2fd3c569b9f9792c3e90127ea
Author: Joel Cornett <joel.cornett@gmail.com>
Date:   Thu Mar 17 13:47:15 2016 -0400

    Cleaned up FlowCache

    Added granularity to prune counts
    Removed memCheck from pruning
    Changed prune_flows -> prune_one for memory handler

13 files changed:
src/flow/flow_cache.cc
src/flow/flow_cache.h
src/flow/flow_control.cc
src/flow/flow_control.h
src/framework/decode_data.h
src/helpers/CMakeLists.txt
src/helpers/Makefile.am
src/helpers/flag_context.h [new file with mode: 0644]
src/memory/memory_cap.cc
src/memory/prune_handler.cc
src/packet_io/active.h
src/protocols/mpls.h
src/stream/stream_api.cc

index a815e66391eadc883a159ec1c33681ceac266199..31bbaec8086b43586882f1a88a00c6bb57b10267 100644 (file)
 #include "config.h"
 #endif
 
-#include "packet_io/active.h"
-#include "time/packet_time.h"
-#include "ips_options/ips_flowbits.h"
 #include "hash/zhash.h"
+#include "helpers/flag_context.h"
+#include "ips_options/ips_flowbits.h"
 #include "main/snort_debug.h"
+#include "packet_io/active.h"
+#include "time/packet_time.h"
 
 #define SESSION_CACHE_FLAG_PURGING  0x01
 
+uint64_t PruneStats::get_total() const
+{
+    uint64_t total = 0;
+    for ( reason_t i = 0;
+          i < static_cast<reason_t>(PruneReason::MAX); ++i )
+    {
+        total += prunes[i];
+    }
+
+    return total;
+}
+
 //-------------------------------------------------------------------------
 // FlowCache stuff
 //-------------------------------------------------------------------------
@@ -46,6 +59,9 @@ FlowCache::FlowCache (
     else
         cleanup_flows = cleanup_count;
 
+    if ( cleanup_flows >= cfg.max_sessions )
+        cleanup_flows = cfg.max_sessions - 1;
+
     if ( !cleanup_flows )
         cleanup_flows = 1;
 
@@ -58,8 +74,10 @@ FlowCache::FlowCache (
     uni_head->next = uni_tail;
     uni_tail->prev = uni_head;
 
-    prunes = uni_count = 0;
+    uni_count = 0;
     flags = 0x0;
+
+    assert(prune_stats.get_total() == 0);
 }
 
 FlowCache::~FlowCache ()
@@ -96,7 +114,6 @@ Flow* FlowCache::find(const FlowKey* key)
             flow->last_data_seen = t;
     }
 
-    last = flow;
     return flow;
 }
 
@@ -136,7 +153,7 @@ Flow* FlowCache::get(const FlowKey* key)
         if ( !prune_stale(timestamp, nullptr) )
         {
             if ( !prune_unis() )
-                prune_excess(false, nullptr);
+                prune_excess(nullptr);
         }
 
         flow = (Flow*)hash_table->get(key);
@@ -147,14 +164,14 @@ Flow* FlowCache::get(const FlowKey* key)
     }
 
     flow->last_data_seen = timestamp;
-    last = flow;
 
     return flow;
 }
 
-int FlowCache::release(Flow* flow, const char*)
+int FlowCache::release(Flow* flow, PruneReason reason)
 {
     flow->reset();
+    prune_stats.update(reason);
     return remove(flow);
 }
 
@@ -168,54 +185,56 @@ int FlowCache::remove(Flow* flow)
 
 uint32_t FlowCache::prune_stale(uint32_t thetime, const Flow* save_me)
 {
-    Flow* flow;
-    uint32_t pruned = 0;
-    Active::suspend();
+    ActiveSuspendContext act_susp;
 
-    /* Pruning, look for flows that have time'd out */
-    flow = (Flow*)hash_table->first();
+    uint32_t pruned = 0;
+    auto flow = static_cast<Flow*>(hash_table->first());
 
-    while ( flow )
+    while ( flow and pruned <= cleanup_flows )
     {
+#if 0
         // FIXIT-L this loops forever if 1 flow in cache
         if (flow == save_me)
         {
+            break;
             if ( hash_table->get_count() == 1 )
                 break;
 
             hash_table->touch();
         }
-
-        else if ((flow->last_data_seen + config.pruning_timeout) < thetime)
+#else
+        // Reached the current flow. This *should* be the newest flow
+        if ( flow == save_me )
         {
-            DebugMessage(DEBUG_STREAM, "pruning stale flow\n");
-            flow->ssn_state.session_flags |= SSNFLAG_TIMEDOUT;
-            release(flow, "stale/timeout");
-            pruned++;
+            // assert( flow->last_data_seen + config.pruning_timeout >= thetime );
+            // bool rv = hash_table->touch(); assert( !rv );
+            break;
         }
-        else
+#endif
+        if ( flow->last_data_seen + config.pruning_timeout >= thetime )
             break;
 
-        if (pruned > cleanup_flows)
-            break;
+        DebugMessage(DEBUG_STREAM, "pruning stale flow\n");
+        flow->ssn_state.session_flags |= SSNFLAG_TIMEDOUT;
+        release(flow, PruneReason::TIMEOUT);
+        ++pruned;
 
-        flow = (Flow*)hash_table->first();
+        flow = static_cast<Flow*>(hash_table->first());
     }
 
-    prunes += pruned;
-    Active::resume();
     return pruned;
 }
 
 uint32_t FlowCache::prune_unis()
 {
+    ActiveSuspendContext act_susp;
+
     // we may have many or few unis; need to find reasonable ratio
     // FIXIT-L max_uni should be based on typical ratios seen in perfmon
     const uint32_t max_uni = (config.max_sessions >> 2) + 1;
 
     Flow* curr = uni_tail->prev;
     uint32_t pruned = 0;
-    Active::suspend();
 
     while ( (uni_count > max_uni) && curr && (pruned < cleanup_flows) )
     {
@@ -225,109 +244,104 @@ uint32_t FlowCache::prune_unis()
         if ( flow->was_blocked() )
             continue;
 
-        release(flow, "unidirectional");
+        release(flow, PruneReason::UNI);
         ++pruned;
     }
-    prunes += pruned;
-    Active::resume();
+
     return pruned;
 }
 
-uint32_t FlowCache::prune_excess(bool memCheck, const Flow* save_me)
+uint32_t FlowCache::prune_excess(const Flow* save_me)
 {
-    /* Free up 'n' flows at a time until we get under the
-     * memcap or free enough flows to be able to create
-     * new ones.
-     */
-    const uint32_t max_cap = config.max_sessions - cleanup_flows;
+    ActiveSuspendContext act_susp;
+
+    auto max_cap = config.max_sessions - cleanup_flows;
+    assert(max_cap > 0);
+
     uint32_t pruned = 0;
-    Active::suspend();
+    uint32_t blocks = 0;
 
-    while (
-        (hash_table->get_count() > 1) &&
-        ((!memCheck && ((hash_table->get_count() > max_cap) || !pruned)) ||
-        (memCheck && memcap.at_max()) ))
+    while ( hash_table->get_count() > max_cap and hash_table->get_count() > blocks )
     {
-        unsigned int blocks = 0;
-        Flow* flow = (Flow*)hash_table->first();
+        auto flow = static_cast<Flow*>(hash_table->first());
+        assert(flow); // holds true because hash_table->get_count() > 0
 
-        for (unsigned i=0; i<cleanup_flows &&
-            (hash_table->get_count() > blocks); i++)
+        if ( flow == save_me or flow->was_blocked() )
         {
-            if ( (flow != save_me) && (!memCheck || !flow->was_blocked()) )
-            {
-                flow->ssn_state.session_flags |= SSNFLAG_PRUNED;
-                release(flow, memCheck ? "memcap/check" : "memcap/stale");
-                pruned++;
-            }
-            else
-            {
-                if ( flow && flow->was_blocked() )
-                    blocks++;
-
-                if ( !hash_table->touch() )
-                    break; // this flow is the only one left
-
-                i--; /* Didn't clean this one */
-            }
-            flow = (Flow*)hash_table->first();
+            if ( flow->was_blocked() )
+                ++blocks;
+
+            // FIXIT-M J we should update last_data_seen upon touch to ensure
+            // the hash_table LRU list remains sorted by time
+            if ( !hash_table->touch() )
+                break;
         }
 
-        /* Nothing (or the one we're working with) in table, couldn't kill it */
-        if (!memCheck && (pruned == 0))
-            break;
+        else
+        {
+            flow->ssn_state.session_flags |= SSNFLAG_PRUNED;
+            release(flow, PruneReason::EXCESS);
+            ++pruned;
+        }
     }
-    prunes += pruned;
-    Active::resume();
+
     return pruned;
 }
 
-void FlowCache::timeout(uint32_t flowCount, time_t cur_time)
+bool FlowCache::prune_one(PruneReason reason)
 {
-    uint32_t flowRetiredCount = 0, flowExaminedCount = 0;
-    uint32_t flowMax = flowCount * 2;
+    // so we don't prune the current flow (assume current == MRU)
+    if ( hash_table->get_count() <= 1 )
+        return false;
+
+    auto flow = static_cast<Flow*>(hash_table->first());
+    assert(flow);
 
-    Flow* flow = (Flow*)hash_table->current();
+    flow->ssn_state.session_flags |= SSNFLAG_PRUNED;
+    release(flow, reason);
+
+    return true;
+}
+
+void FlowCache::timeout(uint32_t num_flows, time_t thetime)
+{
+    uint32_t retired = 0;
+
+    auto flow = static_cast<Flow*>(hash_table->current());
 
     if ( !flow )
-        flow = (Flow*)hash_table->first();
+        flow = static_cast<Flow*>(hash_table->first());
 
-    while ( flow && flowRetiredCount < flowCount && flowExaminedCount < flowMax )
+    while ( flow and retired < num_flows )
     {
-        if ((time_t)(flow->last_data_seen + config.nominal_timeout) > cur_time)
+        if ( flow->last_data_seen + config.nominal_timeout > thetime )
             break;
 
-        flowExaminedCount++;
-
         DebugMessage(DEBUG_STREAM, "retiring stale flow\n");
         flow->ssn_state.session_flags |= SSNFLAG_TIMEDOUT;
-        release(flow, "stale/timeout");
+        release(flow, PruneReason::TIMEOUT);
 
-        flowRetiredCount++;
-        flow = (Flow*)hash_table->current();
+        ++retired;
+
+        flow = static_cast<Flow*>(hash_table->current());
     }
 }
 
-/* Remove all flows from the hash table. */
+// Remove all flows from the hash table.
 int FlowCache::purge()
 {
-    int retCount = 0;
+    ActiveSuspendContext act_susp;
+    FlagContext<decltype(flags)>(flags, SESSION_CACHE_FLAG_PURGING);
 
-    Active::suspend();
-    flags |= SESSION_CACHE_FLAG_PURGING;
-    Flow* flow = (Flow*)hash_table->first();
+    uint32_t retired = 0;
 
-    while ( flow )
+    while ( auto flow = static_cast<Flow*>(hash_table->first()) )
     {
         flow->ssn_state.session_flags |= SSNFLAG_PRUNED;
-        release(flow, "purge whole cache");
-        retCount++;
-        flow = (Flow*)hash_table->first();
+        release(flow, PruneReason::PURGE);
+        ++retired;
     }
 
-    flags &= ~SESSION_CACHE_FLAG_PURGING;
-    Active::resume();
-
-    return retCount;
+    return retired;
 }
 
index 52119c928978a4bbbf524acdd2148bb82a18ea87..f48172f0e7125793bc0c236200530ea7aa5a772c 100644 (file)
 // there is a FlowCache instance for each protocol.
 // Flows are stored in a ZHash instance by FlowKey.
 
+#include <ctime>
+#include <type_traits>
+
 #include "flow/flow_config.h"
-#include "flow/flow_key.h"
 #include "flow/memcap.h"
-#include "stream/stream.h"
+
+class Flow;
+struct FlowKey;
+
+// FIXIT-L J we can probably fiddle with these breakdowns
+enum class PruneReason : uint8_t
+{
+    PURGE = 0,
+    TIMEOUT,
+    EXCESS,
+    UNI,
+    HA_SYNC,
+    CLOSED,
+    USER,
+    MAX
+};
+
+struct PruneStats
+{
+    using reason_t = std::underlying_type<PruneReason>::type;
+
+    uint32_t prunes[static_cast<reason_t>(PruneReason::MAX)] { };
+
+    uint64_t get_total() const;
+    void update(PruneReason reason)
+    { ++prunes[static_cast<reason_t>(reason)]; }
+};
 
 class FlowCache
 {
@@ -45,20 +73,25 @@ public:
     Flow* find(const FlowKey*);
     Flow* get(const FlowKey*);
 
-    int release(Flow*, const char* reason);
+    int release(Flow*, PruneReason = PruneReason::USER);
 
     uint32_t prune_unis();
     uint32_t prune_stale(uint32_t thetime, const Flow* save_me);
-    uint32_t prune_excess(bool memCheck, const Flow* save_me);
-    uint32_t prune_excess() { return prune_excess(false, last); }
-    void timeout(uint32_t flowCount, time_t cur_time);
+    uint32_t prune_excess(const Flow* save_me);
+    bool prune_one(PruneReason);
+    void timeout(uint32_t num_flows, time_t cur_time);
 
     int purge();
     int get_count();
 
-    uint32_t get_max_flows() { return config.max_sessions; }
-    uint32_t get_prunes() { return prunes; }
-    void reset_prunes() { prunes = 0; }
+    uint32_t get_max_flows() const
+    { return config.max_sessions; }
+
+    uint64_t get_prunes() const
+    { return prune_stats.get_total(); }
+
+    void reset_prunes()
+    { prune_stats = PruneStats(); }
 
     void unlink_uni(Flow*);
 
@@ -71,7 +104,6 @@ private:
 private:
     const FlowConfig& config;
     uint32_t cleanup_flows;
-    uint32_t prunes;
     uint32_t uni_count;
     uint32_t flags;
 
@@ -79,7 +111,7 @@ private:
 
     class ZHash* hash_table;
     Flow* uni_head, * uni_tail;
-    const Flow* last = nullptr;
+    PruneStats prune_stats;
 };
 
 #endif
index 57c8dee7d42c5c0f323df8c28029dbafdc967f24..ba941e328f055e245eaa8fc1f395205828187664 100644 (file)
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
 
-#include "flow/flow_control.h"
+#include "flow_control.h"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include <assert.h>
-#include <arpa/inet.h>
+#include <cassert>
 
-#include "flow/flow_cache.h"
+#include "detection/detect.h"
 #include "flow/expect_cache.h"
+#include "flow/flow_cache.h"
 #include "flow/session.h"
-#include "packet_io/active.h"
-#include "packet_io/sfdaq.h"
-#include "utils/stats.h"
-#include "protocols/layer.h"
-#include "protocols/vlan.h"
 #include "managers/inspector_manager.h"
-#include "sfip/sf_ip.h"
-#include "protocols/tcp.h"
-#include "protocols/udp.h"
+#include "packet_io/active.h"
 #include "protocols/icmp4.h"
 #include "protocols/icmp6.h"
-#include "detection/detect.h"
+#include "protocols/tcp.h"
+#include "protocols/udp.h"
+#include "protocols/vlan.h"
+#include "sfip/sf_ip.h"
 
 FlowControl::FlowControl()
 {
@@ -58,6 +54,8 @@ FlowControl::FlowControl()
     get_ip = get_icmp = nullptr;
     get_tcp = get_udp = nullptr;
     get_user = get_file = nullptr;
+
+    last_pkt_type = PktType::NONE;
 }
 
 FlowControl::~FlowControl()
@@ -204,15 +202,15 @@ void FlowControl::delete_flow(const FlowKey* key)
     Flow* flow = cache->find(key);
 
     if ( flow )
-        cache->release(flow, "ha sync");
+        cache->release(flow, PruneReason::HA_SYNC);
 }
 
-void FlowControl::delete_flow(Flow* flow, const char* why)
+void FlowControl::delete_flow(Flow* flow, PruneReason reason)
 {
     FlowCache* cache = get_cache(flow->protocol);
 
     if ( cache )
-        cache->release(flow, why);
+        cache->release(flow, reason);
 }
 
 void FlowControl::purge_flows (PktType proto)
@@ -237,27 +235,15 @@ void FlowControl::prune_flows(PktType proto, Packet* p)
     if (!cache->prune_stale(p->pkth->ts.tv_sec, (Flow*)p->flow))
     {
         // if no luck, try the memcap
-        cache->prune_excess(true, (Flow*)p->flow);
+        cache->prune_excess((Flow*)p->flow);
     }
 }
 
-void FlowControl::prune_flows(PktType proto)
-{
-    auto cache = get_cache(proto);
-    if ( !cache )
-        return;
-
-    cache->prune_excess();
-}
-
-void FlowControl::prune_flows()
+// hole for memory manager/prune handler
+bool FlowControl::prune_one(PruneReason reason)
 {
-    prune_flows(PktType::IP);
-    prune_flows(PktType::ICMP);
-    prune_flows(PktType::TCP);
-    prune_flows(PktType::UDP);
-    prune_flows(PktType::PDU);
-    prune_flows(PktType::FILE);
+    auto cache = get_cache(last_pkt_type);
+    return cache ? cache->prune_one(reason) : false;
 }
 
 void FlowControl::timeout_flows(uint32_t flowCount, time_t cur_time)
index 6f52da29551700a89273619082ec42c31a1bf883..008ee6332d82b97596b8af933238a2d5d8e5db93 100644 (file)
 // this is where all the flow caches are managed and where all flows are
 // processed.  flows are pruned as needed to process new flows.
 
-#include "flow/flow.h"
+#include <cstdint>
+
 #include "flow/flow_config.h"
+#include "framework/decode_data.h"
+#include "framework/inspector.h"
 #include "utils/stats.h"
 
+class Flow;
+class FlowData;
+struct FlowKey;
+struct Packet;
+struct sfip_t;
+
+enum class PruneReason : uint8_t;
+
 class FlowControl
 {
 public:
@@ -55,11 +66,10 @@ public:
     void init_exp(uint32_t max);
 
     void delete_flow(const FlowKey*);
-    void delete_flow(Flow*, const char* why);
+    void delete_flow(Flow*, PruneReason);
     void purge_flows(PktType);
     void prune_flows(PktType, Packet*);
-    void prune_flows(PktType);
-    void prune_flows();
+    bool prune_one(PruneReason);
     void timeout_flows(uint32_t flowCount, time_t cur_time);
 
     char expected_flow(Flow*, Packet*);
@@ -113,6 +123,7 @@ private:
     InspectSsnFunc get_file;
 
     class ExpectCache* exp_cache;
+    PktType last_pkt_type;
 };
 
 #endif
index bf8e5c4b414bab3cdcaa30b5cc98ddad8cbb3898..64913cd26f39141bc0e0718b0ec092b399f1e1e2 100644 (file)
@@ -22,6 +22,7 @@
 
 // Captures decode information from Codecs.
 
+#include <cstdint>
 #include <type_traits>
 
 #include "protocols/mpls.h"
index de1ddd4ca1f4ce01192f5e40b7409d051f0d1e77..8e4053c776221ffced59667886be78d095612c25 100644 (file)
@@ -10,6 +10,7 @@ add_library (helpers STATIC
     ring.h
     ring_logic.h
     swapper.h
+    flag_context.h
 )
 
 target_link_libraries(helpers
index 7749d2ab40c68b9df0f2234961d6f82ff42bc29b..3fe7e94f3c27cef81be62bfefb2b2ddc9090da37 100644 (file)
@@ -14,5 +14,5 @@ process.cc \
 process.h \
 ring.h \
 ring_logic.h \
-swapper.h
-
+swapper.h \
+flag_context.h
diff --git a/src/helpers/flag_context.h b/src/helpers/flag_context.h
new file mode 100644 (file)
index 0000000..4f369e3
--- /dev/null
@@ -0,0 +1,36 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+// flag_context.h author Joel Cornett <jocornet@cisco.com>
+
+#ifndef FLAG_CONTEXT_H
+#define FLAG_CONTEXT_H
+
+template<typename T>
+struct FlagContext
+{
+    FlagContext(T& dst, T flags) : dst(dst), flags(flags)
+    { dst |= flags; }
+
+    ~FlagContext()
+    { dst &= ~flags; }
+
+    T& dst;
+    T flags;
+};
+
+#endif
index bb0413548913012ca7b467edaffa11eb25210b54..587ea8b94a8b405e0b2f3328bac9800653f0de72 100644 (file)
@@ -71,6 +71,8 @@ inline bool free_space(size_t requested, size_t cap, Tracker& trk, Handler& hand
     assert(requested <= cap);
     const auto required = cap - requested;
 
+    // FIXIT-H J call handler repeatedly until unsuccessful or memory
+    // falls below 'required'
     if ( trk.used() > required )
         handler();
 
index 596ab5f5462504f0ecfac5ab78171a2bd1e6f110..037d1837d2b043293d31ec4a2d036eec1298ceb7 100644 (file)
 
 #include "prune_handler.h"
 
-#include <cassert>
-
-#include "stream/stream.h"
+#include "flow/flow_cache.h"
 #include "flow/flow_control.h"
+#include "stream/stream.h"
 
 namespace memory
 {
@@ -32,7 +31,7 @@ void prune_handler()
 {
     // assert(flow_con);
     if ( flow_con )
-        flow_con->prune_flows();
+        flow_con->prune_one(PruneReason::USER);
 }
 
 } // namespace memory
index f33903ab0ed040c1d351f632a2dd970557e6bddf..f967b54126ccda971fd2e83c3b9fa96d59288607 100644 (file)
@@ -160,5 +160,11 @@ private:
     static bool s_enabled;
 };
 
+struct ActiveSuspendContext
+{
+    ActiveSuspendContext() { Active::suspend(); }
+    ~ActiveSuspendContext() { Active::resume(); }
+};
+
 #endif
 
index 5b13f3abfe29cdc2501087a9acc115a28a680310..1c910040311d1d52ccab5d5d20992c58f4bc9ab9 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef PROTOCOLS_MPLS_H
 #define PROTOCOLS_MPLS_H
 
+#include <cstdint>
+
 namespace mpls
 {
 struct MplsHdr
@@ -31,6 +33,7 @@ struct MplsHdr
 };
 } // namespace mpls
 
+// FIXIT-L J constexpr != const, they are orthogonal keywords
 constexpr int MPLS_PAYLOADTYPE_ETHERNET = 1;
 constexpr int MPLS_PAYLOADTYPE_IPV4 = 2;
 constexpr int MPLS_PAYLOADTYPE_IPV6 = 3;
index 6d962b1ebffc49cd6b8e2cd8fdeebf45759662cd..8f4b076053b9c35425b305f14c9d41824d114925 100644 (file)
@@ -171,8 +171,8 @@ void Stream::check_session_closed(Packet* p)
     if (flow->session_state & STREAM_STATE_CLOSED)
     {
         assert(flow_con);
-        flow_con->delete_flow(flow, "closed");
-        p->flow = NULL;
+        flow_con->delete_flow(flow, PruneReason::CLOSED);
+        p->flow = nullptr;
     }
 }