From d831c2497e9e8b2360cbe2026fdb2d736fa07641 Mon Sep 17 00:00:00 2001 From: David Goulet Date: Tue, 27 Aug 2013 15:11:40 -0400 Subject: [PATCH] Get the maximum TCP timeout in sessiond This actually just open some /proc files when calling lttcomm_init_inet() and computes the maximum value a TCP timeout for every possible operations (send/recv/connect). This is the first patch to fix the health check issue of having a smaller delta than the TCP maximum possible timeout. Signed-off-by: David Goulet --- src/bin/lttng-sessiond/main.c | 2 + src/common/defaults.h | 7 ++++ src/common/sessiond-comm/inet.c | 67 +++++++++++++++++++++++++++++++++ src/common/sessiond-comm/inet.h | 23 +++++++++++ 4 files changed, 99 insertions(+) diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 195174a4e..627560f49 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -4652,6 +4652,8 @@ int main(int argc, char **argv) /* Initialize communication library */ lttcomm_init(); + /* This is to get the TCP timeout value. */ + lttcomm_inet_init(); /* Create thread to manage the client socket */ ret = pthread_create(&ht_cleanup_thread, NULL, diff --git a/src/common/defaults.h b/src/common/defaults.h index 7bb10c2af..c115491ec 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -198,6 +198,13 @@ */ #define DEFAULT_METADATA_AVAILABILITY_WAIT_TIME 200000 /* usec */ +/* + * The usual value for the maximum TCP SYN retries time and TCP FIN timeout is + * 180 and 60 seconds on most Linux system and the default value since kernel + * 2.2 thus using the highest value. See tcp(7) for more details. + */ +#define DEFAULT_INET_TCP_TIMEOUT 180 /* sec */ + /* * Default receiving and sending timeout for an application socket. */ diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c index eb0c4fde3..b5a016e6f 100644 --- a/src/common/sessiond-comm/inet.c +++ b/src/common/sessiond-comm/inet.c @@ -50,6 +50,8 @@ static const struct lttcomm_proto_ops inet_ops = { .sendmsg = lttcomm_sendmsg_inet_sock, }; +unsigned long lttcomm_inet_tcp_timeout; + /* * Creates an PF_INET socket. */ @@ -448,3 +450,68 @@ int lttcomm_close_inet_sock(struct lttcomm_sock *sock) return ret; } + +/* + * Return value read from /proc or else 0 if value is not found. + */ +static unsigned long read_proc_value(const char *path) +{ + int ret, fd; + long r_val; + unsigned long val = 0; + char buf[64]; + + fd = open(path, O_RDONLY); + if (fd < 0) { + goto error; + } + + ret = read(fd, buf, sizeof(buf)); + if (ret < 0) { + PERROR("read proc failed"); + goto error_close; + } + + errno = 0; + r_val = strtol(buf, NULL, 10); + if (errno != 0 || r_val < -1L) { + val = 0; + goto error_close; + } else { + if (r_val > 0) { + val = r_val; + } + } + +error_close: + ret = close(fd); + if (ret) { + PERROR("close /proc value"); + } +error: + return val; +} + +LTTNG_HIDDEN +void lttcomm_inet_init(void) +{ + unsigned long syn_retries, fin_timeout, syn_timeout; + + /* Assign default value and see if we can change it. */ + lttcomm_inet_tcp_timeout = DEFAULT_INET_TCP_TIMEOUT; + + syn_retries = read_proc_value(LTTCOMM_INET_PROC_SYN_RETRIES_PATH); + fin_timeout = read_proc_value(LTTCOMM_INET_PROC_FIN_TIMEOUT_PATH); + + syn_timeout = syn_retries * LTTCOMM_INET_SYN_TIMEOUT_FACTOR; + + /* + * Get the maximum between the two possible timeout value and use that to + * get the maximum with the default timeout. + */ + lttcomm_inet_tcp_timeout = max_t(unsigned long, + max_t(unsigned long, syn_timeout, fin_timeout), + lttcomm_inet_tcp_timeout); + + DBG("TCP inet operation timeout set to %lu sec", lttcomm_inet_tcp_timeout); +} diff --git a/src/common/sessiond-comm/inet.h b/src/common/sessiond-comm/inet.h index 89716b8ba..83209bb71 100644 --- a/src/common/sessiond-comm/inet.h +++ b/src/common/sessiond-comm/inet.h @@ -23,6 +23,26 @@ #include "sessiond-comm.h" +/* See man tcp(7) for more detail about this value. */ +#define LTTCOMM_INET_PROC_SYN_RETRIES_PATH "/proc/sys/net/ipv4/tcp_syn_retries" +#define LTTCOMM_INET_PROC_FIN_TIMEOUT_PATH "/proc/sys/net/ipv4/tcp_fin_timeout" + +/* + * The timeout value of a connect() is computed with an algorithm inside the + * kernel using the defined TCP SYN retries so the end value in time is + * approximative. According to tcp(7) man page, a value of 5 is roughly 180 + * seconds of timeout. With that information, we've computed a factor of 36 + * (180/5) by considering that it grows linearly. This is of course uncertain + * but this is the best approximation we can do at runtime. + */ +#define LTTCOMM_INET_SYN_TIMEOUT_FACTOR 36 + +/* + * Maximum timeout value in seconds of a TCP connection for both send/recv and + * connect operations. + */ +extern unsigned long lttcomm_inet_tcp_timeout; + /* Stub */ struct lttcomm_sock; @@ -41,4 +61,7 @@ extern ssize_t lttcomm_recvmsg_inet_sock(struct lttcomm_sock *sock, void *buf, extern ssize_t lttcomm_sendmsg_inet_sock(struct lttcomm_sock *sock, void *buf, size_t len, int flags); +/* Initialize inet communication layer. */ +extern void lttcomm_inet_init(void); + #endif /* _LTTCOMM_INET_H */ -- 2.34.1