From: Victor Julien Date: Fri, 28 Feb 2020 12:17:03 +0000 (+0100) Subject: pcap/file: improve time handling X-Git-Tag: suricata-6.0.0-beta1~687 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=072c421e46abb8d3ddeaea818736a68299a20da5;p=thirdparty%2Fsuricata.git pcap/file: improve time handling This patch addresses two problems. First, various parts of the engine, but most notably the flow manager (FM), use a minimum of the time notion of the packet threads. This did not however, take into account the scenario where one or more of these threads would be inactive for prolonged times. This could lead to the time used by the FM could get stale. This is addressed by keeping track of the last time the per thread packet timestamp was updated, and only considering it for the 'minimum' when it is reasonably current. Second, there was a minor race condition at start up, where the FM would already inspect the hash table(s) while the packet threads weren't active yet. Since FM gets the time from the packet threads, it would use a bogus time of 0. This is addressed by adding a wait loop to the start of the FM that waits for 'time' to get ready. --- diff --git a/src/flow-manager.c b/src/flow-manager.c index 328e973519..0535dbd19f 100644 --- a/src/flow-manager.c +++ b/src/flow-manager.c @@ -740,6 +740,12 @@ static TmEcode FlowManager(ThreadVars *th_v, void *thread_data) */ memset(&ts, 0, sizeof(ts)); + /* don't start our activities until time is setup */ + while (!TimeModeIsReady()) { + if (suricata_ctl_flags != 0) + return TM_ECODE_OK; + } + while (1) { if (TmThreadsCheckFlag(th_v, THV_PAUSE)) { diff --git a/src/tm-threads.c b/src/tm-threads.c index 74ba6e0eb2..15d9999db2 100644 --- a/src/tm-threads.c +++ b/src/tm-threads.c @@ -2103,6 +2103,8 @@ typedef struct Thread_ { struct timeval pktts; /**< current packet time of this thread * (offline mode) */ + uint32_t sys_sec_stamp; /**< timestamp in seconds of the real system + * time when the pktts was last updated. */ } Thread; typedef struct Threads_ { @@ -2226,17 +2228,40 @@ void TmThreadsSetThreadTimestamp(const int id, const struct timeval *ts) int idx = id - 1; Thread *t = &thread_store.threads[idx]; COPY_TIMESTAMP(ts, &t->pktts); + struct timeval systs; + gettimeofday(&systs, NULL); + t->sys_sec_stamp = (uint32_t)systs.tv_sec; SCMutexUnlock(&thread_store_lock); } +bool TmThreadsTimeSubsysIsReady(void) +{ + bool ready = true; + SCMutexLock(&thread_store_lock); + for (size_t s = 0; s < thread_store.threads_size; s++) { + Thread *t = &thread_store.threads[s]; + if (!t->in_use) + break; + if (t->sys_sec_stamp == 0) { + ready = false; + break; + } + } + SCMutexUnlock(&thread_store_lock); + return ready; +} + void TmThreadsInitThreadsTimestamp(const struct timeval *ts) { + struct timeval systs; + gettimeofday(&systs, NULL); SCMutexLock(&thread_store_lock); for (size_t s = 0; s < thread_store.threads_size; s++) { Thread *t = &thread_store.threads[s]; if (!t->in_use) break; COPY_TIMESTAMP(ts, &t->pktts); + t->sys_sec_stamp = (uint32_t)systs.tv_sec; } SCMutexUnlock(&thread_store_lock); } @@ -2248,13 +2273,19 @@ void TmThreadsGetMinimalTimestamp(struct timeval *ts) memset(&nullts, 0, sizeof(nullts)); int set = 0; size_t s; + struct timeval systs; + gettimeofday(&systs, NULL); SCMutexLock(&thread_store_lock); for (s = 0; s < thread_store.threads_size; s++) { Thread *t = &thread_store.threads[s]; - if (t == NULL || t->in_use == 0) - continue; + if (t->in_use == 0) + break; if (!(timercmp(&t->pktts, &nullts, ==))) { + /* ignore sleeping threads */ + if (t->sys_sec_stamp + 1 < (uint32_t)systs.tv_sec) + continue; + if (!set) { local.tv_sec = t->pktts.tv_sec; local.tv_usec = t->pktts.tv_usec; diff --git a/src/tm-threads.h b/src/tm-threads.h index 1c838a7813..6d901e8f18 100644 --- a/src/tm-threads.h +++ b/src/tm-threads.h @@ -243,5 +243,6 @@ int TmThreadsInjectPacketsById(Packet **, int id); void TmThreadsInitThreadsTimestamp(const struct timeval *ts); void TmThreadsSetThreadTimestamp(const int id, const struct timeval *ts); void TmThreadsGetMinimalTimestamp(struct timeval *ts); +bool TmThreadsTimeSubsysIsReady(void); #endif /* __TM_THREADS_H__ */ diff --git a/src/util-time.c b/src/util-time.c index 5aec73e3b0..2d63196e77 100644 --- a/src/util-time.c +++ b/src/util-time.c @@ -87,6 +87,13 @@ void TimeDeinit(void) SCSpinDestroy(¤t_time_spinlock); } +bool TimeModeIsReady(void) +{ + if (live_time_tracking) + return true; + return TmThreadsTimeSubsysIsReady(); +} + void TimeModeSetLive(void) { live_time_tracking = true; diff --git a/src/util-time.h b/src/util-time.h index 48319c805b..a8fb6db672 100644 --- a/src/util-time.h +++ b/src/util-time.h @@ -39,6 +39,7 @@ void TimeSetToCurrentTime(void); void TimeSetIncrementTime(uint32_t); #endif +bool TimeModeIsReady(void); void TimeModeSetLive(void); void TimeModeSetOffline (void); bool TimeModeIsLive(void);