本文首发于我的公众号码农之屋(id: Spider1818),专注于干货分享,包含但不限于Java编程、网络技术、Linux内核及实操、容器技术等。欢迎大家关注,二维码文末可以扫。
导读:SR-IOV(Single Root I/O Virtualization)是一个将PCIe设备(如网卡)共享给虚拟机的标准,通过为虚拟机提供独立的内存空间、中断、DMA流,来绕过VMM实现数据访问。
0、前言
网络I/O虚拟化是服务器虚拟化技术的重要组成部分,在服务器虚拟化技术领域,计算虚拟化(如CPU和内存虚拟化)已经日趋成熟,但是网络I/O虚拟化技术的发展相对比较滞后。
当前主流的网络I/O虚拟化技术有3种:软件模拟、网卡直通和SR-IOV,这3种虚拟化技术在不同程度上实现了网络I/O设备的虚拟化功能。软件模拟是通过Hypervisor层模拟虚拟网卡,实现与物理设备完全一样的接口,虚拟机操作系统无须修改就能直接驱动虚拟网卡,其最大的缺点是性能相对较差;网卡直通支持虚拟机绕过Hypervisor层,直接访问物理I/O设备,具有最高的性能,但是在同一时刻物理I/O设备只能被一个虚拟机独享;SR-IOV是Intel在2007年提出的解决虚拟化网络I/O的硬件技术方案,该技术不仅能够继承网卡直通的高性能优势,而且同时支持物理I/O设备的跨虚拟机共享,具有较好的应用前景。
一、SR-IOV简介
SR-IOV(Single Root I/O Virtualization)是一个将PCIe设备(如网卡)共享给虚拟机的标准,通过为虚拟机提供独立的内存空间、中断、DMA流,来绕过VMM实现数据访问。
SR-IOV引入了两种PCIe functions:
PF(Physical Function):包含完整的PCIe功能,包括SR-IOV的扩张能力,该功能用于SR-IOV的配置和管理。
VF(Virtual Function):包含轻量级的PCIe功能。每一个VF有它自己独享的PCI配置区域,并且可能与其他VF共享着同一个物理资源。
一旦在PF中启用了SR-IOV,就可以通过PF的总线、设备和功能编号访问各个VF的PCIe配置空间。每个VF都具有一个PCIe内存空间,用于映射其寄存器集。VF设备驱动程序对寄存器集进行操作以启用其功能,并且显示为实际存在的PCIe设备。创建VF后,可以直接将其指定给I/O来宾域或各个应用程序。此功能使得虚拟功能可以共享物理设备,并在没有CPU和虚拟机管理程序软件开销的情况下执行I/O。
由此可见,SR-IOV网卡通过将SR-IOV功能集成到物理网卡上,将单一的物理网卡虚拟成多个VF接口,每个VF接口都有单独的虚拟PCIe通道,这些虚拟的PCIe通道共用物理网卡的PCIe通道。每个虚拟机可占用一个或多个VF接口,这样虚拟机就可以直接访问自己的VF接口,而不需要Hypervisor的协调干预,从而大幅提升网络吞吐性能。
二、SR-IOV要求
SR-IOV需要硬件设备的支持,具体的要求,请参考以下描述。
CPU必须支持IOMMU(比如英特尔的VT-d或者AMD的AMD-Vi,Power8处理器默认支持IOMMU)
固件Firmware必须支持IOMMU
CPU根桥必须支持ACS或者ACS等价特性
PCIe设备必须支持ACS或者ACS等价特性
建议根桥和PCIe设备中间的所有PCIe交换设备都支持ACS,如果某个PCIe交换设备不支持ACS,其后的所有PCIe设备只能共享某个IOMMU组,所以只能分配给1台虚机
三、SR-IOV + DPDK使用示例
1、以Intel CPU为例,给VM所在的Host打开IOMMU以及SR-IOV。
# Step 1:修改/etc/default/grub,对每个PF,打开4个VF
>> GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on ixgbe.max_vfs=4"
# Step 2:更新grub配置并重启物理机
>> update-grub && reb
2、重启之后,使用“lspci | grep -i ether”或“ip link show”,查看是否配置成功。以下是使用“ip link show”查看的结果,表示已配置成功。
3、使用“ifconfig”将所有的PF的状态调为“UP”(VF正常工作的前提是对应的PF必须处于UP状态)
4、使用“ip link set”为所有VF配置MAC地址(默认全为0)
>> ip link set vf mac
备注:可通过“ip linkset”查看其余可配置项(其余配置可选),开启spoof checking后,会进行MAC地址检查,如果发现VF要发送的数据包MAC地址不是本身的MAC地址,将会被丢弃。
到这一步,已经可以在Host上使用VF进行收发包了(将VF对应的interfaceUP起来即可)。接下来将配置DPDK + SR-IOV。
5、此示例使用的虚拟软件是qemu-kvm,首先在启动VM时,需要设置qemu-kvm的启动参数,将VF passthrough到VM。
>> qemu-system-x86_64 -enable-kvm -drive file=,if=virtio -cpu host -smp 16 -m 16G -name -device vfio-pci,host= -device vfio-pci,host= -vnc :1 -net none
重点在于通过-devicevfio-pci,host=将VF passthrough到虚拟机,这样VM就可以直接使用VF了。
6、VM启动后,ifconfig -a可以看到passthrough的VFs,将对应VF的interface绑定到DPDK提供的igb_uio驱动就可以在虚拟机中通过DPDK使用VF收发包了。
我的公众号「码农之屋」(id: Spider1818) ,分享的内容包括但不限于 Linux、网络、云计算虚拟化、容器Docker、OpenStack、Kubernetes、SDN、OVS、DPDK、Go、Python、C/C++编程技术等内容,欢迎大家关注。