Linux 高级流控

Linux 流控原理,实现,及实例

主要讲用 TC 工具对 Linux 进行高级流量控制,结合 TC 流控 HOWTO 文档,通过大量实践进行讲述。 根据本文的讲解,可以更深的了解 Linux 流控,对用 Linux 搭建高性能网关有进一步认识。

谢 华鹰, DevOps Engineer, IBM

谢华鹰,男,1983 年 9 月 20 号出生,毕业于北京财经学院计算机应用专业,从事 Linux 系统管理工作,2002 年参加工作 , 先后工作于酷我音乐,行云网,猎聘网。 2014 年初来上海工作于 IBM 上海分公司 CDL-OPS



2014 年 12 月 24 日

Linux 高级流量控制

本篇主要讲用 TC 对 Linux 进行高级流量控制

通过大量实践结合 TC 流控 HOWTO 文档整理而得

如果你对 Linux 流控感兴趣,如果你需要搭建高性能的 Linux 网关 , 本文将会使你受益颇多。

注:至少具备 Linux OS 的中级水平知识,熟悉 TCP/IP, Linux 网卡工作原理,以及配置 Linux 网关的经验,将有助于对本文的理解。

本文参考文档:

Tc 流控 HOWTO 文档 http://www.tldp.org/HOWTO/html_single/Traffic-Control-HOWTO/

Linux TC 流量控制工具 http://wenku.baidu.com/view/f02078db50e2524de5187e45.html


一 . Linux 流控简介

Linux 流控的意义 :

有效的控制 Linux 网卡进出流量 , 了解网卡工作原理 , 搭建高性能的 Linux 网关 , 对 Linux 高级系统流控有进一步的认识。

Linux 流量控制方法 :

控发不控收 , 所以只能对产生瓶颈网卡处的发包速率进行控制 , 而网络瓶颈分析亦为 Linux 网络流控的第一步 .

Linux 流量控制过程分二种:

  1. 队列控制 即 QOS, 瓶颈处的发送队列的规则控制,常见的有 SFQ PRIO
  2. 流量控制 即带宽控制 , 队列的排队整形, 一般为 TBF HTB

    Linux 流量控制算法分二种:

  3. 无类算法 用于树叶级无分支的队列,例如:SFQ
  4. 分类算法 用于多分支的队列,例如:PRIO TBF HTB

Linux 流控实现工具 TC:

Linux 下流量控制工具 , 从 Linux2.2 版开始已并入内核,功能非常强大, 详见参考文档。


二 . 以下文章将以二种算法的不同流控分别介绍:

1. 无类算法 SFQ

a. 队列控制的无类算法 SFQ

SFQ(Stochastic Fairness Queueing 随机公平队列 ) 是公平队列算法家族中的一个简单实现 . 它的精确性不如其它的方法 , 但实现了高度的公平 , 需要的计算量亦很少 .

SFQ 算法主要针对一个 TCP 会话或者 UDP 流 . 流量被分成相当多数量的 FIFO 队列中 , 每个队列对应一个会话 . 数据按照简单轮转的方式发送 , 每个会话都按顺序得到发送机会 . 这种方式非常公平 , 保证了每一个会话都不会没其它会话所淹没 .

SFQ 之所以被称为"随机", 是因为它并不是真的为每一个会话创建一个队列 , 而是使用一个散列算法 , 把所有的会话映射到有限的几个队列中去 . 因为使用了散列 , 所以可能多个会话分配在同一个队列里 , 从而需要共享发包的机会 , 也就是共享带宽 . 为了不让这种效应太明显 ,SFQ 会频繁地改变散列算法 , 以便把这种效应控制在几秒钟之内 ( 时间由参数设定 ).

注 :SFQ 只会发生在数据发生拥堵 , 产生等待队列的网卡上 .. 出口网卡若无等待队列 ,SFQ 亦不起作用 ...

清单 1. 在网卡上建立 SFQ
#tc qdisc add dev eth0 root handle 1: sfq 
 SFQ 参数有 perturb( 重新调整算法间隔 ) quantum  基本上不需要手工调整 : 
 handle 1: 规定算法编号 .. 可以不用设置由系统指定 .. 
