Linux 和 FreeBSD VM 中加速网络的工作方式

在 Azure 中创建虚拟机 (VM) 时,系统会在其配置中为每个虚拟 NIC 创建合成网络接口。 合成接口是 VMbus 设备,并且会使用“netvsc”驱动程序。 使用此合成接口的网络数据包会通过 Azure 主机中的虚拟交换机,并进入数据中心物理网络。

如果 VM 配置了加速网络,则系统会为已配置的每个虚拟 NIC 创建另一个网络接口。 另一个接口是由 Azure 主机中的物理网络 NIC 提供的 SR-IOV 虚拟功能 (VF)。 VF 接口在 Linux 来宾中显示为 PCI 设备。 它在 Linux 中使用 Mellanox mlx4 或 mlx5 驱动程序,因为 Azure 主机使用 Mellanox 的物理 NIC。

大多数网络数据包直接在 Linux 来宾和物理 NIC 之间传输,而无需遍历虚拟交换机或主机上运行的任何其他软件。 由于对硬件的直接访问,与合成接口相比,此过程的网络延迟较低,使用 CPU 处理网络数据包的时间也更少。

不同的 Azure 主机使用不同的 Mellanox 物理 NIC 模型。 Linux 会自动决定是使用“mlx4”驱动程序还是“mlx5”驱动程序。 Azure 基础结构控制 VM 在 Azure 主机上的位置。 如果没有用于指定 VM 部署所使用的物理 NIC 的客户选项,则 VM 必须包含这两个驱动程序。 如果 VM 在停止或解除分配后重新启动,则系统可能会在具有不同的 Mellanox 物理 NIC 模型的硬件上重新部署该 VM。 因此,该 VM 可能会使用另一个 Mellanox 驱动程序。

如果 VM 映像不含 Mellanox 物理 NIC 的驱动程序,则网络功能会继续以虚拟 NIC 的较慢速度运行。 门户、Azure CLI 和 Azure PowerShell 将加速网络功能显示为“已启用”。

在 Azure 中运行时,FreeBSD 会提供与 Linux 相同的加速网络支持。 本文的其余部分将介绍 Linux 并使用 Linux 示例,但可在 FreeBSD 中获取相同功能。

注意

本文包含对术语“从属”的引用,这是 Microsoft 不再使用的术语。 在从软件中删除该术语后,我们会将其从本文中删除。

捆绑

合成网络接口和 VF 接口会自动配对,在大多数情况下充当应用程序使用的单一接口。 Netvsc 驱动程序执行绑定。 根据 Linux 发行版的不同,udev 规则和脚本可帮助命名 VF 接口和配置网络。

如果 VM 配置了多个虚拟 Nic,Azure 主机将为每个 NIC 提供唯一的序列号。 该规则允许 Linux 对每个虚拟 NIC 执行正确的合成和 VF 接口配对。

合成和 VF 接口都拥有相同的 MAC 地址。 从与 VM 中的虚拟 NIC 交换数据包的其他网络实体的角度来看,这些接口共同构成了单个 NIC。 由于存在合成接口和 VF 接口,其他实体不会采取任何特殊操作。

这两个接口可通过 Linux 中的 ifconfigip addr 命令设为可见。 下面是示例 ifconfig 输出:

U1804:~$ ifconfig
enP53091s1np0: flags=6211<UP,BROADCAST,RUNNING,SLAVE,MULTICAST>  mtu 1500
ether 00:0d:3a:f5:76:bd  txqueuelen 1000  (Ethernet)
RX packets 365849  bytes 413711297 (413.7 MB)
RX errors 0  dropped 0  overruns 0  frame 0
TX packets 9447684  bytes 2206536829 (2.2 GB)
TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
inet 10.1.19.4  netmask 255.255.255.0  broadcast 10.1.19.255
inet6 fe80::20d:3aff:fef5:76bd  prefixlen 64  scopeid 0x20<link>
ether 00:0d:3a:f5:76:bd  txqueuelen 1000  (Ethernet)
RX packets 8714212  bytes 4954919874 (4.9 GB)
RX errors 0  dropped 0  overruns 0  frame 0
TX packets 9103233  bytes 2183731687 (2.1 GB)
TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

