一、问题描述
这个问题十年前就已经存在,一直以为是运营商给不够宽带或路由器老化,一直没有理,想着重新买台路由器,选了几个可以刷第三方固件的路由,最后选了磊科N60PRO。经过两天排查后,发现不是运营商问题,是网件R7000路由器底层设置问题;
博主家里是电信上行 500Mbps、下行 50Mbps,光猫桥接,由网件 R7000(固件 Xwrt-Vortex 384.19.0)进行 PPPoE 拨号。网件 R7000 的 LAN 口接入 N60 Pro 作为二级路由,通过有线或 WiFi 连接在 N60 Pro 下测试;
二、故障现象
- 下行:只有 230 Mbps 左右,怎么测都上不去
- 上行:62 Mbps 完全正常,和签约值一致
- 其他:有线直连 R7000、连 N60 Pro 的 WiFi和网线,结果全是 230 Mbps
三、走过的弯路
| 尝试 | 结果 | 为什么不是它 |
|---|---|---|
| 换 WiFi 信道、锁 80MHz | 速度不变 | 有线直连也是 230 |
| 怀疑 DFS 断流 | 无关 | DFS 表现是断连、跳信号,不是限速 |
| 怀疑 N60 Pro 性能不够 | 无关 | 直连 R7000 一样 230 |
| 怀疑测速节点/平台 | 无关 | 官方平台,上行跑满证明链路没问题 |
| 考虑换固件版本 | 方向错了 | 各版本的 CTF 来自同一份博通 SDK,差异有限 |
四、关键证据
1. CPU:单核吃满
查看后台首页的 CPU 占用,两颗核心正常是一起工作,怎么只有一个核心在工作,另一个虽然也有负载,像是"摸鱼",核心二持续不了几秒,全压给核心一负责;
核心1:80~90%
核心2:20-50%R7000 用的 BCM4709 是双核 Cortex-A9。在 Linux 下,网络软中断(softirq)默认只绑在 CPU0 上。这意味着整条转发路径的全部计算量,都由一个核硬扛,另一个核基本帮不上忙。
500M 下行每秒要处理几十万个数据包,CPU0 被打满后,多出来的包只能排队或丢弃,速度自然被压在 230 Mbps 附近。而上行只有 62M,包量少了一个数量级,同一个核完全吃得消——这就解释了为什么上行从来不掉速。
2. nvram:QoS 开着
顺着 “转发路径被加重” 的思路去查配置,命令如下:
nvram get qos_enable # 返回 1
nvram get traffic_analyzer
nvram get rt_traffic
nvram get cut_throttlectf_enable 和 fa_enable 返回空值,一度让人以为是硬件加速没开。后来确认:在这版 Merlin 的 R7000 移植固件里,这两个变量本来就不存在,它们只在部分华硕原厂固件里被写入。返回空不代表 CTF 没启用,只是该固件不用 nvram 变量来记录它。CTF 是内核模块,开机自动加载,由 qos_enable 等开关动态挂钩或解挂。
而 qos_enable=1 是实打实的,Merlin 的机制在于:只要 QoS 开启,硬件 NAT(CTF)就会被强制静默禁用,哪怕网页后台的“启用硬件加速”显示为开启也无效。没有提示、没有警告的隐性互斥关系,怀疑是故障的根源。
顺带还查到一个漏网之鱼:
nvram get qos_type # 返回 2(自适应 QoS 的游戏/流媒体模板残留)
nvram get bwdpi_enable # 返回 0,正常
nvram get wshaper_enable # 返回空,等同于 0
nvram get lpd_enable # 返回空,等同于 0qos_type=2 说明自适应 QoS 的模板还残留在 nvram 里,某些版本会靠它判断是否挂载 QoS 钩子,也需要清零。
五、修复步骤
第一步:网页后台逐项关闭
Merlin 384 里,会挂钩数据包的功能分散在好几个页面,需要关闭:
- 自适应 QoS
- 传统 QoS
- 带宽限制器(Bandwidth Limiter)
- 流量监控 / 实时流量统计
- AiProtection
- 访问控制 / 家长控制
- USB 共享服务(Samba/FTP/AiDisk)
- 系统管理 → 系统设置 → 启用硬件 NAT 加速
第二步:SSH 强制写一遍并重启
nvram set qos_enable=0
nvram set qos_type=0
nvram set wshaper_enable=0
nvram commit
reboot注意:
nvram set和nvram commit执行成功时是静默的,没有任何输出,“没反应” 是正常现象,不要以为命令卡住了;- 必须整机重启,只重启网络服务不生效;
- 如果终端光标不动,按一次
Ctrl+C,或者关掉窗口重连再逐条输入,避免一次性粘贴多行;
第三步:重启后验证
nvram get qos_enable # 必须是 0
nvram get qos_type # 必须是 0
如果想进一步确认 CTF 模块本身在工作:
lsmod | grep ctf # 有输出 = 模块已加载
cat /proc/ctf # 有数字 = 正在处理流量第四步:测速 + 看 CPU
保持和之前一样的测试条件(电脑网线直连 R7000 LAN 口,电信官方测速平台),同时盯着后台首页的 CPU。
六、结果
下行从 230 跳到 678-700,上行保持 62 不变
CPU 核心变化:从“核心1 90%、核心2 闲置”变成了“两个核心各分担 50-70% 左右”
两次测速如下(26-10-09 01:54)