#tc qdisc sh dev eth0 显示算法
#tc qd del dev eth0 root 删除  注 : 默认 eht0 支持 TOS

SFQ 队列一般用在树叶级 , 配合其它流量整形算法一并使用……

b. 流量控制的无类算法 TBF

令牌桶过滤器 (TBF) 是一个简单的队列规定 : 只允许以不超过事先设定的速率到来的数据包通过 , 但可能允许短暂突发流量朝过设定值 .

TBF 很精确 , 对于网络和处理器的影响都很小 , 实现是针对数据的字节数进行的 , 而不是针对数据包进行 , 常用于网关限速 .

TBF 的实现在于一个缓冲器 ( 桶 ), 不断地被一些叫做"令牌"的虚拟数据以特定速率填充着 . (token rate). 桶最重要的参数就是它的大小 , 也就是它能够存储令牌的数量 . 每个到来的令牌从数据队列中收集一个数据包 , 然后从桶中被删除 . 这个算法关联到两个流上——令牌流和数据流 , 于是我们得到 3 种情景 :

A. 数据流以等于令牌流的速率到达 TBF. 这种情况下 , 每个到来的数据包都能对应一个令牌 , 然后无延迟地通过队列 .

B. 数据流以小于令牌流的速度到达 TBF. 通过队列的数据包只消耗了一部分令牌 , 剩下的令牌会在桶里积累下来 , 直到桶被装满 . 剩下的令牌可以在需要以高于令牌流速率发送数据流的时候消耗掉 , 这种情况下会发生突发传输 .

C. 数据流以大于令牌流的速率到达 TBF. 这意味着桶里的令牌很快就会被耗尽 . 导致 TBF 中断一段时间 , 称为"越限". 如果数据包持续到来 , 将发生丢包 . 此种情况最重要 , 因为它可以用来对数据通过过滤器的速率进行整形 . 令牌的积累可以导致越限的数据进行短时间的突发传输而不必丢包 , 但是持续越限的话会导致传输延迟直至丢包 .

清单 2. 在网卡建立 TBF
#tc qd add dev eth1 root handle 1: tbf rate 256kbit burst 10000 latency 50ms 
         速率 256kbit  突发传输 10k  最大延迟 50ms 
#tc -s qd sh dev eth1 统计
#tc qd del dev eth1 root 删除

rate 限制的传输速率 用位来计算

latency 确定了一个包在 TBF 中等待传输的最长等待时间 .

burst 桶的大小 , 以字节计 . 指定了最多可以有多少个令牌能够即刻被使用 .

注 : 管理的带宽越大 , 需要的缓冲器就越大 . 在 Intel 体系上 ,10 兆 bit/s 的速率需要至少 10k 字节的缓冲区

才能达到期望的速率 . 缓冲区太小导致潜在的丢包 .

c. 无类算法除这二种队列以外 , 另有 pfifo_fast( 网卡出口默认根队列规定 )

经常使用的也就是 SFQ/TBF ……

这二种用法如下:

单纯地降低出口速率 , 使用令牌桶过滤器 . 调整桶的配置后可用于控制很高的带宽 .

链路已经塞满 , 保证不会有某一个会话独占出口带宽 , 使用随机公平队列 .

当然最要的还是工作中得来的经验 , 就其应用方面只要能满足需求即可 .. 要做到灵活应用还得大量的实践 ..

2. 分类算法 —— PRIO/CBQ/HTB

分类算法主要作用是可以对多种数据流区别对待 . 一旦数据包进入一个分类的队列规定 , 它就得被送到某一个类中分类 , 对数据包进行分类的工具是过滤器 . 过滤器会返回一个决定 , 队列规定就根据这个决定把数据包送入相应的类进行排队 . 每个子类都可以再次使用它们的过滤器进行进一步的分类 . 直到不需要进一步分类时 , 数据包才进入该类包含的队列规定排队 . 除了能够包含其它队列规定之外 , 绝大多数分类的队列规定能够流量整形

注 : 过滤器对数据包进行分类的工具 , 是从队列规定内部调用的 , 而不是从别处 .( 用在分叉的分支上 )

列规定家族 : 根 , 句柄 , 兄弟和父辈

