]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
pcap/file: improve time handling
authorVictor Julien <victor@inliniac.net>
Fri, 28 Feb 2020 12:17:03 +0000 (13:17 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 3 Mar 2020 08:57:08 +0000 (09:57 +0100)
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.

src/flow-manager.c
src/tm-threads.c
src/tm-threads.h
src/util-time.c
src/util-time.h

index 328e973519f6e7a45b863d41fa293c846d533718..0535dbd19f403dce7bcc0068827ced84af97c33e 100644 (file)
@@ -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)) {
index 74ba6e0eb2d092a60d40d77617067bf65e56701f..15d9999db2498864f9c96864ebb9ca695de434ea 100644 (file)
@@ -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;
index 1c838a781353451eb42ffcc0e3bec5a77eb5c551..6d901e8f18d25ab84e534b217b713cdabdb40fe7 100644 (file)
@@ -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__ */
index 5aec73e3b0fe6dfa44923bbe07c1c47e41809134..2d63196e774a839e9e3774e68a16cffab2db4ea3 100644 (file)
@@ -87,6 +87,13 @@ void TimeDeinit(void)
     SCSpinDestroy(&current_time_spinlock);
 }
 
+bool TimeModeIsReady(void)
+{
+    if (live_time_tracking)
+        return true;
+    return TmThreadsTimeSubsysIsReady();
+}
+
 void TimeModeSetLive(void)
 {
     live_time_tracking = true;
index 48319c805ba970f2afb7fe0cf56ff659a82364d1..a8fb6db67282e6466990a8d9e44c359e9163d27c 100644 (file)
@@ -39,6 +39,7 @@ void TimeSetToCurrentTime(void);
 void TimeSetIncrementTime(uint32_t);
 #endif
 
+bool TimeModeIsReady(void);
 void TimeModeSetLive(void);
 void TimeModeSetOffline (void);
 bool TimeModeIsLive(void);