diff --git a/src/common/sockutil.c b/src/common/sockutil.c index a924026..23bb97c 100644 --- a/src/common/sockutil.c +++ b/src/common/sockutil.c @@ -68,6 +68,34 @@ int sock_set_reuseaddr( int fd, int optval ) return setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) ); } +int sock_set_keepalive_params( int fd, int time, int intvl, int probes) +{ + return sock_set_keepalive(fd, 1) || + sock_set_tcp_keepidle(fd, time) || + sock_set_tcp_keepintvl(fd, intvl) || + sock_set_tcp_keepcnt(fd, probes); +} + +int sock_set_keepalive( int fd, int optval ) +{ + return setsockopt( fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval) ); +} + +int sock_set_tcp_keepidle( int fd, int optval ) +{ + return setsockopt( fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, sizeof(optval) ); +} + +int sock_set_tcp_keepintvl( int fd, int optval ) +{ + return setsockopt( fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, sizeof(optval) ); +} + +int sock_set_tcp_keepcnt( int fd, int optval ) +{ + return setsockopt( fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, sizeof(optval) ); +} + /* Set the tcp_nodelay option */ int sock_set_tcp_nodelay( int fd, int optval ) { diff --git a/src/common/sockutil.h b/src/common/sockutil.h index e79b566..94dbf85 100644 --- a/src/common/sockutil.h +++ b/src/common/sockutil.h @@ -14,9 +14,24 @@ size_t sockaddr_size(const struct sockaddr* sa); */ const char* sockaddr_address_string(const struct sockaddr* sa, char* dest, size_t len); +/* Configure TCP keepalive on a socket */ +int sock_set_keepalive_params( int fd, int time, int intvl, int probes); + +/* Set the SOL_KEEPALIVE otion */ +int sock_set_keepalive(int fd, int optval); + /* Set the SOL_REUSEADDR otion */ int sock_set_reuseaddr(int fd, int optval); +/* Set the tcp_keepidle option */ +int sock_set_tcp_keepidle(int fd, int optval); + +/* Set the tcp_keepintvl option */ +int sock_set_tcp_keepintvl(int fd, int optval); + +/* Set the tcp_keepcnt option */ +int sock_set_tcp_keepcnt(int fd, int optval); + /* Set the tcp_nodelay option */ int sock_set_tcp_nodelay(int fd, int optval); diff --git a/src/server/serve.c b/src/server/serve.c index de6b871..225e384 100644 --- a/src/server/serve.c +++ b/src/server/serve.c @@ -422,6 +422,9 @@ void accept_nbd_client( int slot; char s_client_address[64] = {0}; + FATAL_IF_NEGATIVE( sock_set_keepalive_params( client_fd, CLIENT_KEEPALIVE_TIME, CLIENT_KEEPALIVE_INTVL, CLIENT_KEEPALIVE_PROBES), + "Error setting keepalive parameters on client socket fd %d", client_fd ); + if ( !server_should_accept_client( params, client_address, s_client_address, 64 ) ) { FATAL_IF_NEGATIVE( close( client_fd ), diff --git a/src/server/serve.h b/src/server/serve.h index 5d04e14..1b697f2 100644 --- a/src/server/serve.h +++ b/src/server/serve.h @@ -21,6 +21,9 @@ struct client_tbl_entry { #define MAX_NBD_CLIENTS 16 +#define CLIENT_KEEPALIVE_TIME 30 +#define CLIENT_KEEPALIVE_INTVL 10 +#define CLIENT_KEEPALIVE_PROBES 3 struct server { /* The flexnbd wrapper this server is attached to */ struct flexnbd * flexnbd;