[usb][tcp]usbredir的优化---TCP keepalive

Posted AlwaysGeek

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[usb][tcp]usbredir的优化---TCP keepalive相关的知识,希望对你有一定的参考价值。

前言:
前文《[kvm][qemu]影响虚拟化热迁移的设备》中提到了usbredir技术,也顺便提到了对它的TCP keepalive的优化。
本文分析usbredir的实现,以及这个优化的作用。

分析:
1,usbredir
功能上来说,usbredir通过TCP让usb设备直通访问实现了跨主机
upstream的代码在https://cgit.freedesktop.org/spice/usbredir。

为了方便显示,作者删掉了部分逻辑。从上图来看:
a,使用accept接受连接,client_fd就是要处理的客户端。
b,使用libusb根据vendorid:prodid或者busnum-devnum打开相应的usb设备,得到handle。
c,注册处理函数usbredirserver_read和usbredirserver_write。
d,开始接受处理run_main_loop()。
e,如果main loop退出,则关闭handle,接受下一个连接
通过上面的逻辑,我们看到:
A,一个usbredirserver只能处理一个usb设备(vendorid:prodid或者busnum-devnum)。
B,accept之后,就进入了main loop处理,不再accept新的连接,保证了设备不能被多个连接(在虚拟化场景下,就是多个vm)使用
综上,基本满足了虚拟化的跨主机访问usb设备的使用场景。

2,idle connection
usbredirserver的逻辑中,同时只能保持一个连接可服务。那么,如果这个这个连接意外断开了呢?
如果vm0当前运行在host0上,host0崩溃,或者panic,或者网络断开,那么usbredirserver在没有收到FIN信号的情况下,还是维持一个ESTABLISHED连接。
这个ESTABLISHED连接什么会被发现是idle connection呢?依赖于OS的TCP参数:
/proc/sys/net/ipv4/tcp_keepalive_time
(integer; default: 7200; since Linux 2.2)
              The  number  of  seconds  a  connection  needs  to be idle before TCP begins sending out keep-alive probes.  Keep-alives are sent only when the SO_KEEPALIVE socket option  is  enabled.   The  default value  is  7200  seconds  (2 hours).  An idle connection is terminated after approximately an additional 11 minutes (9 probes an interval of 75 seconds apart) when keep-alive is enabled.

/proc/sys/net/ipv4/tcp_keepalive_intvl
(integer; default: 75; since Linux 2.4)
              The number of seconds between TCP keep-alive probes.

/proc/sys/net/ipv4/tcp_keepalive_probes
(integer; default: 9; since Linux 2.2)
              The maximum number of TCP keep-alive probes to send before giving up and killing the connection  if no response is obtained from the other end.

在默认参数情况下,usbredirserver如果想要发现这个idle connection需要的时间:
tcp_keepalive_time + tcp_keepalive_intvl × tcp_keepalive_probes = 7200 + 75 × 9 = 7875

继续刚刚host0崩溃,那么会在启用HA,在hostN上启动vm0。此时,vm0重新连接usbredir server。在回顾一下第1节中的usbredir server为了保证usb设备是独享的,只使用一个连接的情况,那么,HA之后的vm0将在两个多小时里面不能继续使用这个usb设备

3,tcp keepalive
为了解决上述问题,作者和usbredir的maintainer之间mail几个回合(https://www.mail-archive.com/spice-devel@lists.freedesktop.org/msg42152.html),最终的方案是:
a,tcp_keepalive_time从进程启动的cmdline中获取,如果获取到,并且大于0,则启用keepalive,如果用户没有传递参数,则不启动keepalive,和原来的逻辑一致。
b,tcp_keepalive_intvl是10s,tcp_keepalive_probes是3。
如果用户使用的参数—keepalive 30,则发现idle connection的时间就是30 + 10 × 3 = 60。
patch(https://cgit.freedesktop.org/spice/usbredir/patch/?id=aca0e87db16da1837e07cb52f160f61999745e84)已经merge到了upstream。


以上是关于[usb][tcp]usbredir的优化---TCP keepalive的主要内容,如果未能解决你的问题,请参考以下文章

内核优化

linux 内核优化参数

生产环境下Linux内核参数优化案例代码

centos7 web服务器内核优化

ADB over TCP/IP 在没有连接 USB 电缆的情况下无法工作

libusb 未列出的 USB/IP 仿真设备