intel 82576网卡折腾-sr-iov使用

缘起

前段时间安装的openwrt虚拟机,网卡是基于螃蟹卡虚拟出来的,性能在一些高占用下可能会不稳定。

而intel的服务器网卡,能够通过网卡自带的虚拟化,在一个网卡硬件(pf)上,虚拟出很多的网卡(vf)出来,这些虚拟出来的网卡,每个都可以作为单独网卡使用,非常的方便,这个技术叫做SR-IOV,大家可以搜下技术资料,了解下pf、vf的概念。

因此就某鱼上淘了一张intel 82576的双口千兆网卡来,才65块钱,折腾搞起来~~~

折腾过程

0、不饶圈子,先说下这个intel82576的坑吧

这个82576网卡,在ubuntu server 18.04系统下不用安装驱动,默认已经安装了intel的igb驱动,可以直接认。

坑:网线像是不通,路由器对应端口不亮

intel 82576网卡插上没反应,连不上网络。可能是这张intel网卡做了优化吧(为了省电?),如果没有在系统里声明了网卡物理接口(pf),那么就是像不通一样的。

即使使用ethtool测试,也都是未连接状态

ethtool enp4s0f1 

如果是对vf,或者没有声明pf,则永远都是Link detected: no

需要做的是:在netplan里声明下这个物理接口

发现哪个网卡是pf,可以使用如下脚本

类似这个即是物理网卡 Virtual Functions on Intel Corporation 82576 Gigabit Network Connection. (enp4s0f1):

#!/bin/bash

