简介:面向成都海光网卡用户、服务器管理员和网络运维人员的驱动源码包,主要解决该型号网卡在主流操作系统中无法被正确识别、缺少驱动导致功能受限或性能无法发挥的问题。压缩包共收录22个文件,整体约146KB,内容以14个C源码文件和3个头文件为主体,附带Makefile、mk构建文件和sh编译脚本,并有readme与txt说明书,便于在Linux环境下完成编译、加载和参数核对。目前已有648人学习下载。这份整合包的价值在于提供一套可直接查看与编译的网卡驱动工程,用户无需从分散渠道寻找匹配版本,依照说明文档完成环境配置后即可构建出可用驱动;完整的源码结构也便于系统集成时交叉编译或静态编译,满足嵌入式与服务器场景的定制需求。对驱动开发感兴趣的读者,还可以通过头文件和构建脚本理解驱动框架、设备注册流程与网络数据收发的基本实现,用于二次开发或设备兼容性排查。
1. 海光网卡驱动安装包:让国产服务器在麒麟系统里真正“上网”
一台基于海光CPU的服务器,装完银河麒麟V10,系统起来了,但ip a里只有lo回环口,网卡灯明明亮着,物理口却一个都不认。这是所有信创项目现场最常见的开场白。所谓的海光网卡驱动安装包,解决的就是这个问题:它把海光平台自研网络控制器(比如HL系列、E800系列)的内核驱动模块,装进当前系统的内核树,让eth0、enp*这些网络接口真正出现。适合的人群很明确:做国产化替代的运维工程师、在x86海光服务器上搭KVM虚拟化或K8s集群的SRE,以及所有在麒麟、统信UOS、Debian系系统上被“网卡不识别”卡过脖子的人。这篇笔记把从查询硬件、匹配驱动包,到编译安装、验证收尾的完整路径讲透,顺带把几个翻车率极高的坑标出来。
2. 先认清你要驱动的到底是什么:海光网卡硬件型号与驱动来源
很多人第一反应是去网上搜“海光网卡驱动下载”,但拿到手的安装包对不对,前提是你搞清楚自己服务器上插的究竟是哪一颗网络控制器。
2.1 海光平台网卡的三类常见形态
海光CPU平台上的网卡,实际使用中分为三类。第一类是板载网络控制器,常见于海光主板自带的千兆/万兆电口或光口,芯片可能是海光自研的HL系列,也可能直接用了博通或Intel的PHY芯片(物理层收发器),这时候驱动责任方是海光或主板厂商。第二类是PCIe插槽上的独立网卡,比如浪潮、联想、超微的服务器上搭配的Intel X710/82599、Mellanox ConnectX系列,这类网卡驱动跟海光没有直接关系,去Intel或NVIDIA官网找标准驱动即可。第三类最容易被搞混:海光自研的“海光网络适配器”,在lspci里显示vendor ID为0x1d0f(海光信息),device ID如0x8088、0x8089等——这才是真正需要“海光网卡驱动安装包”的场景。
注意:
lspci显示的海光网络控制器,在部分固件版本下会以“Zhangjiang”或“Hygon”字样出现,不一定是“HaiGuang”全称,别只看品牌字面就下结论。
2.2 驱动包怎么选:内核版本比OS版本更关键
海光官方提供的网卡驱动安装包,通常以源码包(.tar.gz)形式发布,内含多个RPM或DEB的构建脚本,以及针对特定内核版本的patch。选包的第一原则是:你的内核版本号必须落在安装包的KABI兼容范围内。麒麟V10 SP1常见内核是4.19.90系列,统信UOS 1050常见内核是5.10或5.15,Debian 11是5.10、Debian 12是6.1。如果强行把为5.10写的驱动编译在6.1上,大概率会在make阶段报出类似implicit declaration of function或结构体成员不存在的错误——那是内核API变了,不是你的编译姿势错了。
常见做法是去海光官网的驱动下载页,按“服务器/工作站 → 操作系统版本 → 内核版本”三级筛选。下载页不会直接给一个“全家桶”,而是按OS发行版拆包。例如hygon_net_driver_1.x_centos7.9.tar.gz只对应CentOS 7.9 + 3.10内核,拿到麒麟V10上基本编不过。宁可多花10分钟确认内核小版本,也别急着解压执行install.sh——这一步省下的时间会在后面第5章的坑里加倍赔回去。
2.3 确认硬件与系统状态的标准命令序列
在动手下载任何一个安装包之前,先把下面这几条命令跑一遍,输出记到本子上。这不是形式主义,是为后面每一步提供决策依据。
# 查看PCI设备列表里所有网络控制器 lspci -nn | grep -Ei 'ethernet|network' # 查看海光vendor ID对应的具体设备 lspci -nn | grep -i '1d0f' # 查看当前内核版本(区分带+号和带-号的区别) uname -r # 查看系统发行版信息 cat /etc/os-release # 查看已加载的所有与网卡相关的内核模块 lsmod | grep -Ei 'hgn|hige|ixgbe|igb|e1000|bnx2x|mlx'lspci -nn输出里,方括号内是[vendor:device]十六进制对。看到[1d0f:8088]这类组合,基本可以断定这是海光的网络控制器,需要找海光官方驱动。看到[8086:10fb],那是Intel 82599,直接去Intel官网下载ixgbe驱动源码,跟海光一点关系都没有——这是最容易省下半天时间的判断。lsmod的输出能帮你预判:如果系统里已经加载了hgn(Hygon Network)模块但没有对应网口,说明驱动有但固件没匹配;如果什么都没加载,说明编译安装这条路还没人替你走过。
3. 下载与安装:从官网选包到模块加载的完整落地步骤
拿到正确的安装包之后,安装路径通常有两条:RPM/DEB二进制包直接装,或者源码编译安装。生产环境我一般优先选二进制包,因为海光官方在打包时已经把KABI校验、依赖补齐、开机加载脚本都处理好了,省去手动modprobe和depmod的环节。但很多现场拿到的安装包恰恰只有源码,那就得走编译流程。
3.1 确认必备工具链:没有make和gcc,后面全白搭
编译驱动前先确认基础环境。麒麟V10桌面版默认可能没装gcc和make,服务器版通常有。kernel-devel或linux-headers必须跟当前内核小版本一致,比如内核是4.19.90-52.22.v2207.ky10.x86_64,那kernel-devel也必须是同一版本号。查一下再决定要不要补装,避免编译到一半才报找不到generated/autoconf.h——那是内核头文件路径不对的典型症状。
# 检查工具链 which gcc && gcc --version which make && make --version # 检查内核头文件是否存在 ls -d /usr/src/linux-headers-$(uname -r) 2>/dev/null || ls -d /usr/src/kernels/$(uname -r) 2>/dev/null # 如果缺,麒麟V10上补装的常见做法 sudo yum install -y gcc make kernel-devel-$(uname -r) # Ubuntu/Debian系用 apt install -y build-essential linux-headers-$(uname -r)kernel-devel-$(uname -r)这个写法在麒麟、CentOS、Anolis上都适用,但前提是yum源里有跟当前内核完全同版本的devel包。如果源里没有,可以在海光驱动安装包附带的依赖目录里找,或者用yum install kernel-devel装一个最新的,然后reboot进新内核——前提是你愿意为了一个网卡驱动重启生产服务器。我个人习惯是:能不动内核版本就不动,宁可手动下载匹配的kernel-devel RPM包离线安装。
3.2 二进制包安装:RPM与DEB的完整流程
海光官方给麒麟V10提供的驱动包常见命名是higenet(Hygon Intelligent Gigabit Ethernet Network)或hgnet系列,安装形式为rpm -ivh或dpkg -i。下载后先校验包完整性,再安装,然后检查模块是否进入内核树。RPM包安装后,驱动模块通常落在/lib/modules/$(uname -r)/extra/目录下,不会跟内核自带的驱动冲突。
# 校验RPM包完整性 rpm -K higenet-1.x.x.x86_64.rpm # 安装(如果提示依赖缺失,先补齐依赖再装) sudo rpm -ivh higenet-1.x.x.x86_64.rpm # 安装后立即刷新模块依赖 sudo depmod -a # 加载驱动模块 sudo modprobe higenet # 确认模块已加载 lsmod | grep higenet # 确认网口已被识别 ip link showdepmod -a这一步经常被跳过,装完直接modprobe,系统提示module not found。原因就是模块依赖关系文件没有刷新,内核不知道新驱动模块放在哪个路径下。modprobe成功之后,ip link show应该能看到类似enp3s0f0、enp3s0f1的物理网口名称。如果名字还没出现,别急着重启,先看dmesg | tail -50的输出,确认是驱动加载报错还是固件加载失败。
DEB包流程几乎相同:dpkg -i安装,depmod -a刷新,modprobe加载。区别在于DEB包执行完安装脚本后,通常会自己跑一遍depmod,不需要手动执行。但源码包编译安装就不一样——所有步骤都得自己来。
3.3 源码编译安装:解压、配置、编译三步定位
源码包比RPM包多了两个关键步骤:解压后修改Makefile里的内核路径变量,以及根据当前内核版本选择编译模式(静态编译进内核或编译成模块)。海光的源码包里一般带一个INSTALL或README文档,里面会写明针对不同发行版的模块名和加载参数。直接执行./install.sh有时候能一把过,但install.sh内部写死了默认内核路径,遇到非标准路径就得手动改。
# 解压源码包 tar -xzf higenet_src_1.x.tar.gz cd higenet_src # 查看说明文件,确认编译目标 cat README | head -80 # 手动指定内核源码目录编译(重点:路径必须精确到当前内核头文件目录) make KSRC_DIR=/usr/src/linux-headers-$(uname -r) # 安装模块到内核目录 sudo make KSRC_DIR=/usr/src/linux-headers-$(uname -r) modules_install # 刷新模块依赖 sudo depmod -a # 加载 sudo modprobe higenetKSRC_DIR是源码包Makefile里最关键的变量。很多新手直接在源码根目录敲make,报错kernel source tree not found后一脸迷茫——因为默认路径指向/lib/modules/$(uname -r)/build,而这个build是个软链接,指向/usr/src/linux-headers-$(uname -r)。如果链接断了,或者头文件没装,报错就来了。手动指定KSRC_DIR的好处是绕开软链接判断,直接用精确路径。
编译过程如果报错error: unknown type name ‘ktime_t’或implicit declaration of function ‘in_interrupt’,说明源码包的内核API适配层太旧,需要应用包内提供的patch文件。用patch -p1 < xxx.patch打补丁后重新make clean && make。这个环节的教训是:先看README里有没有“对内核版本的要求”段落,再看有没有patches/目录——海光驱动包基本都带,但很多人跳过不看,白白浪费半小时编译报错时间。
3.4 网卡命名与网络配置的最佳实践
驱动加载成功后,网卡命名可能是eth0,也可能是enp3s0f0(PCIe物理位置命名)。麒麟V10默认使用enp*命名,如果系统里同时有板载网卡和PCIe网卡,命名规则可能不一致。我一般在/etc/network/interfaces(Debian系)或/etc/sysconfig/network-scripts/(RHEL系)里,用MAC地址绑定接口名来固定识别,避免重启后接口名漂移。具体做法是写一个/etc/udev/rules.d/70-persistent-net.rules,把MAC地址映射到固定接口名。
# 查看当前系统里所有网卡及其MAC地址 ip link show | grep -A1 'enp\|eth' # 写入持久化规则(以MAC地址为绑定依据) echo 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="3c:ec:ef:xx:xx:xx", NAME="eth0"' | sudo tee /etc/udev/rules.d/70-persistent-net.rules # 重载udev规则 sudo udevadm control --reload-rules sudo udevadm trigger用MAC地址绑定的原因是:海光网卡在BIOS里可能有多网口,不同网口的PCIe BDF(总线/设备/功能号)容易因为插槽顺序变化而改变,但MAC地址是出厂固化的,稳定性最高。写规则时注意MAC地址要小写,冒号分隔符一致,否则udev匹配失败。
4. 驱动验证与性能确认:从网口亮灯到万兆线速测试
安装不等于成功,驱动加载不等于性能达标。网口能up起来只说明驱动和硬件握手成功,但中断分布是否均匀、多队列是否生效、大包吞吐是否达到线速,还需要一套系统的验证流程。这一步是区分“装上能用”和“装上能扛”的分水岭。
4.1 基础验证三件套:ethtool、ip link、ping
先用ethtool确认网卡被驱动识别后的链路参数,再用ping确认二层/三层连通性,最后用iperf3打流确认吞吐量。三步走完,驱动安装这件事才算真正闭环。
# 查看网卡驱动与固件版本,确认驱动名称匹配 ethtool -i eth0 # 查看链路状态、速率、双工模式 ethtool eth0 # 配置IP并启用网口 sudo ip addr add 192.168.10.2/24 dev eth0 sudo ip link set eth0 up # 确认二层通联 ping -c 4 192.168.10.1ethtool -i输出里重点看driver和firmware-version两行。driver必须是higenet或对应海光模块名,如果显示成ixgbe或igb,说明内核用它自带的通用驱动驱动了海光芯片,链路能通但多队列和卸载特性可能残缺。firmware-version有值说明固件被正确加载,显示N/A则要检查/lib/firmware下是否有对应NVM文件。ethtool eth0输出里,Speed从1000Mb/s到10000Mb/s的差别,直接决定要不要调中断和队列参数。
4.2 多队列与中断亲和的参数调优
海光网卡默认支持多队列(RSS),每个队列绑定独立的MSI-X中断,然后通过irqbalance或手动设置/proc/irq/*/smp_affinity把中断分散到不同CPU核。生产环境里常见问题是所有中断都落在CPU0上,导致单核打满、其余核心围观。用ethtool -L设置队列数,用cat /proc/interrupts确认中断分布,用smp_affinity做CPU绑定。
# 查看当前网卡队列数量 ethtool -l eth0 # 设置最大队列数(以硬件支持上限为准) sudo ethtool -L eth0 combined 8 # 确认中断号与CPU分布 cat /proc/interrupts | grep eth0 # 手动绑定中断到不同CPU核(假设中断号从129到136,绑定到CPU0-7) for i in {129..136}; do echo 1 | sudo tee /proc/irq/$i/smp_affinity; doneethtool -l里的combined值是收发队列合并后的总数,上限由硬件决定。设置超过硬件上限会直接报错,设置过低会在高并发时出现丢包。smp_affinity直接写十进制数字,等价于二进制掩码,例如1只绑定CPU0,2绑定CPU1,3绑定CPU0和CPU1。生产环境我一般用irqbalance --hintpolicy=exact或者写一个systemd service在开机后自动配置,避免重启后中断全部回流到CPU0。
4.3 万兆线速验证:iperf3与丢包判定标准
驱动装完、网口起来后,最怕的是“能通但跑不满”。万兆网卡最常见的问题是PCIe通道数不足或中断分配失衡——驱动本身没有错,是平台配置限制了性能。验证手段是用iperf3双向打流,观察吞吐是否达到9.4Gbps以上(万兆端口的理论线速约9.4Gbps有效载荷)。
# 服务端(网卡所在机器) iperf3 -s # 客户端(对端机器,假设服务端IP为192.168.10.2) iperf3 -c 192.168.10.2 -t 60 -P 4 # 反向打流,验证双向 iperf3 -c 192.168.10.2 -t 60 -R-P 4表示四个并发连接,能把多队列的能力压出来。如果单线程只有1Gbps左右,多线程上到9Gbps,说明单队列性能瓶颈在CPU主频或中断处理,可以通过增大rx-buffer(ethtool -G eth0 rx 4096)缓解。如果多线程也只有2-3Gbps,检查网卡连接的PCIe插槽是x8还是x16——很多主板第二根PCIe x16插槽实际只有x4带宽,会直接把万兆吞吐卡死。ethtool -g eth0可以看当前ring buffer数值,ethtool -P eth0确认是否经过了NIC switch。
5. 海光网卡驱动安装的常见踩坑:现象、原因、解决
驱动装不上、网口出不来、重启就丢——这些不是玄学,每条背后都有确切的原因。这节把我这些年见过的真实翻车案例压缩成五条最典型的,每条都按“现象 → 原因 → 解决”排列,能帮你把排查时间从按小时计压到按分钟计。
5.1 现象:RPM包安装完成后modprobe higenet提示module not found
原因:RPM安装脚本里没有自动执行depmod -a,或者内核版本升级后模块依赖文件未刷新。驱动模块虽然文件在磁盘上,但内核不知道去哪里找它。
解决:执行sudo depmod -a,然后重新modprobe higenet。如果还不行,用find /lib/modules -name '*higenet*'看模块具体落在哪个内核版本目录下——有时候RPM把模块装进了新内核目录,而你当前启动的是旧内核,路径对不上。正确做法是确认uname -r对应的模块目录下有.ko文件,没有的话把模块文件复制到对应目录后重新depmod。
5.2 现象:源码编译报错/lib/modules/.../build: No such file or directory
原因:内核头文件包(kernel-devel)没装,或者软链接/lib/modules/$(uname -r)/build指向的目录不存在。在麒麟V10精简安装里,头文件默认不在。
解决:先ls -ld /usr/src/kernels/,确认是否有头文件目录。没有的话yum install -y kernel-devel-$(uname -r)安装精确版本。装了还在报错,就检查软链接:file /lib/modules/$(uname -r)/build,如果是broken symbolic link,ln -sf /usr/src/kernels/4.19.90-52.22.v2207.ky10.x86_64 /lib/modules/$(uname -r)/build,这个链接断掉最常见的原因是kernel-devel装的是不同小版本的内核头文件。
5.3 现象:网口能起来了,但ethtool eth0显示Speed: 1000Mb/s,协商不到万兆
原因:网线质量差或长度超过标准(六类线建议不超过55米)、对端交换端口强制了千兆、网卡EEPROM里默认关闭了万兆使能位。
解决:先换线缆和交换端口排除物理层问题,然后在对端端口speed 10000 duplex full强制万兆,网卡侧同时强制;两侧都重启网卡ip link set eth0 down && ip link set eth0 up。如果强制后链路还是起不来,去官网下NVMUpdate工具刷网卡固件——海光网卡有少量早期固件版本存在万兆协商兼容问题,刷NVM后再用ethtool eth0确认。
5.4 现象:重启后网口名称从eth0变成enp3s0f1,导致IP配置丢失
原因:内核ip link命名规则默认按PCIe总线地址生成,只要插槽位置或BIOS枚举顺序变化,接口名就变。IP配置绑定的还是旧接口名,所以新名称下没有IP,断网。
解决:按第3.4节写入udev规则,用MAC地址绑定固定接口名。注意规则必须在70-persistent-net.rules里写,数字越小优先级越高,千万别覆盖掉系统原有的80-net-setup-link.rules,否则systemd-networkd会把规则覆盖回来。写完规则后udevadm trigger使生效,reboot验证持久性。
5.5 现象:麒麟V10上装好驱动后,打开虚拟机管理器(virt-manager)创建网桥失败,提示“设备没有活动连接”
原因:网卡被NetworkManager接管后,桥接需要把物理网卡的master设置为br0,或者将NM的connection.autoconnect设为yes。而海光网卡驱动加载后,NM默认可能把接口视为“未受管”,nmcli看不到状态。
解决:用nmcli connection add type bridge创建桥接,再nmcli connection add type ethernet slave-type bridge master br0 ifname eth0把物理口桥到br0。如果NM配置被系统禁用,切回/etc/network/interfaces里手动配置bridge,注意同时改/etc/NetworkManager/NetworkManager.conf里managed=true。海光的驱动在桥接模式下通常表现稳定,关键是NM接管策略要跟驱动加载时序匹配,建议把驱动加到modprobe.d里的softdep,确保网口在NM启动前就绪。
5.6 现象:dmesg里报higenet 0000:03:00.0: firmware failed to load,网口起不来
原因:驱动源码包内附的.bin固件文件没有安装到/lib/firmware目录,或者固件文件的权限不对。海光网卡的PHY固件在驱动加载时需要从文件系统读取并下发到网卡芯片,文件缺失直接导致初始化失败。
解决:以解压源码包里fw/目录为例,把.bin文件复制到/lib/firmware/hygon/下,chmod 644,重新modprobe -r higenet && modprobe higenet。注意路径必须跟源码里request_firmware()调用的路径完全一致——这个路径在higenet.h或Makefile里写死了,不按它复制文件等于白放。
6. 驱动升级与编译环境隔离:两个让你少踩坑的进阶习惯
6.1 用dkms管理源码驱动,换内核不丢网卡
从源码编译安装的驱动,最怕的是系统升级内核后模块失效——/lib/modules/新内核/extra/里没有对应.ko文件,网卡直接失联。无论是海光驱动还是Intel ixgbe,我的标准动作是将其接入DKMS体系:源码包解压后,写一个dkms.conf,指定模块名、源码目录和内核匹配规则。这样每次apt upgrade或yum update安装新内核时,DKMS会为每个新内核自动编译并安装匹配的驱动模块。
# 在源码目录下创建dkms.conf cat > dkms.conf << 'EOF' PACKAGE_NAME="higenet" PACKAGE_VERSION="1.0" BUILT_MODULE_NAME[0]="higenet" DEST_MODULE_LOCATION[0]="/kernel/drivers/net/ethernet/hygon/" AUTOINSTALL="yes" MAKE[0]="make KSRC_DIR=/usr/src/linux-headers-$kernelver" EOF # 注册到DKMS并构建 sudo dkms add . sudo dkms build -m higenet -v 1.0 sudo dkms install -m higenet -v 1.0dkms.conf里的$kernelver是变量,DKMS构建时会自动替换为当前内核版本,不用手动改。这个习惯在私有云或K8s节点上尤其值钱——换内核不重启就丢网口的问题,一旦纳入DKMS就再也没发生过。我记得有个项目现场,客户自己执行yum update后重启,所有节点网卡全部失联,只能走IPMI进机房,前后折腾一整天。后来我强制要求驱动统一走DKMS,后续半年里三次内核升级全部平滑过渡,再无同类事件。
6.2 验证驱动的回归清单:升级后必过的一套命令
驱动升级或系统更新后,不需要等出问题再排查。我习惯在每次变更之后跑一套固定验证流,全程不超过两分钟,能覆盖绝大多数驱动级回归风险。这套流程在下一次你升级海光驱动或者给系统打内核补丁时,直接照着抄:
# 1. 确认驱动模块已为当前内核加载 lsmod | grep higenet # 2. 确认网卡接口存在且链路状态正常 ip -br link show # 3. 确认多队列数与硬件能力一致 ethtool -l eth0 | grep -A5 'Current' # 4. 确认没有固件加载错误 dmesg | grep -i higenet | grep -i error # 5. 快速打流验证吞吐未回退(客户端执行,30秒即可) iperf3 -c 192.168.10.2 -t 30 -P 4这五步的本质,是把“驱动加载、接口枚举、队列能力、固件状态、吞吐性能”全部覆盖一遍。其中第4步容易被忽略——有些驱动在dmesg里重复输出固件加载失败但接口还能起来,实际上是降级模式在跑,性能永远跑不满。升级后如果这条命令有输出,哪怕接口工作正常,我也建议立刻回滚驱动版本。
最后补一个我自己的习惯:所有源码包解压后,README文件和patches/目录先看,再动手编译;所有网卡MAC地址绑定规则,写进udev后一定要reboot实测再离开现场。这套流程是从多次夜间变更翻车里换来的,希望帮到你。
本文还有配套的精品资源,点击获取