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.
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 <haproxy/api.h>
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 @@
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 <local> to socket <fd>, unless <flags> is set, in which
* case we try to bind <remote>. <flags> is a 2-bit field consisting of :
* - 0 : ignore remote address (may even be a NULL pointer)
@@ -655,36 +649,6 @@
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 @@
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 @@
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 @@
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);
}
}