Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

基于tc的网络QoS管理

2
Jun
2015

基于tc的网络QoS管理

By Alex
/ in Linux,Network
0 Comments
基础

tc(traffic control)是Linux自带的、功能强大的网络QoS管理/流量塑形工具,利用它,我么可以进行带宽限制、模拟网络延迟和抖动。

本质上,tc是内核封包调度器的配置工具。

术语
qdisc

排队规则,管理设备队列的算法,可以管理ingress/egress方向的队列。

当内核需要通过某个接口发送封包时,封包被enqueue到该接口所配置的qdisc上。随后,内核尝试从qdisc获取到尽可能多的封包,并转送给网络驱动。

root qdisc

直接附到网络设备上的排队规则。默认情况下,它就是pfifo_fast。

classless qdisc

无类别排队规则,对所有封包同等对待。

classful qdisc

这样的排队规则包含多个类别(class),每个类别可以进一步对应其它qdisc。

class

classful qdisc的内部概念,用于对封包差异化处理。每个qdisc可以有多个class,这些每个class可以进一步包含qdisc或者nested class,从而产生树状结构。

Leaf class是没有inner qdisc的class,这种class必须附到某个classless qdisc,后者负责封包的发送。

创建class时,自动附到一个fifo的qdisc。你可以用合适的qdisc替换这个fifo,甚至可以用classful qdisc替换。

当内核从某个classful qdisc dequeue一个封包时,它可能来自任何一个class。某些qdisc可能实现class的优先级,也就是优先dequeue某个class中的封包。

filter

每当封包到达一个有classful qdisc,它都必须被分类(classified)。分类的方法有多种,其中之一是过滤器。

过滤器为classful qdisc确定封包应该归于哪个class,所有配置的过滤器都被调用,直到其中一个返回裁定(verdict)。如果没有任何过滤器返回裁定,处理准则取决于qdisc。

需要注意:过滤器存在于qdisc内部。

scheduling

在分类器的协助下,qdisc能够决定哪个封包先发送,这就是调度,也称为重排(reordering)或优先级调整(prioritizing)。

调度能够满足提升某些流量的交互性(interactivity),同时保证批量传输(bulk transfers)的带宽需求。

shaping

塑形,在发送封包前进行延迟(甚至丢弃)处理,以达到预设的发送速率。塑形总是在egress方向进行。

塑形不仅仅用于带宽限制,还可以用于让流量更加平滑,以获得更好的网络行为。

policing

执行策略,决定是否丢弃封包。丢弃封包可以产生对ingress带宽的限制效果。

每个网络接口可以有一个ingress qdisc用来执行policing。

work-conserving

只要有包可发送就立即发送。换句话说,只要网卡处于可发送状态(对于 egress qdisc 来说),它永远不会延迟包的发送。

non-work-Conserving

某些qdisc,例如tbf,可能会延迟一段时间再将一个包发送出去,以达到期望的带宽 。这意味着它们有时即使有能力,也不会发送封包。

handle

每个class,以及classful qdisc,都具有自己的唯一标识,此标识叫handle。

handle有两部分组成 <major>:<minor>,用户可以在满足下面规则的前提下分配handle:

  1. major/minor都是十六进制整数
  2. major,在qdisc树中,parent相同的节点,必须具有相同的major。root disc的children的major通常设置为1
  3. minor,如果minor为0,则表示当前节点是一个qdisc,如果是其它值,则节点是一个class。所有具有相同parent的class必须具有不同的minor

class的handle也叫classid。

由于qdisc的minor都是0,因此它下面挂的class的major通常设置的和qdisc的major一致。而class的minor不为零,subclass通常以parent的minor作为major。

