diff --git a/include/fluent-bit/flb_network.h b/include/fluent-bit/flb_network.h index 0fb0dbb8f9d..5e8a9dce141 100644 --- a/include/fluent-bit/flb_network.h +++ b/include/fluent-bit/flb_network.h @@ -43,6 +43,18 @@ struct flb_net_setup { /* maximum of times a keepalive connection can be used */ int keepalive_max_recycle; + + /* enable/disable tcp keepalive */ + char tcp_keepalive; + + /* interval between the last data packet sent and the first TCP keepalive probe */ + int tcp_keepalive_time; + + /* the interval between TCP keepalive probes */ + int tcp_keepalive_interval; + + /* number of unacknowledged probes to consider a connection dead */ + int tcp_keepalive_probes; }; /* Defines a host service and it properties */ @@ -69,6 +81,7 @@ int flb_net_socket_tcp_nodelay(flb_sockfd_t fd); int flb_net_socket_blocking(flb_sockfd_t fd); int flb_net_socket_nonblocking(flb_sockfd_t fd); int flb_net_socket_tcp_fastopen(flb_sockfd_t sockfd); +int flb_net_socket_tcp_keepalive(flb_sockfd_t fd, struct flb_net_setup *net); /* Socket handling */ flb_sockfd_t flb_net_socket_create(int family, int nonblock); diff --git a/src/flb_io.c b/src/flb_io.c index 43185bedadf..88d8a0715ca 100644 --- a/src/flb_io.c +++ b/src/flb_io.c @@ -102,6 +102,15 @@ int flb_io_net_connect(struct flb_upstream_conn *u_conn, u_conn->fd, u->tcp_host, u->tcp_port); } + /* set TCP keepalive and it's options */ + if (u->net.tcp_keepalive != FLB_FALSE) { + ret = flb_net_socket_tcp_keepalive(fd, &u->net); + if (ret == -1) { + flb_socket_close(fd); + return -1; + } + } + #ifdef FLB_HAVE_TLS /* Check if TLS was enabled, if so perform the handshake */ if (u->flags & FLB_IO_TLS) { diff --git a/src/flb_network.c b/src/flb_network.c index c2946f22c7c..6581287c18b 100644 --- a/src/flb_network.c +++ b/src/flb_network.c @@ -58,6 +58,10 @@ void flb_net_setup_init(struct flb_net_setup *net) net->keepalive_max_recycle = 0; net->connect_timeout = 10; net->source_address = NULL; + net->tcp_keepalive = FLB_FALSE; + net->tcp_keepalive_time = -1; + net->tcp_keepalive_interval = -1; + net->tcp_keepalive_probes = -1; } int flb_net_host_set(const char *plugin_name, struct flb_net_host *host, const char *address) @@ -186,6 +190,42 @@ int flb_net_socket_tcp_fastopen(flb_sockfd_t fd) return setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)); } + +/* + * Enable TCP keepalive + */ +int flb_net_socket_tcp_keepalive(flb_sockfd_t fd, struct flb_net_setup *net) +{ + int ret = 0; + int enabled = 1; + int time = net->tcp_keepalive_time; + int intvl = net->tcp_keepalive_interval; + int probes = net->tcp_keepalive_probes; + + printf("keepalive = %d, %d %d\n", time, intvl, probes); + + ret |= setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&enabled, sizeof(enabled)); + + if (time >= 0) { + ret |= setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (const void*)&time, sizeof(time)); + } + + if (intvl >= 0) { + ret |= setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, (const void*)&intvl, sizeof(intvl)); + } + + if (probes >= 0) { + ret |= setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, (const void*)&probes, sizeof(probes)); + } + + if (ret) { + flb_error("[net] failed to configure TCP keepalive for connection #%i", fd); + return -1; + } + + return 0; +} + flb_sockfd_t flb_net_socket_create(int family, int nonblock) { flb_sockfd_t fd; diff --git a/src/flb_upstream.c b/src/flb_upstream.c index d8dffff20a4..b70dfa66621 100644 --- a/src/flb_upstream.c +++ b/src/flb_upstream.c @@ -65,6 +65,32 @@ struct flb_config_map upstream_net[] = { "before it is retired." }, + { + FLB_CONFIG_MAP_BOOL, "net.tcp_keepalive", "off", + 0, FLB_TRUE, offsetof(struct flb_net_setup, tcp_keepalive), + "Enable or disable the use of TCP keepalive probes" + }, + + { + FLB_CONFIG_MAP_INT, "net.tcp_keepalive_time", "-1", + 0, FLB_TRUE, offsetof(struct flb_net_setup, tcp_keepalive_time), + "interval between the last data packet sent and the first " + "TCP keepalive probe" + }, + + { + FLB_CONFIG_MAP_INT, "net.tcp_keepalive_interval", "-1", + 0, FLB_TRUE, offsetof(struct flb_net_setup, tcp_keepalive_interval), + "interval between TCP keepalive probes when no response is" + "received on a keepidle probe" + }, + + { + FLB_CONFIG_MAP_INT, "net.tcp_keepalive_probes", "-1", + 0, FLB_TRUE, offsetof(struct flb_net_setup, tcp_keepalive_probes), + "number of unacknowledged probes to consider a connection dead" + }, + /* EOF */ {0} };