简介:面向银河麒麟V10系统的网卡驱动适配源码包,重点解决Intel e1000e与Realtek RTL8125网卡在该国产Linux平台上的编译兼容难题,适用于政企及国防领域关键信息系统的网络部署。资源内含e1000e-3.8.4和RTL8125Linux两套完整驱动,开发者已针对内核环境完成“删除重复定义、修改函数参数”等源码级调整,并附带makefile、编译脚本及README说明,下载后可直接make编译、insmod加载,避免反复排查头文件或符号冲突。整体共56个文件,其中19个C源文件实现驱动核心逻辑,21个头文件定义硬件寄存器及数据结构,makefile与编译脚本负责自动化构建,ethtool工具可用于链路调试,spec文件便于生成安装包;压缩包仅483KB,结构清晰便于移植。当前已有2736人学习下载,适合负责银河麒麟V10网络运维、驱动二次开发以及学习Linux网卡驱动机制的工程师参考使用。
1. 银河麒麟V10网卡驱动编译这件事,卡住的从来不是网卡本身
装完银河麒麟V10,进系统一看网络不可用,又或者明明插的是千兆网卡,协商出来的速率却只有百兆——这类问题在国产化替代落地的机器上出现频率很高。原因往往集中在两块网卡上:Intel 的 e1000e 系列和 Realtek 的 rtl8125 系列。一个是在服务器和主流主板上最常见的千兆方案,另一个是近两年 2.5G 网口异军突起后的首选。两块网卡本身没什么神秘的,真正的分水岭在于:银河麒麟V10 默认内核里带的那份驱动源码,和你手头网卡的硬件版本、以及你要用的网卡特性,到底匹不匹配。很多现场是在内网环境里操作,没有现成的包管理器可用,于是「能不能编译通过」就成了第一个硬门槛。
这篇文章我直接按一线处理顺序来讲:先盘清楚你本地内核到底需要什么编译条件,再分别给出 e1000e 和 rtl8125 从拿到源码到 insmod 成功的完整路径,最后把我在三种不同 CPU 平台(某国产 x86 平台、某飞腾平台、某兆芯平台)上反复踩过的编译错误和套路整理成清单。读者里如果是刚接触麒麟系统的,照着步骤走即可;如果是已经编译失败过几次的老手,重点看第四章,基本覆盖了报错到吐血的常见原因。
2. 编译环境准备:内核头文件与构建工具的三个硬要求
2.1 搞清「内核版本」和「系统版本」的关系,否则头文件一辈子对不上
银河麒麟V10 有几个大版本,底层内核版本从 4.19 到 5.10 甚至更新的都有。很多人第一反应是uname -r看内核版本,然后去网上找一个对应的内核源码包,这方向没错,但忽略了一个最关键的差:系统镜像自带的发行版标识和内核头文件包的版本号经常不一致。比如系统显示是 V10 SP1,内核是 4.19.90,但/usr/src/linux-headers-$(uname -r)这个目录可能根本不存在。这时候你拿到的所谓「内核源码」,编译出来的 .ko 一加载就报version magic错误,因为头文件的 vermagic 和当前内核不匹配。
我一般会先在干净系统上敲这三条命令确认基础状态:
uname -r ls /usr/src/linux-headers-$(uname -r) 2>/dev/null || echo "headers not found" which gcc make如果ls那行输出的是headers not found,说明你没装内核开发包,光有 gcc 和 make 是编译不了驱动的。/usr/src下必须存在与当前内核完全同名的头文件目录,这是硬性条件。注意,很多人会顺手apt install linux-headers-$(uname -r),但在内网环境下这一步往往失败,更可靠的做法是从系统安装镜像的Packages目录里找到对应的kernel-devel或kernel-headers的 rpm 包离线安装。具体包名后缀要和uname -r的输出完全一致,多一个-generic少一个.ky3都不行,没有商量的余地。
另外,检查 gcc 版本时不要只看有没有 —— 内核模块编译用的 gcc 版本和 ld 版本必须能互相配合,老系统上如果 gcc 太老,而驱动源码里用了较新的内联汇编语法,编译时会出现unknown register name之类的奇葩报错。建议至少是 gcc 8 以上,麒麟 V10 的默认源一般能满足,但如果你之前手动降级过 gcc,务必先恢复。
2.2 动态内核模块支持(DKMS)是保底方案,但第一次编译先别裸用
很多教程推荐直接上 DKMS 管理驱动,理由很充分:内核一旦小版本升级,DKMS 会自动重新编译网卡驱动,省得每次升级后网卡又失效。这个思路没问题,但我不建议第一次编译就跳进 DKMS。原因是 DKMS 会把你丢进它的脚本流程里,一旦源码有语法错误或内核接口不匹配,报错日志散落在几个不同位置,新手会被绕晕。我习惯的做法是:先在普通目录下手动编译一次,确认.ko能生成、能被insmod加载,再考虑要不要做成 DKMS 包。
手动编译阶段必要的包和工具就三样:gcc、make、内核头文件。缺一不可,别的都不需要。用yum install gcc make kernel-devel一条命令能解决的就不要折腾。若是在纯内网环境,用安装镜像的本地仓库来安装,Linux 的 rpm 依赖关系会自己处理,前提是你把镜像源配置成file://协议指向挂载点。
2.3 确认当前内核的配置选项:有些模块编了也加载不上
还有一类隐蔽问题:头文件齐了,gcc 也够新,驱动也编译成功了,但insmod时提示operation not permitted,或者没有任何输出但lsmod里就是没有。这种情况八成是内核配置里把某个特性关掉了。最典型的两个配置是CONFIG_MODULE_SIG(模块签名强制)和CONFIG_X86_X32_ABI。如果CONFIG_MODULE_SIG开启且处于强制模式,你的驱动没签名就无法加载,此时必须关闭内核的签名校验,或者在编译驱动时生成并使用对应签名的 key。
查询当前内核配置的方法很简单,直接查看/boot/config-$(uname -r)文件里的对应项:
grep CONFIG_MODULE_SIG /boot/config-$(uname -r) grep CONFIG_X86_X32_ABI /boot/config-$(uname -r)如果CONFIG_MODULE_SIG的值不是n,你需要在这个文件里临时改掉,重新生成内核或使用 modprobe 的--force选项。但--force在这种场景下并不能绕过签名校验,真正干净的处理方法是重新编译内核或关掉 secure boot 后用未签名模块。银河麒麟在部分主板上默认开启了 UEFI 安全启动,这会让模块校验路径变得严格,具体现象和解决我放到第四章细说。
3. 编译 e1000e 驱动:Intel 千兆网卡的最小可复现路径
3.1 从 Intel 官方源码包编译,而不是直接改内核树里的旧模块
银河麒麟V10 内核树里其实自带了 e1000e 驱动,但版本往往比较旧,对新的 I219 系列网卡支持不完整,有些型号甚至无法识别。所以我更推荐直接从 Intel 官方发布的 e1000e 源码包编译,它是以一个独立目录形式给出的,里面有src子目录。注意,Intel 官方包名类似e1000e-x.y.z.tar.gz,这个包是纯驱动源码,不带 configure 脚本。编译方式是在src目录下直接make,靠的是内核头文件目录里的Kbuild体系。
拿到 tarball 后,标准操作是解压并进入src目录:
tar zxf e1000e-*.tar.gz cd e1000e-*/src make clean make这里有几个值得强调的点。第一,make clean不是仪式感,因为源码包里可能残留之前在其他内核版本下编译的中间文件,唯一依赖的 Makefile 变量是KSRC,默认指向/lib/modules/$(shell uname -r)/build,如果你的头文件不在默认路径,就会编出version magic不匹配的 ko 文件。第二,make 过程结束后,正常情况下会在src下生成e1000e.ko。在这个目录下执行modinfo e1000e.ko,可以看到vermagic那一行必须与你uname -r的输出一致,这是判断编译是否真正匹配当前内核的铁标准。
加载顺序也要注意,如果系统里已经有内核自带的 e1000e 模块在运行(哪怕你没主动加载,启动时也可能通过 initramfs 拉起来了),直接insmod你自己的 .ko 会失败,报File exists或者设备忙。先rmmod e1000e再 insmod 是标准动作。如果是通过 ssh 远程操作的机器,这一步有断连风险,建议准备一个带外管理口或者物理终端,这个坑后面会专门说。
3.2 e1000e 的 Makefile 参数与性能相关的模块参数设置
编译e1000e 时,在 src/Makefile 里有一个CFLAGS_EXTRA变量,可以往里面加参数来开启调试或调整某些特性。默认编译出来的驱动在功能和稳定性上是均衡的,但有两个性能相关参数值得现场调整。
第一个是InterruptThrottleRate,这个参数控制网卡中断节流速率,范围是 1000~100000 之间,单位是中断次数/秒。默认值在部分主板上是 2000 或 3000,对纯千兆网络来说够用,但对突发小包场景会出现 CPU 占用偏高的问题。我一般在服务器上把它设为 8000,配合rx-usecs-high等自适应中断合并参数逻辑在驱动内部自动调优。
第二个是RxDescriptors和TxDescriptors,默认是 256,这个值太小了。在跑 iperf3 打流测试时,256 个描述符在高吞吐下很容易丢包。编译的时候不改也可以,用模块参数在加载时指定更灵活。加载命令参考:
rmmod e1000e 2>/dev/null insmod ./e1000e.ko InterruptThrottleRate=8000,8000 RxDescriptors=1024 TxDescriptors=1024注意参数里多个网卡用逗号分割,每个网卡各对应一份设置。如果机器上有多张 e1000e 网卡,而你想对不同网卡用不同参数,逗号后的值一一对应;只写一个值,其余网卡用默认值。insmod 后dmesg | tail里可以看到每个网卡实际的描述符个数,确认参数是否生效。
另外,如果你编译时遇到#error "Please update your kernel to at least 4.4"这类提示,说明源码包版本太新,而你的内核太老。e1000e 源码包对内核版本是向下兼容到一定程度的,比如 3.17 版本的包就明确要求内核高于某个基线。解决办法是换用更老版本的 e1000e 源码包,通常是选择与你当前内核版本发布时期相近的版本即可。
4. rtl8125 驱动编译:2.5G 网卡的源码包与内核接口适配
4.1 拿到源码后第一件事:确认 r8168 和 r8125 的命名陷阱
Realtek 的 2.5G 网卡,市面上驱动包命名比 Intel 家混乱得多。常见的有r8168、r8125、r8126等目录,芯片型号也不同。很多人下载了r8168的包去编,以为能驱动 rtl8125,结果编译过去加载后dmesg报unknown device。这里要清楚一个事实:r8168 驱动对应的是 Realtek 的 8168 系列千兆芯片,而 rtl8125 对应的是 2.5G 芯片。两者 PCI ID 不一样,驱动源码里虽然都挂在同一个目录命名体系下,但内部代码差异不小。
核对 PCI ID 是编译前必须做的一步。在机器上执行:
lspci -nn | grep -i realtek看到形如10ec:8125的输出(10ec 是 Realtek 的 Vendor ID,8125 是 Device ID),才是真正需要 r8125 驱动的设备。如果看到的是10ec:8168,那应该用 r8168 驱动或者内核自带的 r8169。千万别偷懒跳过这一步 —— 我见过有人在飞腾平台上拿 r8125 驱动去驱动板载的 8168 芯片,编是能编过,但网卡就是起不来,因为驱动里的设备 ID 匹配表根本没有这个型号。
另外,rtl8125 的源码包分两个流派:一是 Realtek 官方发布的rtl8125源码包,里面是完整的src目录和 Makefile;二是内核社区维护的r8168驱动,在较新内核里改名为r8169。银河麒麟V10 的默认内核里自带 r8169,但某些国产主板集成的 rtl8125 在 r8169 下的表现不稳定,建议直接用官方 r8125 源码包覆盖。
4.2 修改 Makefile 或 Kconfig 里的内核版本判断逻辑
rtl8125 源码包在编译时最大的障碍是内核接口变化。它的 Makefile 会检查当前内核版本,然后设置不同的编译选项。我自己编译时遇到过两种情况最多:一是源码包只适配到某个较老的内核接口,在 5.10 内核下编译报错,提示某个函数未定义;二是 Makefile 里检测了带-DUSE_OLD_PCI_MSI之类宏,而新内核已经移除了旧的中断注册接口。
常见的处理是直接把 Makefile 里相关版本判断语句改为你的内核版本,让驱动走新接口路径。比如在 Makefile 中搜索KERNEL_VERSION,能看到类似这样的判断:
ifeq ($(shell [ $(KERNEL_VERSION) -ge "5.4" ] && echo yes), yes) EXTRA_CFLAGS += -DHAVE_PCI_MSI_ALLOC endif如果编译报错说pci_alloc_irq_vectors未声明,说明触发的是老路径,把-DHAVE_PCI_MSI_ALLOC手工加到EXTRA_CFLAGS里即可。反之,如果新内核已经把旧接口删掉了,而 Makefile 还默认走旧路径,就会报unknown symbol或隐式函数声明警告。这种情况需要反向操作,把对应内核版本判断改成直接走新路径。
改完 Makefile 后,编译命令与 e1000e 类似:
cd rtl8125-*/src make clean make生成r8125.ko后,推荐先不急着加载。打开驱动目录下的README,确认默认的NIC模块参数。rtl8125 驱动的默认行为是多种 Realtek 网卡都尝试绑定,但在同一台机器上和多网卡共存时,为了避免和已有的 r8169 抢设备,加载时可以指定参数:
insmod ./r8125.ko装好后用dmesg看加载日志。如果显示r8125: probe success,基本就稳了。如果显示device not found,大概率是设备 ID 不匹配,需要确认 PCI ID 和驱动源码里的支持列表是否一致。
4.3 rtl8125 与内核自带 r8169 的共存冲突处理
在实际项目里,很多机器不止一张网卡,可能出现一张 Intel 千兆加一张 Realtek 2.5G 的组合。这时候 r8169 内核模块往往会先抢占 rtl8125 设备。因为 r8169 是内核自带的,启动时就加载了,并且它的设备 ID 表里包含了 rtl8125 的十来个 ID。这样你后来 insmod 的 r8125.ko 会发现设备已经被占用,加载失败或者加载成功但网络接口名不对。
解决办法有两个方向。一是在编译 r8125 时把代码里冲突的 PCI ID 注释掉,让驱动不认这个设备,这个办法治标不治本,且容易改出问题。二是直接禁用内核自带的 r8169 模块,全程使用 r8125。在/etc/modprobe.d/下新建一个配置文件:
echo "blacklist r8169" > /etc/modprobe.d/blacklist-r8169.conf然后重新生成 initramfs:
sudo mkinitrd -f -v /boot/initramfs-$(uname -r).img $(uname -r)注意,银河麒麟 V10 上mkinitrd和dracut都可能存在,用哪个取决于系统默认。可以执行ls /boot/initramfs*看现有文件名,然后对应使用mkinitrd或dracut重新生成。如果连这步也省了,重启后 r8169 照样抢占,你手工加载的 r8125 等于白做。
至于为什么要保留 r8125 而不是直接用 r8169,主要原因是 r8169 对 rtl8125 的支持在某些芯片修订版下不稳定,表现是能协商 2.5G 速率但 iperf3 流量一上来就断流。官方 r8125 驱动在这方面更稳,尤其是做软路由或者 NAS 直通场景时,这个差异很明显。
5. 编译与加载避坑指南:麒麟 V10 下最容易翻车的 5 个细节
5.1 现象:make 报错kernel source tree not found,但头文件目录明明存在
原因:Makefile 里KSRC变量指向的路径不对,或者/lib/modules/$(uname -r)/build这个软链接是断的。很多系统只装了 kernel-headers,没装 kernel-devel,导致 build 目录不存在。
解决:先确认软链接是否存在,ls -l /lib/modules/$(uname -r)/build。如果指向的目录不存在,说明没装 kernel-devel,安装对应 rpm 包或从 iso 的 Packages 目录手工安装即可。装完后再确认 build 目录下能看到Makefile文件,否则头文件树不完整。
5.2 现象:编译通过,insmod 报Exec format error或Invalid module format
原因:在 x86 平台上编译的 .ko 拿到飞腾(ARM64)平台去加载。或者反过来。这种错在国产化环境里特别常见,因为不少人习惯在一台开发机上编好模块再拷到目标机。
解决:必须在目标机上编译,或者严格使用与目标机相同架构和内核版本的构建环境。检查 .ko 的架构可以用file xxx.ko,输出里有x86-64或aarch64,一目了然。
5.3 现象:insmod 成功,但ip link set eth0 up时报No such device或Cannot assign requested address
原因:驱动加载了,但硬件初始化失败。多半是设备被其他驱动抢占,或者 BIOS 里把网卡禁用/设置为混杂模式。更隐蔽的一种是,银河麒麟 V10 在部分主板上默认把网络接口命令规则改成了基于 MAC 的命名,比如enp3s0变成了eno1,此时网卡实际存在但名字不对。
解决:先看dmesg | grep r8125或dmesg | grep e1000e确认硬件 probe 是否成功,再执行ip link show看完整接口列表。如果是名字问题,在/etc/systemd/network/下写一个.link文件固定接口名,或者直接用传统命名规则,把/etc/default/grub里的net.ifnames=0加进去重新生成 grub 配置。
5.4 现象:加载驱动后网络通,但 dmesg 不停刷e1000e: The NVM Checksum Is Not Valid
原因:网卡硬件本身的 NVM(非易失性存储器)校验失败,常见于 Intel 的某些工程样板或者使用第三方固件修改过的网卡。这个问题驱动层面解决不了,但有些板子可以通过更新网卡固件恢复。
解决:先用ethtool -e eth0查看 EEPROM 数据,如果全是 FF 或校验值异常,基本可以断定是硬件层面的 NVM 问题。在项目现场最简单的处理是更换网卡硬件,或者找主板厂商要最新的网卡固件刷入。驱动层面没有可用的编译参数绕过它,因为它发生在硬件初始化的早期阶段。
5.5 现象:UEFI 安全启动开启后,编译好的驱动加载报permission denied或直接被忽略
原因:银河麒麟 V10 默认不会强制开启 UEFI Secure Boot,但你所在的单位如果有统一安全基线,可能在 BIOS 里开启了该功能。Secure Boot 会校验驱动的签名,自编译的 .ko 没有签名,加载被拒绝。
解决:要么在 BIOS 里关闭 Secure Boot,要么用mokutil --import导入自己生成的签名密钥,并为 .ko 签名。如果不想动 BIOS,也可以用 DKMS 配合签名密钥自动处理,具体做法是生成自签名密钥,注册到 MOK 里,然后在 DKMS 的 make 脚本里调用sign-file对生成的 .ko 签名。这属于另一种系统级方案,处理步骤较长,但在很多单位里,这是唯一合规的手段。
6. 验证与开机自启:让网卡驱动真正落地到生产环境
编译驱动和 insmod 成功,只是完成了 30% 的工作。一个驱动要在生产机器上长期稳定运行,必须解决两个问题:一是如何验证它当前的性能和稳定性,二是如何在系统重启后自动加载并保持正确顺序。
验证性能这块,我最常用的是ethtool命令来确认速率和工作模式:
ethtool eth0 ethtool -S eth0 | grep -E "tx_errors|rx_errors|tx_dropped|rx_dropped"如果速率显示的不是预期值(比如 2500Mb/s 只有 1000Mb/s),问题通常出在网线或对端设备上。2.5G 速率必须搭配 Cat5e 以上的网线,且对端交换机端口也要协商到 2.5G。很多现场拿笔记本直连,笔记本网口是 1G 的,那速率自然是 1G,这很正常。真正要关注的是rx_errors这列是否为 0,如果有持续增长的错误计数,优先检查网线质量或强制设置速率双工后再测试。
开机自启这块,如果只是简单地在/etc/rc.local里 insmod,会遇到加载顺序问题:驱动必须在网卡设备被系统枚举前加载。更优雅的做法是把编译好的 .ko 安装到内核模块目录,并执行 depmod:
cp e1000e.ko /lib/modules/$(uname -r)/extra/ cp r8125.ko /lib/modules/$(uname -r)/extra/ depmod -a然后编辑/etc/modules-load.d/network.conf,写入需要预加载的模块名:
echo "e1000e" > /etc/modules-load.d/network.conf echo "r8125" >> /etc/modules-load.d/network.conf这样 systemd 会在网络服务启动前加载这两个模块,避免设备枚举时驱动还没就绪的时序问题。注意,如果你之前 blacklist 了 r8169,这里加载顺序就尤为重要,因为一旦 r8169 先抢占了设备,r8125 加载时就会空手而归。
最后还有一个稳定性的测试技巧:加载驱动后跑一次长时间打流,确认散热和驱动状态正常。
iperf3 -c 192.168.1.1 -t 300 -i 10运行 5 分钟看有没有断流或重传暴涨。如果重传率高企,试着把中断合并参数调大(rtl8125 的tx_wo_fw之类的参数因源码版本而异),或者检查网卡所在 PCIe 插槽的链路速率,很多 2.5G 网卡被插在 PCIe 2.0 x1 的槽位上,带宽瓶颈反而成了天花板。
我现在每拿到一个新环境,都会强制自己先走一遍「确认头文件 → 查 PCI ID → 编译 → 看 vermagic → 加载 → 看 dmesg → 打流验证」这套流程,整套下来十分钟出头,却能筛掉八成以上的网卡驱动问题。有时候现场解决问题的关键不在于你多会写代码,而在于你愿不愿意先把那些最容易翻车的环节按顺序排查完。希望这篇笔记能让你在银河麒麟V10 上搞定这两块网卡时少走几趟弯路,就是它最大的价值了。
本文还有配套的精品资源,点击获取