架构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
                Userspace programs
                     ^
                     |
     +---------------+-----------------------------------------+
     |               Y                                         |
     |    -------> IP Stack                                    |
     |   |              |                                      |
     |   |              Y                                      |
     |   |              Y                                      |
     |   ^              |                                      |
     |   |  / ----------> Forwarding ->                        |
     |   ^ /                           |                       |
     |   |/                            Y                       |
     |   |                             |                       |
     |   ^                             Y          /-qdisc1-\   |
     |   |                            Egress     /--qdisc2--\  |
  --->->Ingress                       Classifier ---qdisc3---- | ->
     |   Qdisc                                   \__qdisc4__/  |
     |                                            \-qdiscN_/   |
     |                                                         |
     +----------------------------------------------------------+

入站流量首先进入ingress qdisc,这里会对封包进行过滤,决定是否丢弃,这个过程就是policing。policing位于入站网络路径的很早期,在这里进行封包过滤是非常高效的。

如果封包没有被丢弃,则它要么交由本地进程处理,要么转发给其它主机。

不管是转发的、还是本地进程产生的封包,出栈前都需要经过egress classifier,然后放到匹配的qdisc中发送出去。

当存在多个网络接口时,每个网络接口都有自己的tc ingress/egress钩子。

内核和tc的交互
1
2
3
4
5
6
7
8
9
10
11
12
13
14
                      1:   root qdisc
                      |
                     1:1    child class
                   /  |  \
                  /   |   \
                 /    |    \
                /     |     \
              1:10  1:11  1:12   child classes
               |      |     |
               |     11:    |    leaf class(classless qdisc)
               |            |
              10:0        12:0   qdisc
              /   \       /   \
           10:1  10:2   12:1  12:2   leaf classes

内核仅仅会和root qdisc进行交互,进行封包入队、出队操作。

对于上面这样的qdisc结构,入队封包可能经过这样的链路而被分类: 1: -> 1:1 -> 1:12 -> 12: -> 12:2,这要求每个节点都挂着一个filter,每个filter需要对经过的封包进行裁定,断言它是否匹配此节点。封包也可能 1: -> 12:2直接分类,root qdisc可以直接决定直接匹配12:2。

当内核请求出队一个封包交给网络接口时,它会向root qdisc发起一个dequeue请求,root qdisc将请求转发给1:1,并逐步向下传递,遍历整棵数以发现封包。

子类dequeue的速度,永远不能超过其祖先允许的速度。我们可能仅需要在root disc上配置,就能够满足整形需求。

排队规则

通过设置若干队列,并且规定每个队列的特质(比如其中的封包总是延迟200ms发送),然后将封包放入特定队列排队,可以管理封包的发送方式。

排队规则(queueing disciplines,qdisc)用于定义一个具有某些特质的封包队列。

无类别排队规则

无类别排队规则(classless qdisc)可以对某个网络接口上的所有流量进行无差别的流量塑形,例如:

  1. 重新调度
  2. 设置延迟
  3. 丢弃封包

在没有配置classful qdisc的情况下,classless qdisc只能附到网络设备的根上:

Shell
1
2
#                网络设备  规则   规则参数
tc qdisc add dev DEV root QDISC QDISC-PARAMETERS

支持的classless qdisc有十几种,这里选几种常用的介绍。

pfifo_fast

先入先出队列,所有封包按照进入的顺序来发送。这是启用了CONFIG_IP_ADVANCED_ROUTER的内核的标准qdisc。

该规则包含三个band(子队列),编号分别为0 1 2,处理规则如下:

  1. 每个band上的封包均以FIFO方式发送
  2. 如果band 0有数据,则不会处理band 1 和band 2
  3. 如果band 1有数据,则不会处理band 2
  4. 内核会检查封包的TOS字段,将“最小延迟”的包放入band0

严格的说,pfifo_fast属于有类别排队规则,因为它的三个band,本质上是class。但是从用户角度来说,它是classless的,因为不支持配置。

该qdisc的参数无法更改。

参数 priomap决定了如何将封包的优先级映射到band。封包的TOS字段占用4bit,每个bit含义如下:

Shell
1
2
3
4
5
6
7
  Binary Decimcal  Meaning
  -----------------------------------------
  1000   8         Minimize delay (md)
  0100   4         Maximize throughput (mt)
  0010   2         Maximize reliability (mr)
  0001   1         Minimize monetary cost (mmc)
  0000   0         Normal Service

组合上述比特,可以有16个不同的TOS,这些TOS对应的优先级、映射到的Band如下表:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  TOS     Bits  Means                    Linux Priority    Band
  ------------------------------------------------------------
  0x0     0     Normal Service           0 Best Effort     1
  0x2     1     Minimize Monetary Cost   1 Filler          2
  0x4     2     Maximize Reliability     0 Best Effort     1
  0x6     3     mmc+mr                   0 Best Effort     1
  0x8     4     Maximize Throughput      2 Bulk            2
  0xa     5     mmc+mt                   2 Bulk            2
  0xc     6     mr+mt                    2 Bulk            2
  0xe     7     mmc+mr+mt                2 Bulk            2
  0x10    8     Minimize Delay           6 Interactive     0
  0x12    9     mmc+md                   6 Interactive     0
  0x14    10    mr+md                    6 Interactive     0
  0x16    11    mmc+mr+md                6 Interactive     0
  0x18    12    mt+md                    4 Int. Bulk       1
  0x1a    13    mmc+mt+md                4 Int. Bulk       1
  0x1c    14    mr+mt+md                 4 Int. Bulk       1
  0x1e    15    mmc+mr+mt+md             4 Int. Bulk       1

参数 txqueuelen则表示发送队列长度,可以通过配置网络接口来修改:

Shell
1
ifconfig eth0 txqueuelen 10
TBF

令牌桶过滤器(token bucket filter),对于没有超过预设速率的流量直接发送,能够容忍超过预设速率的短暂burst。如果仅仅想限制网络接口速率,可以选择此qdisc。tbf是一个单纯的塑形器,从不会调度流量。

适用场景:单纯的对egress流量进行限速。

该qdisc会以特定的速率产生token,这些token存放到桶(一个缓冲区)中,每当封包进入都会消耗token。如果消耗小于那个特定速率,桶会被填满;如果消耗速度大于特定速率,则最终桶会变空。空了就不能继续发送封包了。token以字节数为单位。

在使用理想的minburst的情况下,最多可以塑形大约1mbit/s的正常流量,保证精确的以配置的速率发送封包。

要支持更大的速率,就必须损失minburst,这种情况下,封包平均的以配置的速率发送,但是在毫秒时间尺度上进行度量,发送速率可能大大超标。

命令格式:

Shell
1
2
3
tc qdisc ... tbf
  rate rate burst bytes/cell ( latency ms | limit bytes )
  [ mpu bytes [ peakrate rate mtu bytes/cell ] ]

可用参数:

参数 说明
limit 排队等待可用token的封包的总计最大字节数,和latency互斥
latency 每个封包在TBF中停留的最大时间,和limit互斥
burst
buffer
maxburst

桶的容量,也就是token的数量,单位字节

大的rate需要大的burst,对于10mbit/s的rate,至少需要10kbyte的burst才能达到期望的速率

允许最小的桶容量为:rate / HZ

mpu

最小包单元(Minimum Packet Unit),决定了一个包使用的最少token量,默认0

在以太网中,任何一个封包都不会小于64字节

rate

速率,token的产生速度,对应了带宽

默认情况下,消耗token的速度不受限制,也就是瞬时burst速度不受限制。如果以rate发送数据,则可以持续稳定运行;如果大于rate发送数据则最终令牌会被耗光

peakrate

桶的最大消耗速率,通常不需要设置,除非需要毫秒精度的塑形

为了实现peakrate,使用了次级的TBF,该TBF使用非常小的桶,因此无法支持burst

