[CRIU] [PATCH 3/3] tcp: add ability to restore a fin packet
Kir Kolyshkin
kir at parallels.com
Wed Mar 5 10:40:23 PST 2014
On 03/04/2014 09:18 PM, Andrey Vagin wrote:
> It's required for restoring sockets in closing states:
> TCP_FIN_WAIT{1,2}, TCP_WAIT_STOP, TCP_CLOSING, TCP_LAST_ACK.
>
> A fin packet is restored by sending the conntroll message. This
Sorry I can't help myself to refrain from asking.
Is this word an abbreviation for "connection trolling"?
> interface is choosen, because we are goint to use sendmsg to restore
> sockets in TCP_SYN_SENT and TCP_SYN_RECV states.
>
> Requests in the TCP_SYN_RECV state will be restored by sending messages
> in a proper listen socket. A message will contain address and a conntrol
> messages with sequence numbers.
>
> Sockets in the TCP_SYN_SENT state will be restored by sending messages
> in an unconnected tcp socket. A message will contain remote address and
> an initial sequence number.
>
> Signed-off-by: Andrey Vagin <avagin at openvz.org>
> ---
> include/net/tcp.h | 1 +
> include/uapi/linux/tcp.h | 3 +++
> net/ipv4/tcp.c | 39 +++++++++++++++++++++++++++++++++++++++
> net/ipv4/tcp_input.c | 2 +-
> 4 files changed, 44 insertions(+), 1 deletion(-)
>
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index 56fc366..ca3bd0b 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -561,6 +561,7 @@ void tcp_cwnd_application_limited(struct sock *sk);
> void tcp_resume_early_retransmit(struct sock *sk);
> void tcp_rearm_rto(struct sock *sk);
> void tcp_reset(struct sock *sk);
> +void tcp_fin(struct sock *sk);
>
> /* tcp_timer.c */
> void tcp_init_xmit_timers(struct sock *);
> diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
> index 377f1e5..2cc6876 100644
> --- a/include/uapi/linux/tcp.h
> +++ b/include/uapi/linux/tcp.h
> @@ -199,4 +199,7 @@ struct tcp_md5sig {
> __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
> };
>
> +/* Conntroll message types to repair tcp connections */
> +#define TCP_REPAIR_SEND_FIN 1
> +
> #endif /* _UAPI_LINUX_TCP_H */
> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> index 9a23905..308f7aa 100644
> --- a/net/ipv4/tcp.c
> +++ b/net/ipv4/tcp.c
> @@ -1068,6 +1068,34 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg, int *size)
> return err;
> }
>
> +static int tcp_repair_cmsg(struct sock *sk, struct msghdr *msg)
> +{
> + struct tcp_sock *tp = tcp_sk(sk);
> + struct cmsghdr *cmsg;
> +
> + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
> + if (!CMSG_OK(msg, cmsg))
> + return -EINVAL;
> + if (cmsg->cmsg_level != SOL_TCP)
> + continue;
> +
> + switch (cmsg->cmsg_type) {
> + case TCP_REPAIR_SEND_FIN:
> + if (tp->repair_queue == TCP_RECV_QUEUE)
> + tcp_fin(sk);
> + else if (tp->repair_queue == TCP_SEND_QUEUE)
> + tcp_shutdown(sk, SEND_SHUTDOWN);
> + else
> + return -EINVAL;
> + break;
> + default:
> + return -EINVAL;
> + }
> + }
> +
> + return 0;
> +}
> +
> int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
> size_t size)
> {
> @@ -1084,6 +1112,17 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
> flags = msg->msg_flags;
>
> if (unlikely(tp->repair)) {
> + if (msg->msg_controllen) {
> + if (size != 0)
> + return -EINVAL;
> +
> + err = tcp_repair_cmsg(sk, msg);
> + if (err < 0)
> + goto out_err;
> +
> + goto out;
> + }
> +
> if (tp->repair_queue == TCP_RECV_QUEUE) {
> copied = tcp_send_rcvq(sk, msg, size);
> goto out;
> diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
> index 227cba7..b68ffcd 100644
> --- a/net/ipv4/tcp_input.c
> +++ b/net/ipv4/tcp_input.c
> @@ -3819,7 +3819,7 @@ void tcp_reset(struct sock *sk)
> *
> * If we are in FINWAIT-2, a received FIN moves us to TIME-WAIT.
> */
> -static void tcp_fin(struct sock *sk)
> +void tcp_fin(struct sock *sk)
> {
> struct tcp_sock *tp = tcp_sk(sk);
> const struct dst_entry *dst;
More information about the CRIU
mailing list