NIC_DIR="/sys/class/net"
for i in $( ls $NIC_DIR) ;
do
	if [ -d "${NIC_DIR}/$i/device" -a ! -L "${NIC_DIR}/$i/device/physfn" ]; then
		declare -a VF_PCI_BDF
		declare -a VF_INTERFACE
		k=0
		for j in $( ls "${NIC_DIR}/$i/device" ) ;
		do
			if [[ "$j" == "virtfn"* ]]; then
				VF_PCI=$( readlink "${NIC_DIR}/$i/device/$j" | cut -d '/' -f2 )
				VF_PCI_BDF[$k]=$VF_PCI
				#get the interface name for the VF at this PCI Address
				for iface in $( ls $NIC_DIR );
				do
					link_dir=$( readlink ${NIC_DIR}/$iface )
					if [[ "$link_dir" == *"$VF_PCI"* ]]; then
						VF_INTERFACE[$k]=$iface
					fi
				done
				((k++))
			fi
		done
		NUM_VFs=${#VF_PCI_BDF[@]}
		if [[ $NUM_VFs -gt 0 ]]; then
			#get the PF Device Description
			PF_PCI=$( readlink "${NIC_DIR}/$i/device" | cut -d '/' -f4 )
			PF_VENDOR=$( lspci -vmmks $PF_PCI | grep ^Vendor | cut -f2)
			PF_NAME=$( lspci -vmmks $PF_PCI | grep ^Device | cut -f2).
			echo "Virtual Functions on $PF_VENDOR $PF_NAME ($i):"
			echo -e "PCI BDF\t\tInterface"
			echo -e "=======\t\t========="
			for (( l = 0; l < $NUM_VFs; l++ )) ;
			do
				echo -e "${VF_PCI_BDF[$l]}\t${VF_INTERFACE[$l]}"
			done
			unset VF_PCI_BDF
			unset VF_INTERFACE
			echo " "
		fi
	fi
done

坑:虚拟机不能直通vf

由于在某些主板下,所有的网卡,被分配到同一个iommu的分组里,而虚拟化硬件直通,需要把一个组的设备全部直通,因此不能单独直通一个vf,会报如下的错误。

intel Please ensure all devices within the iommu_group are bound to their vfio bus driver.

这个可以通过自己编译内核,增加acs override解决。

1、网卡插不上咋办,锯接口呗o( ̄︶ ̄)o

买来网卡,开心的拆开机箱准备开干,尴尬的一幕发生了,我的华擎j3455主板,居然tm没有pcie x4的接口,只有x1的接口,而新买的网卡是x4的,于是就插不上了。。。

本来已经准备在某宝买个转接卡了,因为一般pcie接口都是向下兼容的,比如显卡x16的,但是插在主板x8的接口上,依然是可以工作的。

然后不死心,又搜索了一番,发现网上的老哥思想真的活跃,居然可以把x1的接口锯开,直接插x4的网卡上去,真乃人才。。。

锯接口的过程是非常难搞的,我拿一把美工刀,硬是慢慢切下去了,花了有一上午,大家有角磨机的可以省很多功夫,另外,一定要精细些,不然搞断引脚那就彻底废了。

intel82576网卡不通?路由器上灯不亮

经过第一步的折腾,千辛万苦终于可以插上去了,发现一个诡异的事情,接口都是不通的,路由器灯不亮,像是没插线一样。

使用ethtool测试,也是未连接状态。

# 执行ethtool查看网卡状态
ethtool enp4s17f3
Settings for enp4s17f3:
	Supported ports: [ ]
	Supported link modes:   1000baseT/Full
	Supported pause frame use: No
	Supports auto-negotiation: No
	Supported FEC modes: Not reported
	Advertised link modes:  1000baseT/Full
	Advertised pause frame use: No
	Advertised auto-negotiation: No
	Advertised FEC modes: Not reported
	Speed: 1000Mb/s
	Duplex: Full
	Port: Other
	PHYAD: 0
	Transceiver: internal
	Auto-negotiation: offCannot get wake-on-lan settings: Operation not permitted
	Current message level: 0x00000007 (7)
			       drv probe link
	Link detected: no

这个问题,算是对于普通用户使用intel网卡的一个很大的坑,上面的坑里边已经讲了,经过几天的摸索,终于通过获取物理pf,然后将对应的网卡名称在netplan里进行声明解决了。

另外再说一点,对于intel 82576等支持sr-iov的网卡,都是需要先把pf启动起来(即在网卡声明里写上),然后才能使用各个vf的网卡的,包括在系统网卡声明里声明,已经直通给虚拟机,直接操作vf是不行的,完全没法用。

虚拟机直通

经过第一步的折腾,可以在宿主机里正常的使用pf、vf了,接下来就是虚拟机网卡直通了。

1、开启grub的iommu启动参数

使用如下命令开启:

sudo vi /etc/default/grub

# GRUB_CMDLINE_LINUX_DEFAULT=里增加如下参数,记得参数末尾加空格

iommu=pt intel_iommu=on

# update一下grub
sudo update-grub2

sudo reboot

2、在虚拟机里增加虚拟网卡

可以通过virsh edit [虚拟机name] 编辑网卡,在devices段中增加如下参数配置vf虚拟网卡。

<interface type='hostdev' managed='yes'>
      <mac address='33:33:00:33:33:33'/>
      <source>
        <address type='pci' domain='0x0000' bus='0x04' slot='0x11' function='0x5'/>
      </source>
    </interface>

其中这里的mac地址是设置直通的网卡的mac,可以随意设置。 这里的pci地址,可以使用之前的发现intel 网卡信息的脚本里找到。

Virtual Functions on Intel Corporation 82576 Gigabit Network Connection. (enp4s0f1):
PCI BDF		Interface=======		=========
0000:04:10.1	enp4s16f1
0000:04:10.3	enp4s16f3
0000:04:10.5	enp4s16f5
0000:04:10.7	enp4s16f7
0000:04:11.1	enp4s17f1
0000:04:11.3	enp4s17f3

比如要直通enp4s17f3,这里的pc地址就分别是0000:04:11.3

保存退出后,shutdown然后在start虚拟机,就可以啦。

3、解决iommu分组问题导致的不能直通问题

由于内核对于安全性的考虑,导致在同一个pcie通道内的网卡,分组在了统一iommu组内,直通某一个就会报错。

这个问题可以通过自己编译内核解决,可以参考这个项目的方法进行。

补丁文件可以参考这里 https://gitlab.com/Queuecumber/linux-acs-override

操作方法可以参考这里 https://koolshare.cn/thread-166076-1-1.html

注意:这种方法是存在安全隐患的,切勿在公共虚拟化环境下使用
注意:这种方法是存在安全隐患的,切勿在公共虚拟化环境下使用
注意:这种方法是存在安全隐患的,切勿在公共虚拟化环境下使用

同时呢,由于我们是强行的拆解iommu的组,还需要修改下补丁的这一行,据说sata控制器直通存在问题,不建议这种方法直通,网卡应该是可以的。

+        if (!pci_is_pcie(dev) ||
+                pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS))

