From e5bdc51bb5803309938946c710e7233dbf9382a4 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 28 Aug 2020 18:03:10 +0200 Subject: [PATCH] REORG: sock_inet: move default_tcp_maxseg from proto_tcp.c Let's determine it at boot time instead of doing it on first use. It also saves us from having to keep it thread local. It's been moved to the new sock_inet_prepare() function, and the variables were renamed to sock_inet_tcp_maxseg_default and sock_inet6_tcp_maxseg_default. --- include/haproxy/sock_inet.h | 2 ++ src/proto_tcp.c | 40 ++-------------------------------------- src/sock_inet.c | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+), 38 deletions(-) diff --git a/include/haproxy/sock_inet.h b/include/haproxy/sock_inet.h index 6e3718a..d90b419 100644 --- a/include/haproxy/sock_inet.h +++ b/include/haproxy/sock_inet.h @@ -28,6 +28,8 @@ #include extern int sock_inet6_v6only_default; +extern int sock_inet_tcp_maxseg_default; +extern int sock_inet6_tcp_maxseg_default; int sock_inet4_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b); int sock_inet6_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b); diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 144f4bc..44b11e4 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -101,12 +101,6 @@ static struct protocol proto_tcpv6 = { INITCALL1(STG_REGISTER, protocol_register, &proto_tcpv6); -/* Default TCP parameters, got by opening a temporary TCP socket. */ -#ifdef TCP_MAXSEG -static THREAD_LOCAL int default_tcp_maxseg = -1; -static THREAD_LOCAL int default_tcp6_maxseg = -1; -#endif - /* Binds ipv4/ipv6 address to socket , unless is set, in which * case we try to bind . is a 2-bit field consisting of : * - 0 : ignore remote address (may even be a NULL pointer) @@ -655,36 +649,6 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen) int ext, ready; socklen_t ready_len; const char *msg = NULL; -#ifdef TCP_MAXSEG - - /* Create a temporary TCP socket to get default parameters we can't - * guess. - * */ - ready_len = sizeof(default_tcp_maxseg); - if (default_tcp_maxseg == -1) { - default_tcp_maxseg = -2; - fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (fd < 0) - ha_warning("Failed to create a temporary socket!\n"); - else { - if (getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &default_tcp_maxseg, - &ready_len) == -1) - ha_warning("Failed to get the default value of TCP_MAXSEG\n"); - close(fd); - } - } - if (default_tcp6_maxseg == -1) { - default_tcp6_maxseg = -2; - fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); - if (fd >= 0) { - if (getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &default_tcp6_maxseg, - &ready_len) == -1) - ha_warning("Failed ot get the default value of TCP_MAXSEG for IPv6\n"); - close(fd); - } - } -#endif - /* ensure we never return garbage */ if (errlen) @@ -822,9 +786,9 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen) socklen_t len = sizeof(tmpmaxseg); if (listener->addr.ss_family == AF_INET) - defaultmss = default_tcp_maxseg; + defaultmss = sock_inet_tcp_maxseg_default; else - defaultmss = default_tcp6_maxseg; + defaultmss = sock_inet6_tcp_maxseg_default; getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &tmpmaxseg, &len); if (defaultmss > 0 && diff --git a/src/sock_inet.c b/src/sock_inet.c index c5b80da..2966680 100644 --- a/src/sock_inet.c +++ b/src/sock_inet.c @@ -40,6 +40,10 @@ */ int sock_inet6_v6only_default = 0; +/* Default TCPv4/TCPv6 MSS settings. -1=unknown. */ +int sock_inet_tcp_maxseg_default = -1; +int sock_inet6_tcp_maxseg_default = -1; + /* Compares two AF_INET sockaddr addresses. Returns 0 if they match or non-zero * if they do not match. */ @@ -175,6 +179,17 @@ static void sock_inet_prepare() int fd, val; socklen_t len; + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd >= 0) { +#ifdef TCP_MAXSEG + /* retrieve the OS' default mss for TCPv4 */ + len = sizeof(val); + if (getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &val, &len) == 0) + sock_inet_tcp_maxseg_default = val; +#endif + close(fd); + } + fd = socket(AF_INET6, SOCK_STREAM, 0); if (fd >= 0) { #if defined(IPV6_V6ONLY) @@ -183,6 +198,13 @@ static void sock_inet_prepare() if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, &len) == 0 && val > 0) sock_inet6_v6only_default = 1; #endif + +#ifdef TCP_MAXSEG + /* retrieve the OS' default mss for TCPv6 */ + len = sizeof(val); + if (getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &val, &len) == 0) + sock_inet6_tcp_maxseg_default = val; +#endif close(fd); } } -- 1.7.10.4