要达到最大精确度,这个桶可以仅容纳单个封包(不能再细分了,一次最少得发一个2层封包),这种情况下,速率被限制在1mbit/s。这个速率的来由是,内核中断产生频率为jiffy,也就是1/HZ,一般是10ms。每秒钟内核具有100次进行流量塑形的机会,为了最大精确度,每次塑形仅能发送单个封包。如果封包大小为1000字节那么每秒能发送大约1mbit/s

mtu
minburst

指定peakrate桶的容量,为了达到最大精确度,应该设置为网络接口的MTU

如果需要peakrate,而且允许一定的burstiness,可以增大此参数。假设封包大小为1000字节,3000byte的minburst允许大概3mbit/s的peakrate

示例:

Shell
1
2
3
4
5
6
#                                   持续最大速率0.5mb/s
tc qdisc add dev eth0 root tbf rate 0.5mbit
#        5kb的缓冲   最大延迟70ms   峰值速率 1.0mb/s
         burst 5kb   latency 70ms   peakrate 1mbit
#        最精确peakrate行为,peakrate桶的大小设置为MTU
         minburst 1540
SFQ

随机公平排队(stochastic fairness queueing),不做流量塑形,仅基于流(flow,通常对应TCP连接)对待发送封包进行调度。sfq的目标是保证每个流能够公平的获得发送的机会,可以在某种程度上缓和DoS攻击。

适用场景:带宽打满的情况下,确保带宽公平使用。

在入队(enqueueing)时,每个封包基于其哈希值被映射到一个哈希桶(hash bucket),哈希值的来源是:

  1. 从外部classifier(通过tc filter设置)获得
  2. 如果没有外部classifier,则使用一个内部默认classifier,该classifier使用利用封包源地址、目的地址、源/目的端口计算哈希

多个流可能映射到相同的桶。发送封包实际上是每个桶轮流(round robin)发的,因此映射到同一个桶的多个流,获得的配额就相应减少。为了解决此问题,sfq支持每隔一段时间就更换哈希算法。

sfq是随到随发(work-conserving)的,也就是说如果有一个封包带发送且队列空闲,则立刻发送它。这就意味着,在带宽不饱和(也没有其它qdisc做塑形)的情况下,sfq没有意义,所有封包都被立刻发出。

命令格式:

Shell
1
2
3
4
tc  qdisc  ...   [ divisor hashtablesize ]
    [ limit packets ] [ perturb seconds ] [ quantum bytes ] [ flows number ]
    [ depth number ] [ headdrop ] [ redflowlimit bytes ] [ min bytes ] [ max bytes ]
    [ avpkt bytes ] [ burst packets ] [ probability P ] [ ecn ] [ harddrop ]

可用参数:

参数 说明
perturb 每隔多久更换哈希算法,如果不设置则永远不更换。可以设置为10s
quantum 轮换到下一个桶时,当前桶可以出队(dequeue)多少字节,默认一个MTU,不要设置的更小
limit 最多缓存的包数量,超过此数量会导致丢包
divisor 指定哈希表的大小,必须是2的幂,不能大于65536,默认1024
depth 每个流的封包最大数量,默热年127
flows 流的最大数量,默认127

示例:

Shell
1
tc qdisc add dev ppp0 root sfq perturb 10
有类别排队规则

如果想对不同类型的流量做不同处理,考虑使用有类别排队规则(classful qdisc)。

当流量进入一个classful qdisc 时,该qdisc需要将其发送到内部的某个class ,对这个包进行“分类”。分类是通过调用过滤器(filter)完成的,过滤器返回一个断言给 qdisc,qdisc 据此将包 enqueue 到合适的 class。

每个class都可能进一步调用其它过滤器,如果没有这些的过滤器,则封包被enqueue到class自带的qdisc。

PRIO

不支持塑形的容器,具有可配置的classes数量,不同的classes按优先级出队。当高优先级class存在封包尚未出队,则低优先级class不被处理。默认情况下封包的TOS字段决定其优先级。

命令格式:

Shell
1
2
3
tc qdisc ... dev dev ( parent classid | root) [ handle major: ]
    prio [ bands bands ] [ priomap band band band...  ]
    [ estimator interval timeconstant ]

可用参数:

参数 说明
bands

需要创建的band的数量,每个band本质上都是一个class,bind0的handle为major:1,类推

priomap

类似于pfifo_fast的优先级映射

如果没有配置filter来决定如何分类,则默认根据封包优先级,将封包映射到band

示例:

1
2
3
4
5
6
7
8
9
           1:   root qdisc
         / | \
        /  |  \
       /   |   \
     1:1  1:2  1:3    classes
      |    |    |
     10:  20:  30:    qdiscs    qdiscs
     sfq  tbf  sfq
band  0    1    2

root qdisc为具有三个band的PRIO,三个子类,分别挂接SFQ/TBF/SFQ无类别qdisc:

Shell
1
2
3
4
5
6
7
8
9
10
# 添加一个PRIO类型的qdisc,自动有三个class
#           设备      根disc  handle 类型
tc qdisc add dev eth0 root handle 1: prio
 
# 添加一个qdisc给              band0   类型为sfq,分配handle 10
tc qdisc add dev eth0 parent 1:1     handle 10: sfq
# 添加一个qdisc给              band1
tc qdisc add dev eth0 parent 1:2     handle 20: tbf rate 20kbit buffer 1600 limit 3000
# 添加一个qdisc给              band2
tc qdisc add dev eth0 parent 1:3     handle 30: sfq

使用下面的命令可以查看封包统计信息:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
tc -s qdisc ls dev eth0
 
qdisc sfq 30: quantum 1514b
Sent 384228 bytes 274 pkts (dropped 0, overlimits 0)
 
qdisc tbf 20: rate 20Kbit burst 1599b lat 667.6ms
Sent 2640 bytes 20 pkts (dropped 0, overlimits 0)
 
qdisc sfq 10: quantum 1514b
Sent 14926 bytes 193 pkts (dropped 0, overlimits 0)
 
qdisc prio 1: bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
Sent 401836 bytes 488 pkts (dropped 0, overlimits 0) 
HTB

Hierarchical Token Bucket,层级令牌桶,它是一个classful的TBF。适用于下面的场景:

  1. 有一个固定总带宽,想将其分割成几个部分,分别用作不同目的
  2. 每个部分的带宽是有保证的(guaranteed bandwidth)
  3. 还可以允许每个部分向其他部分借带宽

HTB可以作为一个容易理解的CBQ的代替品。和CBQ一样,HTB可以控制egress带宽的占用,可以用一个物理网络连接模拟多个较慢的连接,将不同种类的连接发送到这些模拟的连接中。

HTB使用令牌桶过滤器算法,而不是CBQ那样的估算连接空闲时间,因此它不依赖网络接口的特质,也不需要知道egress接口的实际底层带宽。

HTB中可以包含多个classes,这些classes默认包含一个pfifo_fast qdisc。当封包入队时,HTB使用多种方式决定应该分到哪个class。在常规配置下,在每个节点上,HTB都会寻找一个指令,然后跳转到指令所引用的class。如果class是叶子节点,则在那里入队;如果不是叶子节点,继续前述按指令跳转的过程。

命令格式:

Shell
1
2
3
4
tc qdisc ... dev dev ( parent classid | root) [ handle major: ] htb [ default minor-id ]
 
tc class ... dev dev parent major:[minor] [ classid major:minor ] htb
  rate rate [ ceil rate ] burst bytes [ cburst bytes ] [ prio priority ]

qdisc参数:

参数 说明
default 未分类成功的流量发送到此handle表示的class

class参数:

参数 说明
prio 优先级,值最低的class被最先尝试(是否匹配封包)
rate 给此class及其后代保证的最大带宽
ceil

如果祖代有空闲带宽,则HTB允许借用带宽,这个参数指定rate + 借用带宽一共多大。默认等于rate,也就是不允许借用

