Hotdry.
systems-engineering

Linux VSOCK:绕过TCP/IP栈的VM-主机高速通信与Virtio传输调优

基于AF_VSOCK与virtio传输绕过TCP/IP栈,实现VM-主机低延迟高吞吐通信,提供工程化socket API使用与性能调优参数。

在虚拟化环境中,VM 与主机间的通信往往受限于 TCP/IP 栈的开销,包括协议处理、上下文切换和内存拷贝,导致延迟升高、吞吐受限。Linux VSOCK(AF_VSOCK 地址族)通过 virtio-vsock 传输机制,直接利用共享内存和 virtqueue 实现零拷贝通信,完全绕过网络栈,提供微秒级延迟和 Gbps 级吞吐,适用于 KVM/QEMU 场景下的 guest-agent、日志传输或实时控制平面。

VSOCK 的核心是标准 socket API,但寻址使用 32 位 CID(Context ID)和端口:主机 CID 固定为 2,VM CID 由 hypervisor 分配(如 QEMU 的 guest-cid=3)。支持 SOCK_STREAM(可靠流)和 SOCK_DGRAM(数据报)。创建 socket:socket(AF_VSOCK, SOCK_STREAM, 0)。地址结构struct sockaddr_vm { sa_family_t svm_family; unsigned short svm_reserved1; unsigned int svm_port; unsigned int svm_cid; ... },端口 < 1024 需 CAP_NET_BIND_SERVICE 权限。

工程化使用从配置开始。宿主机加载modprobe vhost_vsock,生成/dev/vhost-vsock/dev/vsock。QEMU 启动 VM 添加-device vhost-vsock-pci,guest-cid=3,或 libvirt XML 中<vsock model='virtio'><cid auto='yes'/></vsock>自动分配 CID。客机内核需 CONFIG_VIRTIO_VSOCKETS=m。CID 查询:ioctl(fd, IOCTL_VM_SOCKETS_GET_LOCAL_CID, &cid)

主机监听示例(C):

#include <sys/socket.h>
#include <linux/vm_sockets.h>
#include <stdio.h>
#include <string.h>

int main() {
    int s = socket(AF_VSOCK, SOCK_STREAM, 0);
    struct sockaddr_vm addr = { .svm_family = AF_VSOCK, .svm_port = 9999, .svm_cid = VMADDR_CID_ANY };
    bind(s, (struct sockaddr*)&addr, sizeof(addr));
    listen(s, 0);
    struct sockaddr_vm peer;
    socklen_t len = sizeof(peer);
    int fd = accept(s, (struct sockaddr*)&peer, &len);
    char buf[1024];
    recv(fd, buf, sizeof(buf), 0);
    printf("Received from CID %u\n", peer.svm_cid);
    close(fd); close(s);
    return 0;
}

VM 客户端连接主机:addr.svm_cid = VMADDR_CID_HOST (2)connect()发送数据。Python 示例类似,使用socket.AF_VSOCK

性能测试显示,VSOCK 在 iperf-vsock 基准下客到主方向达 10Gbps,延迟微秒级,远超 TCP 桥接(受 NAT / 桥接开销影响)。“vsock 提供了一种 socket family:AF_VSOCK,提供 connect/bind/send 等标准操作,但依赖 virtio-vsock 设备绕过协议栈。” 相比 virtio-serial(串口模拟,中断多、单队列),VSOCK 支持多队列、零拷贝。

调优参数清单:

  1. 队列深度:QEMU -device vhost-vsock-pci,guest-cid=3,queues=8,匹配 vCPU 数,提升并发(默认 1)。
  2. 缓冲区:sysctl net.core.rmem_max=16777216 net.core.wmem_max=16777216,增大 socket 缓冲(默认 212992B)。
  3. 中断合并:ethtool-like,但 VSOCK 用irqbalance或 CPU 亲和:taskset -c 0-7 qemu-kvm,绑定中断核心。
  4. 零拷贝启用:内核 vhost_vsock 默认支持,监控/proc/net/vsock统计丢包。
  5. 监控点ss -l -n -p | grep vsock查看连接;perf stat -e cycles,instructions iperf-vsock测 CPU;阈值:丢包 > 1% 调大缓冲,延迟 > 10us 查队列。
  6. 回滚策略:测试负载下 fallback TCP,参数net.ipv4.tcp_rmem="4096 87380 16777216"

风险:实时迁移断开 STREAM 连接,应用需重连逻辑;CID 冲突用 auto 分配;嵌套 VM 需 multi-transport(Linux 5.5+)。安全:CID 隔离防扫描,但勿暴露特权端口。

落地清单:

  • 内核检查:grep -i vsock /boot/config-$(uname -r)
  • 基准脚本:用 nc-vsock(github.com/stefanha/nc-vsock)测吞吐。
  • 高负载:多线程 send/recv,调SO_SNDBUF/RECVBUF至 64MB。

VSOCK 工程化显著降低 VM - 主机通信开销,适用于云原生控制平面或 Kata Containers 嵌套场景。通过上述参数,生产环境可稳定 10Gbps + 吞吐、<5us 延迟。

资料来源

  • man vsock(7): man7.org/linux/man-pages/man7/vsock.7.html
  • QEMU virtio-vsock: wiki.qemu.org/Features/VirtioVsock
  • Benchmarks: stefano-garzarella.github.io/posts/2019-11-08-kvmforum-2019-vsock/
  • Kernel docs: git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/vm_sockets.h

(正文约 1250 字)

查看归档