]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
flow: free spare pool more aggressively
authorVictor Julien <victor@inliniac.net>
Mon, 4 Oct 2021 14:01:47 +0000 (16:01 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 5 Oct 2021 09:04:49 +0000 (11:04 +0200)
The flows exceeding the spare pools config setting would be freed
per at max 100 flows a second. After a high speed test this would
lead to excessive memory use for a long time.

This patch updates the logic to free 10% of the excess flows per
run, freeing multiple blocks of flows as needed.

Bug: #4731.
(cherry picked from commit fa72a5add8d9ebdcc4da5e05a8cd4259ede572d7)

src/flow-spare-pool.c

index ff8402bb4076c175eafdcefaa75e1c650b4d0fae..dc6b8292ec6900c334a969addb3843399716cd20 100644 (file)
@@ -173,28 +173,29 @@ void FlowSparePoolUpdate(uint32_t size)
 {
     const int64_t todo = (int64_t)flow_config.prealloc - (int64_t)size;
     if (todo < 0) {
-        /* remove one block at most at a time */
         uint32_t to_remove = (uint32_t)(todo * -1) / 10;
-        if (to_remove < flow_spare_pool_block_size)
-            return;
+        while (to_remove) {
+            if (to_remove < flow_spare_pool_block_size)
+                return;
 
-        FlowSparePool *p = NULL;
-        SCMutexLock(&flow_spare_pool_m);
-        p = flow_spare_pool;
-        if (p != NULL) {
-            flow_spare_pool = p->next;
-            flow_spare_pool_flow_cnt -= p->queue.len;
-        }
-        SCMutexUnlock(&flow_spare_pool_m);
+            FlowSparePool *p = NULL;
+            SCMutexLock(&flow_spare_pool_m);
+            p = flow_spare_pool;
+            if (p != NULL) {
+                flow_spare_pool = p->next;
+                flow_spare_pool_flow_cnt -= p->queue.len;
+                to_remove -= p->queue.len;
+            }
+            SCMutexUnlock(&flow_spare_pool_m);
 
-        if (p != NULL) {
-            Flow *f;
-            while ((f = FlowQueuePrivateGetFromTop(&p->queue))) {
-                FlowFree(f);
+            if (p != NULL) {
+                Flow *f;
+                while ((f = FlowQueuePrivateGetFromTop(&p->queue))) {
+                    FlowFree(f);
+                }
+                SCFree(p);
             }
-            SCFree(p);
         }
-
     } else if (todo > 0) {
         FlowSparePool *head = NULL, *tail = NULL;