七、原理
问:为什么关掉 QoS 会从“单核吃满”变成“双核各 50%”
1. QoS 开启时(软件转发)
每一个数据包都要完整走完这条链:
网卡中断 → 协议栈 → netfilter/iptables → QoS 队列整形 → NAT 查表 → 路由查找 → 发包这条链全部运行在 CPU0 的软件中断上下文里,是纯单线程,CPU1 无法参与。每包的处理开销很大,500M 下行直接把 CPU0 打满,速度被卡在 290 Mbps。
2. QoS 关闭后(CTF 硬件转发):
首包依然走完整协议栈建立连接信息,但后续大部分数据包绕过了协议栈、netfilter 和队列整形,由 CTF(Cut-Through Forwarding)模块用缓存的转发信息直接处理,每包开销骤降。
剩下的工作:PPPoE 封装解封装、中断处理、TCP 分段重组、测速客户端进程本身,不再局限于 pure-softirq 单线程模型,内核调度器会把它们分配到两个核上。
关键:看 CPU 占用不能只看百分比高低,要看“谁在干活、干的是什么活”。 90%+0% 意味着单核算力耗尽,是瓶颈;50%+50% 意味着负载被摊平,整机还有大量余量。这也是为什么百分比看起来“更忙了”,速度反而翻倍以上。
八、复盘
问:为什么一开始没定位到
回看整个排查过程,博主有几个判断失误:
- “刷机”带偏: “刷完固件就掉速”,第一反应自然是固件版本或驱动问题。实际上刷机本身没问题,出问题的是随配置备份一起恢复回来的 QoS 设置。不同固件版本的默认值也可能不同。
- 过度关注了不存在的变量。
ctf_enable返回空被当成了重要线索,浪费了不少时间。正确的顺序应该是先看 CPU 和qos_enable,再看别的。
正确的排查顺序应该是:
有线直连主路由测速 → 看 CPU 占用分布 → 查 QoS/加速类开关 → 查 DPI/流量统计类功能 → 最后才考虑固件和硬件其中“上行正常、下行掉速”这一条,可以在第一步就直接把范围缩到转发路径上,但没解决这种问题跑偏了。
九、附录
# 排查
nvram get qos_enable
nvram get qos_type
nvram get wshaper_enable
nvram get bwdpi_enable
nvram get lpd_enable
nvram get traffic_analyzer
nvram get rt_traffic
lsmod | grep ctf
cat /proc/ctf
# 修复
nvram set qos_enable=0
nvram set qos_type=0
nvram set wshaper_enable=0
nvram commit
reboot
# 验证
nvram get qos_enable # 必须 0
nvram get qos_type # 必须 0十、总结
1. 别乱点设置:Merlin 有个老毛病:网页后台点应用时,会把 nvram 里残留的 QoS 模板重新读进来,可能悄悄把 qos_enable 写回 1,改完其他设置,需要 SSH 确认一眼 nvram get qos_enable 是不是 0
2. 别乱开功能:自适应 QoS、传统 QoS、带宽限制器、流量监控、AiProtection、USB 共享,只要有一个开着,CTF 就会被静默禁用,直接变回 230 Mbps