burst

(每次中断)最多以ceil速度burst的字节数。应当比所有子代burst之和更大

由于UNIX系统时钟中断频率的原因,不合理的配置会导致实际速率相当的低。以默认10HZ的中断频率为例。每秒能够发送的最大数据量是:

100 × burst

因此,要达到期望10mbits/s的速度,需要的burst大小是12KB:

100 × 12Kbytes × 8 = 10mbit/s

cburst 在不限速(尽网络接口可能)模式下,最多能够burst的字节数。应当比所有子代cburst之和更大

示例:

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 默认分类为30
tc qdisc add dev eth0 root handle 1: htb default 30
 
# 总控,6mbps
tc class add dev eth0 parent 1: classid 1:1 htb rate 6mbit burst 15k
 
# 三个嵌套的子类
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 3mbit ceil 6mbit burst 15k
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 1kbit ceil 6mbit burst 15k
 
# 推荐在子类中使用SFQ
tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10
 
# 配置用来分类的过滤器,使用HTB时所有filter必须全部attach到root
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 80 0xffff flowid 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip sport 25 0xffff flowid 1:20
过滤器

过滤器(filter)也叫分类器(classifier)。

每当封包到达有分叉的节点时,它都需要被分类。分类的方式有很多种,有些qdisc会根据TOS自动分类,有些则需要配置过滤器。

过滤器被classful qdisc用来决定,封包应该被enqueue到哪一个队列。当封包到达qdisc时,其上关联的所有过滤器(称为分类器链,classifier chain)会被依次调用,直到某个返回裁定(verdict)。如果任何过滤器都没有返回verdict,则如何分类取决于qdisc。

u32

通用的、基于任意封包数据的过滤器。

Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 此过滤器是为eth0配置的
tc filter add dev eth0 protocol ip
# 父节点为1:0,也就是根节点       优先级,数字越小优先级越高,越先被调用
  parent 1:0                      prio 1
# u32是过滤器的类型     匹配目标端口是80的IP封包    发送给1:10的那个节点(类)
u32                     match ip dport 80 0xffff    flowid 1:10
 
# 基于CIDR来匹配
tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 \
  match ip dst 4.3.2.1/32 flowid 10:1
 
# 同时根据IP和端口匹配
tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 \
match ip src 4.3.2.1/32 \
match ip sport 80 0xffff     flowid 10:1
 
# 匹配ICMP协议
... match ip protocol 1 0xff
 
# 匹配TOS
tc filter add dev ppp0 parent 1:0 protocol ip prio 10 u32 \
    match ip tos 0x10 0xff flowid 1:4
basic

基于一个ematch表达式进行过滤。

bpf

使用eBPF程序对封包进行过滤。参考:eBPF学习笔记。

cgroup

使用封包所属进程所在的控制组进行过滤。

flow

基于封包所属的流(流根据可选择的key来识别)进行过滤。

fw

根据封包上的fwmark进行过滤,直接将fwmark映射为traffic class。fwmark是内核中的数据,只要没有出内核,不会(因为在各接口之间转发)丢失。

Shell
1
2
3
4
5
# 匹配打了标记6的封包
tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1
 
# 配合下面的命令,可以实现对从eth0发到eth1流量进行塑形
iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6 
route

根据路由表进行封包过滤。

matchall

匹配任何封包。

策略

tc的police action允许限制它所关联到的filter所匹配的流量的带宽。典型的应用是,通过丢弃特定的封包,来保证ingress流量速率。

尽管在发送端进行速率控制更好,但是发送端可能不受我们控制。

可用参数:

参数 说明
rate 封包通过此action的最大速率,超过速率后的处理动作由conform-exceed指定
burst 最大允许的burst字节数
mtu 允许的最大封包大小,超过大小的封包,处理方式和超速一样。默认无限制
peakrate 桶的最大消耗速率
avrate 使用内核中的带宽速率估算器(bandwidth rate estimator),并匹配此参数给出的rate
overhead 单位字节数,计算rate/peakrate时考虑encapsulating成本
linklayer 指定链路层的类别,默认ethernet
estimator

