socket: c/r support for SO_KEEPALIVE

TCP keepalive packets can be used to determine if a connection
is still valid. When the SO_KEEPALIVE option is set, TCP packets
are periodically sent to keep the connection alive.

This patch implements checkpoint/restore support for SO_KEEPALIVE,
TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT options.

Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
This commit is contained in:
Radostin Stoyanov 2019-12-13 00:10:28 +00:00 committed by Andrei Vagin
parent 0980617e24
commit d4e6fc2a0d
5 changed files with 49 additions and 3 deletions

View file

@ -83,7 +83,7 @@ extern void tcp_locked_conn_add(struct inet_sk_info *);
extern void rst_unlock_tcp_connections(void);
extern void cpt_unlock_tcp_connections(void);
extern int dump_one_tcp(int sk, struct inet_sk_desc *sd);
extern int dump_one_tcp(int sk, struct inet_sk_desc *sd, SkOptsEntry *soe);
extern int restore_one_tcp(int sk, struct inet_sk_info *si);
#define SK_EST_PARAM "tcp-established"

View file

@ -551,7 +551,7 @@ static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int fa
switch (proto) {
case IPPROTO_TCP:
err = (type != SOCK_RAW) ? dump_one_tcp(lfd, sk) : 0;
err = (type != SOCK_RAW) ? dump_one_tcp(lfd, sk, &skopts) : 0;
break;
case IPPROTO_UDP:
case IPPROTO_UDPLITE:
@ -747,6 +747,10 @@ static int post_open_inet_sk(struct file_desc *d, int sk)
if (!val && restore_opt(sk, SOL_SOCKET, SO_BROADCAST, &val))
return -1;
val = ii->ie->opts->so_keepalive;
if (!val && restore_opt(sk, SOL_SOCKET, SO_KEEPALIVE, &val))
return -1;
return 0;
}

View file

@ -218,8 +218,26 @@ err_r:
return ret;
}
int dump_one_tcp(int fd, struct inet_sk_desc *sk)
int dump_one_tcp(int fd, struct inet_sk_desc *sk, SkOptsEntry *soe)
{
soe->has_tcp_keepcnt = true;
if (dump_opt(fd, SOL_TCP, TCP_KEEPCNT, &soe->tcp_keepcnt)) {
pr_perror("Can't read TCP_KEEPCNT");
return -1;
}
soe->has_tcp_keepidle = true;
if (dump_opt(fd, SOL_TCP, TCP_KEEPIDLE, &soe->tcp_keepidle)) {
pr_perror("Can't read TCP_KEEPIDLE");
return -1;
}
soe->has_tcp_keepintvl = true;
if (dump_opt(fd, SOL_TCP, TCP_KEEPINTVL, &soe->tcp_keepintvl)) {
pr_perror("Can't read TCP_KEEPINTVL");
return -1;
}
if (sk->dst_port == 0)
return 0;

View file

@ -566,6 +566,22 @@ int restore_socket_opts(int sk, SkOptsEntry *soe)
pr_debug("\tset broadcast for socket\n");
ret |= restore_opt(sk, SOL_SOCKET, SO_BROADCAST, &val);
}
if (soe->has_so_keepalive && soe->so_keepalive) {
pr_debug("\tset keepalive for socket\n");
ret |= restore_opt(sk, SOL_SOCKET, SO_KEEPALIVE, &val);
}
if (soe->has_tcp_keepcnt) {
pr_debug("\tset keepcnt for socket\n");
ret |= restore_opt(sk, SOL_TCP, TCP_KEEPCNT, &soe->tcp_keepcnt);
}
if (soe->has_tcp_keepidle) {
pr_debug("\tset keepidle for socket\n");
ret |= restore_opt(sk, SOL_TCP, TCP_KEEPIDLE, &soe->tcp_keepidle);
}
if (soe->has_tcp_keepintvl) {
pr_debug("\tset keepintvl for socket\n");
ret |= restore_opt(sk, SOL_TCP, TCP_KEEPINTVL, &soe->tcp_keepintvl);
}
tv.tv_sec = soe->so_snd_tmo_sec;
tv.tv_usec = soe->so_snd_tmo_usec;
@ -651,6 +667,10 @@ int dump_socket_opts(int sk, SkOptsEntry *soe)
soe->has_so_broadcast = true;
soe->so_broadcast = val ? true : false;
ret |= dump_opt(sk, SOL_SOCKET, SO_KEEPALIVE, &val);
soe->has_so_keepalive = true;
soe->so_keepalive = val ? true : false;
ret |= dump_bound_dev(sk, soe);
ret |= dump_socket_filter(sk, soe);

View file

@ -23,6 +23,10 @@ message sk_opts_entry {
repeated fixed64 so_filter = 16;
optional bool so_reuseport = 17;
optional bool so_broadcast = 18;
optional bool so_keepalive = 19;
optional uint32 tcp_keepcnt = 20;
optional uint32 tcp_keepidle = 21;
optional uint32 tcp_keepintvl = 22;
}
enum sk_shutdown {