linux tcp repair及tcp热迁移
来源:互联网 发布:android 打开数据连接 编辑:程序博客网 时间:2024/06/04 22:57
概念
比如docker等容器在不同的机器之间无缝迁移(可能由于调度,维护,交割等原因),是常见的需求场景
但是又希望不能中断服务,因此各种虚拟机和容器的热迁移就得到很多关注。
linux也在3.5版本中引入TCP_REPAIR socket选项来支持热迁移
获取状态及还原
当需要迁移的时候,为迁移的socket进入repair模式
setsockopt设置TCP_PREPAIR选项
进入repair模式的要求:
- 需要CAP_NET_ADMIN, 用户命名空间需要有网络管理能力
- socket处于CLOSE状态或ESTABLISHED状态
从内核读取缓存数据
内核缓存区中未发送或未被确认的数据,或者未被应用程序读取的数据
setsockopt设置TCP_REPAIR_QUEUE选项的值分别为TCP_SEND_QUEUE和TCP_RECV_QUEUE, 从两个缓存中读取数据
123456789101112131415161718192021
int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,int flags, int *addr_len){...if (unlikely(tp->repair)) {err = -EPERM;if (!(flags & MSG_PEEK))//只支持peek方式goto out;if (tp->repair_queue == TCP_SEND_QUEUE)//从发送队列中读取err = tcp_peek_sndq(sk, msg, len);goto out;err = -EINVAL;if (tp->repair_queue == TCP_NO_QUEUE)goto out;//正常的peek流程,peek接收队列数据/* 'common' recv queue MSG_PEEK-ing */}...}
迁移完,把这些数据还原到对应的socket缓存中,通过send()接口
1234567891011121314151617181920
int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size){...if (unlikely(tp->repair)) {if (tp->repair_queue == TCP_RECV_QUEUE) {copied = tcp_send_rcvq(sk, msg, size);//放到接收队列goto out_nopush;}err = -EINVAL;if (tp->repair_queue == TCP_NO_QUEUE)goto out_err;//TCP_SEND_QUEUE, 正常模式处理/* 'common' sending to sendq */}...//正常的copy到内核发送缓存,准备发送的处理过程...}
读取和还原tcp协商信息
当握手的时候,会用tcp扩展选项来协商支持的情况,比如sack,timestamp,wscale等
getsockopt TCP_REPAIR_OPTIONS选项来获取这些值, 迁移之后setsockopt还原这些值
读取和还原序号
12345678
case TCP_QUEUE_SEQ:if (tp->repair_queue == TCP_SEND_QUEUE)val = tp->write_seq;else if (tp->repair_queue == TCP_RECV_QUEUE)val = tp->rcv_nxt;elsereturn -EINVAL;break;
读取和还原MSS
1234567
case TCP_MAXSEG:val = tp->mss_cache;if (!val && ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)))val = tp->rx_opt.user_mss;if (tp->repair)val = tp->rx_opt.mss_clamp;break;
读取和还原滑动窗口信息
12345678910111213141516171819202122
case TCP_REPAIR_WINDOW: {struct tcp_repair_window opt;if (get_user(len, optlen))return -EFAULT;if (len != sizeof(opt))return -EINVAL;if (!tp->repair)return -EPERM;opt.snd_wl1= tp->snd_wl1;opt.snd_wnd= tp->snd_wnd;opt.max_window= tp->max_window;opt.rcv_wnd= tp->rcv_wnd;opt.rcv_wup= tp->rcv_wup;if (copy_to_user(optval, &opt, len))return -EFAULT;return 0;}
静默关闭连接
close()将静默关闭,不会发送FIN
1234567891011121314151617181920212223242526272829303132333435363738
void tcp_close(struct sock *sk, long timeout){if (unlikely(tcp_sk(sk)->repair)) {sk->sk_prot->disconnect(sk, 0);} else if (data_was_unread) {/* Unread data was tossed, zap the connection. */NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE);tcp_set_state(sk, TCP_CLOSE);tcp_send_active_reset(sk, sk->sk_allocation);} else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {/* Check zero linger _after_ checking for unread data. */sk->sk_prot->disconnect(sk, 0);NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA);} else if (tcp_close_state(sk)) {tcp_send_fin(sk);}...}int tcp_disconnect(struct sock *sk, int flags){struct inet_sock *inet = inet_sk(sk);struct inet_connection_sock *icsk = inet_csk(sk);struct tcp_sock *tp = tcp_sk(sk);int err = 0;int old_state = sk->sk_state;if (old_state != TCP_CLOSE)tcp_set_state(sk, TCP_CLOSE);/* ABORT function of RFC793 */if (old_state == TCP_LISTEN) {inet_csk_listen_stop(sk);} else if (unlikely(tp->repair)) {sk->sk_err = ECONNABORTED;}...}
还原连接
connect()直接进入ESTABLISH状态, 然后setsockopt各个状态选项,再用send()两个缓存到对应内核队列中
123456789101112131415
int tcp_connect(struct sock *sk){struct tcp_sock *tp = tcp_sk(sk);struct sk_buff *buff;int err;tcp_connect_init(sk);//初始化tcp配置,选项,滑动窗口等if (unlikely(tp->repair)) {tcp_finish_connect(sk, NULL);//repair模式直接进入TCP_ESTABLISHED状态return 0;}...//发送握手包}
原文来自:http://www.cnhalo.net/2016/09/13/linux-tcp-repair/
资料
TCP connection repair
CRIU
阅读全文
0 0
- linux tcp repair及tcp热迁移
- 6.5 TCP Connection Repair
- TCP状态迁移
- tcp状态迁移图
- tcp状态迁移图
- TCP状态迁移
- tcp状态迁移
- TCP状态迁移图
- TCP的状态迁移
- TCP状态迁移
- TCP状态迁移
- TCP的状态迁移
- tcp/ip状态迁移图
- TCP状态迁移,CLOSE_WAIT & FIN_WAIT2
- TCP状态迁移图浅析
- TCP状态迁移图浅析
- TCP状态迁移图浅析
- TCP状态迁移图浅析
- Number类型分析!
- iOS开发之
- 反射
- 参数初始化表,构造、析构函数,友元……
- 调通sina33下的AP6212A0(WIFI+BT)V1.2
- linux tcp repair及tcp热迁移
- Angular开发(二十九)-angular中引入jq开发及angular正确开发姿势
- .奇数平方的一个有趣性质
- 【LeetCode】 Minimum Window Substring
- 《CLR via C#》读书笔记---11事件
- Cookie与Session的区别
- 来说说(Iterator)迭代器模式
- 产品日记:如何去做产品
- bootstrap 不得不说的sass