From: Christopher Faulet Date: Tue, 28 Jul 2020 09:56:13 +0000 (+0200) Subject: MEDIUM: tcp-rules: Use a dedicated expiration date for tcp ruleset X-Git-Tag: v2.3-dev2~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2747fbb7ac1d2db587e88d59743118995c986d6d;p=thirdparty%2Fhaproxy.git MEDIUM: tcp-rules: Use a dedicated expiration date for tcp ruleset A dedicated expiration date is now used to apply the inspect-delay of the tcp-request or tcp-response rulesets. Before, the analyse expiratation date was used but it may also be updated by the lua (at least). So a lua script may extend or reduce the inspect-delay by side effect. This is not expected. If it becomes necessary, a specific function will be added to do this. Because, for now, it is a bit confusing. --- diff --git a/include/haproxy/stream-t.h b/include/haproxy/stream-t.h index 9640111979..b2c8378f1f 100644 --- a/include/haproxy/stream-t.h +++ b/include/haproxy/stream-t.h @@ -180,6 +180,7 @@ struct stream { /* These two pointers are used to resume the execution of the rule lists. */ struct list *current_rule_list; /* this is used to store the current executed rule list. */ void *current_rule; /* this is used to store the current rule to be resumed. */ + int rules_exp; /* expiration date for current rules execution */ struct hlua *hlua; /* lua runtime context */ /* Context */ diff --git a/src/stream.c b/src/stream.c index c8078f5ad8..f2826651ec 100644 --- a/src/stream.c +++ b/src/stream.c @@ -371,6 +371,7 @@ struct stream *stream_new(struct session *sess, enum obj_type *origin) */ s->current_rule_list = NULL; s->current_rule = NULL; + s->rules_exp = TICK_ETERNITY; /* Copy SC counters for the stream. We don't touch refcounts because * any reference we have is inherited from the session. Since the stream diff --git a/src/tcp_rules.c b/src/tcp_rules.c index d80c27ccff..6a31a32670 100644 --- a/src/tcp_rules.c +++ b/src/tcp_rules.c @@ -113,7 +113,7 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit) */ if ((req->flags & CF_SHUTR) || channel_full(req, global.tune.maxrewrite) || - !s->be->tcp_req.inspect_delay || tick_is_expired(req->analyse_exp, now_ms)) + !s->be->tcp_req.inspect_delay || tick_is_expired(s->rules_exp, now_ms)) partial = SMP_OPT_FINAL; else partial = 0; @@ -195,15 +195,16 @@ resume_execution: * we have an explicit accept, so we apply the default accept. */ req->analysers &= ~an_bit; - req->analyse_exp = TICK_ETERNITY; + req->analyse_exp = s->rules_exp = TICK_ETERNITY; DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s); return 1; missing_data: channel_dont_connect(req); /* just set the request timeout once at the beginning of the request */ - if (!tick_isset(req->analyse_exp) && s->be->tcp_req.inspect_delay) - req->analyse_exp = tick_add(now_ms, s->be->tcp_req.inspect_delay); + if (!tick_isset(s->rules_exp) && s->be->tcp_req.inspect_delay) + s->rules_exp = tick_add(now_ms, s->be->tcp_req.inspect_delay); + req->analyse_exp = tick_first((tick_is_expired(req->analyse_exp, now_ms) ? 0 : req->analyse_exp), s->rules_exp); DBG_TRACE_DEVEL("waiting for more data", STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s); return 0; @@ -267,7 +268,7 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit) * - if one rule returns KO, then return KO */ if ((rep->flags & CF_SHUTR) || channel_full(rep, global.tune.maxrewrite) || - !s->be->tcp_rep.inspect_delay || tick_is_expired(rep->analyse_exp, now_ms)) + !s->be->tcp_rep.inspect_delay || tick_is_expired(s->rules_exp, now_ms)) partial = SMP_OPT_FINAL; else partial = 0; @@ -284,19 +285,15 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit) goto resume_execution; } s->current_rule_list = &s->be->tcp_rep.inspect_rules; + s->rules_exp = TICK_ETERNITY; list_for_each_entry(rule, &s->be->tcp_rep.inspect_rules, list) { enum acl_test_res ret = ACL_TEST_PASS; if (rule->cond) { ret = acl_exec_cond(rule->cond, s->be, sess, s, SMP_OPT_DIR_RES | partial); - if (ret == ACL_TEST_MISS) { - /* just set the analyser timeout once at the beginning of the response */ - if (!tick_isset(rep->analyse_exp) && s->be->tcp_rep.inspect_delay) - rep->analyse_exp = tick_add(now_ms, s->be->tcp_rep.inspect_delay); - DBG_TRACE_DEVEL("waiting for more data", STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s); - return 0; - } + if (ret == ACL_TEST_MISS) + goto missing_data; ret = acl_pass(ret); if (rule->cond->pol == ACL_COND_UNLESS) @@ -325,6 +322,7 @@ resume_execution: "for the tcp-response content actions."); goto internal; } + channel_dont_close(rep); goto missing_data; case ACT_RET_DENY: goto deny; @@ -360,15 +358,15 @@ resume_execution: * we have an explicit accept, so we apply the default accept. */ rep->analysers &= ~an_bit; - rep->analyse_exp = TICK_ETERNITY; + rep->analyse_exp = s->rules_exp = TICK_ETERNITY; DBG_TRACE_LEAVE(STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s); return 1; missing_data: - channel_dont_close(rep); /* just set the analyser timeout once at the beginning of the response */ - if (!tick_isset(rep->analyse_exp) && s->be->tcp_rep.inspect_delay) - rep->analyse_exp = tick_add(now_ms, s->be->tcp_rep.inspect_delay); + if (!tick_isset(s->rules_exp) && s->be->tcp_rep.inspect_delay) + s->rules_exp = tick_add(now_ms, s->be->tcp_rep.inspect_delay); + rep->analyse_exp = tick_first((tick_is_expired(rep->analyse_exp, now_ms) ? 0 : rep->analyse_exp), s->rules_exp); DBG_TRACE_DEVEL("waiting for more data", STRM_EV_STRM_ANA|STRM_EV_TCP_ANA, s); return 0;