合成接口名称的形式始终是 eth\<n\>。 根据 Linux 分发版,VF 接口的名称可能采用的形式:eth\<n\>。 或者,由于进行重命名的 udev 规则,它可能有一个不同的 enP\<n\> 形式的名称。

可以使用 shell 命令行来确定特定接口是合成接口还是 VF 接口,此命令行显示接口使用的设备驱动程序:

$ ethtool -i <interface name> | grep driver

如果驱动程序为 hv_netvsc,则为合成接口。 VF 接口的驱动程序名称包含“mlx”。VF 接口也是可识别的,因为它的 flags 字段包含 SLAVE。 此标志说明该接口受具有相同 MAC 地址的合成接口的控制。

IP 地址仅分配给合成接口。 ifconfigip addr 的输出也显示此区别。

应用程序使用情况

应用程序应该只与合成接口交互,就像在任何其他网络环境中一样。 传出网络数据包从 netvsc 驱动程序传输到 VF 驱动程序,然后再通过 VF 接口传输。

传入数据包经 VF 接口接收和处理,然后再传输到合成接口。 例外情况包括仅由合成接口处理的传入 TCP SYN 数据包和广播/多播数据包。

可以验证数据包是否从 ethtool -S eth\<n\> 的输出流经 VF 接口。 包含 vf 的输出行显示了通过 VF 接口的流量。 例如:

U1804:~# ethtool -S eth0 | grep ' vf_'
 vf_rx_packets: 111180
 vf_rx_bytes: 395460237
 vf_tx_packets: 9107646
 vf_tx_bytes: 2184786508
 vf_tx_dropped: 0

如果这些计数器在连续执行“ethtool”命令时递增,则网络流量将流经 VF 接口。

可以使用 lspci 命令验证 VF 接口是否用作 PCI 设备。 例如,在第一代 VM 上,你获得的输出可能与以下输出类似。 (第 2 代 VM 没有旧版 PCI 设备。)

U1804:~# lspci
0000:00:00.0 Host bridge: Intel Corporation 440BX/ZX/DX - 82443BX/ZX/DX Host bridge (AGP disabled) (rev 03)
0000:00:07.0 ISA bridge: Intel Corporation 82371AB/EB/MB PIIX4 ISA (rev 01)
0000:00:07.1 IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)
0000:00:07.3 Bridge: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 02)
0000:00:08.0 VGA compatible controller: Microsoft Corporation Hyper-V virtual VGA
cf63:00:02.0 Ethernet controller: Mellanox Technologies MT27710 Family [ConnectX-4 Lx Virtual Function] (rev 80)

在此示例中,输出的最后一行显示在 Mellanox ConnectX-4 物理 NIC 中识别出了 VF 接口。

ethtool -l”或“ethtool -L”命令(用于获取和设置传输队列和接收队列的数目)对于适用于与“eth<n>”接口交互的指南是例外情况。 此命令可直接用于 VF 接口,以控制 VF 接口的队列数。 VF 接口队列的数量与合成接口队列的数量无关。

解释启动消息

在启动过程中,Linux 会显示许多与 VF 接口的初始化和配置相关的消息。 还会显示有关与合成接口捆绑的信息。 了解这些消息对于识别此过程中出现的任何问题十分实用。

以下是“dmesg”命令的输出示例,只显示到与 VF 接口相关的行。 根据 VM 中 Linux 内核版本和发行版的不同,消息可能略有不同,但总体流是一致的。

[    2.327663] hv_vmbus: registering driver hv_netvsc
[    3.918902] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: VF slot 1 added

已为 eth0 注册 netvsc 驱动程序。

[    6.944883] hv_vmbus: registering driver hv_pci

已注册 VMbus 虚拟 PCI 驱动程序。 此驱动程序在 Azure 中的 Linux VM 中提供核心 PCI 服务。 必须先注册它,然后才能检测和配置 VF 接口。

[    6.945132] hv_pci e9ac9b28-cf63-4466-9ae3-4b849c3ee03b: PCI VMBus probing: Using version 0x10002
[    6.947953] hv_pci e9ac9b28-cf63-4466-9ae3-4b849c3ee03b: PCI host bridge to bus cf63:00
[    6.947955] pci_bus cf63:00: root bus resource [mem 0xfe0000000-0xfe00fffff window]
[    6.948805] pci cf63:00:02.0: [15b3:1016] type 00 class 0x020000
[    6.957487] pci cf63:00:02.0: reg 0x10: [mem 0xfe0000000-0xfe00fffff 64bit pref]
[    7.035464] pci cf63:00:02.0: enabling Extended Tags
[    7.040811] pci cf63:00:02.0: 0.000 Gb/s available PCIe bandwidth, limited by Unknown x0 link at cf63:00:02.0 (capable of 63.008 Gb/s with 8.0 GT/s PCIe x8 link)
[    7.041264] pci cf63:00:02.0: BAR 0: assigned [mem 0xfe0000000-0xfe00fffff 64bit pref]

已检测到列出 GUID(由 Azure 主机分配)的 PCI 设备。 系统会根据 GUID 向其分配 PCI 域 ID(在这种情况下为 0xcf63)。 在 VM 所有可用 PCI 设备中,PCI 域 ID 必须唯一。 此唯一性要求涉及 VM 中可能存在的其他 Mellanox VF 接口、GPU、NVMe 设备和其他设备。

[    7.128515] mlx5_core cf63:00:02.0: firmware version: 14.25.8362
[    7.139925] mlx5_core cf63:00:02.0: handle_hca_cap:524:(pid 12): log_max_qp value in current profile is 18, changing it to HCA capability limit (12)
[    7.342391] mlx5_core cf63:00:02.0: MLX5E: StrdRq(0) RqSz(1024) StrdSz(256) RxCqeCmprss(0)

已检测到使用 mlx 5 驱动程序的 Mellanox VF。 Mlx5 驱动程序开始设备初始化。

[    7.465085] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: VF registering: eth1
[    7.465119] mlx5_core cf63:00:02.0 eth1: joined to eth0

正在使用 netvsc 驱动程序的对应合成接口已检测到匹配的 VF。 mlx5 驱动程序识别其已与合成接口捆绑。

[    7.466064] mlx5_core cf63:00:02.0 eth1: Disabling LRO, not supported in legacy RQ
[    7.480575] mlx5_core cf63:00:02.0 eth1: Disabling LRO, not supported in legacy RQ
[    7.480651] mlx5_core cf63:00:02.0 enP53091s1np0: renamed from eth1

Linux 内核最初名为 VF 接口 eth1。 系统根据 udev 规则将其重命名,以避免与为合成接口指定的名称混淆。

[    8.087962] mlx5_core cf63:00:02.0 enP53091s1np0: Link up

Mellanox VF 接口现已处于激活状态。

[    8.090127] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: Data path switched to VF: enP53091s1np0
[    9.654979] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: Data path switched from VF: enP53091s1np0

这些消息表示捆绑对的数据路径已切换为使用 VF 接口。 约 1.6 秒后,该数据路径将切换回使用合成接口。 此类切换过程在启动过程中可能会出现两三次,并且是配置初始化时的正常行为。

[    9.909128] mlx5_core cf63:00:02.0 enP53091s1np0: Link up
[    9.910595] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: Data path switched to VF: enP53091s1np0
[   11.411194] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: Data path switched from VF: enP53091s1np0
[   11.532147] mlx5_core cf63:00:02.0 enP53091s1np0: Disabling LRO, not supported in legacy RQ
[   11.731892] mlx5_core cf63:00:02.0 enP53091s1np0: Link up
[   11.733216] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: Data path switched to VF: enP53091s1np0

最终消息表示数据路径已切换为使用 VF 接口。 这一过程在 VM 的正常操作过程中为预期行为。

Azure 主机服务

执行 Azure 主机服务时,系统可能会将所有 VF 接口从 VM 中暂时删除。 服务完成后,系统会将 VF 接口重新添加回 VM。 继续正常操作。 尽管 VM 在没有 VF 接口的情况下运行,但网络流量仍会流过合成接口,而不会对应用程序造成任何中断。

在此环境中,Azure 主机服务可能包括更新 Azure 网络基础结构的各种组件或针对 Azure 主机虚拟机监控程序软件的完整升级。 此类服务事件在一定时间间隔内进行,具体取决于 Azure 基础结构的操作需求。 通常情况下,这些事件可能会在一年中出现多次。

