From b6b8c3d6461c758a605d3ce0748eb6f2339378b4 Mon Sep 17 00:00:00 2001 From: Arne Welzel Date: Sat, 12 Feb 2022 17:49:07 +0100 Subject: [PATCH] flow-manager: fix off-by-one in flow_hash row allocation 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 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/flow-manager.c b/src/flow-manager.c index ac3a01f8ea..cac5512d8b 100644 --- a/src/flow-manager.c +++ b/src/flow-manager.c @@ -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); -- 2.47.2