银河麒麟V10网卡驱动编译实战:解决e1000e与RTL8125识别失败
简介面向银河麒麟V10国产化环境提供e1000eIntel与RTL8125Realtek两款网卡驱动的源码包重点解决内核版本适配及编译兼容问题适用于国产化替代、网络功能调试等场景。压缩包共56个文件以C源文件与头文件为主21个.h、19个.c另含Makefile构建脚本、README说明、spec打包配置及网卡支持列表整体仅483KB方便快速下载与检视。驱动针对麒麟内核做了源码级调整包括删除重复定义、修改函数参数等可直接参考编译安装省去大量排查编译错误的精力。压缩包内同时包含e1000e-3.8.4与RTL8125 Linux源码便于对照学习驱动适配流程理解内核模块与硬件交互机制。目前已有2719人学习适合运维工程师、驱动开发者及国产系统适配人员使用。 银河麒麟V10装到一台新主板上最让人头疼的往往不是系统本身而是装完以后网卡不出网。尤其是带Intel千兆网卡I219、I211那种和Realtek 8125 2.5G网卡的机器系统自带驱动要么太老认不出芯片要么压根没有对应模块网络起不来后面什么都干不了。这篇文章记录的是一套我在银河麒麟V10上实测能编译通过的e1000e和rtl8125网卡驱动方案从环境准备到编译安装再到开机自启全部走了一遍把中间踩过的坑一并写出来希望能帮到正在折腾国产系统网卡的朋友。1. 先搞清楚问题出在哪儿为什么银河麒麟V10认不出网卡1.1 银河麒麟V10的内核版本与驱动现状银河麒麟V10的内核版本不像普通发行版那么激进桌面版和服务器版长期都在4.19或5.10这一代x86和ARM还有差异。拿我手头这台机器来说uname -r返回的是4.19.90-20210624.1536.3x8.kylin.x86_64这是一个带kylin定制标记的内核。这个内核已经有几年历史而主板板载网卡往往是这两年才出的新芯片比如Intel的I219-V第17版本、Realtek RTL8125BG内核自带驱动代码里很可能没有对应PCI ID网卡自然不会被识别。另一个坑是银河麒麟的安装镜像为了压缩体积默认不会把所有网卡驱动都带全。很多内网环境装机时是不联网的装完发现ip link只有lo回环接口lspci里明明能看到Ethernet controller但系统里就是找不到对应的eth0。这时候第一反应不应该是不停重启或者换系统而是去查一下内核模块目录里到底有没有这个驱动。执行ls /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/intel/e1000e/看看如果目录里没有e1000e.ko基本可以确定是驱动文件缺失。1.2 为什么优先考虑手动编译而不是等系统更新可能有人会说你直接apt update apt upgrade刷一下内核补丁不就行了吗。问题是银河麒麟V10的软件源更新节奏偏慢而且很多生产机器处于隔离内网根本没有外部网络可访问等官方推送驱动补丁不现实。手动编译内核模块虽然看起来麻烦但它是唯一一个不依赖网络、不依赖官方更新节奏、可重复操作的方案只要内核头文件齐全源码包在手两三分钟就能把驱动编出来加载上。还有一点自己编译驱动不一定要替换内核。我们编译出来的.ko文件是独立于内核本身的安装到了对应的kernel/drivers/net/ethernet目录里和系统自带的模块并存。只要内核不升级这个驱动就一直能用。这样一来风险完全可控出了问题modprobe -r卸载掉系统立即恢复原样比直接换内核稳妥得多。我见过有人为了网卡驱动去重装内核结果系统起不来了完全是得不偿失。1.3 编译前必须确认的4件事动手之前我建议先花两分钟把这四件事确认完能省掉后面一多半的报错排查时间。内核版本执行uname -r记下完整的字符串后面所有路径都跟它相关。银河麒麟的版本字符串里通常带kylin字样别看到版本号和你网上搜到的不一样就慌这很正常。网卡型号执行lspci | grep -i ethernet确认板载网卡的厂商和型号别把Intel网卡当成Realtek驱动拿错源码编译只会白白浪费时间。当前是否已有同厂商模块加载执行lsmod | grep -E e1000e|r8168|r8125如果系统里已经有一个老的e1000e或者r8168后面编译新模块之前要先卸载或加入黑名单否则两个驱动抢同一个网卡会出现奇怪的丢包问题。是否有内核头文件执行ls /lib/modules/$(uname -r)/build如果报错说目录不存在那就是头文件没装先去装环境后面会详细说。2. 环境准备装好这几个包成功率至少翻一倍2.1 安装开发工具链和内核头文件编译内核模块最少需要三样东西编译器gcc、构建工具make、当前内核的头文件。在银河麒麟V10上如果系统是Debian系命令是sudo apt update sudo apt install -y build-essential linux-headers-$(uname -r) dkms如果是RPM系的银河麒麟服务器版用dnf或者yum来装sudo dnf install -y gcc make kernel-devel-$(uname -r) dkms注意linux-headers-$(uname -r)这里的$(uname -r)会自动展开成当前内核版本。银河麒麟的包名和Ubuntu不完全一样但linux-headers-4.19.90-xxx这类带版本号的包通常是存在的。有一种情况是执行完apt search linux-headers-$(uname -r)找不到完全匹配的包这是因为内核版本字符串里可能带了kylin后缀而headers包名没有这时候可以先执行apt search linux-headers-4.19.90-看看有哪些候选版本选最接近的装上。2.2 校验内核头文件是否与当前内核完全匹配头文件装没装对判断标准很简单/lib/modules/$(uname -r)/build这个符号链接是否存在且指向的目录里有Makefile、Module.symvers、include/generated这些关键文件。我见过不少机器目录存在但里面是空的这是安装包损坏或者中途断电导致的直接重新装一次linux-headers就能解决。校验命令ls -l /lib/modules/$(uname -r)/build test -f /lib/modules/$(uname -r)/build/Makefile echo OK如果输出OK环境基本没问题。这里多说一句编译内核模块时gcc的版本最好和编译内核时用的gcc保持一致如果gcc版本差异太大编译出来的模块虽然能编过但加载时可能报版本魔数警告。银河麒麟V10自带的gcc通常和内核配套不用太担心。2.3 顺手把内核模块签名/安全启动问题处理掉现在的商用电脑主板大多默认开启UEFI安全启动Secure Boot在这个模式下内核只加载带有效数字签名的模块我们自己make出来的.ko默认没有签名modprobe的时候会直接报Operation not permitted不仔细看还以为驱动编译错了。如果你的机器开启安全启动有两个选择一是进入BIOS临时关掉Secure Boot等加载完模块再开回去二是给模块做签名流程相对麻烦需要自己生成一对密钥并导入MOK数据库。我的建议是个人电脑或者测试机上直接关掉省心生产环境如果强制要求开安全启动再走MOK签名流程。银河麒麟V10在企业环境里大多数为了兼容各种老设备和自研软件安全启动是默认关闭的装完驱动直接就能用。3. e1000e驱动编译实录Intel千兆网卡的标准解法3.1 获取源码从Intel官网到内核源码包我选了哪条路e1000e驱动有好几个获取渠道Intel官网的standalone驱动包、内核源码目录里的drivers/net/ethernet/intel/e1000e/、以及GitHub上的镜像仓库。我实测下来最稳妥的是直接到Intel官网下载独立驱动包因为里面的Makefile和configure脚本已经适配好了绝大多数发行版环境解压后基本是傻瓜式编译。以e1000e 3.8.4版本为例下载地址在Intel的下载中心文件名类似e1000e-3.8.4.tar.gz。解压tar -zxvf e1000e-3.8.4.tar.gz cd e1000e-3.8.4/src如果是通过GitHub拉源码也可以但要注意分支选择一定要选带release tag的版本不要直接拉mastermaster上的代码未必能在4.19内核上编译通过。我之前拉过一次master分支结果编译报了一堆函数未定义的错换回tag版本就顺畅了。3.2 手工修正Makefile的内核版本判断进入src目录之后先别急着make打开Makefile看一眼开头的几行。e1000e的Makefile里有一个内核版本判断逻辑如果它不认识当前内核版本会直接走一个不支持分支编译出来的模块不是最新代码甚至直接报错。我遇到的情况是这样的银河麒麟V10的内核版本字符串里带了kylin字样Makefile里的判断大多只匹配了x86_64这种通用架构不会因为厂商字段出问题但有个别版本会通过uname -r去匹配内核版本号如果匹配不上就会进入fallback。解决办法很简单把Makefile里的KSRC变量强制指定为当前内核的build目录KSRC ? /lib/modules/$(shell uname -r)/build如果发现make时连kernel build目录都找不到就直接改成写死的路径KSRC : /lib/modules/4.19.90-20210624.1536.3x8.kylin.x86_64/build改完保存然后执行make clean make编译过程一般不会超过一分钟。如果这个时候报错说linux/version.h找不到那就是前面第2步环境没准备好回到第2章把头文件装上。3.3 编译、安装并加载一条命令一条命令说清楚编译成功后src目录下会生成e1000e.ko文件。安装就是把模块复制到系统模块目录sudo make installmake install会自动把e1000e.ko放到/lib/modules/$(uname -r)/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko然后执行depmod -a更新模块依赖关系。之后就可以加载了sudo depmod -a sudo modprobe e1000e加载后验证lsmod | grep e1000e modinfo e1000e | grep version ethtool -i enp3s0 # 换成你自己机器的网卡名ethtool -i输出的driver字段如果是e1000e说明驱动已经接管了这块网卡。如果网卡接口名和系统里原来不一样用ip link看一下有哪些接口再用nmcli device status看一下有没有pending状态。注意如果你系统里原本就有一个自带的e1000e旧模块加载新模块前要先sudo modprobe -r e1000e把旧的卸载掉否则新旧模块冲突网卡可能反复掉线。3.4 让e1000e开机自动加载的三种方式驱动加载一次只能解决当前开机的问题重启之后如果不自动加载一切白搭。最常见的方式是通过/etc/modules-load.d/新建一个配置文件加上模块名echo e1000e | sudo tee /etc/modules-load.d/e1000e.conf这是systemd提供的内核模块预加载机制启动时自动执行modprobe e1000e。如果机器还在用老的SysVinit则改/etc/modules文件在里面加一行e1000e。还有第三种方式就是直接把驱动编译进initramfs适合对启动速度极其敏感的场景但对普通用户来说完全没必要反而会让initramfs更新逻辑变复杂这里不展开。我自己的习惯是第一种简单直接改完重启验证一次就没问题了。4. rtl8125驱动编译全流程Realtek 2.5G网卡的坑我都踩了一遍4.1 源码版本选择r8125与r8168别搞混Realtek官方驱动有个容易踩坑的地方同系列网卡对应不同驱动源码包。千兆RTL8111/8168用的是r8168驱动2.5G的RTL8125用的是r8125驱动两个源码包长得很像但内部实现不同拿错包编译出来加载上去网卡大概率起不来。下载之前先用lspci -v看清楚芯片型号lspci -v | grep -A4 Ethernet看到RTL8125字样就下载r8125看到RTL8111/8168就去找r8168。市面上还有一些社区的r8125源码仓库版本号从9.004.01到9.011.00都有我建议选9.008.00或更新的版本因为老版本对4.19内核的适配还是偏少编译时可能遇到struct net_device结构体字段变化导致的报错。4.2 编译前的关键修改Makefile和内核API适配拿到源码后解压目录结构一般是r8125-9.008.00/ ├── src/ # 真正的驱动源码 ├── Makefile ├── README先进入src目录同样先确认Makefile里的KSRC路径是否正确。Realtek的Makefile会自动执行uname -r绝大多数情况下不用手动改但如果你在编译时使用sudo make环境变量里的uname还是能正常解析这点问题不大。真正需要关注的是老版本源码里针对内核版本判断的#if宏。比如9.005.01版本在部分4.19内核上会报implicit declaration of function ...这都是内核API变化导致的解决办法是换新版本源码不要去强行打补丁没必要把时间耗在和一个驱动源码干架上。我在银河麒麟V10上比较顺利的是9.008.00这个版本直接cd src make clean make能够顺利生成r8125.ko。如果编译报错多半是源码版本和内核不匹配换9.011.00再试一次九成能解决。4.3 rtl8125驱动安装与加载验证生成r8125.ko后安装方式和e1000e一样sudo make install sudo depmod -a sudo modprobe r8125如果你之前系统里加载了r8168或者r8169驱动而它们控制的是同一块RTL8125网卡加载r8125之前最好先卸载掉sudo modprobe -r r8169 r8168 # 按实际加载的模块调整然后才是modprobe r8125。加载完用ip link看网卡是否多出来再用ethtool -i验证driver字段如果显示r8125说明驱动成功接管。这块网卡在系统里显示的名字一般是enp3s0或者eno1之类的看主板布局。我装的那台机器上RTL8125对应的是enp5s0和主板PCIe插槽位置有关不用纠结名字能用就行。4.4 dkms注册从此不再怕内核升级银河麒麟V10如果在后续使用中升级内核手动编译安装的驱动会立刻失效因为新内核的模块目录里没有对应的.ko。与其每次升级内核都手动重编不如在刚开始就直接用DKMS管理。在r8125源码根目录下执行sudo dkms add -m r8125 -v 9.008.00 sudo dkms build -m r8125 -v 9.008.00 sudo dkms install -m r8125 -v 9.008.00dkms add会读取源码目录里的dkms.conf如果没有这个文件可以手动写一个格式大概是PACKAGE_NAMEr8125 PACKAGE_VERSION9.008.00 BUILT_MODULE_NAME[0]r8125 DEST_MODULE_LOCATION[0]/kernel/drivers/net/ethernet/realtek AUTOINSTALLyes这样以后系统升级内核时dkms会自动为新内核重新编译模块不需要每次手动介入。唯一需要注意的是dkms需要提前安装dkms包命令在环境准备那一步已经提到了。5. 常见报错与排查技巧5.1 Invalid module format与版本魔数不匹配这是我见过最多的一种报错症状是modprobe时提示Invalid module format或者version magic ... should be ...。原因几乎都是模块编译时用的内核头文件和当前运行内核不一致或者是头文件路径被污染。排查思路很简单先检查/lib/modules/$(uname -r)/build这个链接到底指向哪再用modinfo e1000e | grep vermagic对比当前内核的vermagic。解决办法是删除旧的编译产物确认头文件版本后重新make clean make。如果你曾经给内核打过自定义补丁还可能需要重新生成Module.symvers但银河麒麟官方内核一般没有这个问题。我碰到过一种特殊情况机器上同时装了多个版本的linux-headers/usr/src目录下有好几个内核版本目录Makefile自动选择了错误的头文件手动指定KSRC路径就解决了。5.2 make报错找不到头文件编译时报fatal error: linux/version.h: No such file or directory基本可以断定是linux-headers-$(uname -r)没装全。银河麒麟的headers包偶尔会依赖缺失比如linux-kbuild-4.19.90-xxx这个包没装上里面才有version.h生成脚本。解决办法sudo apt install -y linux-kbuild-$(uname -r | cut -d- -f1-2)装完之后再重新make一次基本就能通过了。如果还是报错检查一下是不是环境变量CC被改过有些用户装了其他gcc版本或者交叉编译链导致编译时调错了编译器这种情况直接在Makefile里把CC强行指定为/usr/bin/gcc即可。5.3 模块加载成功但网卡不工作的排查链路模块加载成功、lsmod也能看到但网卡就是起不来这种情况优先查三件事网线物理链路是否正常、网卡是否被ip link set down或NetworkManager忽略、驱动是否和另一个同名驱动冲突。用dmesg | tail -50看内核日志如果有probe failed字样大概率是网卡硬件有问题或者PCI电源管理导致设备没上电可以在BIOS里关闭网卡的节能选项再试。还有一个容易被忽略的点编译出来的模块虽然加载成功了但对应的网卡设备可能被内核的udev规则改名了比如原来的eth0被改成enp3s0f0。这时候用nmcli device看一下设备状态如果显示unmanaged说明NetworkManager没有接管在/etc/NetworkManager/NetworkManager.conf的[main]段里加一行pluginsifcfg-rhRPM系或者检查/etc/network/interfaces配置让网络管理工具重新接管接口即可。5.4 常见问题速查表报错/现象大概率原因处理办法modprobe: Operation not permittedSecure Boot拦截未签名模块关闭Secure Boot或给模块签名Invalid module format头文件版本不匹配重新安装对应版本linux-headers后重编version magic不一致gcc/头文件不匹配确保用系统自带gcc并清理重编make: linux/version.h找不到linux-kbuild缺失安装linux-kbuild包加载成功但网络不通驱动冲突/网卡down/节能模式黑名单旧驱动、ip link set up、BIOS关节能编译报implicit declaration源码版本太老不支持当前内核更换新版驱动源码6. 实测经验收尾最后聊点个人的实际操作体会。我在银河麒麟V10上折腾这套网卡驱动好几次最大的感受是只要内核头文件能对上编译本身真的不难大部分时间都花在不知道谁在捣乱上——有时候是系统里残留的旧驱动有时候是Secure Boot有时候是头文件没装全还有一种情况是源码版本太老编译报一堆API错误换了新版本源码就一路畅通。所以遇到编译报错不要硬改源码优先检查版本匹配这比打补丁高效得多。还有一个小技巧编译成功后把.ko文件备份到一个固定目录比如/opt/drivers/如果哪天系统重装或者内核升级导致驱动丢失直接拷过去insmod就能临时顶上至少能让你有网络去干别的事。别问我怎么知道的我第一次重装系统时就是忘了备份又花了一个下午从头编了一遍。这套方案在x86_64架构的银河麒麟V10桌面版和服务器版上都验证过e1000e和rtl8125的编译流程没有本质区别区别只在网卡型号确认和源码版本选择上。希望这篇记录能帮到正在被板载网卡折腾的你少走点弯路。本文还有配套的精品资源点击获取