近来购买了R86S作为家里的主路由来使用,同时申请了千兆宽带并买了猫棒,因此需要一个理论上能达到1000M+传输能力的wan口,毕竟整这么多活就是为了能比千兆再快那么一点点。
但是个人不喜欢使用一些知名或者不知名的Github仓库自己编译的固件,总担心其中存在漏洞或者无法长期维护,同时自己编译固件的成本太高。
因此本文核心解决的问题就是将CX342直通到虚拟机中,并直接由原生的OpenWrt接手万兆网卡并处理网络流量。不借助PVE中的网桥,也不使用SR-IOV(SR-IOV模式下驱动问题可参考)
已经安装过PVE的可以直接跳转到后面的万兆网卡驱动和自恢复相关的说明
设备信息罗列:
- R86S-U(N5105/16G/i226-V/CX342)
- PVE 7.4-3
- OpenWrt 22.03.5
本文略长,可按需跳转:
Sec1:安装PVE简单教程
由于R86S自带一个128G的EMMC硬盘,同时我不打算在R86S中打造All in one,因此选择将PVE安装在EMMC磁盘中,后期将再部署一个Win系统直通核显并24h输出画面。
Step1:将PVE镜像烧录到U盘
该步骤是搞机常见操作,推荐使用rufus烧录,别的无他唯手熟尔。
Step2:将PVE安装到EMMC
- 开机进入启动页面后选择:Advanced Option > Install Proxmox VE >Debug Mode
- 第一次中断进入Shell时,按Ctrl+D继续运行
- 第二次中断进入Shell时,修改文件
/usr/bin/proxinstall
- 找到 “unable to get device ….”那行代码
- 将上一个if中的返回值复制替换最后的else
- 结果如下(局部)
- 保存后继续运行(Ctrl+D)
} elsif ($dev =~ m|^/dev/[^/]+/hd[a-z]$|) {
return "${dev}$partnum";
} elsif ($dev =~ m|^/dev/nvme\d+n\d+$|) {
return "${dev}p$partnum";
} else {
return "${dev}p$partnum";
}
Step3:继续安装PVE
1、在选择硬盘时找准128G的EMMC硬盘安装,并在Option选项中将swapsize固定为0
2、选择国家、时区、键盘布局,填密码和邮箱
3、选择网卡并设置IP,根据个人网络规划设置。在此请勿选择万兆网卡上的网口,因为一会儿要直通,再改来改去很麻烦。
4、完成安装
Step4:PVE配置直通参数
因为本文基于R86S来说明,针对AMD CPU的配置可以参看别的教程,不完全一致需要注意。
放一个官网文档在这里:https://pve.proxmox.com/wiki/PCI(e)_Passthrough
- 修改
/etc/default/grub
文件添加启动参数
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on pci=assign-busses iommp=pt"
- 更新引导参数:
update-grub
- 修改
/etc/modules
文件添加模块
vfio
vfio_iommu_type1
vfio_pci
vfio_virqfd
- 更新启动参数:
update-initramfs -u -k all
- 重启reboot
Sec2:创建OpenWrt虚拟机
根据一切从简的原则创建虚拟机,没提到的就是默认。
General
需要填一个名字,并记住VM ID(后面要用到)
OS
- Do not use any media(不使用任何媒体)
- Guest OS:Linux / 6.x-2.6 Kernel
System
- Machine(机型)选择“q35”
需要在创建时选择,后期改的话可能不生效或无法启动虚拟机,报错信息如下。
TASK ERROR: q35 machine model is not enabled at /usr/share/perl5/PVE/QemuServer/PCI.pm line 410.
Disk
删除自动生成的硬盘,在此不添加硬盘和镜像
CPU
- Cores(核心数):根据需要调整,我选的双核
- Type(类型):强烈建议选择host,据说会影响AES性能
Memory
- 合适的内存大小,我使用4096MiB
Network
- 勾选No network device
- 后面将直通万兆网卡,在此添加普通网络会干扰配置
Sec3:直通网卡并安装驱动
Step1: 由OpenWrt镜像文件创建磁盘
- 上传镜像文件到“ISO Images”并获得实际存储路径。
- 通过Shell命令为虚拟机创建磁盘,此处需要创建虚拟机时指定的VM ID和刚刚上传镜像的路径,很多普通安装帖子里都有截图可参考。
qm importdisk 100 /var/lib/vz/template/iso/openwrt-22.03.5-x86-64-generic-ext4-combined.img local-lvm
Step2: 启用镜像磁盘
双击并确定
Step3: 添加万兆网卡CX342
虚拟机Hardware(硬件)选项卡中,Add(添加)-> PCI Device(PCI设备)
找到网卡并选择,同时选择“All Function”、“ROM-Bar”、“PCI-Express”,三个都要选,然后再添加
如果刚刚在创建虚拟机的时候没有选择Q35,此处就无法选择“PCI-Express”,启动即使有驱动也会引发crash,触发mlx4_load_one failed
,触发mlx4_core device is going to be reset
,然后你就能看到网卡反复重启同时也用不了。
Step4: 无网络环境安装驱动
在创建虚拟机时未创建虚拟网口,所以没法通过网络把驱动传进去,能不能手动输入进去更是没试过。因此采用取巧的方法,找一个空U盘将驱动复制进去,并通过挂载物理U盘的方式传递驱动。
此处需要用的驱动是:kmod-mlx4-core_5.10.176-1_x86_64
下载链接(版本对应):https://downloads.openwrt.org/releases/22.03.5/targets/x86/64/packages/
其中的版本号需要根据使用的OpenWrt内核版本找到,不需要自己编译,也不需要无网络升级不匹配的内核。这个驱动只依赖内核,所以别绕弯子解决问题。点名批评一个距离答案很近的博客,看看URL里的版本号也不至于走弯路。
U盘复制安装不多写了,Linux基础操作,分区格式用Fat32最稳,NTFS再见。
cd /tmp
mkdir usb
mount /dev/sdb1 /tmp/usb
cd usb
opkg install kmod-mlx4-core_5.10.176-1_x86_64.ipk
Step5: 安装后配置
通过ip addr
确认驱动正常识别网卡后就可开展其他的Openwrt部署工作了,帖子很多,根据需要食用即可。
Sec4:解决光纤掉线后不会自恢复
系统在长期运行的过程中,可能因为光模块或网卡或改动需要,出现wan口掉线的场景。经过观察后发现mlx4模块不会自动恢复在线状态。内核日志报
mlx4_en: eth4: Link Down
网上相关的讨论和方案有:
https://github.com/openwrt/openwrt/issues/13310
https://forum.openwrt.org/t/eth4-link-stays-down-after-unplugging-and-replugging-cable/135999
https://github.com/nasbdh9/openwrt/commit/5940f3fbb5d42da17e6720942d69a1ef8916f312?diff=unified
在这里,为了避免重新编译openwrt(太麻烦了不想搞),才用定时监控网口状态的方式自动触发内核的hotplug事件来实现网口重新上线。同时怀疑和我的上级交换机协商速率和运营商的宽带配置有关系,但是无法确定,因为lan口掉线后会自动恢复。
找个地方写个检测脚本:
#!/bin/sh
eth_name=$1
eth_status=$(ethtool $eth_name | grep Speed | cut -d' ' -f2)
if [ "$eth_status" = "Unknown!" ]; then
echo $(date "+%Y-%m-%d %H:%M:%S")" Interface eth1 is down. Try to recovery it."
ethtool -s $eth_name speed 10000
fi
需要安装ethtool管理工具,opkg install ethtool
。 然后,“系统”->“计划任务”中添加以下定时任务并保存,注意路径问题。
* * * * * sh /root/shell/mlx4_auto_online.sh eth1 >> /root/shell/mlx4.log
完事后就可以保持wan口是在线状态,即使掉线时间也不会很久。正常情况下,一次重试就能拉起网口状态。
另外,ip link
命令有很大概率无法恢复接口状态,因为没有触发mlx4驱动中接口配置变化。如果有更直接的触发命令也欢迎补充。
我的r86s直通不了, 会报irq busy好像
我的这个应该是初版, 一个千兆两个2.5G的那款, 我的这个cx341在pcie 00:04上
CX342?不是CX341吗