]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: tcp: add explicit support for delayed ACK in connect()
authorWilly Tarreau <w@1wt.eu>
Sat, 24 Nov 2012 09:24:27 +0000 (10:24 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 24 Nov 2012 09:24:27 +0000 (10:24 +0100)
Commit 24db47e0 tried to improve support for delayed ACK upon connect
but it was incomplete, because checks with the proxy protocol would
always enable polling for data receive and there was no way of
distinguishing data polling and delayed ack.

So we add a distinct delack flag to the connect() function so that
the caller decides whether or not to use a delayed ack regardless
of pending data (eg: when send-proxy is in use). Doing so covers all
combinations of { (check with data), (sendproxy), (smart-connect) }.

include/proto/proto_tcp.h
include/proto/stream_interface.h
include/types/protocol.h
src/checks.c
src/proto_tcp.c

index a41e025a879a75484100b8313e0d1c0383661472..d55f4c544bc44dddc0e6f77e70c8b88c5137b97e 100644 (file)
@@ -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);
index 7c9595a1f209573c4a042e10f2b4f523893653d2..c8202bccaf29c0cb93fb99d71011097bd3adfb2c 100644 (file)
@@ -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;
 
index a8e020ca2d080583b4500c8a9bb9f0adaac43ce0..0af2ed8a35c14f4386b4132d966a8c5835d29c1d 100644 (file)
@@ -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 */
 
index 7f49547bafc046b2c08eeb26802a3dd71d4c8801..b23fa86bcec1bcc7983d40f1fe2fe9ad6953aa00 100644 (file)
@@ -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;
index 2b8d148d15fd37a957924976318c360a716ce0df..fd9b03d86ddd56799c78d11092a4eaecabf680b0 100644 (file)
@@ -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 <data> 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 <data> 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 <delack> 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