01
简介
网络功能虚拟化(NFV)是一种将传统上在专有硬件上运行的网络服务虚拟化的方式。这些服务通常被打包为部署在标准服务器上的虚拟机(VM),称为虚拟化网络功能(VNF)。由于性能是VNF的关键要求,因此往往使用设备直通的方式将整个网络设备专门分配给在虚拟机内运行的客户操作系统,以实现接近原生设备的性能和隔离的安全性。
在云原生时代,微服务和容器在生产环境中得到了广泛的应用。在容器中,只有操作系统被虚拟化,而不是像虚拟机那样虚拟化底层硬件。与虚拟机相比,容器提供了更大的灵活性、更精细的粒度和更少的开销。因此,将网络功能放在容器中运行的云原生网络功能(CNF),成为了VNF的继任者。
当下,容器正在成为在边缘部署服务的一种典型方式。然而,容器的启动延迟会极大地限制短任务的效率,而越来越多的边缘工作负载被归类为需要快速响应的短任务[1]。对于这些工作负载,减少容器启动时间变得越来越重要。尽管业界已经探索了大量减少容器启动延迟的方法[2],但仍有一些设备层面的开销对启动时间的影响需要解决。
本文介绍了如何使用英特尔可扩展I/O虚拟化(Intel Scalable IOV)的平台和网络设备来减少云原生网络功能在直通模式下的启动时间。通过搭建测试环境,测试结果证明Intel Scalable IOV可以显著缩短启动时间。
这篇文章适用于通信服务提供商或任何希望改进其云原生网络功能的用户。尽管本文的目标是展示在云原生网络功能环境中减少启动时间,但这里使用的技术可以作为任何容器或网络部署中减少启动时间的参考。
作者: 曹亚辉 吴菁菁 等
02
概论
本章简要介绍了用于NFV的SR-IOV解决方案,以及它是如何将延迟引入网络功能启动时间的。然后,从每个组件的角度详细描述了如何启用Intel Scalable IOV。此外,还详细分析了Intel Scalable IOV如何减少网络功能启动时间。最后,给出了测试搭建步骤,结果表明在容器运行环境中,网络功能的启动时间明显缩短。
虽然本文解释了如何通过Intel Scalable IOV减少CNF启动时间,但本文中演示的系统设置和技术运用,可以作为任何试图改善直通设备容器启动时间的用户的参考指南。
2.1 应对的挑战
SR-IOV广泛用于NFV,是一种允许一个PCIe设备呈现多个独立的物理PCIe设备的规范。SR-IOV通过引入物理功能(PFs)和虚拟功能(VFs)的概念来工作。PF是功能齐全的PCIe功能,可以完全控制整个PCIe设备,而VF对PCIe设备的控制有限。在NFV中,PF通常被分配给NFV基础设施,用于控制平面管理,而VF则被分配给VNF,作为虚拟机内的PCI直通设备,提供接近原生设备的性能和硬件隔离。
通常情况下,设备启动包括通用设备初始化阶段和厂商特定初始化阶段。对于SR-IOV VF中的厂商特定初始化,大部分启动延迟是由PF和VF之间的通信引起的。已经有一些针对PF-VF通信的优化。对于通用PCIe设备初始化SR-IOV VF,设备必须严格遵循PCIe规范定义的初始化程序。这导致了CNF在SRIOV VF直通时,有明显的启动延迟。
在本文中,我们提出了自己的解决方案,通过消除SR-IOV中严格的初始化时序(如设备重置)来减少CNF在直通设备上的启动时间。由于驱动程序探测的设备是一个虚拟设备(VDEV),它是由Intel Scalable IOV中的软件模拟的。它不再需要遵循PCIe规范要求的时序流程,并允许从软件的角度进行更灵活的初始化优化。
2.2 技术描述
Intel Scalable IOV是一种可扩展且灵活的硬件辅助I/O虚拟化方法,建立在现有PCI Express功能的基础上,使其能够轻松得到符合PCI Express Endpoint设计和软件生态系统的支持[3]。Intel Scalable IOV定义了一种方法,可以将大量多路复用设备接口以精细的粒度分配给隔离的域。该体系结构将设备共享的粒度定义为可分配设备接口(ADI)。设备功能上的所有ADI使用与设备的PCIe功能对应的相同PCIe Requester ID(总线/设备/功能编号)。进程地址空间标识符(PASID)用于区分针对不同ADI执行的upstream memory transaction,并传达给对应的地址空间。
在CNF中为网络设备启用Intel Scalable IOV,需要以下硬件和软件组件:
• 第 4 代英特尔至强可扩展处理器
• 系统软件和协议栈
• 英特尔800系列网卡和设备驱动程序
• DPDK用户空间库和网络驱动程序
在Intel Scalable IOV框架中,应用程序和VDEV之间的访问被定义为“data path”或“control path”(图1):
1. VDEV上的data path操作直接映射到底层ADI硬件以提高性能。在这种情况下,DPDK Intel Adaptive Virtual Function(IAVF)轮询模式驱动程序(PMD)分配的内存可以由英特尔 800系列网卡直接读取/写入。data path通常是从英特尔800系列网卡发送的带有PASID前缀的PCIe upstream memory transaction,通过支持可扩展模式的IOMMU,直接进入用户空间DPDK进程内存。
2. control path 操作由虚拟设备构造模块(VDCM)模拟,以获得更大的灵活性。在VDCM的辅助下,ADI被组成为VDEV并分配给用户空间。每当用户空间应用程序访问control path内的某些VDEV区域(例如PCIe CSR/BAR)时,根据当前实现,通过VFIO驱动程序框架和VFIO枚举设备(VFIO MDEV)进行路由,访问就会被VDCM捕捉。
由于Intel Scalable IOV利用硬件扩展data path,并为control path组成设备,因此它为高密度实例需求提供了出色的可扩展性,同时为control path保持了极大的灵活性。
图1 Intel Scalable IOV体系结构
2.2.1 第 4 代英特尔至强可扩展处理器
Intel Scalable IOV依赖于可扩展模式地址转换,Intel VT-d从3.0版本起引入了此功能。第4代英特尔至强可扩展处理器是首批实现Intel VT-d 3.0的处理器之一,它增加了对DMA重映射的可扩展模式转换的支持,并启用PASID细粒度转换功能。
2.2.2 系统软件和协议栈
要在第4代英特尔至强可扩展处理器上启用可扩展模式,英特尔 IOMMU驱动程序必须支持Intel VT-d 3.0/Scalable Mode。英特尔在Linux内核5.2上提供了可扩展模式IOMMU驱动程序支持。
为了将ADI传递到用户空间并将其组成VDEV,VFIO[4]/MDEV[5]框架将资源集合专用于VM或容器。英特尔在Linux内核5.11上为ADI提供了上游VFIO/MDEV支持。
本文中提到的所有软件默认情况下都运行在Linux操作系统中。
2.2.3 英特尔800系列网卡和设备驱动程序
英特尔 800系列网卡是一款100 Gbps网卡,旨在优化包括NFV在内的网络工作负载。为了在data path上支持Intel Scalable IOV,英特尔800系列网卡支持PASID PCIe功能,因此每个ADI的PCIe upstream memory transaction都可以通过指定的PASID值进行区分。与transaction相关的20位PASID通过英特尔800系列网络网卡上的PCI Express PASID TLP前缀传输,实现PASID细粒度地址转换。
为了在control path上支持Intel Scalable IOV,需要VDCM将ADI组成VDEV。为了实现基于VFIO中介框架的VDCM,通过回调函数注册MDEV操作来进行设备仿真和管理。当前的VDCM实现被封装为设备驱动程序的一部分。
2.2.4 DPDK
DPDK是一个开源软件项目,由用于加速在各种CPU架构上运行的数据包处理工作负载的库组成。DPDK通过使用VFIO框架提供接近原生设备的性能和硬件级别的隔离,为SR-IOV VF直通设备提供了成熟的支持。在初始化阶段,DPDK将扫描Linux PCI总线,并探测设备是否已与vfio PCI驱动程序绑定,这意味着设备处于直通模式。检测包括两个阶段:如上所述的通用PCIe设备初始化和厂商特定初始化。
英特尔推出了一个RFC版本的MDEV总线补丁[6],以支持DPDK上的Intel Scalable IOV初始化。这个补丁主要是用来扫描Linux MDEV总线,如果是作为PCI设备组成的,就像普通PCI设备一样探测设备。为了支持通过ADI,大部分英特尔以太网AVF轮询模式驱动程序(PMD)代码经过一些小的修改后被重新使用。
2.2.5 Mediated 设备生命周期
由于设备实际上是由Intel Scalable IOV中的VDCM模拟的,因此MDEV的生命周期由软件管理。
Mediated设备的典型生命周期如图2所示。
1. 管理员加载英特尔800系列网卡设备驱动程序,VDCM作为驱动程序的一部分注册VFIO Mediated设备(MDEV)。
2. 管理员通过在文件系统条目中写入一些通用唯一标识符(UUID)来创建MDEV,设备驱动程序将为此MDEV分配ADI:
echo "83b8f4f2-509f-382f-3c1e-e6bfe0fa1002" > /sys/class/mdev_bus/0000:XX:XX.X/mdev_supported_types/icevdcm/create
3. 当DPDK进程启动时,EAL将探测MDEV。然后,PASID值由设备驱动程序请求并由IOMMU驱动程序分配。初始化成功后,EAL打开MDEV并执行常规设备初始化。常规设备初始化成功后,将加载IAVF PMD,并开始设备特定的初始化。
4. DPDK进程通过发出VFIO设备读/写来执行control path操作,该操作通过系统软件和协议栈,最终进入英特尔网卡设备驱动程序中的VDCM模块。
5. DPDK进程通过向英特尔800系列 网卡硬件上的ADI发出DMA读/写请求来执行data path操作。DMA读/写请求是由PF的PCIe请求者ID(总线/设备/功能编号)和PASID识别的PCIe upstream memory transaction,并对IOMMU地址转换和每个ADI的保护。
6. 当你退出DPDK进程时,MDEV也会关闭。
7. 通过如下命令Destroy MDEV:
echo 1 > /sys/bus/mdev/devices/83b8f4f2-509f-382f-3c1e-e6bfe0fa1002/remove
图2 Mediated 设备生命周期序列
2.2.6 通过英特尔可扩展I/O虚拟化缩短启动时间
直观地说,应用程序的启动时间可以映射到"open MDEV"和"control-path operation"的时间,如图2所示。
对于DPDK应用程序,初始化过程包括以下列出的阶段:
1. EAL初始化:EAL负责访问底层资源,如硬件和内存空间。它提供了一个通用接口,对应用程序和库隐藏环境细节。从设备的角度来看,EAL将扫描Linux PCI总线,执行通用设备初始化,并通过加载厂商驱动程序执行厂商特定的初始化。
2. MBUF分配:MBUF通常携带发送到网络适配器或从网络适配器接收的网络数据包,它可以是任何数据(如控制数据和事件)。
3. 设备配置:此阶段用于配置设备的发送队列、接收队列、mac地址和其他设置。一旦所有设置成功,设备就开始发送和接收网络数据包。
对于在SR-IOV VF上运行的DPDK应用程序,当VF在EAL初始化期间被探测到并首次打开时,PCIe FLR被隐式触发(第一次重置)以执行设备重置。由于设备必须在PCIe规范定义的某个时间段内完成FLR,因此软件必须在该时间段内保持繁忙等待以满足时序要求。更糟糕的是,EAL将显示调用VFIO设备重置,这将导致另一个FLR(第二次重置)和延迟。根据PCIe规范,重置周期可能持续大约几百毫秒。
对于在Intel Scalable IOV VDEV上运行的DPDK应用程序,由于所有控制路径都由VDCM模拟,因此设备实际上是一种软件呈现。软件具有很大的灵活性,可以消除真实设备所需的严格时间和程序。因此,可以去除SR-IOV VF案例下不必要的首次复位。对于第二次重置,设备也不需要遵循PCIe FLR计时程序。VDCM可以以更轻量级的方式以更少的时间来实现设备重置。
03
部署
测试环境由DPDK testpmd探测MDEV设置,MDEV由英特尔E810-CQDA2网卡作为底层支撑,并运行在第4代英特尔至强可扩展处理器上。为了模拟CNF运行时环境,应用程序被设置为在容器内运行。为了展示Intel Scalable IOV的优势,增加了SR-IOV VF测试作为对比,VF由英特尔E810-CQDA2网卡作为底层支撑,并运行在第4代英特尔至强可扩展处理器上。除了通过Intel Scalable IOV ADI或SR-IOV VF之间的差异外,其余设置都是相同的。完整的系统设置显示在表1中.
表1 服务器配置
3.1 Intel Scalable IOV VDEV(Test-VDEV)的测试配置
在本测试中,VDEV被设置为通过DPDK testpmd进程。通过将VFIO group设备节点传递到容器中,testpmd可以通过VFIO MDEV框架对VDEV执行control path和data path操作。
图3 Intel Scalable IOV VDEV的测试配置
3.1.1 Test-VDEV配置步骤
使用以下命令配置Linux kernel引导参数:
intel_iommu=on,sm_on
1. 加载英特尔 E810设备驱动程序并创建MDEV。
2. 配置2M huge page并且挂载为 /dev/hugepages
# echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB
# echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB
# mount -t hugetlbfs -o pagesize=2M none /dev/hugepages
3. 使用预先构建的docker镜像启动容器。
# docker run -it --name={NAME} --privileged --device=/dev/vfio/459 --device=/dev/vfio/vfio -
-ulimit memlock=-1:-1 -v /dev/hugepages:/dev/hugepages -v /dev:/dev {IMAGE}
4. 加载DPDK testpmd
# dpdk-testpmd -c 0x3 -a 83b8f4f2-509f-382f-3c1e-e6bfe0fa1001 –
3.2 SR-IOV VF测试配置
在本测试中,SR-IOV VF被设置为通过DPDK testpmd进程。通过将VFIO group设备节点传递到容器中,testpmd可以通过VFIO PCI框架直接访问VF。
图4 SR-IOV VF 测试配置
3.2.1 Test-VF 配置步骤
使用以下命令配置Linux Kernel引导参数:
intel_iommu=on,sm_on
1. 加载英特尔E810设备驱动程序,并创建SR-IOV VF.
# insmod ice.ko
# echo 1 > /sys/bus/pci/devices/0000:16:00.0/sriov_numvfs
2. 绑定 SR-IOV VF和vfio-pci驱动程序
# {DPDK_SOURCE_DIR}/usertools/dpdk-devbind.py -b vfio-pci 16:01.0
3. 配置2M huge page,并挂载为/dev/hugepages
# echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB
# echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB
# mount -t hugetlbfs -o pagesize=2M none /dev/hugepages
4. 使用预先构建的docker镜像启动容器。
# docker run -it --name={NAME} --privileged --device=/dev/vfio/459 --device=/dev/vfio/vfio -
-ulimit memlock=-1:-1 -v /dev/hugepages:/dev/hugepages -v /dev:/dev {IMAGE}
5. 加载DPDK testpmd
# dpdk-testpmd -c 0x3 -a 16:01.0 –
04
测试结果
Test-VDEV and Test-VF 的benchmark如图5所示,详细数据见表2。
图5 Test-VDEV and Test-VF 启动时间
对于Test-VDEV,完成所有初始化需要191毫秒。对于Test-VF,完成所有初始化需要376毫秒。根据表2,Test-VDEV只需要30毫秒即可完成通用设备初始化,而Test-VF需要214毫秒。除此之外,其余部件在Test-VDEV或Test-VF时所花费的时间相似。
表2 Test-VDEV 和 Test-VF的启动时间对比
因此,由于执行通用设备初始化所需的时间要少得多,Intel Scalable IOV显著减少了容器环境中testpmd的启动时间。
05
总结
本文介绍了如何在第4代英特尔至强可扩展处理器和英特尔 800系列网卡上利用英特尔可扩展I/O虚拟化,由于灵活的设备构建和软件的生命周期管理,减少了CNF在直通设备上的启动时间。
从硬件和软件组件的角度全面介绍了如何启用Intel Scalable IOV,并定性分析了为什么可以缩短启动时间。最后,给出了测试配置和结果,证明Intel Scalable IOV在容器运行时环境中可以显著缩短启动时间。
虽然这些知识专门用于减少CNF的启动时间,但这些硬件和软件组件所实现的技术可以作为一个用户参考来优化直通设备上的应用程序启动时间。
引用文献
1. Fu, S., Mittal, R., Zhang, L. and Ratnasamy, S., 2020. Fast and efficient container startup at the edge via dependency scheduling. In 3rd USENIX Workshop on Hot Topics in Edge Computing (HotEdge 20).
2. The Application of Kata Containers in Baidu AI Cloud White Paper.
3. Intel Scalable I/O Virtualization Technical Specification
4. https://www.kernel.org/doc/html/latest/driver-api/vfio.html
5. Until then, MDEV will be deprecated and VFIO is under refactoring in Linux community
https://lore.kernel.org/kvm/BN9PR11MB5433B1E4AE5B0480369F97178C189@BN9PR11MB5433.namprd11.prod.outlook.com/
6. https://patches.dpdk.org/project/dpdk/cover/20210601030644.3318-1-chenbo.xia@intel.com/
参考文档
1. DPDK WIKI
https://en.wikipedia.org/wiki/Data_Plane_Development_Kit
2. 英特尔800系列网卡
https://www.intel.com/content/www/us/en/products/details/ethernet/800-network-adapters.html
3. Intel Scalable I/O Virtualization 技术规范
https://www.intel.com/content/www/us/en/develop/download/intel-scalable-io-virtualization-technical-specification.html
4. Intel Virtualization Technology for Directed I/O Architecture 规范
https://www.intel.com/content/www/us/en/develop/download/intel-virtualization-technology-for-directed-io-architecture-specification.html
5. PCIE基础规范Rev4.0 V1.0
https://members.pcisig.com/wg/PCISIG/document/10912?downloadRevision=active
6单根I/O 虚拟化和共享规范
https://members.pcisig.com/wg/PCI-SIG/document/download/8238
7. Kata容器在百度AI云的应用白皮书
https://katacontainers.io/collateral/ApplicationOfKataContainersInBaiduAICloud.pdf
专用术语
缩写 | 全称 |
ADI | Assignable Device Interface |
CNF | Cloud-native Network Function |
DMA | Direct Memory Access |
DPDK | Data Plane Development Kit |
EAL | Environment Abstraction Layer |
FLR | Function Level Reset |
IAVF | Intel Adaptive Virtual Function |
Intel Scalable IOV | Intel Scalable I/O Virtualization |
IOMMU | I/O Memory Management Unit |
MBUF | Message Buffer |
MDEV | Mediated Device |
NFV | Network Function Virtualization |
PASID | Process Address Space Identifier |
PF | Physical Function |
PMD | Poll Mode Driver |
RFC | Request for Comment |
SR-IOV | Single Root I/O Virtualization |
UUID | Universally Unique Identifier |
VDCM | Virtual Device Composition Module |
VDEV | Virtual Device |
VF | Virtual Function |
VFIO | Virtual Function I/O |
VM | Virtual Machine |
VNF | Virtual Network Function |
转载须知
推荐阅读
点点“赞”和“在看”,给我充点儿电吧~