使用 queue tree 配置 RouterOS 流控
本文介绍两种流量整形。方案一适用于家庭或小型网络:使用 CAKE 对上下行分别做总速率整形和流公平;方案二适用于需要单独限制 BT、PT 等大流量设备或服务的场景。两种方案不要同时启用
1. 使用 CAKE 做低延迟整形
CAKE 同时提供主动队列管理(AQM)和流量公平。本方案只在两个实际的出方向接口上建立 queue tree,因此 IPv4 和 IPv6 都可以直接覆盖。
queue tree 是单向队列。下载流量最终从路由器发往局域网,所以下载队列的父接口应是 LAN 出口;上传流量最终从路由器发往互联网,所以上传队列的父接口应是 WAN 出口。父接口必须按自己的拓扑修改,不能直接照抄示例名称。
1.1 确定需要自定义的参数
| 占位符 |
含义 |
示例 |
<LAN_EGRESS_INTERFACE> |
面向客户端的实际出方向接口;可能是 bridge1、lan 或 VLAN 接口 |
lan |
<WAN_EGRESS_INTERFACE> |
面向互联网的实际出方向接口;PPPoE 应填写 PPPoE 逻辑接口,而不是底层以太网口 |
pppoe-out1 |
<DOWNLOAD_RATE> |
下载整形上限,填写实测稳定下载速率以下的值 |
900M |
<UPLOAD_RATE> |
上传整形上限,填写实测稳定上传速率以下的值 |
100M |
速率建议先从未整形时稳定实测值的 90%~95% 开始,再用满载延迟测试微调。900M 和 100M 只是本文示例;如果宽带不是约 1G/100M,不要直接使用这两个数值。
1.2 添加 CAKE queue type
下面的 cake-bandwidth=0 表示把方向总速率统一写在 queue tree 的 max-limit 中,避免在两个位置维护不同的速率。
1 2 3
| /queue type add cake-ack-filter=none cake-bandwidth=0 cake-diffserv=besteffort cake-flowmode=dual-dsthost cake-nat=no cake-overhead=0 cake-rtt=100ms cake-rtt-scheme=internet cake-wash=no kind=cake name=CAKE-Down add cake-ack-filter=none cake-bandwidth=0 cake-diffserv=besteffort cake-flowmode=dual-srchost cake-nat=yes cake-overhead=0 cake-rtt=100ms cake-rtt-scheme=internet cake-wash=no kind=cake name=CAKE-Up
|
如果系统中已经存在同名的 CAKE-Down、CAKE-Up,直接复用并核对参数,不要重复执行 add。
参数选择说明:
- 下载使用
dual-dsthost,按局域网内的目的主机做公平调度,避免单个设备或大量连接占满下载带宽。
- 上传使用
dual-srchost,按局域网内的源主机做公平调度,避免单个设备占满上传带宽。
- 上传使用
cake-nat=yes,让经过源地址转换的多个内网设备仍能被 CAKE 区分;下载队列已经位于 LAN 出口,使用 cake-nat=no 即可。
cake-diffserv=besteffort 不按 DSCP 做业务优先级分类,重点是降低排队延迟和保证多主机公平。如果确实需要 DNS、游戏或语音的显式优先级,应单独设计 DSCP/业务分类,不要把旧方案的端口标记规则和本方案无条件叠加。
- 普通以太网或已留出余量的 PPPoE 宽带可先使用
cake-overhead=0;DSL、VDSL、DOCSIS 等链路应根据接入方式重新核对 overhead 参数。
1.3 配置 queue tree
先把下面尖括号中的 用户自定义项 替换成自己的值,再执行命令:
1 2 3
| /queue tree add bucket-size=0.01 max-limit=<DOWNLOAD_RATE> name=CAKE-Download parent=<LAN_EGRESS_INTERFACE> priority=8 queue=CAKE-Down add bucket-size=0.01 max-limit=<UPLOAD_RATE> name=CAKE-Upload parent=<WAN_EGRESS_INTERFACE> priority=8 queue=CAKE-Up
|
例如,局域网出口名为 lan、PPPoE 逻辑接口名为 pppoe-out1,实测后选择 900M/100M 时,才对应下面的实际配置:
1 2 3
| /queue tree add bucket-size=0.01 max-limit=900M name=CAKE-Download parent=lan priority=8 queue=CAKE-Down add bucket-size=0.01 max-limit=100M name=CAKE-Upload parent=pppoe-out1 priority=8 queue=CAKE-Up
|
不需要为这个方案添加 packet-mark,也不需要为 IPv4、IPv6 分别添加 mangle 标记规则。对于 PPPoE,上传父接口通常填 pppoe-out1;只有在路由器实际通过 DHCP 或静态地址从 wan 接入互联网时,才应把父接口改成 wan。如果 LAN 使用桥,父接口应填真正承载客户端出方向流量的桥或三层接口,而不是想当然地填写某个桥端口。
1.4 检查、切换与验证
1 2 3 4
| /queue tree print detail /queue type print detail /ip firewall filter print where action=fasttrack-connection /ip settings print
|
RouterOS 的 FastTrack 会绕过 simple queue 和 parent=global 的 queue tree;如果自行把本方案改成 parent=global,必须先处理 FastTrack。使用接口作为父队列时也应通过满载测试确认队列计数器确实在增长。
分别进行一次下载和上传满载测试,同时观察:
1 2
| /queue tree print stats /system resource print
|
满载时队列的 rate 应接近对应的 max-limit,延迟不应像未整形时一样明显上升;CPU 长时间满载时,应降低整形速率或换用更轻量的队列类型。空闲时 queued-bytes=0、dropped=0 只能说明当前没有排队,不能证明满载时整形一定正常。
参考:MikroTik CAKE 文档、MikroTik Queue Tree 文档。
2. 使用 mangle 分类的分级限速
方案二适用于需要把 BT、PT 等大流量设备或服务放到低优先级,同时为 DNS、小包和普通 Web 流量保留较高调度优先级的场景。它依赖 mangle 的 packet-mark 和 queue tree 的叶子队列,配置复杂度明显高于方案一。
本方案使用真实接口作为 queue tree 的父接口:下载父接口是 LAN 出口,上传父接口是实际的 WAN 出口。PPPoE 场景应填写 PPPoE 逻辑接口,而不是底层物理网卡。
方案一和方案二不要同时启用。下面所有尖括号中的内容都是 用户自定义项;示例值仅用于说明格式。
2.1 确定需要自定义的参数
| 占位符 |
含义 |
示例 |
<LAN_EGRESS_INTERFACE> |
面向客户端的实际出方向接口 |
lan |
<WAN_EGRESS_INTERFACE> |
面向互联网的实际出方向接口;PPPoE 使用逻辑接口 |
pppoe-out1 |
<UPLOAD_RATE> |
上传总上限 |
50M |
<DOWNLOAD_RATE> |
下载总上限 |
400M |
<PT_UPLOAD_RATE> |
所有 PT 客户端合计的上传上限 |
10M |
<PT_DOWNLOAD_RATE> |
所有 PT 客户端合计的下载上限 |
100M |
<PT_IPV4_1>、<PT_IPV4_2> |
PT 客户端的固定 IPv4 地址 |
10.0.0.55 |
<PT_IPV6_1>、<PT_IPV6_2> |
PT 客户端的稳定 IPv6 地址 |
2001:db8::55 |
PT 客户端最好使用 DHCP 静态租约、固定容器地址或稳定的 IPv6 地址。不要把示例 IP、MAC 地址或 IPv6 前缀直接照抄到自己的网络中。这里将多个 PT 客户端放进同一个地址列表,因此它们在同一方向会共享同一个 PT 队列;上传和下载仍然是两个独立的限额,不会自动合并成一个双向总额度。
2.2 添加 queue type
优先级由 queue tree 叶子队列的 priority 控制,不需要为 DNS、Web、PT 等每一种流量复制一套不同的 fq-codel 参数。下面所有叶子队列共用一个较保守的 FQ-CoDel 类型,也避免大量队列的内存上限叠加。
1 2
| /queue type add fq-codel-flows=1024 fq-codel-interval=100ms fq-codel-limit=8192 fq-codel-memlimit=32.0MiB fq-codel-quantum=1514 fq-codel-target=5ms kind=fq-codel name=Fq_Codel
|
如果系统中已经存在同名的 Fq_Codel,直接复用并核对参数,不要重复执行 add。不要使用固定编号修改系统默认的 queue type。
2.3 创建 PT 客户端地址列表
本方案使用 IP 地址列表,不使用 MAC 地址作为主要匹配条件。MAC 地址只在客户端和 RouterOS 处于同一二层网段且地址稳定时才适合作为补充条件。
1 2 3
| /ip firewall address-list add address=<PT_IPV4_1> list=PT_CLIENTS comment="QUEUE PT client 1" add address=<PT_IPV4_2> list=PT_CLIENTS comment="QUEUE PT client 2"
|
1 2 3
| /ipv6 firewall address-list add address=<PT_IPV6_1> list=PT_CLIENTS_V6 comment="QUEUE PT client 1" add address=<PT_IPV6_2> list=PT_CLIENTS_V6 comment="QUEUE PT client 2"
|
2.4 IPv4 mangle 分类
本方案在 forward 链中使用专用的 queue_mark_v4/queue_mark_v6 分类链,不在 prerouting 链重复标记。最后的 jump 规则使用 place-before=0 插入 forward 链最前面:先完成队列分类,遇到 return 后再继续执行原有的策略路由和其他 mangle 规则。
分类链中的队列标记全部使用 passthrough=yes。不要把队列标记改成 passthrough=no,否则可能导致返回主链后的策略路由标记不执行。
qB/PT 默认放在最低优先级,因此先标记 PT 连接和数据包;后面的 DNS、Web、小包规则都带有 packet-mark=no-mark,不会覆盖 PT 标记。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| /ip firewall mangle add action=mark-connection chain=queue_mark_v4 comment="QUEUE PT source" connection-mark=no-mark connection-state=new new-connection-mark=PT-connection passthrough=yes src-address-list=PT_CLIENTS add action=mark-connection chain=queue_mark_v4 comment="QUEUE PT destination" connection-mark=no-mark connection-state=new dst-address-list=PT_CLIENTS new-connection-mark=PT-connection passthrough=yes add action=mark-packet chain=queue_mark_v4 comment="QUEUE PT packet" connection-mark=PT-connection new-packet-mark=PT-packet packet-mark=no-mark passthrough=yes
add action=mark-packet chain=queue_mark_v4 comment="QUEUE DNS UDP" new-packet-mark=Dns-packet packet-mark=no-mark passthrough=yes port=53 protocol=udp add action=mark-packet chain=queue_mark_v4 comment="QUEUE DNS TCP" new-packet-mark=Dns-packet packet-mark=no-mark passthrough=yes port=53,853 protocol=tcp
add action=mark-packet chain=queue_mark_v4 comment="QUEUE Web TCP" new-packet-mark=Web-packet packet-mark=no-mark passthrough=yes port=80,443,8080 protocol=tcp add action=mark-packet chain=queue_mark_v4 comment="QUEUE Web UDP" new-packet-mark=Web-packet packet-mark=no-mark passthrough=yes port=80,443,8080 protocol=udp
add action=mark-packet chain=queue_mark_v4 comment="QUEUE small packet" connection-bytes=0-256000 new-packet-mark=Small-packet packet-mark=no-mark packet-size=0-512 passthrough=yes add action=return chain=queue_mark_v4 comment="QUEUE return to existing mangle rules" add action=jump chain=forward comment="QUEUE classify before existing forward rules" jump-target=queue_mark_v4 place-before=0
|
如果不需要 DNS、Web 或小包分类,可以不添加对应规则。端口分类只是近似匹配:443 也可能是视频、下载或其他 QUIC 流量,DoH/DoQ 也不一定会命中 DNS 规则。
2.5 IPv6 mangle 分类
IPv6 使用同样的顺序和 passthrough=yes,但地址列表必须填写自己的稳定 IPv6 地址。不要把一个客户端的 IPv6 地址写成另一个地址,也不要假设隐私地址会长期不变。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| /ipv6 firewall mangle add action=mark-connection chain=queue_mark_v6 comment="QUEUE PT source" connection-mark=no-mark connection-state=new new-connection-mark=PT-connection passthrough=yes src-address-list=PT_CLIENTS_V6 add action=mark-connection chain=queue_mark_v6 comment="QUEUE PT destination" connection-mark=no-mark connection-state=new dst-address-list=PT_CLIENTS_V6 new-connection-mark=PT-connection passthrough=yes add action=mark-packet chain=queue_mark_v6 comment="QUEUE PT packet" connection-mark=PT-connection new-packet-mark=PT-packet packet-mark=no-mark passthrough=yes
add action=mark-packet chain=queue_mark_v6 comment="QUEUE DNS UDP" new-packet-mark=Dns-packet packet-mark=no-mark passthrough=yes port=53 protocol=udp add action=mark-packet chain=queue_mark_v6 comment="QUEUE DNS TCP" new-packet-mark=Dns-packet packet-mark=no-mark passthrough=yes port=53,853 protocol=tcp
add action=mark-packet chain=queue_mark_v6 comment="QUEUE Web TCP" new-packet-mark=Web-packet packet-mark=no-mark passthrough=yes port=80,443,8080 protocol=tcp add action=mark-packet chain=queue_mark_v6 comment="QUEUE Web UDP" new-packet-mark=Web-packet packet-mark=no-mark passthrough=yes port=80,443,8080 protocol=udp
add action=mark-packet chain=queue_mark_v6 comment="QUEUE small packet" connection-bytes=0-256000 new-packet-mark=Small-packet packet-mark=no-mark packet-size=0-512 passthrough=yes add action=return chain=queue_mark_v6 comment="QUEUE return to existing mangle rules" add action=jump chain=forward comment="QUEUE classify before existing forward rules" jump-target=queue_mark_v6 place-before=0
|
2.6 配置 queue tree
父队列只负责方向总上限,叶子队列负责分类、优先级和 PT 限速。父队列是 inner queue,不再额外指定 fq-codel;所有叶子队列共用 Fq_Codel。
5M 和 10M 是 DNS、小包的示例上限,可按实际带宽调整或删除。它们必须小于对应方向的父队列上限。PT 上限是所有地址列表成员在同一方向的合计上限;如果只需要低优先级、不需要硬限速,可以把 PT 上限设置为对应父队列上限。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| /queue tree add bucket-size=0.01 max-limit=<UPLOAD_RATE> name=UP parent=<WAN_EGRESS_INTERFACE> add max-limit=5M name=1_Dns_up packet-mark=Dns-packet parent=UP priority=1 queue=Fq_Codel add max-limit=10M name=2_Small_up packet-mark=Small-packet parent=UP priority=2 queue=Fq_Codel add max-limit=<UPLOAD_RATE> name=3_Web_up packet-mark=Web-packet parent=UP priority=3 queue=Fq_Codel add max-limit=<UPLOAD_RATE> name=6_Nomark_up packet-mark=no-mark parent=UP priority=6 queue=Fq_Codel add max-limit=<PT_UPLOAD_RATE> name=7_PT_up packet-mark=PT-packet parent=UP priority=7 queue=Fq_Codel
add bucket-size=0.01 max-limit=<DOWNLOAD_RATE> name=DOWN parent=<LAN_EGRESS_INTERFACE> add limit-at=5M max-limit=5M name=1_Dns_down packet-mark=Dns-packet parent=DOWN priority=1 queue=Fq_Codel add limit-at=10M max-limit=10M name=2_Small_down packet-mark=Small-packet parent=DOWN priority=2 queue=Fq_Codel add max-limit=<DOWNLOAD_RATE> name=3_Web_down packet-mark=Web-packet parent=DOWN priority=3 queue=Fq_Codel add max-limit=<DOWNLOAD_RATE> name=6_Nomark_down packet-mark=no-mark parent=DOWN priority=6 queue=Fq_Codel add max-limit=<PT_DOWNLOAD_RATE> name=7_PT_down packet-mark=PT-packet parent=DOWN priority=7 queue=Fq_Codel
|
这里的 UP 父接口在当前 PPPoE 拓扑中应替换为 pppoe-out1,不是底层的 wan。如果使用 DHCP 或静态地址接入互联网,才填写实际的 WAN 逻辑接口名称。
优先级从 1 到 8,1 最高、8 最低。优先级只负责父队列拥塞时的调度顺序;如果需要 PT 无论其他流量如何都不能超过某个速率,应设置 <PT_UPLOAD_RATE> 和 <PT_DOWNLOAD_RATE>,而不是只依赖 priority。
2.7 与策略路由共存及验证
本方案与策略路由共存的关键是:分类跳转规则位于 forward 链最前面,专用分类链中的队列标记使用 passthrough=yes,并通过 return 回到原有 mangle 流程。不要删除 place-before=0,也不要把队列标记规则写成 passthrough=no。
启用规则后,已有连接可能还没有新的 connection-mark;让 PT 客户端重新建立连接,或等待旧连接超时后再观察统计。
1 2 3
| /queue tree print stats /ip firewall mangle print detail /ipv6 firewall mangle print detail
|
检查 PT-packet、Dns-packet、Web-packet 和 Small-packet 对应的 mangle 计数器是否增长,再检查 queue tree 对应叶子队列的 bytes、packets 和 rate。如果 mangle 有计数但 queue tree 没有计数,优先检查 packet-mark 名称和父接口;如果 mangle 计数为零,优先检查规则顺序、地址列表和是否仍处于连接的旧状态。
最后进行下载、上传和多 PT 客户端同时传输测试,并观察 CPU。相比方案一,这套方案有更多 mangle 匹配和分类队列,低配置设备不宜直接照抄高带宽示例。