flow: exact flow timeout

Use a more precise calculation for timing out flows, using both the
seconds and the micro seconds.

Ticket: #7455.
pull/12371/head
Victor Julien 6 months ago committed by Victor Julien
parent 677c0fd41c
commit 48301bf28c

@ -764,8 +764,6 @@ static Flow *TcpReuseReplace(ThreadVars *tv, FlowLookupStruct *fls, FlowBucket *
#ifdef UNITTESTS
}
#endif
/* time out immediately */
old_f->timeout_at = 0;
/* get some settings that we move over to the new flow */
FlowThreadId thread_id[2] = { old_f->thread_id[0], old_f->thread_id[1] };
old_f->flow_end_flags |= FLOW_END_FLAG_TCPREUSE;
@ -833,20 +831,22 @@ static inline void MoveToWorkQueue(ThreadVars *tv, FlowLookupStruct *fls,
}
}
static inline bool FlowIsTimedOut(const Flow *f, const uint32_t sec, const bool emerg)
static inline bool FlowIsTimedOut(const Flow *f, const SCTime_t ts, const bool emerg)
{
if (unlikely(f->timeout_at < sec)) {
return true;
} else if (unlikely(emerg)) {
extern FlowProtoTimeout flow_timeouts_delta[FLOW_PROTO_MAX];
int64_t timeout_at = f->timeout_at -
FlowGetFlowTimeoutDirect(flow_timeouts_delta, f->flow_state, f->protomap);
if ((int64_t)sec >= timeout_at)
return true;
SCTime_t timesout_at;
if (emerg) {
extern FlowProtoTimeout flow_timeouts_emerg[FLOW_PROTO_MAX];
timesout_at = SCTIME_ADD_SECS(f->lastts,
FlowGetFlowTimeoutDirect(flow_timeouts_emerg, f->flow_state, f->protomap));
} else {
timesout_at = SCTIME_ADD_SECS(f->lastts, f->timeout_policy);
}
/* do the timeout check */
if (SCTIME_CMP_LT(ts, timesout_at)) {
return false;
}
return true;
}
/** \brief Get Flow for packet
*
@ -907,8 +907,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, (uint32_t)SCTIME_SECS(p->ts), emerg));
const bool timedout =
(fb_nextts < (uint32_t)SCTIME_SECS(p->ts) && FlowIsTimedOut(f, p->ts, emerg));
if (timedout) {
next_f = f->next;
MoveToWorkQueue(tv, fls, fb, f, prev_f);

@ -174,6 +174,9 @@ again:
/** \internal
* \brief check if a flow is timed out
* Takes lastts, adds the timeout policy to it, compared to current time `ts`.
* In case of emergency mode, timeout_policy is ignored and the emerg table
* is used.
*
* \param f flow
* \param ts timestamp
@ -183,16 +186,20 @@ again:
*/
static bool FlowManagerFlowTimeout(Flow *f, SCTime_t ts, uint32_t *next_ts, const bool emerg)
{
uint32_t flow_times_out_at = f->timeout_at;
SCTime_t timesout_at;
if (emerg) {
extern FlowProtoTimeout flow_timeouts_delta[FLOW_PROTO_MAX];
flow_times_out_at -= FlowGetFlowTimeoutDirect(flow_timeouts_delta, f->flow_state, f->protomap);
extern FlowProtoTimeout flow_timeouts_emerg[FLOW_PROTO_MAX];
timesout_at = SCTIME_ADD_SECS(f->lastts,
FlowGetFlowTimeoutDirect(flow_timeouts_emerg, f->flow_state, f->protomap));
} else {
timesout_at = SCTIME_ADD_SECS(f->lastts, f->timeout_policy);
}
if (*next_ts == 0 || flow_times_out_at < *next_ts)
*next_ts = flow_times_out_at;
if (*next_ts == 0 || (uint32_t)SCTIME_SECS(timesout_at) < *next_ts)
*next_ts = (uint32_t)SCTIME_SECS(timesout_at);
/* do the timeout check */
if ((uint64_t)flow_times_out_at >= SCTIME_SECS(ts)) {
if (SCTIME_CMP_LT(ts, timesout_at)) {
return false;
}

@ -195,8 +195,6 @@ void FlowInit(ThreadVars *tv, Flow *f, const Packet *p)
f->protomap = FlowGetProtoMapping(f->proto);
f->timeout_policy = FlowGetTimeoutPolicy(f);
const uint32_t timeout_at = (uint32_t)SCTIME_SECS(f->startts) + f->timeout_policy;
f->timeout_at = timeout_at;
if (MacSetFlowStorageEnabled()) {
DEBUG_VALIDATE_BUG_ON(FlowGetStorageById(f, MacSetGetFlowStorageID()) != NULL);

@ -41,7 +41,6 @@
(f)->dp = 0; \
(f)->proto = 0; \
(f)->livedev = NULL; \
(f)->timeout_at = 0; \
(f)->timeout_policy = 0; \
(f)->vlan_idx = 0; \
(f)->next = NULL; \
@ -88,7 +87,6 @@
(f)->vlan_idx = 0; \
(f)->ffr = 0; \
(f)->next = NULL; \
(f)->timeout_at = 0; \
(f)->timeout_policy = 0; \
(f)->flow_state = 0; \
(f)->tenant_id = 0; \

@ -397,10 +397,6 @@ void FlowHandlePacketUpdate(Flow *f, Packet *p, ThreadVars *tv, DecodeThreadVars
/* update the last seen timestamp of this flow */
if (SCTIME_CMP_GT(p->ts, f->lastts)) {
f->lastts = p->ts;
const uint32_t timeout_at = (uint32_t)SCTIME_SECS(f->lastts) + f->timeout_policy;
if (timeout_at != f->timeout_at) {
f->timeout_at = timeout_at;
}
}
#ifdef CAPTURE_OFFLOAD
} else {
@ -1169,9 +1165,6 @@ void FlowUpdateState(Flow *f, const enum FlowState s)
const uint32_t timeout_policy = FlowGetTimeoutPolicy(f);
if (timeout_policy != f->timeout_policy) {
f->timeout_policy = timeout_policy;
const uint32_t timeout_at = (uint32_t)SCTIME_SECS(f->lastts) + timeout_policy;
if (timeout_at != f->timeout_at)
f->timeout_at = timeout_at;
}
}
#ifdef UNITTESTS

@ -391,11 +391,6 @@ typedef struct Flow_
uint8_t ffr;
};
/** timestamp in seconds of the moment this flow will timeout
* according to the timeout policy. Does *not* take emergency
* mode into account. */
uint32_t timeout_at;
/** Thread ID for the stream/detect portion of this flow */
FlowThreadId thread_id[2];
@ -406,8 +401,8 @@ typedef struct Flow_
/** flow hash - the flow hash before hash table size mod. */
uint32_t flow_hash;
/** timeout policy value in seconds to add to the lastts.tv_sec
* when a packet has been received. */
/** timeout in seconds by policy, add to Flow::lastts to get actual time this times out.
* Ignored in emergency mode. */
uint32_t timeout_policy;
/* time stamp of last update (last packet). Set/updated under the

Loading…
Cancel
Save