From b91da3f4bf4ab30428e50a0c6734fcb931e3d85e Mon Sep 17 00:00:00 2001 From: Yash Tibrewal Date: Thu, 6 Sep 2018 15:26:36 -0700 Subject: [PATCH] Add support for reading channel args --- src/core/lib/iomgr/port.h | 1 - .../lib/iomgr/socket_utils_common_posix.cc | 87 ++++++++++++++++--- src/core/lib/iomgr/socket_utils_posix.h | 8 +- src/core/lib/iomgr/tcp_client_posix.cc | 3 +- .../iomgr/tcp_server_utils_posix_common.cc | 3 +- 5 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index bc58ed13c07..807b9bf85ae 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -77,7 +77,6 @@ #define GRPC_LINUX_SOCKETUTILS 1 #endif #endif -#include #ifdef LINUX_VERSION_CODE #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) #define GRPC_HAVE_TCP_USER_TIMEOUT diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc index b7fc833608b..4ef3d8319fd 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -41,6 +41,7 @@ #include #include +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/sockaddr.h" @@ -222,25 +223,83 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) { return GRPC_ERROR_NONE; } -#define DEFAULT_TCP_USER_TIMEOUT 20000 /* 20 seconds */ +/* The default values for TCP_USER_TIMEOUT are currently configured to be in + * line with the default values of KEEPALIVE_TIMEOUT as proposed in + * https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md */ +#define DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */ +#define DEFAULT_SERVER_TCP_USER_TIMEOUT_MS 20000 /* 20 seconds */ + +static int g_default_client_tcp_user_timeout_ms = + DEFAULT_CLIENT_TCP_USER_TIMEOUT_MS; +static int g_default_server_tcp_user_timeout_ms = + DEFAULT_SERVER_TCP_USER_TIMEOUT_MS; +static bool g_default_client_tcp_user_timeout_enabled = false; +static bool g_default_server_tcp_user_timeout_enabled = true; + +void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client) { + if (is_client) { + g_default_client_tcp_user_timeout_enabled = enable; + if (timeout > 0) { + g_default_client_tcp_user_timeout_ms = timeout; + } + } else { + g_default_server_tcp_user_timeout_enabled = enable; + if (timeout > 0) { + g_default_server_tcp_user_timeout_ms = timeout; + } + } +} /* Set TCP_USER_TIMEOUT */ -grpc_error* grpc_set_socket_tcp_user_timeout(int fd, int val) { +grpc_error* grpc_set_socket_tcp_user_timeout( + int fd, const grpc_channel_args* channel_args, bool is_client) { #ifdef GRPC_HAVE_TCP_USER_TIMEOUT - int newval; - socklen_t len = sizeof(newval); - if (val == 0) { - val = DEFAULT_TCP_USER_TIMEOUT; - } - if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &val, sizeof(val))) { - return GRPC_OS_ERROR(errno, "setsockopt(TCP_USER_TIMEOUT)"); + bool enable; + int timeout; + if (is_client) { + enable = g_default_client_tcp_user_timeout_enabled; + timeout = g_default_client_tcp_user_timeout_ms; + } else { + enable = g_default_server_tcp_user_timeout_enabled; + timeout = g_default_server_tcp_user_timeout_ms; } - if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) { - return GRPC_OS_ERROR(errno, "getsockopt(TCP_USER_TIMEOUT)"); + if (channel_args) { + for (unsigned int i = 0; i < channel_args->num_args; i++) { + if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) { + const int value = grpc_channel_arg_get_integer( + &channel_args->args[i], grpc_integer_options{0, 1, INT_MAX}); + /* Continue using default if value is 0 */ + if (value == 0) { + continue; + } + /* Disable if value is INT_MAX */ + enable = value != INT_MAX; + } else if (0 == strcmp(channel_args->args[i].key, + GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) { + const int value = grpc_channel_arg_get_integer( + &channel_args->args[i], grpc_integer_options{0, 1, INT_MAX}); + /* Continue using default if value is 0 */ + if (value == 0) { + continue; + } + timeout = value; + } + } } - if (newval != val) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Failed to set TCP_USER_TIMEOUT"); + if (enable) { + int newval; + socklen_t len = sizeof(newval); + if (0 != setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, + sizeof(timeout))) { + return GRPC_OS_ERROR(errno, "setsockopt(TCP_USER_TIMEOUT)"); + } + if (0 != getsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &newval, &len)) { + return GRPC_OS_ERROR(errno, "getsockopt(TCP_USER_TIMEOUT)"); + } + if (newval != timeout) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Failed to set TCP_USER_TIMEOUT"); + } } #else gpr_log(GPR_INFO, "TCP_USER_TIMEOUT not supported for this platform"); diff --git a/src/core/lib/iomgr/socket_utils_posix.h b/src/core/lib/iomgr/socket_utils_posix.h index 8550bd1324d..71a304dc4ef 100644 --- a/src/core/lib/iomgr/socket_utils_posix.h +++ b/src/core/lib/iomgr/socket_utils_posix.h @@ -53,8 +53,12 @@ grpc_error* grpc_set_socket_low_latency(int fd, int low_latency); /* set SO_REUSEPORT */ grpc_error* grpc_set_socket_reuse_port(int fd, int reuse); -/* Set TCP_USER_TIMEOUT to val, or the default value if val is 0. */ -grpc_error* grpc_set_socket_tcp_user_timeout(int fd, int val); +/* Configure the default values for TCP_USER_TIMEOUT */ +void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client); + +/* Set TCP_USER_TIMEOUT */ +grpc_error* grpc_set_socket_tcp_user_timeout( + int fd, const grpc_channel_args* channel_args, bool is_client); /* Returns true if this system can create AF_INET6 sockets bound to ::1. The value is probed once, and cached for the life of the process. diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc index c2a08922116..b71f5570940 100644 --- a/src/core/lib/iomgr/tcp_client_posix.cc +++ b/src/core/lib/iomgr/tcp_client_posix.cc @@ -76,7 +76,8 @@ static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd, if (!grpc_is_unix_socket(addr)) { err = grpc_set_socket_low_latency(fd, 1); if (err != GRPC_ERROR_NONE) goto error; - err = grpc_set_socket_tcp_user_timeout(fd, 0 /* set to gRPC default */); + err = grpc_set_socket_tcp_user_timeout(fd, channel_args, + true /* is_client */); if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd); diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc index 20b9037c68f..6cebc840241 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc @@ -166,7 +166,8 @@ grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd, if (err != GRPC_ERROR_NONE) goto error; err = grpc_set_socket_reuse_addr(fd, 1); if (err != GRPC_ERROR_NONE) goto error; - err = grpc_set_socket_tcp_user_timeout(fd, 0 /* set to gRPC default */); + err = grpc_set_socket_tcp_user_timeout(fd, s->channel_args, + false /* is_client */); if (err != GRPC_ERROR_NONE) goto error; } err = grpc_set_socket_no_sigpipe_if_possible(fd);