网络类-tc限速(基于网卡)

工具教程6天前发布 hank
47 0 0

tc介绍

在日常的 Linux 节点运维与底层网络架构管理中,面对复杂的流量竞争,我们经常需要对特定业务进行精准的带宽限制与保障。Linux 内核网络协议栈自带了一把流量整形的“尖刀”——TC (Traffic Control)。

TC 是 Linux 内核中负责网络流量控制的模块。默认情况下,网络接口的发包策略是 FIFO(先进先出),尽最大努力传输。但通过 TC,我们可以对网卡的**出站流量(Egress)**进行排队、整形、丢弃等干预,从而实现 QoS(服务质量)保障。

tc一般是有三个核心组件,Qdisc(排队规则)、Class(类别)、Filter(过滤)

但是需要注意的是,不是所有的排队规则qdisc都会有这三个东西,比如只有qdisc的,咱们一般叫它无分类排队规则 (Classless Qdiscs),它的结构就比较简单,没有class(类别),也不需要filter(过滤器)。所有经过网卡的包一视同仁地排队。
比较常见的有

• fq_codel / cake:用来解决队列拥塞、降低游戏延迟的“神仙算法”。
• sfq (随机公平队列):尽量让每个连接公平传输。
• tbf (令牌桶过滤器):用来做最简单的整体限速(不能借用带宽,只能卡死一个上限),运营商可能就是通过令牌桶来进行板卡限速的,卡pcdn用户。
• pfifo_fast:Linux 默认的先进先出队列。

咱们网卡默认的可能就是fq_codel

第二种就是有分类规则的(Classful Qdiscs)
这就是包含 qdisc(根节点)、class(子类抽屉)和 filter(分拣员)的复杂体系。不仅仅是 HTB,只要是需要精细化分组的算法,都在这个阵营。
• 特点: 呈现树状结构。你可以无限嵌套(比如在 1000M 的根类下建 2 个 500M 的子类,在其中一个 500M 的子类下再建 2 个 250M 的孙子类)。必须依靠 filter 才能把数据包正确引导到对应的叶子节点。
但是现在filter似乎都不怎么用了,如果确实要过滤,可以结果iptables等打标机,来结合使用,一般都不会自己去写tc filter过滤,好像很晦涩,语法也不太人性。

常见代表:
• htb(分层令牌桶):目前最主流、最容易理解的带宽分配算法。
• hfsc(分层公平服务曲线):** 比 HTB 更高级但也极其复杂的算法,OpenWrt 的高级 QoS 插件(如 SQM)底层有时会用它,能同时保证带宽和极低的实时延迟。
• prio (严格优先级):** 不限速,只给流量排个先后优先级(VIP通道优先走,平民通道等VIP走完了再走)。
• cbq: HTB 的老前辈,因为配置太反人类,现在基本被淘汰了。

htb测试

这里以HTB算法测试展开,简单了解一下tc限速的原理。
大致思路是,netns设置虚拟网卡做好网络拓扑+tc流量整形+iperf3打流测试

netns创建虚拟网卡


使用netns(network namespace)模拟
一对veth虚拟网卡设备,veth1当宿主机的网卡,veth2当tc_test里面的

# 1. 创建名为 tc_test 的 network namespace
ip netns add tc_test

# 2. 创建一对 veth 虚拟网卡设备 (veth0 和 veth1)
ip link add veth0 type veth peer name veth1

# 3. 将 veth1 移入我们刚才创建的 ns_test 命名空间中
ip link set veth1 netns tc_test

# 4. 为 Root Namespace 中的 veth0 配置 IP 并启动
ip addr add 10.0.0.1/24 dev veth0
ip link set veth0 up

# 5. 为 tc_test 中的 veth1 配置 IP 并启动
ip netns exec tc_test ip addr add 10.0.0.2/24 dev veth1
ip netns exec tc_test ip link set veth1 up
网络类-tc限速(基于网卡)

流量整形

tc流量整形

#在tc_test的veth1 上配qdisc

#根队列
ip netns exec tc_test tc qdisc add dev veth1 root handle 10: htb default 10
#子类class,rate保证带宽,ceil闲时触发最大带宽。一般会设置一个父类,多个子类。
ip netns exec tc_test tc class add dev veth1 parent 10: classid 10:1 htb rate 5mbit ceil 5mbit
ip netns exec tc_test tc class add dev veth1 parent 10:1 classid 10:10 htb rate 1mbit ceil 2mbit

ip netns exec tc_test tc qdisc show dev veth1
ip netns exec tc_test tc class show dev veth1
网络类-tc限速(基于网卡)

iperf3打流测试

iperf3打流

#服务端,默认监听5201
iperf -s
#namespace内的veth2当客户端,打veth1
ip netns exec tc_test iperf3 -c 10.0.0.1 -t 100 -i 1
网络类-tc限速(基于网卡)

添加时间的限速

带宽一般是搭配时间段来进行限制的,或者进行全天的限速。这里介绍一种的办法进行限速,即通过定时任务的办法进行change,tc qdisc的时候有一个参数default 10,即在class类里面parent 10:1 classid 10:10的规则,通过定时任务,定期修改这个规则实现动态调整,而不是删除/添加.
这里模拟,每天0点开始限速,18点解除限速的定时任务来展开
crontab -e

# 每天凌晨 00:00 触发:限速
# 将 10:10 队列的阈值调整为基础 1M,最高弹性借用到 2M
0 0 * * * /usr/sbin/ip netns exec tc_test /usr/sbin/tc class change dev veth1 parent 10:1 classid 10:10 htb rate 1mbit ceil 2mbit
# 每天傍晚 18:00 触发:解除限速
# 将 10:10 队列的阈值直接拉满,与其父类classid 10:1的5M一样
0 18 * * * /usr/sbin/ip netns exec tc_test /usr/sbin/tc class change dev veth1 parent 10:1 classid 10:10 htb rate 5mbit ceil 5mbit

这里直接执行测试了,执行change后继续打流,发现放开了
0 18 * * * /usr/sbin/ip netns exec tc_test /usr/sbin/tc class change dev veth1 parent 10:1 classid 10:10 htb rate 5mbit ceil 5mbit

还有一种就是通过iptables的mangle表使用time模块、mark标记来实现,但是这里没实验成功,听ai讲是
基于 CentOS 8 / RHEL 8 的现代操作系统由于底层切换至 nf_tables,官方已将 xt_time 内核模块移除,导致规则无法下发。
ip netns exec tc_test iptables -t mangle -A POSTROUTING -o veth1 -m time –timestart 00:00 –timestop 18:00 –kerneltz -j MARK –set-mark 10

备注:
其实htb只是属于一个模块,内核模块 sch_htb,并不是所有硬件都会支持,比如碰见rk3528等类型,会提示Error: Specified qdisc kind is unknown.模块不支持!
可以用添加qdisc规则命令检测是否支持:
tc qdisc add dev eth0 root handle 314: htb default 1

© 版权声明

相关文章