diff --git a/include/proto/proto_tcp.h b/include/proto/proto_tcp.h index a41e025a8..d55f4c544 100644 --- a/include/proto/proto_tcp.h +++ b/include/proto/proto_tcp.h @@ -30,7 +30,7 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct sockaddr_storage *remote); void tcpv4_add_listener(struct listener *listener); void tcpv6_add_listener(struct listener *listener); -int tcp_connect_server(struct connection *conn, int data); +int tcp_connect_server(struct connection *conn, int data, int delack); int tcp_connect_probe(struct connection *conn); int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir); int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir); diff --git a/include/proto/stream_interface.h b/include/proto/stream_interface.h index 7c9595a1f..c8202bcca 100644 --- a/include/proto/stream_interface.h +++ b/include/proto/stream_interface.h @@ -111,7 +111,7 @@ static inline int si_connect(struct stream_interface *si) if (unlikely(!si_ctrl(si) || !si_ctrl(si)->connect)) return SN_ERR_INTERNAL; - ret = si_ctrl(si)->connect(si->conn, !channel_is_empty(si->ob)); + ret = si_ctrl(si)->connect(si->conn, !channel_is_empty(si->ob), !!si->send_proxy_ofs); if (ret != SN_ERR_NONE) return ret; diff --git a/include/types/protocol.h b/include/types/protocol.h index a8e020ca2..0af2ed8a3 100644 --- a/include/types/protocol.h +++ b/include/types/protocol.h @@ -56,7 +56,7 @@ struct protocol { int (*unbind_all)(struct protocol *proto); /* unbind all bound listeners */ int (*enable_all)(struct protocol *proto); /* enable all bound listeners */ int (*disable_all)(struct protocol *proto); /* disable all bound listeners */ - int (*connect)(struct connection *, int data); /* connect function if any */ + int (*connect)(struct connection *, int data, int delack); /* connect function if any */ int (*get_src)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve src addr */ int (*get_dst)(int fd, struct sockaddr *, socklen_t, int dir); /* syscall used to retrieve dst addr */ diff --git a/src/checks.c b/src/checks.c index 7f49547ba..b23fa86bc 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1318,9 +1318,10 @@ static struct task *process_chk(struct task *t) * - SN_ERR_INTERNAL for any other purely internal errors * Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted. * Note that we try to prevent the network stack from sending the ACK during the - * connect() when a pure TCP check is used. + * connect() when a pure TCP check is used (without PROXY protocol). */ - ret = s->check.proto->connect(conn, (s->proxy->options2 & PR_O2_CHK_ANY) ? 1 : 2); + ret = s->check.proto->connect(conn, s->proxy->options2 & PR_O2_CHK_ANY, + s->check.send_proxy ? 1 : (s->proxy->options2 & PR_O2_CHK_ANY) ? 0 : 2); conn->flags |= CO_FL_WAKE_DATA; if (s->check.send_proxy) conn->flags |= CO_FL_LOCAL_SPROXY; diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 2b8d148d1..fd9b03d86 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -221,12 +221,13 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so * bind addresses are still determined locally (due to the possible need of a * source port). conn->target may point either to a valid server or to a backend, * depending on conn->target. Only OBJ_TYPE_PROXY and OBJ_TYPE_SERVER are - * supported. The parameter indicates when non-zero that data will - * immediately follow the connection and will tune the ACK behaviour after - * the connect : - * - 0 = always send it - * - 1 = send it unless the backends has the tcp-smart-connect option - * - 2 = never send it + * supported. The parameter is a boolean indicating whether there are data + * waiting for being sent or not, in order to adjust data write polling and on + * some platforms, the ability to avoid an empty initial ACK. The argument + * allows the caller to force using a delayed ACK when establishing the connection : + * - 0 = no delayed ACK unless data are advertised and backend has tcp-smart-connect + * - 1 = delayed ACK if backend has tcp-smart-connect, regardless of data + * - 2 = delayed ACK regardless of backend options * * It can return one of : * - SN_ERR_NONE if everything's OK @@ -241,7 +242,7 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct so * it's invalid and the caller has nothing to do. */ -int tcp_connect_server(struct connection *conn, int data) +int tcp_connect_server(struct connection *conn, int data, int delack) { int fd; struct server *srv; @@ -421,9 +422,9 @@ int tcp_connect_server(struct connection *conn, int data) #if defined(TCP_QUICKACK) /* disabling tcp quick ack now allows the first request to leave the * machine with the first ACK. We only do this if there are pending - * data in the buffer or if we plan to close after SYN/ACK (TCP checks). + * data in the buffer. */ - if (data == 2 || (data && (be->options2 & PR_O2_SMARTCON))) + if (delack == 2 || ((delack || data) && (be->options2 & PR_O2_SMARTCON))) setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &zero, sizeof(zero)); #endif