作者:isshe
日期:2018.09.19
邮箱:i.sshe@outlook.com
github: https://github.com/isshe
1. 前言
接触了TC以后,感觉就是:别说入门了,根本连门都找不到。
网上资料一大堆,但是就是看得头痛并且一脸懵逼。
但是这篇文章并不对TC相关基础概念进行介绍。网络上一搜基本都是关于概念介绍
以及TC+iptables
或者TC + 单ifb
的。
这篇文章的关键词:tc
、ifb
、fw
、htb
。主要希望能更灵活地实现一些流控的功能。
2. 约定及环境
环境:
- openwrt路由器
一些约定:
-
出口/入口:站在用户的角度,对用户而言,也就是上传=出口,下载=入口。
一些关键信息: -
TC的整形一般情况下,只能对出口流量(egress)进行。
- 对于
wan口
来说:下载是ingress,上传是egress - 对于
lan口
来说:下载是egress,上传是ingress - 因此,常规做法是,在lan口做下载流控,在wan口做上传流控
- 对于
3. 需求、问题及解决方案
3.1 需求
探索一个工具,通常是因为一些需求。
最本质的需求:对入口/下载
和出口/上传
流量中重要的
流量进行保障,提升冲浪?体验。
重要与否是根据个人需求。文章中指的重要的流量:游戏、语音通话等(流量不大并对延时要求高的流量);不重要的流量:下载等(流量大并对延时要求低的)
3.2 最终实现图
[wan1] \ / [lan1]
[wan2]-- ifb0 ----ifb1 -- [lan2]
[wan3] / \ [lan3]
-
优点:
- 支持多lan、多wan;
- 流控内容可定制性高,可实现复杂的流控。
- 配置简单(相比使用TC+U32+iptables)
-
缺点:
- 需要编写流量识别模块(识别IP?识别协议?识别应用?)
- 需要编写内核打标记模块。
-
这两个模块可以合二为一。
3.3 遇到的问题
-
1.如何只对外网流量(lan-wan)进行控制,不对内网流量(lan-lan)进行控制?
- 很简单,不使用常规做法,不用lan口,不对lan口做任何流控。
-
刚开始的尝试是,对lan-lan流量进行过滤。但是最后没有这样实现:1.不灵活,IP识别困难,外网IP也可以当做内网IP用;2.对不关注的流量进行操作,有性能损耗。
-
2.使用wan口的话,
egress/上传
的流控如何识别lan口的IP?egress的流量,经过nat以后,源IP不再是lan段的IP,因此无法标识具体的IP/用户。----> ingress ---> | ---> netfilter ---> | ---> egress -------------------------------------------------------- (打mark)nat转换 TC流控
- 解决方法是使用
fw
分类器。在netfilter的forward上挂一个自定义的模块(如:MyMark)
,根据需求打mark,这里可以任意发挥想象,直觉可以实现任意你想到的功能。(牛13吹起来) fw
分类器,根据mark来分类:把打了1111
标记的分类到1:10
tc filter add dev ifbx parent 1: protocol ip prio 1 handle 1111 fw flowid 1:10
- 解决方法是使用
-
3.如何做到对
上传
和下载
都进行流控,并且不使用lan口?- 这里用的是
ifb
;还有其他方式,但是没细看。 -
ifb
原理就是开一些接口,把实际接口的ingress流量转到这些ifb接口的egress上;这样看起来会有一定的性能损耗。但是记得文档上说,对性能影响不大。(待查实)
- 这里用的是
-
4.如果采用打mark的形式,会遇到问题:打mark是在
netfilter
那里,但是ingress处流控在netfilter之前,将无法使用mark?----> ingress ---> | ---> netfilter(打mark) ---> | ---> egress
- 这个人家实现ifb的时候已经考虑到了:把eth0的所有IP协议流量转到ifb0,并把链接跟踪的mark恢复到skb->mark中。
tc filter add dev eth0 parent ffff: protocol ip prio 0 u32 match u32 0 0 action connmark action mirred egress redirect dev ifb0
- 这个人家实现ifb的时候已经考虑到了:把eth0的所有IP协议流量转到ifb0,并把链接跟踪的mark恢复到skb->mark中。
-
5.如果其他程序(如mwan3)也使用了skb->mark的话,怎么办?
- mark是按位操作的。例如:mwan3使用0x0000-0xff00,我们就可以用
0x01xxxx-0xffxxxx(16-23位)
- 问题2中的配置可以改为: (注意
65536/ff0000
!)-
tc filter add dev ifbx parent 1: protocol ip prio 1 handle 65536/ff0000 fw flowid 1:10
-
-
mwan3新版本貌似可以自定义mark范围了…不过没关系,还是可以指定。
- mark是按位操作的。例如:mwan3使用0x0000-0xff00,我们就可以用
-
6.如何实现保障?
- 用htb进行保障,同时还支持优先级。
-
注意:要预留突发带宽。例如10Mbps,要预留1-2M作为突发带宽。
4. 相关文档
- LARTC-zh_CN.GB2312_流控高级应用
- Tc-man、Htb-man等man
- TC-HOWTO
- HTB手册