8

Linux流量控制(Traffic Control)介绍

 2 years ago
source link: http://just4coding.com/2022/08/05/tc/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Linux流量控制(Traffic Control)介绍

2022-08-05 Network

流量控制Traffic Control简称TC,表示网络设备接收和发送数据包的排队机制。比如,数据包的接收速率、发送速率、多个数据包的发送顺序等。

Linux实现了流量控制子系统,它包括两部分:

  • 内核部分的traffic control框架
  • 用户态的规则配置工具:iproute2软件包中的tc程序

它们有些类似于内核态的netfilter框架和用户态的iptables程序。但相较于netfilter, 关于tc的资料非常少,并且也较为古老,彻底理解它的机制还是需要对照源码。

Traffic Control的作用包括以下几种:

  • 调整(Shaping): 通过推迟数据包发送来控制发送速率,只用于网络出方向(egress)
  • 时序(Scheduling):调度不同类型数据包发送顺序,比如在交互流量和批量下载类型数据包之间进行发送顺序的调整。只用于网络出方向(egress)
  • 监督(Policing): 根据到达速率决策接收还是丢弃数据包,用于网络入方向(ingress)
  • 丢弃(Dropping): 根据带宽丢弃数据包,可以用于出入两个方向

要实现对数据包接收和发送的这些控制行为,需要使用队列结构来临时保存数据包。在Linux实现中,把这种包括数据结构和算法实现的控制机制抽象为结构队列规程:Queuing discipline,简称为qdiscqdisc对外暴露两个回调接口enqueuedequeue分别用于数据包入队和数据包出队,而具体的排队算法实现则在qdisc内部隐藏。不同的qdisc实现在Linux内核中实现为不同的内核模块,在系统的内核模块目录里可以查看前缀为sch_的模块:

[root@server ~]# ls -l /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_*
-rw-r--r--. 1 root root 7612 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_atm.ko.xz
-rw-r--r--. 1 root root 9628 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_cbq.ko.xz
-rw-r--r--. 1 root root 4880 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_choke.ko.xz
-rw-r--r--. 1 root root 4488 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_codel.ko.xz
-rw-r--r--. 1 root root 5004 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_drr.ko.xz
-rw-r--r--. 1 root root 5792 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_dsmark.ko.xz
-rw-r--r--. 1 root root 6328 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_fq_codel.ko.xz
-rw-r--r--. 1 root root 6032 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_fq.ko.xz
-rw-r--r--. 1 root root 5716 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_gred.ko.xz
-rw-r--r--. 1 root root 9088 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_hfsc.ko.xz
-rw-r--r--. 1 root root 10868 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_htb.ko.xz
-rw-r--r--. 1 root root 2288 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_ingress.ko.xz
-rw-r--r--. 1 root root 4460 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_mqprio.ko.xz
-rw-r--r--. 1 root root 4116 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_multiq.ko.xz
-rw-r--r--. 1 root root 6556 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_netem.ko.xz
-rw-r--r--. 1 root root 2256 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_plug.ko.xz
-rw-r--r--. 1 root root 3908 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_prio.ko.xz
-rw-r--r--. 1 root root 8924 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_qfq.ko.xz
-rw-r--r--. 1 root root 4940 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_red.ko.xz
-rw-r--r--. 1 root root 5264 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_sfb.ko.xz
-rw-r--r--. 1 root root 7552 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_sfq.ko.xz
-rw-r--r--. 1 root root 5116 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_tbf.ko.xz
-rw-r--r--. 1 root root 4976 Apr 21 2018 /usr/lib/modules/3.10.0-862.el7.x86_64/kernel/net/sched/sch_teql.ko.xz

qdisc的实现可以非常简单,比如只包含单个队列,数据包先进先出,如: pfifo, 代码位于net/sched/sch_fifo.c。也可以实现相当复杂的调度逻辑。比如,可以根据数据包的属性进行过滤分类,而针对不同的分类:class采用不同的算法来进行处理。class可以理解为qdisc的载体,它还可以包含子类与qdisc。用来实现过滤逻辑的组件叫做filter,也叫做分类器classfier, 它需要挂载在qdisc或者class上。

基于qdisc, classfilter种三元素可以构建出非常复杂的树形qdisc结构,极大扩展流量控制的能力。

对于树形结构的qdisc, 当数据包流程最顶层qdisc时,会层层向下递归进行调用。如,父对象(qdisc/class)的enqueue回调接口被调用时,其上所挂载的所有filter依次被调用,直到一个filter匹配成功。然后将数据包入队到filter所指向的class,具体实现则是调用class所配置的Qdiscenqueue函数。没有成功匹配filter的数据包分类到默认的class中。

1.png

大约在15年的时候,TC框架实现中又加入了Classifier-Action机制。上文提到的filter实际作用就是classifier,当数据包匹配到特定的filter之后,可以执行该filter所挂载的actions对数据包进行处理。

2.png

filteraction也可以实现为独立的内核模块,tc框架的扩展性非常灵活。

一个网络接口有两个默认的qdisc锚点。入方向的锚点叫做ingress, 出方向叫做root。入方向的ingress功能比较有限,不能挂载其他的class,只是做为Classifier-Action机制的挂载点。

qdiscclass的标识符叫做handle, 它是一个32位的整数,分为majorminor两部分,各占16位,表达方式为:m:n, mn省略时,表示0

m:0一般表示qdisc, 对于class, minor一般从1开始,而m使用它所挂载的qdiscmajor号。

root qdischandle一般使用1:0表示,ingress一般使用ffff:0表示。

具体的匹配逻辑可以参考这篇文章:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK