Linux 上的 Azure 网络适配器 (MANA) 和 DPDK

Azure 网络适配器 (MANA) 是适用于 Azure 虚拟机的新硬件,可实现更高的吞吐量和可靠性。 若要使用 MANA,用户必须修改其 DPDK 初始化例程。 与旧硬件相比,MANA 需要两项更改:

  • 轮询模式驱动程序 (PMD) 的 MANA EAL 参数不同于以前的硬件。
  • 在 DPDK 初始化开始之前,Linux 内核必须释放对 MANA 网络接口的控制。

示例代码中概述了 MANA DPDK 的设置过程。

介绍

旧版 Azure Linux VM 依赖于 mlx4 或 mlx5 驱动程序以及随附的硬件来实现加速网络。 Azure DPDK 用户可以通过将总线地址传递给 DPDK EAL 来选择要包含或排除的特定接口。 MANA DPDK 的设置过程略有不同,因为每个加速网络接口一个总线地址的假设不再成立。 MANA PMD 使用 MAC 地址(而不是使用 PCI 总线地址)来确定应绑定到哪个接口。

MANA DPDK EAL 参数

当不存在 --vdev 参数时,MANA PMD 会探测系统上的所有设备和端口;--vdev 参数不是必需的。 在测试环境中,通常需要保留一个(主)接口,用于提供与 VM 的 SSH 连接。 若要将 DPDK 与可用 VF 的子集一起使用,用户应在 --vdev 参数中传递 MANA 设备的总线地址和接口的 MAC 地址。 有关更多详细信息,请参阅用于演示 MANA 上的 DPDK EAL 初始化的示例代码。

有关 DPDK 环境抽象层 (EAL) 的常规信息,请参阅:

MANA 的 DPDK 要求

要在 MANA 硬件上使用 DPDK,需要 Linux 内核 6.2 或更高版本,或者需要来自最新 Linux 内核的以太网和 InfiniBand 驱动程序的后端口。 它还需要特定版本的 DPDK 和用户空间驱动程序。

MANA DPDK 需要以下驱动程序集:

  1. Linux 内核以太网驱动程序(5.15 内核及更高版本)
  2. Linux 内核 InfiniBand 驱动程序(6.2 内核及更高版本)
  3. DPDK MANA 轮询模式驱动程序(DPDK 22.11 及更高版本)
  4. libmana 用户空间驱动程序(rdma-core v44 及更高版本)

支持的市场映像

下面列出了包含使用 MANA 时适用于 DPDK 的向后移植补丁的映像,这不是一个详尽列表:

  • Red Hat Enterprise Linux 8.9
  • Red Hat Enterprise Linux 9.4
  • Canonical Ubuntu Server 20.04 (5.15.0-1045-azure)
  • Canonical Ubuntu Server 22.04 (5.15.0-1045-azure)

注意

MANA DPDK 不适用于 Windows;它仅适用于 Linux VM。

示例:查找 MANA

注意

本文假定系统上安装了包含 lspci 命令的 pciutils 包。

# check for pci devices with ID:
#   vendor: Microsoft Corporation (1414)
#   class:  Ethernet Controller (0200)
#   device: Microsft Azure Network Adapter VF (00ba)
if [[ -n `lspci -d 1414:00ba:0200` ]]; then
    echo "MANA device is available."
else
    echo "MANA was not detected."
fi

示例:DPDK 安装 (Ubuntu 22.04)

注意

本文假定系统上安装了兼容的内核和 rdma-core。

DEBIAN_FRONTEND=noninteractive sudo apt-get install -q -y build-essential libudev-dev libnl-3-dev libnl-route-3-dev ninja-build libssl-dev libelf-dev python3-pip meson libnuma-dev

pip3 install pyelftools

# Try latest LTS DPDK, example uses DPDK tag v23.07-rc3
git clone https://github.com/DPDK/dpdk.git -b v23.07-rc3 --depth 1
pushd dpdk
meson build
cd build
ninja
sudo ninja install
popd

示例:Testpmd 设置和 netvsc 测试

