]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
flow-manager: fix off-by-one in flow_hash row allocation
authorArne Welzel <arne.welzel@corelight.com>
Sat, 12 Feb 2022 16:49:07 +0000 (17:49 +0100)
committerVictor Julien <vjulien@oisf.net>
Wed, 27 Apr 2022 09:14:27 +0000 (11:14 +0200)
The current code doesn't cover all rows when more than one flow manager is
used. It leaves a single row between ftd->max and ftd->min of the next
manager orphaned. As an example:

    hash_size=1000
    flowmgr_number=3
    range=333

    instance  ftd->min  ftd->max
    0         0         333
    1         334       666
    2         667       1000

    Rows not covered: 333, 666

(cherry picked from commit 8ef066318d7c4dd9b6686dbebd621c790828c384)

src/flow-manager.c

index ac3a01f8ea41c788f0f8ea738a680330124d3174..cac5512d8b6f162b1296601b24f685e679824f39 100644 (file)
@@ -670,20 +670,20 @@ static TmEcode FlowManagerThreadInit(ThreadVars *t, const void *initdata, void *
     if (ftd == NULL)
         return TM_ECODE_FAILED;
 
-    ftd->instance = SC_ATOMIC_ADD(flowmgr_cnt, 1);
+    /* Ensure instance is the value prior to the add */
+    ftd->instance = SC_ATOMIC_FETCH_AND_ADD(flowmgr_cnt, 1);
     SCLogDebug("flow manager instance %u", ftd->instance);
 
     /* set the min and max value used for hash row walking
      * each thread has it's own section of the flow hash */
     uint32_t range = flow_config.hash_size / flowmgr_number;
-    if (ftd->instance == 1)
-        ftd->max = range;
-    else if (ftd->instance == flowmgr_number) {
-        ftd->min = (range * (ftd->instance - 1));
+
+    ftd->min = ftd->instance * range;
+    ftd->max = (ftd->instance + 1) * range;
+
+    /* last flow-manager takes on hash_size % flowmgr_number extra rows */
+    if ((ftd->instance + 1) == flowmgr_number) {
         ftd->max = flow_config.hash_size;
-    } else {
-        ftd->min = (range * (ftd->instance - 1));
-        ftd->max = (range * ftd->instance);
     }
     BUG_ON(ftd->min > flow_config.hash_size || ftd->max > flow_config.hash_size);