From fdcb007ad899e8565159b3d29c5f76b0403ef81f Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Mon, 6 May 2019 18:32:29 +0200 Subject: [PATCH] MEDIUM: proto: Change the prototype of the connect() method. The connect() method had 2 arguments, "data", that tells if there's pending data to be sent, and "delack" that tells if we have to use a delayed ack inconditionally, or if the backend is configured with tcp-smart-connect. Turn that into one argument, "flags". That way it'll be easier to provide more informations to connect() without adding extra arguments. --- include/proto/proto_tcp.h | 2 +- include/proto/stream_interface.h | 3 ++- include/types/protocol.h | 5 ++++- src/checks.c | 16 ++++++++-------- src/proto_sockpair.c | 11 ++++++----- src/proto_tcp.c | 19 +++++++++++-------- src/proto_uxst.c | 11 ++++++----- 7 files changed, 38 insertions(+), 29 deletions(-) diff --git a/include/proto/proto_tcp.h b/include/proto/proto_tcp.h index d4e09c7a65..76f89b1f34 100644 --- a/include/proto/proto_tcp.h +++ b/include/proto/proto_tcp.h @@ -29,7 +29,7 @@ int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct sockaddr_storage *remote); int tcp_pause_listener(struct listener *l); -int tcp_connect_server(struct connection *conn, int data, int delack); +int tcp_connect_server(struct connection *conn, int flags); 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 3cccc8fce1..8a4b77afe0 100644 --- a/include/proto/stream_interface.h +++ b/include/proto/stream_interface.h @@ -489,7 +489,8 @@ static inline int si_connect(struct stream_interface *si, struct connection *con return SF_ERR_INTERNAL; if (!conn_ctrl_ready(conn) || !conn_xprt_ready(conn)) { - ret = conn->ctrl->connect(conn, !channel_is_empty(si_oc(si)), 0); + ret = conn->ctrl->connect(conn, channel_is_empty(si_oc(si)) ? + CONNECT_HAS_DATA : 0); if (ret != SF_ERR_NONE) return ret; diff --git a/include/types/protocol.h b/include/types/protocol.h index 378e2b0e16..a33d12922b 100644 --- a/include/types/protocol.h +++ b/include/types/protocol.h @@ -73,7 +73,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, int delack); /* connect function if any */ + int (*connect)(struct connection *, int flags); /* connect function if any, see below for flags values */ 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 */ int (*drain)(int fd); /* indicates whether we can safely close the fd */ @@ -85,6 +85,9 @@ struct protocol { struct list list; /* list of registered protocols */ }; +#define CONNECT_HAS_DATA 0x00000001 /* There's data available to be sent */ +#define CONNECT_DELACK_SMART_CONNECT 0x00000002 /* Use a delayed ACK if the backend has tcp-smart-connect */ +#define CONNECT_DELACK_ALWAYS 0x00000004 /* Use a delayed ACK */ #endif /* _TYPES_PROTOCOL_H */ /* diff --git a/src/checks.c b/src/checks.c index aeb3b79b66..a7b4b2fcea 100644 --- a/src/checks.c +++ b/src/checks.c @@ -1545,7 +1545,7 @@ static int connect_conn_chk(struct task *t) struct protocol *proto; struct tcpcheck_rule *tcp_rule = NULL; int ret; - int quickack; + int connflags = 0; /* we cannot have a connection here */ if (conn) @@ -1637,14 +1637,15 @@ static int connect_conn_chk(struct task *t) cs_attach(cs, check, &check_conn_cb); /* only plain tcp-check supports quick ACK */ - quickack = check->type == 0 || check->type == PR_O2_TCPCHK_CHK; - - if (tcp_rule && tcp_rule->action == TCPCHK_ACT_EXPECT) - quickack = 0; + if (check->type != 0) + connflags |= CONNECT_HAS_DATA; + if ((check->type == 0 || check->type == PR_O2_TCPCHK_CHK) && + (!tcp_rule || tcp_rule->action != TCPCHK_ACT_EXPECT)) + connflags |= CONNECT_DELACK_ALWAYS; ret = SF_ERR_INTERNAL; if (proto && proto->connect) - ret = proto->connect(conn, check->type, quickack ? 2 : 0); + ret = proto->connect(conn, connflags); #ifdef USE_OPENSSL @@ -2845,8 +2846,7 @@ static int tcpcheck_main(struct check *check) ret = SF_ERR_INTERNAL; if (proto && proto->connect) ret = proto->connect(conn, - 1 /* I/O polling is always needed */, - (next && next->action == TCPCHK_ACT_EXPECT) ? 0 : 2); + CONNECT_HAS_DATA /* I/O polling is always needed */ | (next && next->action == TCPCHK_ACT_EXPECT) ? 0 : CONNECT_DELACK_ALWAYS); if (check->current_step->conn_opts & TCPCHK_OPT_SEND_PROXY) { conn->send_proxy_ofs = 1; conn->flags |= CO_FL_SEND_PROXY; diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c index 713da370ab..97a93480af 100644 --- a/src/proto_sockpair.c +++ b/src/proto_sockpair.c @@ -49,7 +49,7 @@ static void sockpair_add_listener(struct listener *listener, int port); static int sockpair_bind_listener(struct listener *listener, char *errmsg, int errlen); static int sockpair_bind_listeners(struct protocol *proto, char *errmsg, int errlen); -static int sockpair_connect_server(struct connection *conn, int data, int delack); +static int sockpair_connect_server(struct connection *conn, int flags); /* Note: must not be declared as its list will be overwritten */ static struct protocol proto_sockpair = { @@ -237,7 +237,7 @@ int send_fd_uxst(int fd, int send_fd) * The connection's fd is inserted only when SF_ERR_NONE is returned, otherwise * it's invalid and the caller has nothing to do. */ -static int sockpair_connect_server(struct connection *conn, int data, int delack) +static int sockpair_connect_server(struct connection *conn, int flags) { int sv[2], fd, dst_fd = -1; @@ -289,7 +289,8 @@ static int sockpair_connect_server(struct connection *conn, int data, int delack } /* if a send_proxy is there, there are data */ - data |= conn->send_proxy_ofs; + if (conn->send_proxy_ofs) + flags |= CONNECT_HAS_DATA; if (global.tune.server_sndbuf) setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &global.tune.server_sndbuf, sizeof(global.tune.server_sndbuf)); @@ -334,10 +335,10 @@ static int sockpair_connect_server(struct connection *conn, int data, int delack * layer when the connection is already OK otherwise we'll have * no other opportunity to do it later (eg: health checks). */ - data = 1; + flags |= CONNECT_HAS_DATA; } - if (data) + if (flags & CONNECT_HAS_DATA) conn_xprt_want_send(conn); /* prepare to send data if any */ return SF_ERR_NONE; /* connection is OK */ diff --git a/src/proto_tcp.c b/src/proto_tcp.c index d4cad223a7..e668a85f10 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -266,11 +266,11 @@ static int create_server_socket(struct connection *conn) * depending on conn->target. Only OBJ_TYPE_PROXY and OBJ_TYPE_SERVER are * 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 : + * 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 + * - CONNECT_DELACK_SMART_CONNECT = delayed ACK if backend has tcp-smart-connect, regardless of data + * - CONNECT_DELACK_ALWAYS = delayed ACK regardless of backend options * * Note that a pending send_proxy message accounts for data. * @@ -287,7 +287,7 @@ static int create_server_socket(struct connection *conn) * it's invalid and the caller has nothing to do. */ -int tcp_connect_server(struct connection *conn, int data, int delack) +int tcp_connect_server(struct connection *conn, int flags) { int fd; struct server *srv; @@ -481,7 +481,10 @@ int tcp_connect_server(struct connection *conn, int data, int delack) * machine with the first ACK. We only do this if there are pending * data in the buffer. */ - if (delack == 2 || ((delack || data || conn->send_proxy_ofs) && (be->options2 & PR_O2_SMARTCON))) + if (flags & (CONNECT_DELACK_ALWAYS) || + ((flags & CONNECT_DELACK_SMART_CONNECT || + (flags & CONNECT_HAS_DATA) || conn->send_proxy_ofs) && + (be->options2 & PR_O2_SMARTCON))) setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &zero, sizeof(zero)); #endif @@ -572,10 +575,10 @@ int tcp_connect_server(struct connection *conn, int data, int delack) * layer when the connection is already OK otherwise we'll have * no other opportunity to do it later (eg: health checks). */ - data = 1; + flags |= CONNECT_HAS_DATA; } - if (data) + if (flags & CONNECT_HAS_DATA) conn_xprt_want_send(conn); /* prepare to send data if any */ return SF_ERR_NONE; /* connection is OK */ diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 980a22649b..42e0dc878f 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -48,7 +48,7 @@ static int uxst_bind_listener(struct listener *listener, char *errmsg, int errlen); static int uxst_bind_listeners(struct protocol *proto, char *errmsg, int errlen); static int uxst_unbind_listeners(struct protocol *proto); -static int uxst_connect_server(struct connection *conn, int data, int delack); +static int uxst_connect_server(struct connection *conn, int flags); static void uxst_add_listener(struct listener *listener, int port); static int uxst_pause_listener(struct listener *l); static int uxst_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir); @@ -430,7 +430,7 @@ static int uxst_pause_listener(struct listener *l) * The connection's fd is inserted only when SF_ERR_NONE is returned, otherwise * it's invalid and the caller has nothing to do. */ -static int uxst_connect_server(struct connection *conn, int data, int delack) +static int uxst_connect_server(struct connection *conn, int flags) { int fd; struct server *srv; @@ -510,7 +510,8 @@ static int uxst_connect_server(struct connection *conn, int data, int delack) } /* if a send_proxy is there, there are data */ - data |= conn->send_proxy_ofs; + if (conn->send_proxy_ofs) + flags |= CONNECT_HAS_DATA; if (global.tune.server_sndbuf) setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &global.tune.server_sndbuf, sizeof(global.tune.server_sndbuf)); @@ -585,10 +586,10 @@ static int uxst_connect_server(struct connection *conn, int data, int delack) * layer when the connection is already OK otherwise we'll have * no other opportunity to do it later (eg: health checks). */ - data = 1; + flags |= CONNECT_HAS_DATA; } - if (data) + if (flags & CONNECT_HAS_DATA) conn_xprt_want_send(conn); /* prepare to send data if any */ return SF_ERR_NONE; /* connection is OK */ -- 2.39.5