一、技術簡介
VF-LAG(Virtual Function Link Aggregation Group) 是 Mellanox/NVIDIA 網卡(如 ConnectX-5/6/7)支持的一種硬件級鏈路聚合技術。它允許將多端口物理網卡的 SR-IOV 虛擬功能(VF)跨端口聚合到同一個 LAG 組,實現高可用和LB,提升虛擬化環境下的網絡性能和可靠性。
VF-LAG 相較于傳統 SR-IOV,主要有以下優勢:
- 高可用性(HA)
- 傳統 SR-IOV:每個 VF 只能綁定在單一物理端口(PF),如果該端口鏈路斷開,VF 網絡中斷。
- VF-LAG:單個 VF 綁定在 LAG(多個物理端口聚合)上,任一物理端口斷開,VF 仍可通過其他端口通信,實現鏈路冗余和無縫切換。
- LB
- 傳統 SR-IOV:VF 的流量只能走單一物理端口,如果該端口鏈路斷開,VF 網絡中斷。
- VF-LAG:VF 的流量可在多個物理端口間分擔,實現流量的均衡。
- 簡化網絡配置
- 傳統 SR-IOV:需要在主機側做 Bonding 或 Teaming,配置復雜,且 SR-IOV VF 直通場景下主機 Bonding 無法直接作用于 VF。
- VF-LAG:LAG 聚合在硬件/固件層實現,VF 直通給虛擬機/容器后,VM/容器側無需做 Bonding,網絡高可用和 LB 自動生效。
- 更好的虛擬化支持
- 傳統 SR-IOV:VF 直通后,虛擬機/容器側無法感知和利用多端口聚合。
- VF-LAG:VF 直通后,VM/容器自動獲得 LAG 能力,無需額外配置,適合云原生和高性能虛擬化場景。
- 簡化運維
- 傳統 SR-IOV:鏈路聚合、故障切換等需主機和虛擬機多層配合,運維復雜。
- VF-LAG:所有聚合和切換在硬件完成,極大簡化網絡運維。
因此,可以看出VF-LAG 讓 SR-IOV VF 具備了硬件級 LAG 的高可用和LB能力,極大提升了虛擬化和云原生場景下的網絡可靠性與性能,同時簡化了運維。
二、原理簡述
- 傳統 SR-IOV:每個 VF 只能綁定在單一物理端口。
- VF-LAG:多個物理端口組成 LAG,VF 綁定在 LAG 上,流量可在多個端口間分擔。
- VF-LAG 由固件和驅動協同實現,DPDK 側無需特殊適配。
三、配置步驟
3.1 前置條件
需要有支持 VF-LAG 的 Mellanox 雙端口網卡(如 ConnectX-5/6/7),VF-LAG 不支持跨網卡,需要使用同一張網卡的 2 個端口組建 BOND。
# lshw -c network -businfo
Bus info Device Class Description
==========================================================
pci@0000:01:00.0 enp1s0f0np0 network MT2892 Family [ConnectX-6 Dx]
pci@0000:01:00.1 enp1s0f1np1 network MT2892 Family [ConnectX-6 Dx]
3.2 配置步驟
- 啟用 sriov 功能
# echo 4 > /sys/class/net/enp1s0f0np0/device/sriov_numvfs
# echo 4 > /sys/class/net/enp1s0f1np1/device/sriov_numvfs
# ip link show enp1s0f0np0
692: enp1s0f0np0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 94:6d:ae:8f:c1:c2 brd ff:ff:ff:ff:ff:ff
vf 0 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking off, link-state auto, trust off, query_rss off
vf 1 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking off, link-state auto, trust off, query_rss off
vf 2 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking off, link-state auto, trust off, query_rss off
vf 3 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking off, link-state auto, trust off, query_rss off
# ip link show enp1s0f1np1
693: enp1s0f1np1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 94:6d:ae:8f:c1:c3 brd ff:ff:ff:ff:ff:ff
vf 0 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking off, link-state auto, trust off, query_rss off
vf 1 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking off, link-state auto, trust off, query_rss off
vf 2 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking off, link-state auto, trust off, query_rss off
vf 3 link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff, spoof checking off, link-state auto, trust off, query_rss off
- 解綁 vf 驅動
# lshw -c network -businfo
Bus info Device Class Description
==========================================================
pci@0000:01:00.0 enp1s0f0np0 network MT2892 Family [ConnectX-6 Dx]
pci@0000:01:00.1 enp1s0f1np1 network MT2892 Family [ConnectX-6 Dx]
pci@0000:01:00.2 enp1s0f0v0 network ConnectX Family mlx5Gen Virtual Function
pci@0000:01:00.3 enp1s0f0v1 network ConnectX Family mlx5Gen Virtual Function
pci@0000:01:00.4 enp1s0f0v2 network ConnectX Family mlx5Gen Virtual Function
pci@0000:01:00.5 enp1s0f0v3 network ConnectX Family mlx5Gen Virtual Function
pci@0000:01:04.2 enp1s0f1v0 network ConnectX Family mlx5Gen Virtual Function
pci@0000:01:04.3 enp1s0f1v1 network ConnectX Family mlx5Gen Virtual Function
pci@0000:01:04.4 enp1s0f1v2 network ConnectX Family mlx5Gen Virtual Function
pci@0000:01:04.5 enp1s0f1v3 network ConnectX Family mlx5Gen Virtual Function
# echo 0000:01:00.2 > /sys/bus/pci/drivers/mlx5_core/unbind
# echo 0000:01:00.3 > /sys/bus/pci/drivers/mlx5_core/unbind
# echo 0000:01:00.4 > /sys/bus/pci/drivers/mlx5_core/unbind
# echo 0000:01:00.5 > /sys/bus/pci/drivers/mlx5_core/unbind
# echo 0000:01:04.2 > /sys/bus/pci/drivers/mlx5_core/unbind
# echo 0000:01:04.3 > /sys/bus/pci/drivers/mlx5_core/unbind
# echo 0000:01:04.4 > /sys/bus/pci/drivers/mlx5_core/unbind
# echo 0000:01:04.5 > /sys/bus/pci/drivers/mlx5_core/unbind
- 配置網卡 switchdev模式 && 開啟硬件offload
VF LAG 需要將 LAG 功能 offload 到硬件 eswitch,并且需要下發對應的匹配規則,因此需要網卡配置 switchdev 模式,并開啟網卡硬件offload功能。
# devlink dev eswitch set pci/0000:01:00.0 mode switchdev
# devlink dev eswitch set pci/0000:01:00.1 mode switchdev
# devlink dev eswitch show pci/0000:01:00.0
pci/0000:01:00.0: mode switchdev inline-mode none encap-mode basic
# devlink dev eswitch show pci/0000:01:00.1
pci/0000:01:00.1: mode switchdev inline-mode none encap-mode basic
# ethtool -K enp1s0f0np0 hw-tc-offload on
# ethtool -K enp1s0f1np1 hw-tc-offload on
# ethtool -k enp1s0f0np0 | grep hw-tc-offload
hw-tc-offload: on
# ethtool -k enp1s0f1np1 | grep hw-tc-offload
hw-tc-offload: on
- 配置 BOND
vf lag 需要組建硬件的 bond,該bond 只能使用同一張物理網卡的兩個物理口組建 bond,不可以跨網卡。支持的 bond 模式有三種:Active-backup、XOR 和 LACP。使用硬件offload功能之后,通過下發規則,使兩個 pf 口的數據包可轉發到任何一個 pf 下的 vf 口。對于 vf 口出向的流量在 主備 bond 模式下,只有一個 pf 運行,VF 的流量只會通過該 pf 口;在 XOR 或 LACP bond 模式下,如果兩個 PF 均正常運行,則 vf 出向的流量會在這兩個 pf 之間進行流量均衡。
以下使用常用的 LACP bond 的模式為例:
# modprobe bonding mode=802.3ad
# ip link add vf-bond type bond mode 802.3ad
# ip link set enp1s0f0np0 down
# ip link set enp1s0f1np1 down
# ip link set enp1s0f0np0 master vf-bond
# ip link set enp1s0f1np1 master vf-bond
# ip link set enp1s0f0np0 up
# ip link set enp1s0f1np1 up
# mst status -v
MST modules:
------------
MST PCI module is not loaded
MST PCI configuration module loaded
PCI devices:
------------
DEVICE_TYPE MST PCI RDMA NET NUMA
ConnectX6DX(rev:0) /dev/mst/mt4125_pciconf0.1 01:00.1 mlx5_bond_0 net-enp1s0f1npf1vf0,net-enp1s0f1npf1vf3,net-vf-bond,0
ConnectX6DX(rev:0) /dev/mst/mt4125_pciconf0 01:00.0 mlx5_bond_0 net-enp1s0f0npf0vf2,net-vf-bond,net-enp1s0f0npf0vf0,0
# dmest -T
...
[四 6月 26 18:07:45 2025] mlx5_core 0000:01:00.0 enp1s0f0np0: Link down
[四 6月 26 18:07:45 2025] vf-bond: (slave enp1s0f0np0): Enslaving as a backup interface with a down link
[四 6月 26 18:07:52 2025] mlx5_core 0000:01:00.1 enp1s0f1np1: Link down
[四 6月 26 18:07:52 2025] vf-bond: (slave enp1s0f1np1): Enslaving as a backup interface with a down link
[四 6月 26 18:07:52 2025] mlx5_core 0000:01:00.0 enp1s0f0np0: Link up
[四 6月 26 18:07:52 2025] mlx5_core 0000:01:00.0: lag map active ports: 1, 2
[四 6月 26 18:07:52 2025] mlx5_core 0000:01:00.0: shared_fdb:1 mode:hash
[四 6月 26 18:07:52 2025] mlx5_core 0000:01:00.1 enp1s0f1np1: Link down
[四 6月 26 18:07:52 2025] mlx5_core 0000:01:00.0: Operation mode is single FDB
[四 6月 26 18:07:59 2025] mlx5_core 0000:01:00.1 enp1s0f1np1: Link up
[四 6月 26 18:07:59 2025] mlx5_core 0000:01:00.0 enp1s0f0np0: Link up
...
- 重新綁定 vf 驅動
# echo 0000:01:00.2 > /sys/bus/pci/drivers/mlx5_core/bind
# echo 0000:01:00.3 > /sys/bus/pci/drivers/mlx5_core/bind
# echo 0000:01:00.4 > /sys/bus/pci/drivers/mlx5_core/bind
# echo 0000:01:00.5 > /sys/bus/pci/drivers/mlx5_core/bind
# echo 0000:01:04.2 > /sys/bus/pci/drivers/mlx5_core/bind
# echo 0000:01:04.3 > /sys/bus/pci/drivers/mlx5_core/bind
# echo 0000:01:04.4 > /sys/bus/pci/drivers/mlx5_core/bind
# echo 0000:01:04.5 > /sys/bus/pci/drivers/mlx5_core/bind
- 下發規則
下面簡單下發一條入向的規則到兩個 pf 口作為測試使用,該規則匹配目的 vf mac,將流量均轉發到該 vf representor port。
# ethtool -i enp1s0f0npf0vf0
driver: mlx5e_rep
version: 5.10.0-136.12.0.88.4.ctl3.x86_6
firmware-version: 22.43.2026 (MT_0000000359)
expansion-rom-version:
bus-info:
supports-statistics: yes
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no
# ethtool -i enp1s0f0v0
driver: mlx5_core
version: 24.10-1.1.4
firmware-version: 22.43.2026 (MT_0000000359)
expansion-rom-version:
bus-info: 0000:01:00.2
supports-statistics: yes
supports-test: yes
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: yes
# ethtool -K enp1s0f0npf0vf0 hw-tc-offload on
# tc qdisc add dev vf-bond ingress_block 22 ingress
# tc qdisc add dev enp1s0f0np0 ingress_block 22 ingress
# tc qdisc add dev enp1s0f1np1 ingress_block 22 ingress
# tc filter add block 22 protocol 0x0800 parent ffff: prio 1 flower dst_mac 52:54:00:00:00:01 action mirred egress redirect dev enp1s0f0npf0vf0
- testpmd 接管 vf
交換機側需要配置 lacp bond,對端打多流,這里略過。
# dpdk-testpmd -l 1-2 -n 4 -a 0000:01:00.2 -- -i
testpmd> mac_addr set 0 52:54:00:00:00:01
testpmd> set verbose 1
Change verbose level from 0 to 1
testpmd> start
打流的過程中,可以發現 vf 口可以抓到對應的報文。在交換機側通過切換對應的 PF 口鏈路狀態,可以看到 vf 口均可以正常收到報文。