改成

+        if (!pci_is_pcie(dev))

经过自行编译内核,然后安装后,使用如下命令开启内核,

sudo vi /etc/default/grub

# GRUB_CMDLINE_LINUX_DEFAULT=里增加如下参数,记得参数末尾加空格

pcie_acs_override=downstream,multifunction

# update一下grub

sudo update-grub2

sudo reboot

4、openwrt安装intel vf驱动

由于默认情况下,openwrt没有按照igbvf的驱动,可以在openwrt里使用如下命令安装:

opkg updateopkg install kmod-igbvf

一些有用的命令和tips

# 查看网卡信息
lshw -c network -businfo

# 查看iommu组信息
find /sys/kernel/iommu_groups/ -type l

# 查看详细的iommu组信息
for d in /sys/kernel/iommu_groups/*/devices/*; do n=${d#*/iommu_groups/*}; n=${n%%/*}; printf 'IOMMU Group %s ' "$n"; lspci -nns "${d##*/}"; done;

# 查看内核的iommu信息
dmesg |grep -i iommu

vf的使用,必须是对应的pf在线才能用起来,pf和vf只有pf在宿主内启用起来即在网络接口那里进行声明,可以不用绑定ip地址,只声明下就可以,然后vf可以直通给虚拟机作为普通网卡

由于虚拟出来的设备很多,需要辨别哪些pf、vf是插了网线的那个接口,建议使用文章开头的脚本来做

需要asc控制补丁才能单独设备分组,在iommu里分配设备直通到虚拟机

openwrt自带igb驱动,可以直接驱动intel 82576网卡,但是不能使用igbvf驱动宿主的vf虚拟网卡,需要安装 kmod-igbvf

pihole换了虚拟化vf的网卡后不能使用,是dns设置界面,默认是只监听其中一个网卡的,选择第三项,监听所有即可。

经过验证,是由于使用了intel网卡同一个网卡虚拟出的2个vf导致的问题,可能导致只监听一个网卡接口的设置下,判断不准导致其他客户端不能解析域名。

总结

整个折腾过程的坑非常的多,可能由于折腾的是专业的服务器领域的东西,好像资料也很少,整个过程非常的曲折。我一度以为这个网卡是坏的,我打磨的pcie 1接口是坏的。。。。 直到我切换到windows系统里,可以正常识别网卡。

生命在于折腾吧。。。另外总算知道了intel网卡sr-iov的用法了。即,宿主机绑定pf,然后虚拟机直通vf。中间的通信,通过宿主和虚拟机的驱动进行。

参考资料

https://linuxconfig.org/how-to-detect-whether-a-physical-cable-is-connected-to-network-card-slot-on-linux

https://yq.aliyun.com/articles/721471

https://gitlab.com/Queuecumber/linux-acs-override

https://forums.unraid.net/topic/72027-iommu-group-splitting-for-pcie-passthrough-no-success-please-help/

https://heiko-sieger.info/iommu-groups-what-you-need-to-consider/

https://blog.acelan.idv.tw/2018/01/13/Build-Ubuntu-Kernel-on-PPA/

https://lkml.org/lkml/2013/5/30/513

https://koolshare.cn/thread-166076-3-1.html

https://www.reddit.com/r/VFIO/comments/8muu74/acs_patch_will_not_let_me_select_specific_devices/

https://software.intel.com/en-us/articles/configure-sr-iov-network-virtual-functions-in-linux-kvm

https://www.cnblogs.com/liuhongru/p/11068460.html

https://openwrt.org/packages/pkgdata/kmod-igbvf


已有3位网友发表了看法:

1L访客 2022-01-05 19:46:03 回复
生命在于折腾。居然还有锯接口这招。高人就是多!
2L访客 2022-12-17 00:21:32 回复
关于这张网卡,想请教下,有时间吗
3Lyfst35 2022-12-30 18:22:48 回复
iommu分组报错,不修改grub或内核的解决方法:尝试换插槽(比如从x1换成x16)
echo: write error: no such file or directory的办法:bios设置把pci ari support打开(在iommu一个页面)

发表评论

必填

选填

选填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。