每块网卡都有一个出口"根队列规定", 缺省情况下是前面提到的 pfifo_fast 队列规定 . 每个队列规定都指定一个句柄 , 以便以后的配置语句能够引用这个队列规定 . 除了出口队列规定之外 , 每块网卡还有一个入口 , 以便 policies 进入的数据流 .

队列规定的句柄有两个部分 : 一个主号码和一个次号码 . 习惯上把根队列规定称为"1:", 等价于"1:0". 队列规定的次号码永远是 0. 类的主号码必须与它们父辈的主号码一致 .

数据包如何出队并交给硬件

当内核决定把一个数据包发给网卡的时候 , 根队列规定 1: 会得到一个出队请求 , 然后把它传给 1:1, 然后依次传给 10:,12: 和 13:( 子类自定义 ), 然后试图从它们中进行 dequeue() 操作 . 也就是说 , 内核需要遍历整颗树 , 换句话说 , 类及其兄弟仅仅与其"父队列规定"进行交谈 , 而不会与网卡进行交谈 . 只有根队列规定才能由内核进行出队操作 ! 更进一步 , 任何类的出队操作都不会比它们的父类更快 . 我们可以把 SFQ 作为一个子类 , 放到一个可以进行流量整形的父类中 , 从而能够同时得到 SFQ 的调度功能和其父类的流量整形功能 .

a. 队列控制的分类算法 PRIO

PRIO 分类优先算法 ( 从左至右优先发包 ), 队列规定并不进行整形 , 它仅仅根据你配置的过滤器把流量进一步细分 . 你可以认为 PRIO 队列规定是 pfifo_fast 的一种衍生物 , 区别在每个频道都是一个单独的类 , 而非简单的 FIFO.

当数据包进入 PRIO 队列规定后 , 将根据你给定的过滤器设置选择一个类 . 缺省情况下有三个类 , 这些类仅包含纯 FIFO 队列规定而没有更多的内部结构 . 你可以把它们替换成你需要的任何队列规定 . 每当有一个数据包需要出队时 , 首先处理 :1 类 . 只有当标号更小的类中没有需要处理的包时 , 才会标号大的类 .

PRIO 配置范例示意图:

大批量数据使用 30:, 交互数据使用 20: 或 10:.

清单 3. 在网卡建立 PRIO
 #tc qdisc add dev eth0 root handle 1: prio 
  # 此命令立即创建了类 : 1:1, 1:2, 1:3 ( 缺省三个子类 ) 
  #tc qdisc add dev eth0 parent 1:1 handle 10: sfq 
  #tc qdisc add dev eth0 parent 1:2 handle 20: tbf rate 20kbit buffer 1600 limit 3000 
    注 : 此为 TBF 限速的另一写法 , 前文有讲解 . 
  #tc qdisc add dev eth0 parent 1:3 handle 30: sfq

主要参数有 :( 后续有实例 )

bands 创建频道的数目 . 每个频道实际上就是一个类 跟 priomap 参数配合使用

注 : 频道是类 , 缺省情况下命名为主标号 :1 到主标号 :3. 如果你的 PRIO 队列规定是 12:, 把数据包过滤到

12:1 将得到最高优先级 . 0 频道的次标号是 1!1 频道的次标号是 2, 以此类推 .

priomap 给 tc 提供过滤器 , 如不提供 PRIO 队列规定将参考 TC_PRIO 的优先级来决定如何给数据包入队 .

b. 流量整形的分类算法 CBQ

CBQ 的工作机制是确认链路的闲置时间足够长 , 以达到降低链路实际带宽的目的 . 为此 , 它要计算两个数据包的平均发送间隔 . 操作期间 , 有效闲置时间的测量使用 EWMA(exponential weighted moving average, 指数加权移动均值 ) 算法 , 也就是说最近处理的数据包的权值比以前的数据包按指数增加 .UNIX 的平均负载也是这样算出来的 . 计算出来的平均时间值减去 EWMA 测量值 , 得出的结果叫做"avgidle". 最佳的链路负载情况下 , 这个值应当是 0: 数据包严格按照计算出来的时间间隔到来 . 在一个过载的链路上 ,avgidle 值应当是负的 . 如果这个负值太严重 ,CBQ 就会暂时禁止发包 , 称为"overlimit"( 越限 ). 相反地 , 一个闲置的链路应该有很大 avgidle 值 , 这样闲置几个小时后 , 会造成链路允许非常大的带宽通过 . 为了避免这种局面 , 我们用 maxidle 来限 avgidle

