介绍
关于usbredir client功能的描述,可以参考文档《usbredir client 功能说明书》,这个文档,分析了在不同操作系统平台,如何实现这个功能。
跨平台支持
基于不同操作系统平台Windows和Linux,对于支持分门别类众多的usb外设,重定向都会用到libusb这个库来访问usb设备,也可以说重定向usb设备的驱动程序是基于libusb实现的。在仔细分析阅读了libusb代码后,发现其在windows下,没有实现“Win-USB-like APIs”中这类(Isochronous)usb报文的传输接口,因此某些设备如摄像头、打印机就无法正常工作,所以,在windows平台,usbredir client暂时不支持。另外,在linux平台,我们的设计实现基于Ubuntu>=12.04。
参考文档及术语
VDI | Virtual Device Interfaces |
Usb redirection | The protocol redirection USB traffic from a single USB device, to a different (virtual) machine then the one to which the USB device is attached |
Usbredir client | Usb redirection host side functionality execution |
Libusb | A library for USB device access from Linux, windows user space |
Spicec | VDI protocol |
XfreeRdp | VDI protocol |
|
|
基础架构
Usb 重定向协议规范中,包括源主机(usb-host)和目的主机(usb-guest)两端,源端和目的端通过网络连接,通信基于可靠的TCP传输。源端设备应是装了usbredir client的PC、瘦终端,目的端是基于Qemu/KVM的虚拟机。
Figure-1,usbredir client重定向usb报文到虚拟机usbredir设备,这个虚拟的usbredir设备就是根据被重定向的物理usb设备各种配置信息虚拟化出来的,在虚拟机里看到的设备就如同物理设备本身,安装了这个设备的物理驱动后,就可以正常操作设备了。
Figure - 1
虚拟机配置
虚拟的usbredir设备,可以在虚拟机启动时就创建,或者运行时动态创建。动态创建虽然在资源管理上比较优越,但是,为了做到动态管理,需要能获得和处理usb设备的动态状态,这些个状态是需通过usbredir client封装并传输到虚拟机,额外增加了程序的复杂度。参考spice支持usb重定向,为每个虚拟机静态配置了4个usbredir虚拟设备,虚拟机的XML文件增加下面的配置项:
<redirdevbus=’usb’ type=’tcp’>
<source mode=’bind’ host=’0.0.0.0’ service=’8000’/>
</redirdev>
<redirdev bus=’usb’ type=’tcp’>
<source mode=’bind’ host=’192.168.7.253’service=’8001’/>
</redirdev>
<redirdev bus=’usb’ type=’tcp’>
<source mode=’bind’ host=’0.0.0.0’service=’8002’/>
</redirdev>
<redirdev bus=’usb’ type=’tcp’>
<source mode=’bind’ host=’0.0.0.0’service=’8003’/>
</redirdev>
其中,mode配置项的值’bind’,表示它是提供服务给其他请求者的,认为是server角色,与它相反的配置就是’connect’,认为是client角色。
host配置项的值如’0.0.0.0’,是对外服务的IP地址,这个地址可以有两种形式,unicast地址或者anycast地址,unicast地址一般就是虚拟机所在的服务器的物理IP地址,如果指定了该IP地址,就只接受该网络接口来的请求。Anycast地址表示不受地址的限制,只要是usbredir的请求,都可以接受。
service配置的值如’8000’,这个数字8000就是服务端口,后面会有讲到usbredir client在建立连接重定向设备时会用到该端口。
Bus配置项的值’usb’和type配置项的值’tcp’,顾名思义,代表这个重定向设备是基于usb总线的,网络传输层面是基于TCP这个面向连接的可靠传输协议的,而不是UDP,所以程序员就不需要关心usbredir traffic是否会丢包、延时,网络拥塞之类的问题。
usbredir client模块架构
usbredir client在系统中是一个独立的程序,设计成多线程模式,它主要依赖于下面的几个共享库:libusbreirhost.so、libusbredirparser.so、libusb-1.0.so、libpthread.so、libc.so。如图Figure-2,示例说明了这几个功能模块在系统层面的关系。
Figure – 2
是否启用usb设备重定向由用户来控制,在usb设备重定向“打开”,usbredir client进程就会被创建,否则,usbredir client会释放资源,进程会退出。
Figure – 3
Figure – 3,示例说明了usbredir client几个线程的相关关系。
usb外设监控(monitor)线程
usbredir client缺省会创建一个线程monitor,该线程实时监控是否有usb设备插入或者拔出,它通过raw socket接受到插拔的事件消息后,分别做后续的处理。
创建socket,以及绑定地址的函数示例如下:
Filtering
对于分门别类的usb外设,哪类设备哪个设备应被重定向,或者不被重定向,都由设定的filters决定。Filters的规则参考文档《usbredir client 功能说明书》,系统缺省不重定向usb外设,需要被重定向某类设备如usb打印机或者某个设备根据规则添加到rule。规则保存在这个文件:“/etc/usbredir_rules”,文件缺省的内容如下:
这个文件的内容更新后,usbredir client需重启后才会使更新生效。下面的函数是根据设定的规则来检查某个usb设备是否允许被重定向的。
usb事件处理线程event
usbredir client创建、删除事件处理线程,同时也维护着这些线程的管理信息,线程的管理结构如下:
其中:
pthread_id,在创建线程成功后,就可以获得该值。
port,在“虚拟机配置”章节,提到了系统默认会创建的4个虚拟机的服务端口,这几个端口系统会预留,统一用port pool管理,用来分配或者回收。
serverip,虚拟机所在的Host的IP地址,而不是虚拟机本身IP地址。
vendor_id,被重定向的usb设备的产商ID。
product_id,被重定向的usb设备的产品ID。
sockfd,与usb guest通信的网络套接字。
host,usbredir协议host控制结构。
status,线程的运行状态,在usb设备拔出后,设定这个状态,事件线程释放资源,自动退出。
mutex,互斥信号量。
usbredir client的控制结构
usbredir client管理状态服务控制结构如下:
其中:
libusb_ctx,libusb控制用于访问物理usb设备。
rules,外设重定向过滤规则。
port,服务端口池。
源代码
https://github.com/basenlv/usbredir-client,转载文档内容和代码请说明出处。
(另寻windows平台,具备丰富usb 设备驱动开发者,共同实现跨平台usb redirection)
测试用例
测试usbredir cient是否工作,可以用下面的测试程序:
usbredir-client[-p|--portlist <port1:port2> [-s|--server <serverip>]