2个不稳定版本
0.2.0 | 2024年7月23日 |
---|---|
0.1.0 | 2023年7月24日 |
#28 在 Unix API
154 每月下载量
150KB
3K SLoC
vhost-device-vsock
设计
该软件包引入了一个vhost-device-vsock设备,该设备使虚拟机中的应用程序(即虚拟机内的应用程序)与主机上的应用程序(即虚拟机外的应用程序)之间能够通信。虚拟机中的应用程序通过VM套接字(即AF_VSOCK套接字)进行通信。主机上的应用程序连接到主机上的Unix套接字(即通过AF_UNIX套接字进行通信)。软件包的主要组件分为以下文件
- packet.rs
- 引入了表示单个vsock数据包处理方法的VsockPacket结构。
- rxops.rs
- 引入了各种vsock操作,这些操作被入队到rxqueue中,然后发送到虚拟机。公开了RxOps结构。
- rxqueue.rs
- rxqueue包含对应于该连接的挂起rx操作。队列表示为位图,因为我们处理面向连接的连接。该模块包含各种队列操作方法。公开了RxQueue结构。
- thread_backend.rs
- 在主机和客户机之间复用连接,并调用每个连接对应的方法来处理数据和数据包。公开了 VsockThreadBackend 结构。
- txbuf.rs
- 模块用于缓冲从客户机发送到主机的数据。该模块公开了 LocalTxBuf 结构。
- vhost_user_vsock_thread.rs
- 模块公开了 VhostUserVsockThread 结构。它还处理新的主机发起的连接,并为将主机连接注册到 epoll fd 提供接口。还提供了遍历 rx 和 tx 队列的接口。
- vsock_conn.rs
- 模块引入了代表客户机和主机之间单个 vsock 连接的 VsockConnection 结构。它还根据数据包类型处理数据包。
- vhu_vsock.rs
- 公开了主要的 vhost 用户 vsock 后端接口。
用法
运行 vhost-device-vsock 设备
vhost-device-vsock --guest-cid=<CID assigned to the guest> \
--socket=<path to the Unix socket to be created to communicate with the VMM via the vhost-user protocol> \
--uds-path=<path to the Unix socket to communicate with the guest via the virtio-vsock device> \
[--tx-buffer-size=<size of the buffer used for the TX virtqueue (guest->host packets)>] \
[--queue-size=<size of the vring queue>] \
[--groups=<list of group names to which the device belongs concatenated with '+' delimiter>]
或者
vhost-device-vsock --vm guest_cid=<CID assigned to the guest>,socket=<path to the Unix socket to be created to communicate with the VMM via the vhost-user protocol>,uds-path=<path to the Unix socket to communicate with the guest via the virtio-vsock device>[,tx-buffer-size=<size of the buffer used for the TX virtqueue (guest->host packets)>][,queue-size=<size of the vring queue>][,groups=<list of group names to which the device belongs concatenated with '+' delimiter>]
多次指定 --vm
参数以指定多个设备,例如
vhost-device-vsock \
--vm guest-cid=3,socket=/tmp/vhost3.socket,uds-path=/tmp/vm3.vsock,groups=group1+groupA \
--vm guest-cid=4,socket=/tmp/vhost4.socket,uds-path=/tmp/vm4.vsock,tx-buffer-size=32768,queue-size=256
或者使用配置文件
vhost-device-vsock --config=<path to the local yaml configuration file>
配置文件示例
vms:
- guest_cid: 3
socket: /tmp/vhost3.socket
uds_path: /tmp/vm3.sock
tx_buffer_size: 65536
queue_size: 1024
groups: group1+groupA
- guest_cid: 4
socket: /tmp/vhost4.socket
uds_path: /tmp/vm4.sock
tx_buffer_size: 32768
queue_size: 256
groups: group2+groupB
运行 VMM(例如 QEMU)
qemu-system-x86_64 \
<normal QEMU options> \
-object memory-backend-memfd,id=mem0,size=<Guest RAM size> \ # size == -m size
-machine <machine options>,memory-backend=mem0 \
-chardev socket,id=char0,reconnect=0,path=<vhost-user socket path> \
-device vhost-user-vsock-pci,chardev=char0
工作示例
shell1$ vhost-device-vsock --vm guest-cid=4,uds-path=/tmp/vm4.vsock,socket=/tmp/vhost4.socket
或者如果您想配置 TX 缓冲区大小和 vring 队列大小
shell1$ vhost-device-vsock --vm guest-cid=4,uds-path=/tmp/vm4.vsock,socket=/tmp/vhost4.socket,tx-buffer-size=65536,queue-size=1024
shell2$ qemu-system-x86_64 \
-drive file=vm.qcow2,format=qcow2,if=virtio -smp 2 \
-object memory-backend-memfd,id=mem0,size=512M \
-machine q35,accel=kvm,memory-backend=mem0 \
-chardev socket,id=char0,reconnect=0,path=/tmp/vhost4.socket \
-device vhost-user-vsock-pci,chardev=char0
客户机监听
iperf
# https://github.com/stefano-garzarella/iperf-vsock
guest$ iperf3 --vsock -s
host$ iperf3 --vsock -c /tmp/vm4.vsock
netcat
guest$ nc --vsock -l 1234
host$ nc -U /tmp/vm4.vsock
CONNECT 1234
主机监听
iperf
# https://github.com/stefano-garzarella/iperf-vsock
host$ iperf3 --vsock -s -B /tmp/vm4.vsock
guest$ iperf3 --vsock -c 2
netcat
host$ nc -l -U /tmp/vm4.vsock_1234
guest$ nc --vsock 2 1234
兄弟虚拟机通信
如果您添加了多个虚拟机,并且它们的设备配置了至少一个共同的组名,它们可以相互通信。如果您没有明确指定组名,将默认分配一个名为 default
的设备,并且所有此类设备都将能够相互通信。或者您可以为每个设备选择不同的组名列表,只有具有至少一个共同组的设备才能相互通信。
例如,如果您有两个 CID 为 3 和 4 的虚拟机,您可以运行以下命令来使它们通信
shell1$ vhost-device-vsock --vm guest-cid=3,uds-path=/tmp/vm3.vsock,socket=/tmp/vhost3.socket,groups=group1+group2 \
--vm guest-cid=4,uds-path=/tmp/vm4.vsock,socket=/tmp/vhost4.socket,groups=group1
shell2$ qemu-system-x86_64 \
-drive file=vm1.qcow2,format=qcow2,if=virtio -smp 2 \
-object memory-backend-memfd,id=mem0,size=512M \
-machine q35,accel=kvm,memory-backend=mem0 \
-chardev socket,id=char0,reconnect=0,path=/tmp/vhost3.socket \
-device vhost-user-vsock-pci,chardev=char0
shell3$ qemu-system-x86_64 \
-drive file=vm2.qcow2,format=qcow2,if=virtio -smp 2 \
-object memory-backend-memfd,id=mem0,size=512M \
-machine q35,accel=kvm,memory-backend=mem0 \
-chardev socket,id=char0,reconnect=0,path=/tmp/vhost4.socket \
-device vhost-user-vsock-pci,chardev=char0
请注意,这里指定 groups
参数只是为了清晰,但如果您想使用默认组并使所有设备相互通信,则不需要指定它。当您想对可以相互通信的设备有更精细的控制时,指定组列表很有用。
# nc-vsock patched to set `.svm_flags = VMADDR_FLAG_TO_HOST`
guest_cid3$ nc-vsock -l 1234
guest_cid4$ nc-vsock 3 1234
许可证
本项目许可协议为以下之一
- Apache 许可证,版本 2.0
- BSD-3-Clause 许可证
依赖项
~6.5MB
~121K SLoC