的值不能太大 .

理论上讲 , 如果发生越限 ,CBQ 就会禁止发包一段时间 ( 长度就是事先计算出来的传输数据包之间的时间间隔 ), 然后通过一个数据包后再次禁止发包 .

清单 4. WEB 服务器的流量控制为 5Mbps,SMTP 流量控制在 3Mbps 上 . 而且二者一共不得超过 6Mbps, 互相之间允许借用带宽
 #tc qdisc add dev eth0 root handle 1:0 cbq bandwidth 100Mbit avpkt 1000 cell 8 
  #tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 100Mbit rate 6Mbit weight  
    0.6Mbit prio 8 allot 1514 cell 8 maxburst 20 avpkt 1000 bounded 
    这部分按惯例设置了根为 1:0, 并且绑定了类 1:1. 也就是说整个带宽不能超过 6Mbps. 
  #tc class add dev eth0 parent 1:1 classid 1:3 cbq bandwidth 100Mbit rate 5Mbit weight 
    0.5Mbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000 
  #tc class add dev eth0 parent 1:1 classid 1:4 cbq bandwidth 100Mbit rate 3Mbit weight 
    0.3Mbit prio 5 allot 1514 cell 8 maxburst 20 avpkt 1000 
    建立了 2 个类 . 注意我们如何根据带宽来调整 weight 参数的 . 两个类都没有配置成"bounded", 但它们都连
  接到了类 1:1 上 , 而 1:1 设置了"bounded". 所以两个类的总带宽不会超过 6Mbps. 别忘了 , 同一个 CBQ 下面的子
  类的主号码都必须与 CBQ 自己的号码相一致 ! 
  #tc qdisc add dev eth0 parent 1:3 handle 30: sfq 
  #tc qdisc add dev eth0 parent 1:4 handle 40: sfq 
    缺省情况下 , 两个类都有一个 FIFO 队列规定 . 但是我们把它换成 SFQ 队列 , 以保证每个数据流都公平对待 . 
  #tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip sport 80 0xffff flowid 
    1:3 
  #tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip sport 25 0xffff flowid 
    1:4

CBQ 流量整形算法相对比较复杂 , 工作中还常用 ... 示例中的各参数请参阅 :HOWTO 中文文档 ..Linux 流量控制 II--- 分类算法 PRIO/CBQ/HTB

c. 流量整形的分类算法 HTB

HTB(Hierarchical Token Bucket) 分层的令牌桶一个分类的令牌桶过滤器 , 工作原理和相关配置同于 TBF.. 拥有 TBF 的各项性能 , 可参阅 TBF 的工作细节 ...

清单 5. 环境与要求同上述 CBQ 的例子
#tc qdisc add dev eth0 root handle 1: htb default 30 
  #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 
  #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 
  # 添加过滤器 , 直接把流量导向相应的类 : 
  #U32="tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32"
  #$U32 match ip dport 80 0xffff flowid 1:10 
  #$U32 match ip sport 25 0xffff flowid 1:20

三 . Linux 流量控制之 U32 过滤规则

过滤器是对数据包进行分类工具 , 过滤器用与把数据包分类并放入相应的子队列 , 这些过滤器在分类的队列规定内部被调用 . 为了决定用哪个类处理数据包 , 必须调用所谓的"分类器链" 进行选择 . 这个链中包含了这个分类队列规定所需的所有过滤器 . 常用到的为 U32 过滤器

分类的一示例图:

当一个数据包入队的时候 , 每一个分支处都会咨询过滤器链如何进行下一步 . 典型的配置是在 1:1 处有一个过滤器把数据包交给 12:, 然后 12: 处的过滤器在把包交给 12:2. 你可以把后一个过滤器同时放在 1:1 处 , 而得到效率的提高 .

另外 , 你不能用过滤器把数据包向"上"送 . 而且 , 使用 HTB 的时候应该把所有的规则放到根上 ..

注 : 数据包只能向"下"进行入队操作 ! 只有处队的时候才会上到网卡所在的位置来 . 他们不会落到树的最

底层后送到网卡 ...

