nftables 不执行 QoS 调度,仅负责流量分类与标记(如 meta mark 或 DSCP),为 tc 提供调度依据;tc 才真正实现带宽限制、优先级排队等 QoS 功能。

nftables 本身不直接执行 QoS(服务质量)调度,但它承担关键的“分类与标记”角色——这是整个 Linux QoS 策略的第一步和前提。真正的带宽限制、优先级排队、延迟控制由 tc(traffic control)完成;nftables 的任务是把不同业务流量精准识别出来,并打上标记(如 meta mark 或 ip dscp),供 tc 后续按类调度。
用 nftables 标记流量,为 tc 提供分类依据
标记方式有两种主流路径,选其一即可:
-
内核标记(netfilter mark):轻量、仅本机有效,适合配合 tc 的
fwclassifier 使用。
例:给 SSH 流量打标记 0x100nft add rule inet filter output tcp dport 22 meta mark set 0x100 -
DSCP 字段标记(网络层标记):写入 IP 头部的 TOS 字段,可被下游路由器识别,适合跨设备 QoS。
例:将 VoIP 流量设为 EF(Expedited Forwarding)nft add rule inet filter prerouting udp dport {5060, 5061} ip dscp set 0xb8
注意:DSCP 标记需在 prerouting(转发前)或 output(本机发出)链操作,确保标记在包离开前生效;而 netfilter mark 可在任意链设置,但需确保后续 tc 规则在同一方向(如出向标记,就配出向 tc)。
按业务类型分层标记,避免混用
不要只靠端口判断,结合协议、连接状态、源/目标网段更可靠:
- VoIP 信令(SIP)+ 媒体流(RTP)分开标记:
udp dport 5060-5061→ DSCP EF;udp dport 10000-20000 ct state established→ DSCP AF41 - 关键管理流量(SSH、HTTPS 管理接口)设高优先级:
tcp dport {22, 443} ip saddr 10.10.0.0/16→ mark 0x200 - 限速类流量(如下载、P2P)主动降权:
tcp dport {80, 443} ip daddr 192.168.100.0/24→ mark 0x001
标记值建议用十六进制且预留空间(如 0x100、0x200),方便后期扩展;避免用 0 或 1 这类易冲突的值。
与 tc 协同工作的典型流程
标记只是起点,必须搭配 tc 才能生效。典型配合步骤如下:
- 先用 nftables 分类并打标(如上)
- 用 tc 创建 HTB 队列根规则:
tc qdisc add dev eth0 root handle 1: htb default 30 - 用 tc 添加 class 并绑定标记:
tc class add dev eth0 parent 1: classid 1:10 htb rate 20mbit ceil 100mbit prio 1tc filter add dev eth0 parent 1: protocol ip u32 match ip mark 0x100 flowid 1:10 - 对低优先级类限制带宽或引入延迟:
tc class add dev eth0 parent 1: classid 1:30 htb rate 5mbit ceil 5mbit
关键点:tc 的 u32 或 fw classifier 会读取 nftables 设置的 meta mark 或 IP 层字段,从而把包送入对应 class。没有这一步,标记就只是“贴标签”,不会影响调度。
验证标记是否生效
别跳过验证环节,常见检查方法:
- 实时查看 nftables 计数器:
nft -a list chain inet filter output(加-a显示 handle,便于定位) - 抓包确认 DSCP 值:
tcpdump -i eth0 -nn -v 'ip[1] & 0xfc != 0'(显示非默认 DSCP 的包) - 查 tc 分类统计:
tc -s class show dev eth0,观察各 class 的 packets/bps 是否增长
若标记没触发,优先检查链挂载位置(如 DSCP 必须在 prerouting/output)、方向一致性(in/out 对应 tc 的 ingress/egress)、以及 tc filter 是否正确引用了 mark 或 dscp 字段。

















