BUG/MINOR: tcpcheck: Disable QUICKACK only if data should be sent after connect

It is only a real problem for agent-checks when there is no agent string to
send. The condition to disable TCP_QUICKACK was only based on the action
type following the connect one. But it is not always accurate. indeed, for
agent-checks, there is always a SEND action. But if there is no "agent-send"
string defined, nothing is sent. In this case, this adds 200ms of latency
with no reason.

To fix the bug, a flag is now used on the CONNECT action to instruct there
are data that should be sent after the connect. For health-checks, this flag
is set if the action following the connect is a SEND action. For
agent-checks, it is set if an "agent-send" string is defined.

This patch should fix the issue #1836. It must be backported as far as 2.2.

(cherry picked from commit 871dd82117f1e9a673938c6987ddf8989485d384)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 549dc891e949aef086102b04a2bc530cb6457722)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 3971f8a33d27c599e6af6688db3ce80eb4280980)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/include/haproxy/tcpcheck-t.h b/include/haproxy/tcpcheck-t.h
index 29cb4cc..439fe18 100644
--- a/include/haproxy/tcpcheck-t.h
+++ b/include/haproxy/tcpcheck-t.h
@@ -35,6 +35,7 @@
 #define TCPCHK_OPT_DEFAULT_CONNECT 0x0008  /* Do a connect using server params */
 #define TCPCHK_OPT_IMPLICIT        0x0010  /* Implicit connect */
 #define TCPCHK_OPT_SOCKS4          0x0020  /* check the connection via socks4 proxy */
+#define TCPCHK_OPT_HAS_DATA        0x0040  /* data should be sent after conncetion */
 
 enum tcpcheck_send_type {
 	TCPCHK_SEND_UNDEF = 0,  /* Send is not parsed. */
diff --git a/src/check.c b/src/check.c
index 1a40b6f..2205063 100644
--- a/src/check.c
+++ b/src/check.c
@@ -1715,6 +1715,13 @@
 		LIST_INSERT(srv->agent.tcpcheck_rules->list, &chk->list);
 	}
 
+	/* <chk> is always defined here and it is a CONNECT action. If there is
+	 * a preset variable, it means there is an agent string defined and data
+	 * will be sent after the connect.
+	 */
+	if (!LIST_ISEMPTY(&srv->agent.tcpcheck_rules->preset_vars))
+		chk->connect.options |= TCPCHK_OPT_HAS_DATA;
+
 
 	err = init_check(&srv->agent, PR_O2_TCPCHK_CHK);
 	if (err) {
diff --git a/src/tcpcheck.c b/src/tcpcheck.c
index 587a609..d79ad47 100644
--- a/src/tcpcheck.c
+++ b/src/tcpcheck.c
@@ -1190,10 +1190,8 @@
 	if (proto && proto->connect) {
 		int flags = 0;
 
-		if (check->tcpcheck_rules->flags & TCPCHK_RULES_PROTO_CHK)
-			flags |= CONNECT_HAS_DATA;
-		if (!next || next->action != TCPCHK_ACT_EXPECT)
-			flags |= CONNECT_DELACK_ALWAYS;
+		if (connect->options & TCPCHK_OPT_HAS_DATA)
+			flags = (CONNECT_HAS_DATA|CONNECT_DELACK_ALWAYS);
 		status = proto->connect(conn, flags);
 	}
 
@@ -3736,6 +3734,8 @@
 	 * comment is assigned to the following rule(s).
 	 */
 	list_for_each_entry_safe(chk, back, px->tcpcheck_rules.list, list) {
+		struct tcpcheck_rule *next;
+
 		if (chk->action != prev_action && prev_action != TCPCHK_ACT_COMMENT)
 			ha_free(&comment);
 
@@ -3750,6 +3750,9 @@
 		case TCPCHK_ACT_CONNECT:
 			if (!chk->comment && comment)
 				chk->comment = strdup(comment);
+			next = get_next_tcpcheck_rule(&px->tcpcheck_rules, chk);
+			if (next && next->action == TCPCHK_ACT_SEND)
+				chk->connect.options |= TCPCHK_OPT_HAS_DATA;
 			/* fall through */
 		case TCPCHK_ACT_ACTION_KW:
 			ha_free(&comment);