ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

[virtio](七):virtio-net、vhost-net 与数据面下沉

[virtio](七):virtio-net、vhost-net 与数据面下沉 第六篇用 virtio-blk 串起了一次块 I/O。本篇进入网络路径virtio-net 如何用 TX/RX virtqueue 交换数据包为什么基础 QEMU 网络路径会成为瓶颈vhost-net 又是如何把高频数据面下沉到 host kernel 的1. virtio-net 为什么更复杂virtio-net 和 virtio-blk 一样使用 virtqueue但网络设备的复杂度更高。原因包括收发方向同时高频packet buffer 长度变化大latency 和 throughput 都敏感支持 checksum offload、TSO、UFO、GSO 等能力支持 multiqueue有 control virtqueue后端可能是 tap、bridge、vhost、vhost-user 或用户态网络栈virtio-net 不只是把请求交给某个 backend。它还要处理网络包格式、offload 语义、队列分布、中断优化和 backend 协作。2. virtio-net 的基本队列virtio-net 通常至少有 TX 和 RX 两类队列。TX virtqueue: guest 发送 packet 给 host RX virtqueue: guest 提供 receive bufferhost 把 packet 写入 guest多队列场景下会有多组 TX/RX queue pair。简化模型queue pair 0: tx0, rx0 queue pair 1: tx1, rx1 control queue: configuration commandsTX 和 RX 的 descriptor 使用方式不同。TX 是 guest 把 packet 内容放进 descriptordevice 读取。RX 是 guest 先提供空 bufferdevice 收到 host packet 后写入。3. TX 路径Guest 发送网络包时路径大致是Guest application sends data | v Guest TCP/IP stack | v virtio-net driver | | fill TX descriptor chain v tx virtqueue | | kick v QEMU virtio-net / vhost backend | v tap / socket / host network在 descriptor chain 中通常包含virtio-net header packet data buffersvirtio-net header 用来表达 offload 相关信息例如 checksum、GSO 类型等。QEMU 或 vhost backend 需要根据 negotiated features 正确解释这些字段。4. RX 路径接收路径方向相反。Guest driver 需要提前把 receive buffers 放到 RX virtqueue。路径是Guest virtio-net driver | | add empty RX buffers v rx virtqueue | v host network receives packet | v QEMU / vhost backend writes packet into RX buffer | v used ring interrupt | v Guest network stack receives packet这点和块设备不同。RX 没有 guest 主动发起一个“读请求”那么直观。Guest 是提前提供 bufferdevice 在 packet 到来后填充。如果 guest 没有及时补充 RX bufferhost packet 可能被丢弃或延迟。5. QEMU 基础网络路径不使用 vhost 时QEMU virtio-net device model 负责处理 virtqueue。发送路径Guest TX virtqueue | v QEMU virtio-net | v QEMU net client | v tap / socket / user network接收路径host network backend | v QEMU net client | v QEMU virtio-net | v Guest RX virtqueue这条路径语义清楚但高吞吐时开销明显。开销来源包括QEMU 主循环调度virtqueue descriptor 解析eventfd 和中断处理数据复制或映射host kernel 与 QEMU 用户态切换packet batching 不足6. 为什么需要 vhost-netvhost-net 的目标是把高频网络数据面从 QEMU 用户态下沉到 host kernel。基础 QEMU 路径Guest virtio-net driver | v virtqueue in guest RAM | v QEMU virtio-net device model | v tap / host networkvhost-net 路径Guest virtio-net driver | v virtqueue in guest RAM | v vhost-net kernel backend | v tap / host network stack这样可以减少 QEMU 主循环参与让 host kernel 直接处理部分 virtqueue 数据面。7. QEMU 如何把数据面交给 vhostvhost-net 并不是自动知道 guest virtqueue 在哪里。QEMU 需要把一组信息交给 vhost backendguest memory regionsvring descriptor addressavail ring addressused ring addressqueue sizekick eventfdcall eventfdbackend fd例如 tap fdnegotiated features简化流程QEMU creates virtio-net device | v Guest configures virtqueues | v QEMU sets up vhost backend | v QEMU passes memory and vring info to vhost | v vhost handles TX/RX data plane这就是“QEMU 控制面vhost 数据面”的典型结构。8. QEMU 控制面还保留什么使用 vhost-net 后QEMU 仍然保留大量控制面状态。包括virtio device statusfeature negotiationconfig spaceMAC addresslink statusqueue enable statemultiqueue configurationcontrol virtqueuemigration coordinationbackend lifecyclereset handlingvhost-net 负责高频 packet 数据面但不会替代 QEMU 作为虚拟设备所有者。这点非常重要。如果认为“用了 vhost 就绕过 QEMU”会误解迁移、reset、feature 和设备配置路径。9. control virtqueuevirtio-net 还有 control virtqueue用于处理一些控制命令。例如MAC filterVLAN filterpromiscuous modemultiqueue configurationoffload configuration这些控制命令不一定走 vhost 数据面。很多情况下QEMU 仍然要处理 control queue 或协调 backend。这再次说明 QEMU 不是单纯的数据搬运者它维护的是设备语义和管理状态。10. multiqueue 与性能virtio-net multiqueue 允许多个 queue pair 并行处理网络包。简化模型vCPU0 - tx0/rx0 vCPU1 - tx1/rx1 vCPU2 - tx2/rx2 vCPU3 - tx3/rx3好处提高并发吞吐减少单队列锁竞争配合 RSS / 多核处理提高 vhost 数据面并行度代价队列配置更复杂中断和 CPU 亲和性更重要迁移状态更多调试路径更分散多队列性能不仅取决于 virtio-net还取决于 host scheduler、vCPU pinning、tap、vhost worker 和中断分布。11. packet completion 与中断TX completion 表示 host 已经处理了 guest 提交的 packet bufferguest 可以回收 buffer。RX completion 表示 host 已经把收到的 packet 写入 guest bufferguest 应该交给网络栈处理。路径类似backend processes packet | v write used ring | v signal call eventfd / inject interrupt | v Guest virtio-net interrupt handler通知策略会显著影响性能。高吞吐场景常常需要 batching 和 interrupt moderation。低延迟场景则需要控制批量带来的等待时间。12. 迁移对 virtio-net 的挑战virtio-net 迁移比 virtio-blk 更麻烦。需要考虑TX/RX queue indexpending packetsoffload featuresMAC/link statecontrol queue statevhost backend statein-flight descriptorsbackend 是否支持迁移如果迁移时一个 packet 已经进入 backend 但还没完成QEMU 和 vhost 需要协调避免 target 上丢包、重复完成或 queue 状态错乱。这也是 vhost 提升性能同时增加系统复杂度的典型例子。13. 源码阅读入口本篇可以看hw/net/virtio-net.cinclude/hw/virtio/virtio-net.hinclude/standard-headers/linux/virtio_net.hhw/virtio/vhost.cnet/Linuxdrivers/net/virtio_net.c阅读问题virtio-net TX/RX queue 在哪里初始化TX descriptor chain 如何解析成 packetRX buffer 如何补充和消耗control virtqueue 处理哪些命令vhost-net 在哪里启动和停止QEMU 传给 vhost 的 memory 和 vring 信息有哪些completion interrupt 如何触发14. 本篇小结virtio-net 使用 TX/RX virtqueue 交换网络包。基础 QEMU 路径由 QEMU virtio-net device model 处理数据面语义清晰但高吞吐下开销较高。vhost-net 把高频数据面下沉到 host kernel减少 QEMU 主循环和用户态往返但 QEMU 仍然保留控制面、设备状态和迁移编排。可以把本篇压缩成一句话virtio-net 的性能关键在于把 packet 数据面从 QEMU 控制面中分离出来vhost-net 负责快路径QEMU 负责设备语义、配置和迁移。15. 下一篇预告vhost-user 与独立用户态数据面下一篇讨论 vhost-user。会回答vhost-user 和 vhost-kernel 有什么区别QEMU 如何通过 Unix socket 和 backend 通信为什么 DPDK 场景常用 vhost-uservhost-user 给迁移和故障恢复带来什么复杂度下一篇的问题可以写成如果数据面不在 QEMU也不在 host kernel而是在另一个用户态进程里virtio 路径会变成什么样
返回列表