vDPA测试环境搭建

要求:

  • 运行 Linux 发行版的计算机。本指南使用 CentOS 9-stream,但对于其他 Linux 发行版,特别是对于 Red Hat Enterprise Linux 7,命令不应有重大变化。

  • 具有 sudo 权限的用户

  • ~ 主目录中有 25 GB 的可用空间

  • 至少 8GB 内存

首先,我们安装我们需要的软件包:

sudo yum install qemu-kvm libvirt-daemon-qemu libvirt-daemon-kvm libvirt virt-install libguestfs-tools-c kernel-tools dpdk dpdk-tools

创建 VM

首先,从以下网站下载最新的 CentOS-Cloud-Base 映像:

user@host $ sudo wget -O /var/lib/libvirt/images/CentOS-Stream-GenericCloud-9-20240212.0.x86_64.qcow2 https://cloud.centos.org/centos/9-stream/x86_64/images/CentOS-Stream-GenericCloud-9-20240212.0.x86_64.qcow2

(请注意,上面的 URL 可能会更改,请将其更新为 https://cloud.centos.org/centos/9-stream/x86_64/images中的最新 qcow2 映像。

制作image的副本,以便将来可以重用它(用这种方法,我们可以启动很多个虚拟机,但镜像只占用很小的磁盘空间):

user@host $ sudo qemu-img create -f qcow2 -b  /var/lib/libvirt/images/CentOS-Stream-GenericCloud-9-20240212.0.x86_64.qcow2 -F qcow2  /var/lib/libvirt/images//vhuser-test1.qcow2

如果我们导出以下变量,则可以使用非特权用户(推荐)执行此操作的 libvirt 命令:

user@host $ export LIBVIRT_DEFAULT_URI="qemu:///system"

现在,清理命令(将密码更改为您自己的密码,卸载和安装一些工具):

user@host $ sudo virt-sysprep --root-password password:changeme --uninstall cloud-init --selinux-relabel -a /var/lib/libvirt/images/vhuser-test1.qcow2 --network --install "dpdk,dpdk-tools,pciutils"

如果出现报错:

Error: Failed to download metadata for repo 'appstream': Cannot prepare internal mirrorlist: No URLs in mirrorlist

创建shell脚本

$ cat scripts 
#!/bin/bash
cd /etc/yum.repos.d/
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*

,并使用如下命令:

user@host $ sudo virt-sysprep --root-password password:changeme --run ./scripts --uninstall cloud-init --selinux-relabel -a /var/lib/libvirt/images/vhuser-test1.qcow2 --network --install "dpdk,dpdk-tools,pciutils"

此命令挂载文件系统并自动应用一些基本配置,以便映像可以重新引导。

配置VM网络

我们还需要一个网络来连接我们的 VM。Libvirt 处理网络的方式与管理虚拟机的方式类似,您可以使用 XML 文件定义网络,然后通过命令行启动或停止它。

在这个例子中,我们将使用一个名为default的网络,为了方便起见,它的定义包含在 libvirt 中。以下命令定义default网络,启动它并检查它是否正在运行。

user@host $ virsh net-define /usr/share/libvirt/networks/default.xml
Network default defined from /usr/share/libvirt/networks/default.xml
user@host $ virsh net-start default
Network default started
user@host $virsh net-listName      State    Autostart   Persistent
--------------------------------------------default   active   no          yes

/usr/share/libvirt/networks/default.xml内容如下:

$ cat /usr/share/libvirt/networks/default.xml1 <network>2   <name>default</name>3   <bridge name="virbr0"/>4   <forward/>5   <ip address="192.168.122.1" netmask="255.255.255.0">6     <dhcp>7       <range start="192.168.122.2" end="192.168.122.254"/>8     </dhcp>9   </ip>10 </network>

该文件定义了一个内核网桥virbr0,网桥的ip、掩码和作为dhcp server时分配的ip范围。我们也可以自定义其他的网络。

最后,我们可以使用 virt-install 来创建 VM。此命令行实用程序为一组已知操作系统创建所需的定义。这将为我们提供基本定义,然后我们可以自定义这些定义:

user@host $ virt-install --import --name vdpa-test1 --ram=5120 --vcpus=3 \
--nographics --accelerate --machine q35 \--network network:default,model=virtio --mac 02:ca:fe:fa:ce:aa \--debug --wait 0 --console pty \--disk /var/lib/libvirt/images/vdpa-test1.qcow2,bus=virtio --os-variant centos-stream9

此命令的选项用于指定 vCPU 的数量、VM 的 RAM 量以及我们希望 VM 连接到的磁盘路径和网络。
osinfo-query os | grep centos 可以查询os版本。

您可能已经注意到,与 Vhost 用户动手操作相比,有一个区别,因为我们将机器类型指定为“q35”而不是默认的“pc”类型。这是启用对虚拟 IOMMU 的支持的要求。

除了根据我们指定的选项定义虚拟机外,virt-install 命令还应该为我们启动虚拟机,因此我们应该能够列出它:

user@host $ virsh listId   Name       State
------------------------------1 vdpa-test1   running

瞧!我们的 VM 正在运行。我们需要尽快对其定义进行一些更改。所以我们现在将关闭它:

user@host $ virsh shutdown vdpa-test1

Host环境准备

DPDK 有助于以最佳方式分配和管理内存缓冲区。在 Linux 上,这需要使用 hugepage 支持,该支持必须在正在运行的内核中启用。使用大于通常 4K 大小的页面可以减少页面总数,从而减少 TLB(Translation Lookaside Buffers)查找,从而提高性能。需要这些查找才能将虚拟地址转换为物理地址。为了在引导过程中分配 hugepages,我们在引导加载程序配置中的内核参数中添加了以下内容。

user@host $ sudo grubby --args="default_hugepagesz=1G hugepagesz=1G hugepages=6" --update-kernel /boot/<your kernel image file>

这有什么作用?

default_hugepagesz=1G: make all created hugepages by default 1G bighugepagesz=1G: for the hugepages created during startup set the size to 1G as wellhugepages=6: create 6 hugepages (of size 1G) from the start. These should be seen      after booting in /proc/meminfo

现在可以重新引导主机。在它出现后,我们可以通过运行以下命令来检查我们对内核参数的更改是否有效:

user@host $ cat /proc/cmdline

Guest环境准备

virt-install 命令使用 libvirt 创建并启动了 VM。要将基于 DPDK 的 vswitch testpmd 连接到 QEMU,我们需要添加 vhost-user 接口的定义(由 UNIX 套接字支持),并将虚拟 IOMMU 设置到 XML 的 device 部分:

user@host $ virsh edit vdpa-test1

让我们从添加所有必要的设备开始,以使 Virtio-net 设备与 IOMMU 支持一起工作。

首先,我们需要创建一个专用于 Virtio-net 设备的 pcie-root-port,我们将用作 vDPA 设备,以便它有自己的 IOMMU group。否则,它将与同一总线上的其他设备共享,从而阻止它在用户空间中使用:

<controller type='pci' index='8' model='pcie-root-port'><model name='pcie-root-port'/><target chassis='8' port='0xe'/><address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</controller>

解惑IOMMU

然后,我们可以使用 vhost-user 后端添加 Virtio-net 设备,并将其插入我们刚刚创建的 pcie-root-port(总线 8)。我们还需要启用 IOMMU 和 ATS(地址转换服务)支持:

最后,我们添加 IOMMU 设备,启用中断重新映射和 IOTLB 支持:
<iommu model='intel'><driver intremap='on' iotlb='on'/>
</iommu>

要使启用了 IOMMU 的 vhost-user 正常工作,还需要进行一些其他 XML 调整。

首先,就像在 vhost-user 动手操作 中一样,我们需要让 guest 使用huge pages,这是通过在 guest 定义中添加以下内容来完成的:

  <memoryBacking><hugepages><page size='1048576' unit='KiB' nodeset='0'/></hugepages><locked/></memoryBacking><numatune><memory mode='strict' nodeset='0'/></numatune>

字段含义参考libvirt xml memoryBacking。

为了让 vhost-user 后端能够访问内存,我们需要在 guest 配置中添加一个额外的设置。这是一个重要的设置,如果没有它,我们将看不到任何正在传输的数据包:

<cpu mode='host-passthrough' check='none'><topology sockets='1' cores='3' threads='1'/><numa><cell id='0' cpus='0-2' memory=’5242880’ unit='KiB' memAccess='shared'/></numa>
</cpu>

字段含义参考libvirt xml host-passthrough

最后,我们需要让 Qemu 管理 I/O APIC,以便中断重新映射工作:

<features><acpi/><apic/><ioapic driver='qemu'/>
</features>

字段含义参考libvirt xml ioapic driver=‘qemu’
现在我们需要启动我们的guest。由于我们将其配置为连接到 vhost-user UNIX 套接字,因此我们需要确保它们在guest启动时可用。这是通过启动 testpmd 来实现的,它将为我们打开套接字:

user@host $ sudo testpmd -l 0,2 --socket-mem=1024 -n 4 \--vdev 'net_vhost0,iface=/tmp/vhost-user1,iommu-support=1'  -- \--portmask=1 -i --rxq=1 --txq=1 \--nb-cores=1 --forward-mode=io

最后一件事,因为我们连接到 vhost-user unix 套接字,我们需要让 QEMU 以 root 身份运行这个实验。为此,请在 /etc/libvirt/qemu.conf 中设置 “user = root”。这是我们的特殊用例所必需的,但一般不建议这样做。事实上,读者应该在阅读这篇动手文章后,通过注释掉“user = root”设置来恢复设置。

现在,我们可以使用以下命令启动 VM:virsh start

user@host $ virsh start vdpa-test1

以 root 身份登录。我们在 guest 中做的第一件事是向内核命令行添加一些参数,以在启动时保留一些巨大的页面,并在直通模式下启用对 IOMMU 的内核支持:

root@guest $ sudo grubby --args="default_hugepagesz=1G hugepagesz=1G hugepages=2 intel_iommu=on iommu=pt" --update-kernel /boot/<your kernel image file>

为了应用新的内核参数,让我们重新启动客户机。
以上也可以通过host实现:

sudo virt-sysprep -v --run-command 'grubby --args="default_hugepagesz=1G hugepagesz=1G hugepages=6" --update-kernel=ALL' -a  /var/lib/libvirt/images/vhuser-test1.qcow2

在启动时,我们现在可以将 virtio 设备绑定到 vfio-pci 驱动程序。为了能够做到这一点,我们需要首先加载所需的内核模块。

root@guest $ modprobe vfio-pci

让我们先找出 virtio-net 设备的 PCI 地址。

root@guest $ dpdk-devbind --status net
…
Network devices using kernel driver
===================================
0000:01:00.0 'Virtio network device 1041' if=eth0 drv=virtio-pci unused=virtio_pci,vfio-pci *Active*
0000:08:00.0 'Virtio network device 1041' if=eth1 drv=virtio-pci unused=virtio_pci,vfio-pci

在输出中,在未标记为active的部分中查找 virtio-device。我们可以用dpdk-devbind来做这个实验:

root@guests $ dpdk-devbind.py -b vfio-pci 0000:08:00.0

现在,客户机已准备好运行我们基于 DPDK 的 vDPA 应用程序。但在试验 vDPA 之前,我们首先要确保在启用 IOMMU 时,我们可以将 Virtio 设备与其 Virtio PMD 驱动程序结合使用 testpmd:

root@guests $ testpmd -l 0,1 --socket-mem 1024 -n 4 -- --portmask=1 -i --auto-start

然后,我们可以在主机 testpmd 实例中启动数据包转发,并在 IO 转发循环中注入突发数据包:

HOST testpmd> start tx_first 512

为了检查一切是否正常工作,我们可以通过重复调用 show port stats all 命令来检查任一 testpmd 实例中的端口统计信息:

HOST testpmd> show port stats all######################## NIC statistics for port 0  ########################RX-packets: 60808544   RX-missed: 0          RX-bytes:  3891746816RX-errors: 0RX-nombuf:  0         TX-packets: 60824928   TX-errors: 0          TX-bytes:  3892795392Throughput (since last show)Rx-pps:     12027830Tx-pps:     12027830############################################################################

搭建环境图

创建加速数据路径

构建 vDPA 应用程序

在确保Host和Guest都正确配置后,让乐趣开始吧!

正如在上一篇文章中提到的,Virtio-vDPA DPDK 驱动程序,它支持使用半虚拟化的 Virtio-net 设备或完整的 Virtio 卸载硬件 NIC,正在上游 DPDK 邮件列表中进行审查,因此在官方上游版本中尚不可用(计划在 v19.11 版本中提供)。
这意味着我们必须应用引入此驱动程序的系列并构建 DPDK,而不是使用 DPKD 下游包。

首先,让我们安装所有依赖项来构建 DPDK:

root@guests $ yum install git gcc numactl-devel kernel-devel

然后我们构建 DPDK 库:

root@guests $ git clone https://gitlab.com/mcoquelin/dpdk-next-virtio.git dpdk
root@guests $ cd dpdk
root@guests $ export RTE_SDK=`pwd`
root@guests $ export RTE_TARGET=x86_64-native-linuxapp-gcc
root@guests $ make -j2 install T=$RTE_TARGET DESTDIR=install

最后,我们构建了 DPDK 树中提供的 vDPA 示例应用程序。此应用程序将探测 vDPA 驱动程序,并使用 vDPA 框架将 vDPA 设备绑定到 vhost-user 套接字:

root@guests $ cd examples/vdpa
root@guests $ make

启动 vDPA 应用程序

如果还没有完成,我们需要将 Virtio-net 设备绑定到 vfio-pci 驱动程序:

root@guests $ dpdk-devbind.py -b vfio-pci 0000:08:00.0

然后,我们可以启动 vdpa 应用程序,请求它将可用的 vDPA 设备绑定到以 . /tmp/vdpa为前缀的 Vhost 用户套接字

为了使用 Virtio-vDPA 驱动程序而不是 Virtio PMD 探测 Virtio-net 设备,我们必须在 EAL 命令行中将“vdpa=1”设备参数传递给列入白名单的设备。

由于在此示例中只有一个 vDPA 设备,因此应用程序将在以下位置创建单个 vhost-user 套接字/tmp/vdpa0

root@guests $ ./build/examples/dpdk-vdpa -l 0,2 --socket-mem 1024 -w 0000:08:00.0,vdpa=1 -- --iface /tmp/vdpa
EAL: Detected 3 lcore(s)
EAL: Detected 1 NUMA nodes
EAL: Multi-process socket /var/run/dpdk/rte/mp_socket
EAL: Selected IOVA mode 'VA'
EAL: Probing VFIO support...
EAL: VFIO support initialized
EAL: WARNING: cpu flags constant_tsc=yes nonstop_tsc=no -> using unreliable clock cycles !
EAL: PCI device 0000:08:00.0 on NUMA socket -1
EAL:   Invalid NUMA socket, default to 0
EAL:   probe driver: 1af4:1041 net_virtio
EAL: PCI device 0000:08:00.0 on NUMA socket 0
EAL:   probe driver: 1af4:1041 net_virtio_vdpa
EAL:   using IOMMU type 1 (Type 1)
iface /tmp/vdpa
VHOST_CONFIG: vhost-user server: socket created, fd: 27
VHOST_CONFIG: bind to /tmp/vdpa0
enter 'q' to quit

Note:因为qemu开启了iommu,所以IOVA mode自动选择了"VA"。

启动用户应用程序

现在,绑定到 vDPA 设备的 vhost-user 套接字已准备好使用,我们可以启动将使用accelerated Virtio datapath的应用程序。

在现实生活中,它可以传递给虚拟机,以便其 Virtio 数据路径绕过主机,但我们已经在客户机中运行,因此这意味着设置嵌套虚拟化。

其他可能的情况是将 vhost-user 套接字传递给容器,以便它可以从高速接口中受益,但我们稍后将在以后的文章中介绍这一点。

为了简单起见,我们将只启动一个 testpmd 应用程序,它将使用 Virtio-user PMD 连接到 vhost-user 套接字。Virtio-user PMD 重用了 Virtio PMD 中的数据路径,但它不是通过 PCI 管理控制路径,而是实现了 vhost-user 协议的主端。

由于我们已经运行了一个 DPDK 应用程序,因此我们必须注意为它将分配的 hugepages 的文件名添加前缀。这要归功于以下命令:

root@guests $ ./install/bin/testpmd -l 0,2 --socket-mem 1024 --file-prefix=virtio-user --no-pci --vdev=net_virtio_user0,path=/tmp/vdpa0

就是这样,我们的加速数据路径已经设置好了!为了确认一切正常,让我们再次尝试注入一些数据包,看看它是否工作正常:

HOST testpmd> start tx_first 512HOST testpmd> show port stats all######################## NIC statistics for port 0  ########################RX-packets: 3565442688 RX-missed: 0          RX-bytes:  228188332032RX-errors: 0RX-nombuf:  0         TX-packets: 3565459040 TX-errors: 0          TX-bytes:  228189378560Throughput (since last show)Rx-pps:     11997065Tx-pps:     11997065############################################################################

在这里插入图片描述
上面描述的是在虚拟环境里,启动了dpdk-vdpa[vhost-user server]和testpmd[vhost-user client]实现通信。使用virtio-user PMD driver,而不需要使用qemu作为[vhost-user client]进行测试。以上测试都不包含热迁移内容。

结论

在这篇文章中,我们使用 DPDK 的 vDPA 框架创建了一个标准的加速数据路径。在直接使用 Virtio PMD 运行初始 testpmd 和设置 vDPA 后运行之间,我们引入了 vDPA 层,以在不影响性能的情况下提供额外的灵活性。

此框架的价值在于,您现在可以试验 vDPA 控制平面,而无需供应商 NIC 支持业界目前正在开发的 vDPA 数据平面(硬件中的环布局支持)。

现在,我们将从 VM 领域转移到容器领域。接下来的实践文章将基于此框架进行构建,以在本地和混合云部署中试验 vDPA 加速容器。

附录

[Centos 8 qcow2镜像下载网址] https://cloud.centos.org/centos/8/x86_64/images/
[Centos 9 stream qcow2镜像下载网址] https://cloud.centos.org/centos/9-stream/x86_64/images/
[virt-sysprep用法]虚拟化技术之kvm镜像模板制作工具virt-sysprep.
vdpa动手博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/488166.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

抖音视频提取软件使用功能|抖音视频下载工具

我们的抖音视频提取软件是一款功能强大、易于操作的工具&#xff0c;旨在解决用户在获取抖音视频时需要逐个复制链接、下载的繁琐问题。我们的软件支持通过关键词搜索和分享链接两种方式获取抖音视频&#xff0c;方便用户快速找到自己感兴趣的内容。 主要功能模块&#xff1a;…

华为 OD 一面算法原题

2.2 亿彩票公布调查结果 昨天&#xff0c;闹得沸沸扬扬的《10 万中 2.2 亿》的彩票事件&#xff0c;迎来了官方公告。 简单来说&#xff0c;调查结果就是&#xff1a;一切正常&#xff0c;合规合法。 关于福利彩票事件&#xff0c;之前的推文我们已经分析过。 甚至在后面出现《…

Jetson Xavier NX 与笔记本网线连接 ,网络共享,ssh连接到vscode

Jetson Xavier NX 与笔记本网线连接 &#xff0c;网络共享&#xff0c;ssh连接到vscode Jetson Xavier NX桌面版需要连接显示屏、鼠标和键盘&#xff0c;操作起来并不方便&#xff0c;因此常常需要ssh远程连接到本地笔记本电脑&#xff0c;这里介绍一种连接方式&#xff0c;通过…

FreeRtos Queue(三)

本篇主要分析向队列中发送消息 xQueueGenericSend 这个函数。 大致分为两个逻辑&#xff1a; 1、当队列没满的时候的处理 2、当队列没满的时候的处理 主意&#xff1a;整个xQueueGenericSend是在for(;;)中处理的 一、队列没满的case 队列的数据结构图可参考&#xff1a;F…

【Linux进阶之路】Socket —— “UDP“ “TCP“

文章目录 一、再识网络1. 端口号2. 网络字节序列3.TCP 与 UDP 二、套接字1.sockaddr结构2.UDP1.server端1.1 构造函数1.2 Init1.3 Run 2.客户端1.Linux2.Windows 3.TCP1. 基本接口2. 客户端3. 服务端1.版本12.版本23.版本34.版本4 三、守护进程尾序 温馨提示&#xff1a;文章较…

C#与VisionPro联合开发——INI存储和CSV存储

1、INI存储 INI 文件是一种简单的文本文件格式&#xff0c;通常用于在 Windows 环境中存储配置数据。INI 文件格式由一系列节&#xff08;section&#xff09;和键值对&#xff08;key-value pairs&#xff09;组成&#xff0c;用于表示应用程序的配置信息。一个典型的 INI 文…

开放词汇场景图生成Open vocabulary scene graph generation

文章目录 1. 【2022ECCV】Towards Open-vocabulary Scene Graph Generation with Prompt-based Finetuning摘要和结论引言模型框架实验 2. 【2023CVPR】Learning to Generate Language-supervised and Open-vocabulary Scene Graph using Pre-trained Visual-Semantic Space摘要…

基于ssm的校园帮系统设计与实现(源码+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于ssm的校园帮系统设计…

7-liunx服务器规范

目录 概况liunx日志liunx系统日志syslog函数openlog 可以改变syslog默认输出方式 &#xff0c;进一步结构化 用户信息进程间的关系会话ps命令查看进程关系 系统资源限制改变工作目录和根目录服务器程序后台话 概况 liunx服务器上有很多细节需要注意 &#xff0c;这些细节很重要…

TESTLINK 测试用例数据结构解析

一、node_types 测试组件信息表 我们查询表 select * from testlink.node_types; 得到如下结果 二、nodes_hierarchy 测试用例目录层次表 我们以下图的项目为例&#xff0c;来讲解 1、测试项目 首先&#xff0c;我们有个Train的项目&#xff0c;存在表testprojects中&#…

浅拷贝导致的bug

错误代码&#xff1a; //初始化formTableData的值 const formTableData ref({saleOrderTime:,saleOrderDetails:[] });const showModal async (item) > {//调接口获取后端返回的数据let data (await api.searchSaleOrderById({saleOrderId:item.id})).dataconsole.log(&…

5分钟JavaScript快速入门

目录 一.JavaScript基础语法 二.JavaScript的引入方式 三.JavaScript中的数组 四.BOM对象集合 五.DOM对象集合 六.事件监听 使用addEventListener()方法添加事件监听器 使用onX属性直接指定事件处理函数 使用removeEventListener()方法移除事件监听器 一.JavaScript基础…