estimator SAMPLE AVERAGE

用于调优内核的速率估算器,两个参数用于控制采样频率、多长时间计算一次平均值

conform-exceed

conform-exceed EXCEEDACT[/NOTEXCEEDACT]

定义超速/超大后的处理方式:

continue  什么都不做,如果还有其它的action则继续处理
drop/shot 丢弃封包
ok/pass 接收封包
reclassify 将封包重置为部匹配action关联到的那个filter,这导致继续匹配封包
pipe 传递给下一个action处理

下面的例子,用u32过滤器和ingress qdisc实现1mbit/s的限速:

Shell
1
2
3
4
5
tc qdisc add dev eth0 handle ffff: ingress
 
tc filter add dev eth0 parent ffff: u32 \
                   match u32 0 0 \
                   police rate 1mbit burst 100k

注意ingress qdisc不是一个真实的qdisc,它仅仅是为了让过滤器有挂钩点。 

动作

动作(Acion)可以作为过滤器的一部分,如果封包匹配过滤器,过滤器返回分类结果之前关联的动作会按顺序一个个执行。

动作能够对分类结果作出响应,甚至去改变分类结果,尽管没有任何内置的动作去改变分类结果。

通用的动作框架是从策略演化而来的。比如上一章的例子,可以改写为动作:

Shell
1
2
3
tc filter add dev eth0 parent ffff: u32 \
        match u32 0 0 \
        action police rate 1mbit burst 100k

为过滤器u32添加多个动作:

Shell
1
2
3
4
5
tc filter add dev eth0 parent ffff: u32 \
        match u32 0 0 \
        # 重定向超速的流量给lo而非丢弃
        action police rate 1mbit burst 100k conform-exceed pipe \
        action mirred egress redirect dev lo
命令格式
Shell
1
2
3
4
tc [ TC_OPTIONS ] actions add | change | replace ACTSPEC
 
ACTSPEC := action ACTNAME ACTPARAMS [ INDEXSPEC ] [ COOKIESPEC ]
               [ FLAGS ] [ HWSTATSSPEC ] [ CONTROL ]
内置动作
bpf

为匹配的封包执行一个BPF程序。

connmark

将封包上的fwmark设置到它的连接上。工作方式是,在conntrack表中查找匹配的条目,如果找到,则存储标记。

csum

触发封包Checksum的重新计算,支持协议IPv4, ICMP, IGMP, TCP, UDP

ipt

将封包传递给指定的iptables目标,这样可以直接使用iptables extensions,而不需要设置fwmark然后通过规则匹配到特定netfilter规则。

mirred

镜像或者重定向封包。常常和ifb伪设备联用,在多个网络接口甚至ingress流量之间共享公共的QoS设置。

nat

执行无状态NAT,应该使用iptables而不是这个动作实现NAT。

pedit

一般性的封包编辑,允许修改封包的任意内容。

police

应用带宽限制策略。

skbedit

修改关联的封包数据,支持修改队列映射、优先级字段、fwmark值。

vlan

添加或移除VLAN头。 

CONTROL

提示tc执行了当前动作之后应该做什么:

CONTROL 说明
reclassify 跳转到动作的父对象(qdisc)的第一个过滤器,重新进行分类
pipe 继续执行(当前过滤器的)下一个动作,默认
drop 丢弃封包,不执行其它动作
continue 继续调用下一个过滤器进行分类操作
pass 返回到调用qdisc,结束分类处理
← MongoDB学习笔记
Mac OS X知识集锦 →

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • Linux网络知识集锦
  • IPVS模式下ClusterIP泄露宿主机端口的问题
  • Linux文本编辑器
  • Ubuntu下安装JDK1.7
  • Linux运行级别和启动顺序

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • Bazel学习笔记 37 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2