如果应用程序仅与合成接口交互,则 VF 接口和合成接口之间的自动切换可确保此类服务事件不会干扰工作负载。 由于使用了合成接口,在这些过程中,延迟和 CPU 负载可能会更高。 此类过程的持续时间通常为 30 秒,但有时可能持续几分钟。

在服务事件期间删除和重新添加的 VF 接口在 VM 的“dmesg”输出中可见。 以下是相关的典型输出:

[   8160.911509] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: Data path switched from VF: enP53091s1np0
[   8160.912120] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: VF unregistering: enP53091s1np0
[   8162.020138] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: VF slot 1 removed

数据路径已脱离 VF 接口,并已取消注册 VF 接口。 此时,Linux 已删除了 VF 接口的所有知识,并以如同未启用加速网络的方式般运行。

[   8225.557263] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: VF slot 1 added
[   8225.557867] hv_pci e9ac9b28-cf63-4466-9ae3-4b849c3ee03b: PCI VMBus probing: Using version 0x10002
[   8225.566794] hv_pci e9ac9b28-cf63-4466-9ae3-4b849c3ee03b: PCI host bridge to bus cf63:00
[   8225.566797] pci_bus cf63:00: root bus resource [mem 0xfe0000000-0xfe00fffff window]
[   8225.571556] pci cf63:00:02.0: [15b3:1016] type 00 class 0x020000
[   8225.584903] pci cf63:00:02.0: reg 0x10: [mem 0xfe0000000-0xfe00fffff 64bit pref]
[   8225.662860] pci cf63:00:02.0: enabling Extended Tags
[   8225.667831] pci cf63:00:02.0: 0.000 Gb/s available PCIe bandwidth, limited by Unknown x0 link at cf63:00:02.0 (capable of 63.008 Gb/s with 8.0 GT/s PCIe x8 link)
[   8225.667978] pci cf63:00:02.0: BAR 0: assigned [mem 0xfe0000000-0xfe00fffff 64bit pref]

服务完成后重新添加 VF 接口时,将检测到拥有指定 GUID 的新 PCI 设备。 系统已为其分配与之前相同的 PCI 域 ID (0xcf63)。 针对重新添加的 VF 接口的处理方式与在初始启动过程中的处理方式类似。

[   8225.679672] mlx5_core cf63:00:02.0: firmware version: 14.25.8362
[   8225.888476] mlx5_core cf63:00:02.0: MLX5E: StrdRq(0) RqSz(1024) StrdSz(256) RxCqeCmprss(0)
[   8226.021016] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: VF registering: eth1
[   8226.021058] mlx5_core cf63:00:02.0 eth1: joined to eth0
[   8226.021968] mlx5_core cf63:00:02.0 eth1: Disabling LRO, not supported in legacy RQ
[   8226.026631] mlx5_core cf63:00:02.0 eth1: Disabling LRO, not supported in legacy RQ
[   8226.026699] mlx5_core cf63:00:02.0 enP53091s1np0: renamed from eth1
[   8226.265256] mlx5_core cf63:00:02.0 enP53091s1np0: Link up

mlx5 驱动程序会初始化 VF 接口,接口现在可正常运行。 此时的输出与初始启动时的输出类似。

[   8226.267380] hv_netvsc 000d3af5-76bd-000d-3af5-76bd000d3af5 eth0: Data path switched to VF: enP53091s1np0

数据路径已切换回使用 VF 接口。

在非运行 VM 中禁用或启用加速网络

可以使用 Azure CLI 在未运行 VM 中的虚拟 NIC 上禁用或启用加速网络。 例如: 。

$ az network nic update --name u1804895 --resource-group testrg --accelerated-network false

禁用来宾 VM 中启用的加速网络将生成“dmesg”输出。 这与系统在 Azure 主机维护期间删除 VF 接口的输出相同。 而启用加速网络则会生成与在 Azure 主机服务后重新添加 VF 接口时相同的“dmesg”输出。

这些 Azure CLI 命令可用于模拟 Azure 主机服务。 然后,你可以验证你的应用程序不会错误地依赖于与 VF 接口的直接交互。

后续步骤