From bd1a193877cf72af7bbcf795d453fd1f1036f1ca Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Tue, 30 Sep 2014 15:24:24 +0200 Subject: [PATCH] flow: fix flow logging at shutdown Move all flows from the hash to the recycler at shutdown. Bug #1260 --- src/flow-manager.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/flow-manager.c b/src/flow-manager.c index e663f568f0..2b2f939dae 100644 --- a/src/flow-manager.c +++ b/src/flow-manager.c @@ -395,6 +395,87 @@ next: return cnt; } +/** + * \internal + * + * \brief move all flows out of a hash row + * + * \param f last flow in the hash row + * + * \retval cnt removed out flows + */ +static uint32_t FlowManagerHashRowCleanup(Flow *f) +{ + uint32_t cnt = 0; + + do { + FLOWLOCK_WRLOCK(f); + + Flow *next_flow = f->hprev; + + int state = FlowGetFlowState(f); + + /* remove from the hash */ + if (f->hprev != NULL) + f->hprev->hnext = f->hnext; + if (f->hnext != NULL) + f->hnext->hprev = f->hprev; + if (f->fb->head == f) + f->fb->head = f->hnext; + if (f->fb->tail == f) + f->fb->tail = f->hprev; + + f->hnext = NULL; + f->hprev = NULL; + + if (state == FLOW_STATE_NEW) + f->flow_end_flags |= FLOW_END_FLAG_STATE_NEW; + else if (state == FLOW_STATE_ESTABLISHED) + f->flow_end_flags |= FLOW_END_FLAG_STATE_ESTABLISHED; + else if (state == FLOW_STATE_CLOSED) + f->flow_end_flags |= FLOW_END_FLAG_STATE_CLOSED; + + f->flow_end_flags |= FLOW_END_FLAG_TIMEOUT; + + /* no one is referring to this flow, use_cnt 0, removed from hash + * so we can unlock it and move it to the recycle queue. */ + FLOWLOCK_UNLOCK(f); + + FlowEnqueue(&flow_recycle_q, f); + + cnt++; + + f = next_flow; + } while (f != NULL); + + return cnt; +} + +/** + * \brief remove all flows from the hash + * + * \retval cnt number of removes out flows + */ +static uint32_t FlowCleanupHash(void){ + uint32_t idx = 0; + uint32_t cnt = 0; + + for (idx = 0; idx < flow_config.hash_size; idx++) { + FlowBucket *fb = &flow_hash[idx]; + + FBLOCK_LOCK(fb); + + if (fb->tail != NULL) { + /* we have a flow, or more than one */ + cnt += FlowManagerHashRowCleanup(fb->tail); + } + + FBLOCK_UNLOCK(fb); + } + + return cnt; +} + extern int g_detect_disabled; typedef struct FlowManagerThreadData_ { @@ -837,6 +918,9 @@ void FlowKillFlowRecyclerThread(void) ThreadVars *tv = NULL; int cnt = 0; + /* move all flows still in the hash to the recycler queue */ + FlowCleanupHash(); + /* make sure all flows are processed */ do { SCCtrlCondSignal(&flow_recycler_ctrl_cond);