请注意以下在使用 MANA 的情况下运行 DPDK 的示例代码。 建议在 Azure 上使用直接到 vf 的“netvsc”配置,以实现 MANA 的最大性能。

注意

DPDK 要求启用 2MB 或 1GB 巨页。 示例采用了附加了 2 个加速网络 NIC 的 Azure VM。

# Enable 2MB hugepages.
echo 1024 | tee /sys/devices/system/node/node*/hugepages/hugepages-2048kB/nr_hugepages

# Assuming use of eth1 for DPDK in this demo
PRIMARY="eth1"

# $ ip -br link show master eth1 
# > enP30832p0s0     UP             f0:0d:3a:ec:b4:0a <... # truncated
# grab interface name for device bound to primary
SECONDARY="`ip -br link show master $PRIMARY | awk '{ print $1 }'`"
# Get mac address for MANA interface (should match primary)
MANA_MAC="`ip -br link show master $PRIMARY | awk '{ print $3 }'`"


# $ ethtool -i enP30832p0s0 | grep bus-info
# > bus-info: 7870:00:00.0
# get MANA device bus info to pass to DPDK
BUS_INFO="`ethtool -i $SECONDARY | grep bus-info | awk '{ print $2 }'`"

# Set MANA interfaces DOWN before starting DPDK
ip link set $PRIMARY down
ip link set $SECONDARY down


## Move synthetic channel to user mode and allow it to be used by NETVSC PMD in DPDK
DEV_UUID=$(basename $(readlink /sys/class/net/$PRIMARY/device))
NET_UUID="f8615163-df3e-46c5-913f-f2d2f965ed0e"
modprobe uio_hv_generic
echo $NET_UUID > /sys/bus/vmbus/drivers/uio_hv_generic/new_id
echo $DEV_UUID > /sys/bus/vmbus/drivers/hv_netvsc/unbind
echo $DEV_UUID > /sys/bus/vmbus/drivers/uio_hv_generic/bind

# MANA single queue test
dpdk-testpmd -l 1-3 --vdev="$BUS_INFO,mac=$MANA_MAC" -- --forward-mode=txonly --auto-start --txd=128 --rxd=128 --stats 2

# MANA multiple queue test (example assumes > 9 cores)
dpdk-testpmd -l 1-6 --vdev="$BUS_INFO,mac=$MANA_MAC" -- --forward-mode=txonly --auto-start --nb-cores=4  --txd=128 --rxd=128 --txq=8 --rxq=8 --stats 2

故障排除

未能将接口设置为 down。

未能将 MANA 绑定设备设置为 DOWN 可能会导致数据包吞吐量较低或为零。 未能释放设备可能会导致与传输队列相关的 EAL 错误消息。

mana_start_tx_queues(): Failed to create qp queue index 0
mana_dev_start(): failed to start tx queues -19

无法启用巨页。

尝试启用巨页并确保该信息在 meminfo 中可见。

EAL: No free 2048 kB hugepages reported on node 0
EAL: FATAL: Cannot get hugepage information.
EAL: Cannot get hugepage information.
EAL: Error - exiting with code: 1
Cause: Cannot init EAL: Permission denied

使用 --vdev="net_vdev_netvsc0,iface=eth1" 时吞吐量较低

为了在 Azure 上实现高性能,不建议对 net_failsafenet_vdev_netvsc 轮询模式驱动程序进行故障转移配置。 DPDK 版本 20.11 或更高版本的 netvsc 配置可能会产生更好的结果。 为了实现最佳性能,请确保 Linux 内核、rdma-core 和 DPDK 包满足列出的 DPDK 和 MANA 要求。

rdma-core 的版本不匹配

rdma-core 和 linux 内核的不匹配随时可能发生;当用户从源代码构建 rdma-core、DPDK 和 linux 内核的某种组合时,通常会出现这种情况。 这种版本不匹配可能会导致 MANA 虚拟功能 (VF) 的探测失败。

