From: Victor Julien Date: Wed, 18 Sep 2024 10:03:46 +0000 (+0200) Subject: flow/worker: improve flow timeout time accuracy X-Git-Tag: suricata-8.0.0-beta1~589 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ada2bfe009665a7925db1d2e7e0b68b32b6eb8fa;p=thirdparty%2Fsuricata.git flow/worker: improve flow timeout time accuracy When timing out flows, use the timestamp from the "owning" thread. This avoids problems with threads being out of sync with each other. Ticket: #7455. --- diff --git a/src/flow-hash.c b/src/flow-hash.c index 77c74bb6e2..da494199d7 100644 --- a/src/flow-hash.c +++ b/src/flow-hash.c @@ -831,7 +831,8 @@ static inline void MoveToWorkQueue(ThreadVars *tv, FlowLookupStruct *fls, } } -static inline bool FlowIsTimedOut(const Flow *f, const SCTime_t ts, const bool emerg) +static inline bool FlowIsTimedOut( + const FlowThreadId ftid, const Flow *f, const SCTime_t pktts, const bool emerg) { SCTime_t timesout_at; if (emerg) { @@ -841,13 +842,36 @@ static inline bool FlowIsTimedOut(const Flow *f, const SCTime_t ts, const bool e } else { timesout_at = SCTIME_ADD_SECS(f->lastts, f->timeout_policy); } - /* do the timeout check */ - if (SCTIME_CMP_LT(ts, timesout_at)) { - return false; + /* if time is live, we just use the pktts */ + if (TimeModeIsLive() || ftid == f->thread_id[0] || f->thread_id[0] == 0) { + if (SCTIME_CMP_LT(pktts, timesout_at)) { + return false; + } + } else { + SCTime_t checkts = TmThreadsGetThreadTime(f->thread_id[0]); + /* do the timeout check */ + if (SCTIME_CMP_LT(checkts, timesout_at)) { + return false; + } } return true; } +static inline uint16_t GetTvId(const ThreadVars *tv) +{ + uint16_t tv_id; +#ifdef UNITTESTS + if (RunmodeIsUnittests()) { + tv_id = 0; + } else { + tv_id = (uint16_t)tv->id; + } +#else + tv_id = (uint16_t)tv->id; +#endif + return tv_id; +} + /** \brief Get Flow for packet * * Hash retrieval function for flows. Looks up the hash bucket containing the @@ -899,6 +923,7 @@ Flow *FlowGetFlowFromHash(ThreadVars *tv, FlowLookupStruct *fls, Packet *p, Flow return f; } + const uint16_t tv_id = GetTvId(tv); const bool emerg = (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY) != 0; const uint32_t fb_nextts = !emerg ? SC_ATOMIC_GET(fb->next_ts) : 0; /* ok, we have a flow in the bucket. Let's find out if it is our flow */ @@ -907,8 +932,8 @@ Flow *FlowGetFlowFromHash(ThreadVars *tv, FlowLookupStruct *fls, Packet *p, Flow do { Flow *next_f = NULL; FLOWLOCK_WRLOCK(f); - const bool timedout = - (fb_nextts <= (uint32_t)SCTIME_SECS(p->ts) && FlowIsTimedOut(f, p->ts, emerg)); + const bool timedout = (fb_nextts <= (uint32_t)SCTIME_SECS(p->ts) && + FlowIsTimedOut(tv_id, f, p->ts, emerg)); if (timedout) { next_f = f->next; MoveToWorkQueue(tv, fls, fb, f, prev_f);