清单 6. 过滤器过滤示例
 #tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip dport 22 0xffff flowid 10:1 
    在 10: 节点添加一个过滤规则 , 优先权 1: 凡是去往 22 口 ( 精确匹配 ) 的 IP 数据包 , 发送到频道 10:1.. 
  #tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip sport 80 0xffff flowid 10:1 
    在 10: 节点添加一个过滤规则 , 优先权 1: 凡是来自 80 口 ( 精确匹配 ) 的 IP 数据包 , 发送到频道 10:1.. 
  #tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2 
    在 eth0 上的 10: 节点添加一个过滤规则 , 它的优先权是 2: 凡是上二句未匹配的 IP 数据包 , 发送到频道 10:2.. 
  #tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip dst 4.3.2.1/32 flowid 10:1 
    去往 4.3.2.1 的包发送到频道 10:1 其它参数同上例
  #tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip src 1.2.3.4/32 flowid 10:1 
    来自 1.2.3.4 的包发到频道 10:1 
  #tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2 
    凡上二句未匹配的包送往 10:2 
  #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 
    可连续使用 match, 匹配来自 1.2.3.4 的 80 口的数据包

常用到的过滤命令一览

 #tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 -------

根据源 / 目的地址

源地址段 'match ip src 1.2.3.0/24'

目的地址段 'match ip dst 4.3.2.0/24'

单个 IP 地址 'match ip 1.2.3.4/32'

根据源 / 目的端口 , 所有 IP 协议

源 'match ip sport 80 0xffff' 0xffff 表所有数据包

目的 'match ip dport 80 0xffff'

根据 IP 协议 (tcp, udp, icmp, gre, ipsec)

icmp 是 1:'match ip protocol 1 0xff' 1 是根据 /etc/protocols 协议号来定

根据 fwmark

#iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6 
      #tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1

注 :handle 根据过滤器的不同 , 含义也不同

按 TOS 字段

#tc filter add dev ppp0 parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff

flowid 1:4 选择交互和最小延迟的数据流 匹配大量传输 , 使用"0x08 0xff".

#tc filter add dev eth0 protocol ip parent 1:0 pref 10 u32 match u32 00100000 00ff0000

at 0 flowid 1:10 匹配那些 TOS 字段带有'最小延迟'属性的数据包


四 . Linux 流量控制 --- 实例解析

以下实例由实际工作环境要求编写而得:

1. PRIO 分类优先算法 ( 从左至右优先发包 )

网卡工作示例图:
清单 7. PRIO 分类优先算法示例 ( 从左至右优先发包 )
 #tc ad add dev eth0 root handle 1: prio hands 3 priomap 1---1 16 个 1(tos 比特 ) 表示所有数据包
    注 : 此命令自动在 1: 下创建三子类 1:1 1:2 1:3 此例中只用到 1:1 
  #tc qd add dev eth0 parent 1:1 handle 11:sfq 
  #tc qdisc add dev eth0 parent 1:1 handle 12: tbf rate 20kbit 
  buffer 1600 limit 3000 
  #tc qd add dev eth0 parent 1:1 handle 13:sfq 
  #tc filter add dev eth0 parent 1:1 prio 1003 protocol ip 
      u32 match ip src 192.168.1.0/24 flowid 1:13 
  #tc filter add dev eth0 parent 1:1 prio 1001 protocol ip 
       u32 match ip src 10.0.0.0/8 flowid 1:12 
  #tc filter add dev eth0 parent 1:1 protocol ip prio 1001 
   u32 match ip tos 0x10 0xff flowid 1:11  交互和最小延迟的数据流

2. HTB 分层令牌桶