EAL: Probe PCI driver: net_mana (1414:ba) device: 7870:00:00.0 (socket 0)
mana_arg_parse_callback(): key=mac value=00:0d:3a:76:3b:d0 index=0
mana_init_once(): MP INIT PRIMARY
mana_pci_probe_mac(): Probe device name mana_0 dev_name uverbs0 ibdev_path /sys/class/infiniband/mana_0
mana_probe_port(): device located port 2 address 00:0D:3A:76:3B:D0
mana_probe_port(): ibv_alloc_parent_domain failed port 2
mana_pci_probe_mac(): Probe on IB port 2 failed -12
EAL: Requested device 7870:00:00.0 cannot be used
EAL: Bus (pci) probe failed.
hn_vf_attach(): Couldn't find port for VF
hn_vf_add(): RNDIS reports VF but device not found, retrying

这可能是因为将包含向后移植补丁的内核用于了具有较新版本的 rdma-core 的 mana_ib。 根本原因是内核 RDMA 驱动程序与用户空间 rdma-core 库之间的交互。

RDMA 的 Linux 内核 uapi 包含 RDMA 提供程序 ID 的列表,在内核的向后移植版本中,此 ID 值可能不同于 rdma-core 库中的版本。

{!注意} 示例代码片段来自 Ubuntu 5.150-1045 linux-azurerdma-core v46.0

// Linux kernel header
// include/uapi/rdma/ib_user_ioctl_verbs.h
enum rdma_driver_id {
	RDMA_DRIVER_UNKNOWN,
	RDMA_DRIVER_MLX5,
	RDMA_DRIVER_MLX4,
	RDMA_DRIVER_CXGB3,
	RDMA_DRIVER_CXGB4,
	RDMA_DRIVER_MTHCA,
	RDMA_DRIVER_BNXT_RE,
	RDMA_DRIVER_OCRDMA,
	RDMA_DRIVER_NES,
	RDMA_DRIVER_I40IW,
	RDMA_DRIVER_IRDMA = RDMA_DRIVER_I40IW,
	RDMA_DRIVER_VMW_PVRDMA,
	RDMA_DRIVER_QEDR,
	RDMA_DRIVER_HNS,
	RDMA_DRIVER_USNIC,
	RDMA_DRIVER_RXE,
	RDMA_DRIVER_HFI1,
	RDMA_DRIVER_QIB,
	RDMA_DRIVER_EFA,
	RDMA_DRIVER_SIW,
	RDMA_DRIVER_MANA, //<- MANA added as last member of enum after backporting
};

// Example mismatched rdma-core ioctl verbs header
// on github: kernel-headers/rdma/ib_user_ioctl_verbs.h
// or in release tar.gz: include/rdma/ib_user_ioctl_verbs.h
enum rdma_driver_id {
	RDMA_DRIVER_UNKNOWN,
	RDMA_DRIVER_MLX5,
	RDMA_DRIVER_MLX4,
	RDMA_DRIVER_CXGB3,
	RDMA_DRIVER_CXGB4,
	RDMA_DRIVER_MTHCA,
	RDMA_DRIVER_BNXT_RE,
	RDMA_DRIVER_OCRDMA,
	RDMA_DRIVER_NES,
	RDMA_DRIVER_I40IW,
	RDMA_DRIVER_IRDMA = RDMA_DRIVER_I40IW,
	RDMA_DRIVER_VMW_PVRDMA,
	RDMA_DRIVER_QEDR,
	RDMA_DRIVER_HNS,
	RDMA_DRIVER_USNIC,
	RDMA_DRIVER_RXE,
	RDMA_DRIVER_HFI1,
	RDMA_DRIVER_QIB,
	RDMA_DRIVER_EFA,
	RDMA_DRIVER_SIW,
	RDMA_DRIVER_ERDMA,  // <- This upstream has two additional providers
	RDMA_DRIVER_MANA,   // <- So MANA's ID in the enum does not match
};

这种不匹配会导致 MANA 提供程序代码加载失败。 请使用 gdb 来跟踪 dpdk-testpmd 的执行,以确认加载的是 ERDMA 提供程序而不是 MANA 提供程序。 对于内核和 rdma-core,MANA driver_id 必须一致。 当这些 ID 匹配时,MANA PMD 会正确加载。