基于虚拟网桥物理接口的QoS流量控制问题排查及优化方案咨询
你好,我仔细看了你的问题描述和配置,核心问题出在流量路径的链选择错误,导致iptables/ebtables只匹配到了极少的数据包,下面给你一步步分析和解决:
一、问题根源:规则放错了链,没抓到真实的上传流量
你要限制的是内网接口(比如eth0.2)到上游eth1的上传流量,这部分流量属于网桥转发流量(从eth0.2进入br-lan,再转发到eth1),而不是进入路由器本机的流量。
1. iptables的问题
你把标记规则放在了PREROUTING链,这个链仅处理进入路由器本机的数据包(比如路由器自己接收的管理包、DNS查询等),而绝大多数内网设备的上传流量属于转发流量,会走FORWARD链,根本不会经过PREROUTING,所以匹配数自然极少。
2. ebtables的问题
同理,你把ebtables规则放在了INPUT链,这个链也是处理进入路由器本机的桥接数据包,转发的流量会走FORWARD链,所以同样抓不到大部分上传流量。
二、快速修复方案
方案1:修正iptables规则到正确的链
先删除原来的错误规则,然后把标记规则加到FORWARD链,并且明确匹配从eth0.2进来、要转发到eth1的流量:
# 删除PREROUTING上的旧规则 iptables -t mangle -D PREROUTING -m physdev --physdev-in eth0.2 -j HAHA # 添加到FORWARD链,精准匹配上传流量 iptables -t mangle -I FORWARD -m physdev --physdev-in eth0.2 --physdev-out eth1 -j HAHA
执行后,你再用iptables -t mangle -nvL FORWARD查看匹配数,应该会和eth0.2的TX数据包数对应上了,tc的限速也会生效。
方案2:修正ebtables规则(如果想用ebtables标记)
如果你倾向用ebtables,同样要把规则移到FORWARD链,并且转成iptables能识别的fwmark:
# 删除INPUT上的旧规则 ebtables -t filter -D INPUT -i eth0.2 -j mark --mark-set 8 --mark-target CONTINUE # 添加到FORWARD链标记转发流量 ebtables -t filter -A FORWARD -i eth0.2 -j mark --mark-set 8 --mark-target CONTINUE # 把ebtables的标记转成iptables的fwmark,供tc识别 iptables -t mangle -A FORWARD -m mark --mark 8 -j MARK --set-mark 666
三、更简洁的替代方案:直接给下游接口做Ingress限速
其实不需要绕网桥标记这么麻烦,你可以直接给每个内网接口(比如eth0.2、wlan0)配置Ingress限速,限制进入网桥的流量(也就是上传流量的入口),配置更简单直观:
# 给eth0.2配置上传限速10Mbps tc qdisc add dev eth0.2 ingress handle ffff: tc filter add dev eth0.2 parent ffff: protocol ip prio 1 u32 match ip src 0.0.0.0/0 \ police rate 10Mbit burst 10k drop flowid :1 # 给wlan0(ssid1)配置下载限速20Mbps(下载流量从eth1进来转发到wlan0,所以在eth1的Ingress链做限制) tc qdisc add dev eth1 ingress handle ffff: tc filter add dev eth1 parent ffff: protocol ip prio 1 u32 match ip dst 192.168.1.0/24 \ match physdev out wlan0 police rate 20Mbit burst 10k drop flowid :1
这种方式每个接口独立配置,不需要依赖网桥的netfilter规则,稳定性和可维护性更强。
四、额外注意事项
- 确保网桥的netfilter参数正确开启:
sysctl -w net.bridge.bridge-nf-call-iptables=1 sysctl -w net.bridge.bridge-nf-filter-vlan-tagged=1
这两个参数确保vlan接口(比如eth0.2)的流量能被iptables的physdev模块识别。
- tc规则的层级合理性:你当前的HTB层级是对的(root → 总带宽类 → 子限速类),但要确保未标记的流量走默认类(
default 1对应1:1),避免影响其他接口的流量。
备注:内容来源于stack exchange,提问作者Ryan.Ran