网卡工作示例图:
清单 8. HTB 分层令牌桶示例
 #tc qd del dev eth1 root 
  #tc qdisc add dev eth1 root handle 1: htb default 12 
  #tc class add dev eth1 parent 1: classid 1:1 htb rate 2Mbit burst 1500000 在 1: 下定义子类 1:1 
  #tc class add dev eth1 parent 1:1 classid 1:11 htb rate 512kbit burst 150000 ceil 1Mbit 
  #tc qd add dev eth1 parent 1:11 handle 111: sfq 
  #tc class add dev eth1 parent 1:1 classid 1:12 htb rate 1Mbit burst 150000 ceil 1Mbit 
  #tc qd add dev eth1 parent 1:12 handle 122: sfq 注 : 亦可不在 1:12 class 下定义 122: qd 
  #tc class add dev eth1 parent 1:1 classid 1:13 htb rate 2Mbit burst 150000 ceil 2Mbit 
  #tc qd add dev eth1 parent 1:13 handle 133: sfq 
  #tc filter add dev eth1 parent 1: prio 10001 protocol ip 
      u32 match ip src 192.168.1.0/24 flowid 1:12  其它二类亦如此 ..

3. ADSL 上网流量限控脚本

ADSL 带宽是下行 3200Kbit, 上行只有 320Kbit

网卡工作示例图:
清单 9. 上网流量限控脚本示例
 tc qdisc add dev eth0 root handle 1: htb default 24 
  tc class add dev eth0 parent 1: classid 1:1 htb rate 300kbit ceil 300kbit prio 0 
  tc class add dev eth0 parent 1: classid 1:2 htb rate 150kbit prio 3 
  tc class add dev eth0 parent 1:1 classid 1:11 htb rate 300kbit ceil 300kbit prio 1 
  tc class add dev eth0 parent 1:1 classid 1:12 htb rate 150kbit ceil 250kbit prio 2  
  tc class add dev eth0 parent 1:2 classid 1:21 htb rate 100kbit ceil 150kbit prio 4 
  tc class add dev eth0 parent 1:2 classid 1:22 htb rate 30kbit ceil 140kbit prio 5 
  tc class add dev eth0 parent 1:2 classid 1:23 htb rate 15kbit ceil 130kbit prio 6 
  tc class add dev eth0 parent 1:2 classid 1:24 htb rate 5kbit ceil 50kbit prio 7 
  tc qdisc add dev eth0 parent 1:11 handle 111: sfq perturb 5 
  tc qdisc add dev eth0 parent 1:12 handle 112: sfq perturb 5 
  tc qdisc add dev eth0 parent 1:21 handle 121: sfq perturb 10 
  tc qdisc add dev eth0 parent 1:22 handle 122: sfq perturb 10 
  tc qdisc add dev eth0 parent 1:23 handle 133: sfq perturb 10 
  tc qdisc add dev eth0 parent 1:24 handle 124: sfq perturb 10 
  tc filter add dev eth0 parent 1:0 protocol ip prio 1 handle 1 fw classid 1:11 
  tc filter add dev eth0 parent 1:0 protocol ip prio 2 handle 2 fw classid 1:12 
  tc filter add dev eth0 parent 1:0 protocol ip prio 3 handle 3 fw classid 1:21 
  tc filter add dev eth0 parent 1:0 protocol ip prio 4 handle 4 fw classid 1:22 
  tc filter add dev eth0 parent 1:0 protocol ip prio 5 handle 5 fw classid 1:23 
  tc filter add dev eth0 parent 1:0 protocol ip prio 6 handle 6 fw classid 1:24

1:11 最高优先级的数据包通道优先通过 , 主要为一些 ACK SYN 确认包 .. 必要时全部占用 .. 全速

1:12 是很重要的数据道 , 给多点 , 最少给一半 , 但需要时可以再多一点 .

rate 规划 1:2 = 1:21 + 1:22 + 1:23 + 1:24 一般总数在 50%-80% 左右

1:21 http,pop 最常用 , 人数较多 , 易导致堵塞 , 不能给得太多 , 但不益太少 .

1:22 smtp 通道 , 优先低于 1:21 以防发大的附件大量占用带宽

1:23 ftp-data 数据通道可能大量上传文件 ,rate 不能给得太多 ,ceil 设置大些 ( 其它通道剩余带宽应用 )

1:24 无所谓通道 , 就是一般不是平时工作上需要的通道了 , 给小点 , 防止这些人在妨碍有正常工作需要的人

其次的工作即在 iptables 端对相应数据包打上标记 ...

4. Linux+NAT+TC

脚本是 Linux NAT 网关实例 , 根据此脚本思路 , 可进一步细致的进行针对于数据包的限制 ..

清单 10. Linux Nat 网关实例
 echo 1 > /proc/sys/net/ipv4/ip_forward 
  iptables -F 
  iptables -t nat -F 
  iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT 
   --to-source 124.42.97.36 
  iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT 
  --to-source 124.42.97.36 
  iptables -I PREROUTING -t mangle -p tcp -s 192.168.0.0/24 -j MARK 
   --set-mark 1 
  iptables -I PREROUTING -t mangle -p tcp -s 192.168.1.0/24 -j MARK 
  --set-mark 2 
    注 : 可分数据包类型标记
  tc qdisc del dev eth0 root 
    # 加一个根队列 , 速率用网卡的速率 10Mbit,也可用上传的速率
  tc qdisc add dev eth0 root handle 100: cbq bandwidth 10Mbit avpkt 1000 
    # 加一个根类
  tc class add dev eth0 parent 100:0 classid 100:1 cbq bandwidth 10Mbit 
                   rate 10Mbit allot 1514 weight 1Mbit prio 8 maxburst 
                   8 avpkt 1000 bounded 
    # 加一个子类用于内网 1 速率限制为 300Kbit 
  tc class add dev eth0 parent 100:1 classid 100:2 cbq bandwidth 10Mbit 
                   rate 300Kbit allot 1513 weight 30Kbit prio 5 maxburst 
                   8 avpkt 1000 bounded 
    # 加一个子类用于内网 2 速率限制为 320Kbit 
  tc class add dev eth0 parent 100:1 classid 100:3 cbq bandwidth 10Mbit 
                   rate 320Kbit allot 1513 weight 32Kbit prio 6 maxburst 
                   8 avpkt 1000 bounded 
    # 设置队列规则
  tc qdisc add dev eth0 parent 100:2 sfq quantum 1514b perturb 15 
  tc qdisc add dev eth0 parent 100:3 sfq quantum 1514b perturb 15 
    # 将队列和 fw 过滤器映射起来 其中 hand 1 的 1 是开始用 iptables 做的标记 hand 2 的 2 也是开始用
  iptables 做的标记
  tc filter add dev eth0 parent 100:0 protocol ip prio 1 handle 
  1 fw classid 100:2 
  tc filter add dev eth0 parent 100:0 protocol ip prio 2 handle 
  2 fw classid 100:3 
  流量监测相关命令 : 
     tc -s qdisc/class ls dev eth0 
     tc -s qdisc/class ls dev eth1

5. Linux 网关 / 服务器限速 ---HTB

清单 11. Linux 网关 / 服务器 HTB 限速
	#!/bin/sh 
    PWD=/home/huaying/net 
    TC=/sbin/tc 
    $TC class ls dev eth0 
    $TC qdisc del dev eth0 root 
    $TC qdisc add dev eth0 root handle 1: htb r2q 1 
    U32="$TC filter add dev eth0 parent 1: protocol ip prio 16 u32" 
    while read line 
    do 
     ip=`echo $line | awk '{print $1}'` 
     limit=`echo $line | awk '{print $2}'` 
     $TC class add dev eth0 parent 1: classid 1:$ip htb rate 
     "$limit"kbit burst 1k 
     $U32  match ip dst 192.168.1.$ip/32 flowid 1:$ip 
    done < $PWD/ip_limit 
      注 :ip_limit 分行记录 , 第一列为 ip, 第二列为限制的带宽 , 二列以 tables 分开 ..   
  服务器限速
    #!/bin/sh 
    /sbin/tc qdisc del dev eth0 root 
    /sbin/tc qdisc add dev eth0 root handle 1:0 htb r2q 1 
    /sbin/tc class add dev eth0 parent 1:0 classid 1:1 htb rate 
    75mbit burst 10k 
    /sbin/tc filter add dev eth0 parent 1: protocol ip prio 16 
     u32  match ip dst 0.0.0.0/0 flowid 1:1 
    /sbin/tc class ls dev eth0 
      最大限制服务器 eth0 流量在 75Mbit/s

参考资料

  • 访问 developerWorks Linux 专区,了解关于信息管理的更多信息,获取技术文档、how-to 文章、培训、下载、产品信息以及其他资源。
  • 加入 developerWorks 中文社区。查看开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户交流。

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux
ArticleID=993665
ArticleTitle=Linux 高级流控
publish-date=12242014