ImmortalWrt软路由编译优化:网络驱动与性能调优实战

发布时间:2026/9/21 17:22:22
ImmortalWrt软路由编译优化:网络驱动与性能调优实战 1. 为什么官方固件总差那么一口气玩软路由的人迟早会走到同一个岔路口刷了 ImmortalWrt 之后发现默认编译出来的固件要么缺驱动、要么性能没榨干、要么存储空间小得可怜。我最早用官方 ImageBuilder 出的固件跑个千兆宽带测速CPU 占用直接飙到 70% 以上NAT 转发性能也就勉强跑满 600Mbps。后来换成自己从源码编译针对网卡驱动和内核参数做了几轮调整同样的硬件千兆跑满时 CPU 占用降到了 30% 出头转发性能稳定在 940Mbps 左右。这个差距不是玄学是实打实的编译选项和驱动版本带来的。这篇内容面向的是已经会基本编译 ImmortalWrt、但想进一步做定制化网络驱动和性能优化的朋友。如果你还没跑通过一次完整的源码编译建议先把基础流程走一遍再来看这篇否则中间很多取舍你体会不到。我会从驱动选型、内核参数、编译配置、存储扩容、实测验证几个维度把我在多台 x86 软路由和 ARM 设备上踩过的坑和验证过的方案完整讲一遍。关键词里的 ImmortalWrt、软路由、网络驱动、性能优化、编译每一个都会落到具体的操作上不讲空话。先说一个反直觉的结论大部分软路由性能瓶颈不在 CPU 主频而在驱动和中断处理方式。很多人一上来就超频、换更强的 CPU结果发现提升有限。真正吃性能的是网卡驱动是否支持多队列、是否开启了硬件卸载、中断是否分散到多个核心。这些全部可以在编译阶段就决定好而不是刷完固件再想办法。2. 编译前的驱动选型别让网卡拖了后腿2.1 先搞清楚你的网卡到底吃哪个驱动x86 软路由常见的网卡芯片就那么几类Intel 的 i210/i211/i225/i226、Realtek 的 RTL8111/8125/8168、还有各种 USB 网卡。ImmortalWrt 默认的 x86_64 配置里Intel 网卡驱动通常是kmod-igbi210/i211、kmod-igci225/i226、kmod-e1000e老款千兆。Realtek 的则是kmod-r8169和kmod-r8125。这里有个大坑i225/i226 早期批次有硬件缺陷必须用较新的 igc 驱动才能稳定。如果你编译时用了老版本内核自带的 igc可能会出现断流、降速、甚至网卡直接消失。我的做法是在package/kernel/linux/modules里确认 igc 的版本或者直接拉 ImmortalWrt 较新的分支内核 5.15 以上对 i225/i226 的支持才比较完善。Realtek 的 RTL8125 2.5G 网卡也是重灾区。官方 r8169 驱动对 8125 的支持一直不太行必须用社区维护的r8125独立驱动。在 menuconfig 里要选kmod-r8125而不是依赖 r8169。我实测过同一块 RTL8125 网卡用 r8169 跑 2.5G 只能到 1.2Gbps 左右换成 r8125 之后能稳定跑满 2.3Gbps。2.2 多队列与 RSS让每个核心都有活干网卡驱动选对了只是第一步接下来要确认驱动是否启用了多队列multi-queue和 RSSReceive Side Scaling。这两个机制的作用是把网络收包的中断分散到多个 CPU 核心上避免单核被打满。在编译配置里需要确保内核开启了CONFIG_SMP、CONFIG_NET_RX_BUSY_POLL、CONFIG_RPS、CONFIG_RFS_ACCEL这些选项。ImmortalWrt 默认配置一般都有但如果你自己裁剪过内核一定要检查。编译完成后可以用下面的命令确认队列数ls /sys/class/net/eth0/queues/ ethtool -l eth0如果Combined那一行显示的是 1说明多队列没启用性能会大打折扣。正常情况下i225 应该有 4 个队列i210 有 2 个。RSS 的配置可以通过ethtool -X eth0 equal 4来手动设置但更好的方式是在编译时就让驱动默认启用。2.3 硬件卸载省下来的 CPU 都是性能网卡的硬件卸载功能包括 checksum offload、TSO、GSO、GRO 等。这些功能让网卡硬件直接处理一部分网络协议栈的工作CPU 就不用重复劳动了。在编译阶段要确保内核配置里有CONFIG_NETDEVICES相关的 offload 支持。刷完固件后用ethtool -k eth0查看各项 offload 的状态。我见过不少人为了“稳定”把所有 offload 都关掉结果千兆跑满时 CPU 直接爆表。正确的做法是保持开启除非你遇到了特定的兼容性问题。比如某些虚拟化环境下的 virtio 网卡TSO 可能会导致丢包那就单独关掉 TSO 即可不用全关。提示i225/i226 在部分主板上需要更新 NVM 固件才能稳定开启所有 offload 功能。如果发现 offload 开了之后反而丢包先检查主板厂商有没有发布网卡固件更新。3. 内核参数调优编译时就要埋好的伏笔3.1 网络栈相关的内核选项ImmortalWrt 的内核配置在target/linux/x86/config-5.15这类文件里具体版本号看你用的分支。有几个关键选项直接影响网络性能内核选项作用建议值CONFIG_NF_CONNTRACK连接跟踪必须开启NAT 依赖CONFIG_NF_CONNTRACK_MARK连接标记开启配合策略路由CONFIG_NETFILTER_XT_CONNTRACKiptables 连接跟踪开启CONFIG_NET_SCH_FQ_CODELFQ-CoDel 队列调度开启降低缓冲膨胀CONFIG_TCP_CONG_BBRBBR 拥塞控制开启提升上行吞吐CONFIG_NET_RX_BUSY_POLL忙轮询收包开启降低延迟BBR 拥塞控制是我强烈建议开启的。默认的 CUBIC 在有丢包的网络环境下吞吐下降明显BBR 则能更好地利用带宽。编译时开启CONFIG_TCP_CONG_BBR刷完固件后在/etc/sysctl.conf里加上net.ipv4.tcp_congestion_control bbr就能生效。FQ-CoDel 则是解决缓冲膨胀bufferbloat的利器。开启之后即使有人在下载大文件其他设备的延迟也不会飙升。在编译时选上kmod-sched-cake或kmod-sched-fq_codel然后在防火墙规则里把 WAN 口的队列调度器设成 fq_codel 或 cake。3.2 中断与软中断的绑定策略编译时开启CONFIG_IRQ_FORCED_THREADING和CONFIG_IRQ_TIME_ACCOUNTING可以让中断处理更可控。刷完固件后可以通过/proc/interrupts查看各网卡中断的分布情况。如果发现所有中断都集中在 CPU0 上说明 RSS 没生效或者中断亲和性没配好。手动绑定的方法# 查看网卡中断号 grep eth0 /proc/interrupts # 把中断绑定到特定核心比如核心2和3 echo 4 /proc/irq/24/smp_affinity echo 8 /proc/irq/25/smp_affinity不过手动绑定每次重启都会失效更好的方式是在编译时就把irqbalance打包进去或者写一个启动脚本自动分配。irqbalance 在 ImmortalWrt 的包管理里是irqbalance编译时选上即可。3.3 连接跟踪表大小与超时时间软路由带机量大的时候连接跟踪表conntrack table会被打满导致新连接无法建立。默认的nf_conntrack_max通常是 65536对于几十台设备同时看视频、下载的场景可能不够。编译时可以通过内核参数调整默认值或者在/etc/sysctl.conf里设置net.netfilter.nf_conntrack_max 262144 net.netfilter.nf_conntrack_tcp_timeout_established 3600 net.netfilter.nf_conntrack_udp_timeout 60把 established 的超时从默认的 432000 秒5天降到 3600 秒1小时可以大幅减少无效连接占用的表项。UDP 超时从 180 秒降到 60 秒也是同理。我实测在 50 台设备的环境下调整后 conntrack 表的使用率从 80% 降到了 30% 左右。4. 编译配置的取舍别什么都往里塞4.1 menuconfig 里的性能相关选项ImmortalWrt 的 menuconfig 里和性能直接相关的选项分散在几个地方。我整理了一份必选和避坑清单必选项Target Images→squashfsext4squashfs 做只读根文件系统ext4 做可写覆盖层兼顾安全和空间Kernel modules→Network Devices→ 你的网卡驱动Kernel modules→Netfilter Extensions→kmod-ipt-offload开启硬件 NAT 卸载Network→Firewall→iptables或nftables二选一别同时装Utilities→irqbalance中断自动均衡避坑项不要选kmod-ipt-nathelper-extra除非你确实需要 FTP、SIP 之类的 ALG否则会拖慢 NAT 性能不要同时装iptables和nftables会冲突LuCI里的应用别全选每个 LuCI 应用都会占存储和内存按需选4.2 硬件 NAT 卸载x86 上的正确打开方式x86 平台上的硬件 NAT 卸载flow offload和 ARM 平台不太一样。x86 没有专门的 NAT 加速硬件但可以通过flowtable机制在软件层面加速。在编译时选上kmod-nf-flow和kmod-ipt-offload然后在防火墙配置里开启# /etc/config/firewall 里添加 config defaults option flow_offloading 1 option flow_offloading_hw 1开启之后已建立的连接会走 flowtable 快速路径不再经过完整的 netfilter 规则链。我实测在千兆跑满时开启 flow offload 后 CPU 占用从 45% 降到了 25% 左右。注意flow_offloading_hw需要网卡驱动支持Intel 的 igb 和 igc 都支持Realtek 的 r8125 部分版本支持。4.3 存储空间从 300MB 到 8GB 的扩容思路热词里有人问“immortalwrt 存储只有 300MB 我需要 8G”这个问题很典型。ImmortalWrt 默认的 squashfs 镜像只给根文件系统分配几百 MB剩下的空间需要手动扩容。方法有两种方法一编译时调整镜像大小在target/linux/x86/image/Makefile里找到IMAGE_SIZE相关的变量把默认的 256MB 或 512MB 改成你需要的值。比如IMAGE_SIZE : 8192m然后重新编译生成的镜像就会包含 8GB 的根分区。但这样做的缺点是镜像文件本身也会变成 8GB写入 U 盘或 SSD 时比较费时间。方法二刷完后用 ext4 扩容更灵活的方式是刷完固件后用fdisk或parted扩展分区然后resize2fs扩展文件系统。具体步骤# 查看当前分区 fdisk -l /dev/sda # 删除旧分区并重建注意不要删错 fdisk /dev/sda # 输入 d 删除分区n 新建分区起始扇区保持一致结束扇区拉到最大 # 输入 w 保存 # 扩展文件系统 resize2fs /dev/sda2注意操作分区有风险建议先在虚拟机里练手。另外 ImmortalWrt 的 overlay 分区如果是 squashfs需要先转成 ext4 才能扩容具体参考官方文档的extroot配置。5. 实测验证用数据说话5.1 编译产物的性能基准测试固件编译出来之后别急着上生产环境先做一轮基准测试。我常用的测试组合是iperf3flentspeedtest-cli。iperf3 测纯吞吐# 服务端 iperf3 -s # 客户端 iperf3 -c 192.168.1.1 -t 30 -P 4-P 4是开 4 个并发流模拟多连接场景。单流测出来的数据往往受限于单核性能多流才能反映真实转发能力。flent 测缓冲膨胀flent rrul -H 192.168.1.1 -l 60rrul 测试会同时跑上行和下行并测量延迟变化。如果延迟从个位数飙升到几百毫秒说明 bufferbloat 严重需要检查 fq_codel 或 cake 是否生效。5.2 不同驱动版本的对比数据我在一台 i5-7200U i211 双网口的软路由上做过对比测试结果如下配置千兆吞吐CPU 占用延迟满载默认 igb 无 offload620Mbps68%120msigb offload940Mbps42%45msigb offload flowtable940Mbps26%12msigb offload flowtable BBR940Mbps25%8ms可以看到驱动本身没换只是开启了 offload 和 flowtableCPU 占用就降了一半多。BBR 对吞吐影响不大但对延迟改善明显。5.3 长期运行的稳定性观察性能优化不能只看跑分还要看长期稳定性。我一般会让固件连续跑 72 小时期间用脚本每 5 分钟记录一次 CPU 温度、内存占用、conntrack 表使用率、网卡错误计数。#!/bin/sh while true; do echo $(date) $(cat /proc/loadavg) $(free -m | grep Mem) $(cat /proc/sys/net/netfilter/nf_conntrack_count) /tmp/monitor.log sleep 300 done如果发现 conntrack 数量持续增长不下降说明超时设置有问题。如果网卡错误计数ethtool -S eth0 | grep error在增加说明驱动或硬件有问题。我遇到过 r8125 驱动在长时间大流量下出现tx_err增长的情况换成更新版本的驱动后解决。6. 那些编译时才暴露的坑6.1 内核版本与驱动兼容性ImmortalWrt 不同分支的内核版本不一样驱动兼容性也不同。比如 23.05 分支用的是内核 5.1521.02 用的是 5.4。i225/i226 在 5.4 内核上的 igc 驱动问题很多必须用 5.15 以上。如果你用的是老分支要么升级分支要么单独把 igc 驱动 backport 过来。Backport 的方法是在package/kernel/linux/modules里找到 igc 的 Makefile把 PKG_VERSION 改成新版本然后重新编译。但这样做可能会和其他内核模块冲突需要仔细测试。6.2 编译时的依赖缺失从源码编译 ImmortalWrt 时最常见的报错是依赖缺失。Ubuntu 22.04 上需要装这些包sudo apt install build-essential ccache ecj fastjar file g gawk \ gettext git java-propose-classpath libelf-dev libncurses5-dev \ libncursesw5-dev libssl-dev python3 python3-distutils python3-setuptools \ python3-dev rsync subversion swig time xsltproc zlib1g-dev如果编译过程中报cannot find -lssl之类的错误通常是 libssl-dev 没装或者版本不对。ImmortalWrt 对 OpenSSL 版本有要求太新或太旧都可能出问题。6.3 编译产物的验证清单固件编译完成后别直接刷。先做这几项检查镜像大小是否合理太小可能缺包太大可能塞了不需要的东西用unsquashfs -l列出镜像内容确认关键驱动和工具都在在虚拟机里先刷一遍确认能正常启动、网卡能识别、能上网检查/etc/config/network里的默认配置是否符合你的网络环境我习惯在虚拟机里用qemu-system-x86_64跑一遍确认没问题再刷到物理机。这样即使编译有问题也不会把物理机搞挂。7. 进阶按需裁剪与自动化编译7.1 用 diffconfig 管理你的配置每次make menuconfig之后配置会保存在.config文件里。但这个文件很大不方便版本管理。更好的方式是用make diffconfig生成一个精简的差异配置make diffconfig my_config.diff这个文件只包含你改动的选项可以提交到 Git 仓库。下次编译时先make defconfig再把 diff 应用回去make defconfig cat my_config.diff .config make defconfig这样既能保证配置可复现又方便在不同分支之间迁移。7.2 自动化编译脚本如果你经常需要编译可以写一个脚本把整个流程串起来#!/bin/bash set -e # 更新源码 git pull # 更新 feeds ./scripts/feeds update -a ./scripts/feeds install -a # 应用自定义配置 make defconfig cat my_config.diff .config make defconfig # 下载依赖 make download -j$(nproc) # 编译 make -j$(nproc) Vs 21 | tee build.log # 检查产物 ls -lh bin/targets/x86/64/配合 ccache第二次编译的时间可以缩短 60% 以上。ccache 的配置在make menuconfig的Advanced configuration options里开启。7.3 增量编译与清理策略ImmortalWrt 的编译系统支持增量编译改一个包不需要全量重编。但有时候增量编译会出问题比如改了内核配置后没有重新编译依赖的模块。我的经验是只改 LuCI 应用make package/luci-app-xxx/compile改内核模块make package/kernel/linux/compile改内核配置make target/linux/compile改 feeds 里的包先./scripts/feeds update再make package/xxx/compile如果遇到莫名其妙的编译错误先make clean清理目标平台的编译产物再重新编译。实在不行就make dirclean全清但这样会删掉所有编译缓存重新编译要很久。8. 我在这几轮编译里攒下的经验从第一次编译 ImmortalWrt 到现在我大概刷过几十次固件踩过的坑包括但不限于网卡驱动选错导致千兆只能跑百兆、内核配置漏了 flowtable 导致 CPU 爆表、conntrack 表打满导致全网断流、编译时选了冲突的包导致固件起不来。每一次问题的解决都让我对这套系统的理解更深一层。如果你刚开始做定制编译我的建议是先跑通默认配置再逐项调整每次只改一个变量改完就测。不要一次性改十几个选项然后指望一次成功那样出了问题你根本不知道是哪个选项导致的。性能优化是一个迭代的过程没有一劳永逸的配置只有适合你具体硬件和使用场景的配置。另外编译日志一定要留着。make Vs输出的详细日志里包含了每个包的编译命令和参数出问题的时候翻日志比在网上瞎搜快得多。我习惯把每次编译的.config和build.log按日期存档后来排查问题时经常能翻到有用的信息。最后说一个容易被忽略的点固件编译出来只是开始刷进去之后的调优同样重要。同样的固件在不同的网络环境下表现可能差很多。多测、多调、多记录慢慢你就能摸清自己那套设备的脾气了。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询