
前阵子给机器加了一张Realtek RTL8125 2.5G PCIe网卡装好Ubuntu 24.04后发现一个很尴尬的现象局域网里从NAS拖单个大文件速度始终稳定在110MB/s左右怎么调都上不去。查了半天dmesg里清清楚楚写着driver: r8169问题一下子就明白了——系统默认挂的是内核通用驱动它可没有为2.5G网卡做专门的优化。后来我在一个软路由群吐槽发现遇到这个坑的不止我一个就连Windows下板载RTL8125的用户也经常在论坛里抱怨“明明换了2.5G交换机速度还是千兆”。这篇文章就说一件事如何在Ubuntu下彻底告别r8169切换到Realtek官方r8125驱动并用DKMS把驱动管理起来让以后升级内核也不用再折腾。整个过程不涉及复杂的交叉编译照着做就能搞定适合所有被Realtek 2.5GbE网卡折磨过的Linux用户。1. 问题定位先搞清楚你的网卡和驱动现状1.1 为什么r8169驱动在Realtek 2.5GbE网卡上不给力r8169这个驱动是内核自带的通用Realtek网卡驱动它要兼顾RTL8168系列千兆网卡、RTL8125系列2.5G网卡甚至还有部分老旧的百兆芯片。问题是Linux内核维护者和Realtek官方驱动的开发节奏并不同步导致r8169对RTL8125的支持一直处于“能用但不够好”的状态。典型的表现在几个方面第一协商速度虽然显示2500Mb/s但实际吞吐量跑不满用iperf3测试经常会卡在900Mbps到1.5Gbps之间第二大流量传输时软中断占用CPU特别高我用sar看了一眼单核软中断占比能到60%以上第三部分固件版本下会出现网卡掉线、重启后无法识别、或者从睡眠唤醒后丢链接的毛病。有人会说既然r8169能用那凑合着用不就行了如果你只是日常办公、看看网页确实感觉不出来。但如果你是NAS用户、软路由玩家或者需要频繁拷贝大文件2.5G网卡跑成千兆水平硬件钱等于白花了。基础链路在那里驱动不给力只能从软件层面解决。1.2 确认网卡型号与当前驱动状态动手之前先确认你手里的网卡到底是不是RTL8125系列以及当前系统到底在用什么驱动。lspci -nnk | grep -i ethernet输出里能看到类似这样的信息03:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8125 2.5GbE Controller [10ec:8125] (rev 05) Subsystem: Realtek Semiconductor Co., Ltd. RTL8125 2.5GbE Controller [10ec:8125] Kernel driver in use: r8169注意看“Kernel driver in use”这一行如果显示的是r8169那说明你正走在几乎所有Realtek 2.5G用户都踩过的老路上。RTL8125的PCI设备ID通常是10ec:8125如果显示的是10ec:8168那是千兆的RTL8168不在本文讨论范围内但也同样可以换成官方r8168驱动。再用ethtool看一眼当前驱动的能力ethtool -i enp3s0这里enp3s0是我机器上的网卡接口名你的机器可能叫eth0、eno1之类的以实际ip link show输出为准。正常情况下你会看到driver: r8169firmware-version可能为空这说明驱动没有加载专用的固件文件。另外一个重要命令是dmesg | grep -i r8169如果开机日志里出现“r8169 0000:03:00.0: Direct firmware load for rtl_nic/rtl8125a-3.fw failed”之类的字样说明驱动试图加载RTL8125的固件但失败了这往往就是吞吐量上不去的直接原因之一。内核自带的r8169驱动虽然能识别芯片但固件加载路径可能有缺失或者固件版本太旧跟Windows下Realtek官方驱动的表现完全不是一个量级。2. 方案选型为什么选择Realtek官方r8125驱动 DKMS2.1 三种驱动方案的横向对比面对RTL8125网卡你并不是只有一种选择。我梳理了一下大致有三条路可以走第一种是继续用内核自带的r8169零成本、零操作但问题是你得忍受吞吐量不达标、CPU占用偏高、偶尔断流这些毛病。如果路由器、交换机、网线都没问题基本可以确定是驱动拖后腿。第二种是用Realtek官方发布的r8125驱动源码手动编译安装。这个方案能让网卡发挥出应有的性能因为Realtek官方会根据芯片的具体特性做优化比内核通用驱动靠谱得多。缺点是Linux内核升级后驱动模块需要重新编译因为内核API一直在变旧的.ko文件在新内核下很可能无法加载。手动编译一次两次还能忍但每次升级内核都要来一遍真的会让人崩溃。第三种就是本文要讲的r8125驱动 DKMS。DKMS全称Dynamic Kernel Module Support它会把驱动源码注册到系统里在内核升级时自动重新编译并安装对应的模块。也就是说你只需要折腾一次以后内核怎么升级驱动都会自动适配。我为什么最终选择第三种方案因为它把“发音量”和“免维护”结合在了一起。Realtek官方驱动负责性能DKMS负责适配内核变化两边各干各的活非常省心。2.2 DKMS的工作原理DKMS用一句话解释就是让内核模块的源码常驻系统在新内核安装完成后自动重新编译。具体工作方式如下你把驱动源码放到/usr/src/r8125-版本号目录下然后用dkms命令把它登记进DKMS的数据库。系统里每安装一个新内核DKMS都会检查一遍注册过的模块清单如果发现某个模块还没有针对当前内核版本编译过就自动执行编译和安装。这就好比你去健身房办了张年卡以后每次开门你都直接进去练不需要每次都办临时卡。之前手动编译驱动的方式相当于每次内核升级都重新办卡DKMS把这件重复劳动彻底干掉了。我喜欢用这个方案还有另一个原因出了问题好回滚。DKMS的所有模块都安装在/lib/modules/$(uname -r)/updates/dkms/目录下如果新驱动有问题dkms remove一键卸载再modprobe r8169就能回到原来的状态不像手动编译那样容易把系统搞乱。3. 实战准备下载驱动源码与环境依赖3.1 从Realtek官方获取r8125源码Realtek官方其实长期维护着Linux下的r8125驱动只是官网上这个入口藏得比较深很容易找不到。你可以去Realtek官网的“下载中心”在产品分类里选“网卡芯片”搜索RTL8125然后在软件下载里找Linux驱动。下载到的是一个tar.bz2压缩包文件名通常是r8125-9.012.03.tar.bz2这种格式版本号会随着时间更新。我写这篇文章时用的版本是9.012.03但你可能下载到更新的版本没关系操作流程是一样的只要把命令里的版本号替换成你自己的就行。下载完之后建议先校验一下文件的完整性避免下载损坏导致编译到一半报错md5sum r8125-9.012.03.tar.bz2把输出的MD5值和官网公布的校验值对比一下。当然如果你用浏览器直接下载一般不会有损坏问题但服务器上用wget下载时这个步骤还是挺有必要的。除了官网GitHub上也有不少人维护了r8125的DKMS封装比如awesometic/realtek-r8125-dkms。这个仓库把官方源码和dkms.conf打包好了可以直接用dkms命令安装。如果你在Ubuntu 22.04或24.04上用的是比较新的内核直接用这个仓库也省事。不过我个人更推荐从官方下载源码自己写dkms.conf因为这样你能知道整个流程每一步在干什么出问题的时候排查起来也更有头绪。3.2 安装编译依赖与内核头文件在编译任何内核模块之前系统里必须有完整的编译工具链和与当前内核版本匹配的头文件。sudo apt update sudo apt install -y build-essential dkms linux-headers-generic这里有一个容易被忽视的细节为什么不直接装linux-headers-$(uname -r)而要装linux-headers-generic因为linux-headers-generic是一个虚拟包它会跟随内核的更新自动安装对应版本的头文件。DKMS的价值就在于内核升级后自动重编驱动如果只装了当前版本的头文件下次内核一升级头文件没跟上DKMS就会编译失败到时候网卡又变回r8169了。所以直接用linux-headers-generic是最省心的做法。如果你用的是Ubuntu的HWE内核Hardware Enablement内核那可能还需要装hwe版本的头文件sudo apt install -y linux-headers-generic-hwe-24.04装完以后可以确认一下dkms status ls /usr/src/linux-headers-$(uname -r)如果能看到linux-headers目录存在说明编译环境就绪了。这里再提一句最好先把系统里所有能升级的包都升一遍尤其是内核本身。因为如果当前内核比较老r8125新版本驱动可能会用一些新内核才有的API编译时容易报错。先把系统更新到最新可以少踩很多坑。4. 核心步骤编译安装r8125驱动并注册DKMS4.1 解压源码与调整dkms.conf下载完毕、依赖装好之后正式进入驱动安装环节。先把源码解压放到DKMS能扫描到的位置。DKMS默认会扫描/usr/src目录下的所有“包名-版本号”格式的文件夹所以我们把源码解压后复制到/usr/src下tar xjf r8125-9.012.03.tar.bz2 sudo cp -r r8125-9.012.03 /usr/src/ cd /usr/src/r8125-9.012.03接下来需要确认目录下有没有dkms.conf这个文件。Realtek官方原版压缩包里通常没有它默认提供的是一个autorun.sh脚本调用Makefile直接编译安装。但我们既然要用DKMS管理驱动就必须让DKMS知道该如何编译和安装这个模块。如果没有dkms.conf就自己创建一个sudo nano dkms.conf我建议的内容如下版本号根据你的实际目录名修改PACKAGE_NAMEr8125 PACKAGE_VERSION9.012.03 BUILT_MODULE_NAME[0]r8125 DEST_MODULE_LOCATION[0]/kernel/drivers/net/ethernet/realtek AUTOINSTALLyes MAKE[0]make -C ${kernel_source_dir} modules M${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build CLEANmake -C ${kernel_source_dir} clean M${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build解释一下关键参数的含义PACKAGE_NAME和PACKAGE_VERSIONDKMS数据库里登记的名称和版本号会作为/usr/src子目录的匹配依据。BUILT_MODULE_NAME[0]指定编译产物模块名。DEST_MODULE_LOCATION[0]模块安装在/lib/modules/内核版本/updates/dkms下的相对路径。AUTOINSTALLyes告诉DKMS新内核安装后自动编译这个模块。MAKE[0]编译命令。这里用了RTL8125官方驱动标准的内核模块构建方式。不同的型号或版本Makefile可能略有差异建议先打开源码目录下的Makefile看一眼确认支持外置编译。官方驱动源码里通常包含有“modules”这个make目标用上述配置就能成功。4.2 DKMS add / build / install 三板斧配置文件准备好后DKMS的操作就非常标准了。先把模块登记进DKMSsudo dkms add -m r8125 -v 9.012.03如果一切正常会输出类似于“DKMS: add completed.”的信息。然后开始编译sudo dkms build -m r8125 -v 9.012.03这一步会真正调用Makefile编译内核模块编译过程中会输出一大堆日志。如果编译失败别急着慌先去查日志sudo tail -n 100 /var/lib/dkms/r8125/9.012.03/build/make.log最常见的原因无非是内核头文件没装全或者源码本身和当前内核版本不兼容。看到“ERROR: modpost: ... undefined”之类的字眼基本都是头文件版本不匹配回去重新装linux-headers-generic再试。编译通过后安装模块文件sudo dkms install -m r8125 -v 9.012.03这时可以确认一下模块文件是否已经生成ls -l /lib/modules/$(uname -r)/updates/dkms/r8125.ko看到文件存在说明DKMS这步已经完成。这时候用dkms status应该能看到类似这样的输出r8125/9.012.03, 6.8.0-45-generic, x86_64: installed这个状态表示驱动已经注册成功等新内核升级时它会自动重新编译。4.3 让旧驱动r8169不再抢占网卡r8125驱动虽然装好了但系统重启后内核可能会优先加载r8169因为它是内核自带的驱动优先级高于第三方DKMS模块。解决这个问题的方法是把r8169列入黑名单。创建一个黑名单配置文件sudo tee /etc/modprobe.d/blacklist-r8169.conf blacklist r8169然后更新模块依赖关系sudo depmod -a接下来卸载当前的r8169模块并加载新的r8125模块sudo rmmod r8169 sudo modprobe r8125这里有个细节要注意rmmod r8169时如果提示“Module r8169 is in use by ...”说明网卡接口正在被使用。你需要先把网卡down掉或者断开该接口上的网络连接再执行rmmod。sudo ip link set enp3s0 down sudo rmmod r8169 sudo modprobe r8125 sudo ip link set enp3s0 up如果你用的Ubuntu默认有NetworkManager接管网络down掉网卡后网络会短暂断开这属于正常现象。加载完r8125后再up网卡接口NetworkManager会自动重连。等到这一步再执行ethtool -i enp3s0你会看到driver: r8125 version: 9.012.03这说明网卡已经被新的官方驱动接管。为了确保重启后一切正常你还需要做最后一步验证——重启系统然后再次检查驱动状态。如果重启后依然显示r8125说明blacklist生效了DKMS驱动的自动加载也正常。5. 验证与调优确认驱动生效与性能达标5.1 验证驱动加载与硬件识别重启之后第一件事就是确认没翻车lsmod | grep r8125正常会输出一行r8125 147456 0同时验证一下r8169有没有被加载正常情况下列命令应该没有任何输出lsmod | grep r8169接着用ethtool看看网卡的协商状态ethtool enp3s0重点看Speed那一行如果显示Speed: 2500Mb/s说明网卡正常工作在2.5G速率。如果你连接的交换机或路由器网口不支持2.5G这里会显示1000Mb/s那就不是驱动问题了是硬件链路限制。还有一个容易被忽略的点有些主板或独立网卡上有多个网口驱动换了以后接口名可能会变化。比如原来叫enp3s0换驱动后系统可能按新顺序重新命名接口。建议用ip link show把所有接口列表看一眼找到真正连接网线的那一个别盯着老接口名看半天以为驱动没生效。5.2 局域网吞吐实测与参数微调驱动确认加载后就到了最激动人心的测速环节。用iperf3在两个机器之间跑一下TCP吞吐量。先在另一台机器上启动服务端iperf3 -s在当前机器上连接并测速iperf3 -c 192.168.1.10 -t 30 -P 4在千兆交换机下iperf3的结果一般是940Mbps左右。如果驱动正常工作且两端都是2.5G口测试结果应该在2.3Gbps到2.37Gbps之间。注意iperf3跑出来的数值跟CPU性能、PCIe通道带宽、网卡中断分配都有关系别指望能跑满2.5Gbps的理论线速2.3Gbps以上就算正常了。如果在r8169下只能跑900Mbps出头换完驱动后能跑到2.3Gbps那说明驱动切换非常成功。如果你的网卡虽然显示2500Mb/s但iperf3速率始终在1Gbps到1.5Gbps之间徘徊可以试着做几个调优动作关闭EEE节能以太网这个功能有时会导致Realtek网卡在高速传输时降速sudo ethtool --set-eee enp3s0 eee off调整中断合并参数降低CPU中断频率适合大流量传输场景sudo ethtool -C enp3s0 rx-usecs 8 tx-usecs 8某些环境下可以关闭TSO和GSO规避特定驱动版本在BDP较大时的Bugsudo ethtool -K enp3s0 tso off gso off这些调优项不一定每次都有用但对Realtek网卡来说值得一试。需要注意的是ethtool的配置重启后会失效。如果你测试出来某些参数确实有效果建议用systemd service方式做一个开机自动执行。比如创建一个简单的服务[Unit] DescriptionEthtool tuning for r8125 Afternetwork-online.target Wantsnetwork-online.target [Service] Typeoneshot ExecStart/usr/sbin/ethtool -s enp3s0 speed 2500 duplex full autoneg off ExecStart/usr/sbin/ethtool --set-eee enp3s0 eee off ExecStart/usr/sbin/ethtool -C enp3s0 rx-usecs 8 tx-usecs 8 RemainAfterExityes [Install] WantedBymulti-user.target保存到/etc/systemd/system/ethtool-tune.service然后sudo systemctl enable ethtool-tune.service下次重启后这些参数会自动生效不会再丢。6. 常见问题与排查实录速查表心得在实际操作过程中我遇到过不少问题也帮朋友排查过几台机器。这里整理一份高频问题速查表省得你踩同款坑。现象可能原因排查/解决办法dkms build编译报错内核头文件没装或版本不匹配重新安装linux-headers-generic确认真实版本查看make.log定位具体错误加载模块时报module verification failed系统开启了Secure Boot在BIOS中临时关闭Secure Boot或使用mokutil导入DKMS的MOK签名modprobe r8125找不到模块DKMS安装未成功dkms status查看模块状态确认/lib/modules/$(uname -r)/updates/dkms/r8125.ko存在加载r8125后网卡仍然被r8169接管黑名单未生效检查/etc/modprobe.d/blacklist-r8169.conf执行depmod -a后重启网速仍然只有千兆协商速率不是2.5Gethtool查看Speed字段检查网线、交换机、路由器端口是否都为2.5G重启后驱动丢失DKMS未注册成功或内核头文件缺失dkms status查看是否显示installed确认linux-headers-generic已安装内核升级后DKMS没有自动编译AUTOINSTALL未设置为yes或头文件缺失检查dkms.conf中AUTOINSTALLyes安装linux-headers-generic这里重点讲讲Secure Boot的问题。现在很多品牌主板出厂默认开启Secure BootUbuntu在这类机器上安装时也默认开启了安全引导。内核模块如果未经签名是无法被加载的。DKMS在编译模块时其实会生成一个MOKMachine Owner Key密钥但你需要在系统里手动信任这个公钥。操作方式如下sudo mokutil --import /var/lib/dkms/mok.pem执行后会要求设置一个一次性密码重启后在蓝屏MOK管理界面里选择Enroll MOK输入刚才的密码确认导入。如果你不想折腾这套证书流程也可以直接在BIOS里关闭Secure Boot这取决于你对安全性的要求和动手能力。再补充一个我实际踩过的坑有一次我把r8125的dkms.conf里MAKE[0]写错了少传了M参数编译时实际是在内核源码目录而不是驱动源码目录执行make modules结果编译出来的模块文件是空的加载时报了一堆“Unknown symbol”错误。这个问题排查了很久才发现是dkms.conf的路径变量用错了。所以别小看配置文件里面${kernel_source_dir}和${dkms_tree}这些变量是有实际意义的用的不对就会编译出一堆“对不上号”的二进制文件。另外如果哪天新驱动出了问题想回退到r8169操作也很简单sudo dkms remove r8125/9.012.03 --all sudo rm /etc/modprobe.d/blacklist-r8169.conf sudo depmod -a sudo modprobe r8169这样就恢复原样了。记得重启一下让系统重新加载模块。还有一个小技巧如果你在编译安装后发现用ethtool -i看到的driver是r8125但dmesg里同时出现了r8169和r8125两个驱动的日志这是因为r8169在启动早期加载过后来被r8125顶掉了。只要最终生效的driver是r8125就没问题。别被dmesg里历史的r8169输出干扰判断。我个人在实际操作中的体会是Realtek 2.5G网卡在Linux下并不是不能用而是默认的r8169驱动太“敷衍”了。很多人一遇到速度不达标就怀疑是网卡硬件问题或者干脆换一张Intel网卡其实只要换成官方r8125驱动性能差距立刻就能体现出来。而且用DKMS管理之后内核升级这个最大的痛点也被解决了整个体验跟Windows下装官方驱动已经非常接近。最后再分享一个小技巧如果你用的是Ubuntu Server这种没有图形界面的系统建议在升级内核之前看一下dkms status确认r8125的状态是installed。如果显示bad或者build先查明原因再重启不然容易陷入“开机没网→没法下载头文件→头文件不全→编译失败”的死循环。只要DKMS状态健康内核升级这种事就可以放心地交给系统后台去做了。