带宽管理:
  TC中规定描述带宽:
  mbps = 1024 kbps = 1024 * 1024 bps => byte/s
  mbit = 1024 kbit => kilo bit/s
  mb = 1024 kb = 1024 * 1024 b =>byte
  mbit = 1024kbit => kilo bit.
  默认: 数字使用bps和 b方式存储.

无类队列规则: 它能够接受数据和重新编排、延时或丢弃数据包,默认使用pfifo_fast队列规则.

pfifo_fast:
  特点: 对任何数据包都使用FIFO(先进先出)队列,来存放入队。但它有3个所谓的"频道",对
    每一个频道都使用FIFO规则,内核会优先将TCP的TOS标志位(“最小延迟”)置位的数据包
    放入0频道,其它的放入1和2频道中,当然这是默认行为. 三个频道按照0,1,2的顺序,依次
    等待处理,即0频道有数据包等待发送,1频道的包就不会发送,若1频道有包等待发送,则
    2频道的包将不会被发送。
  

  txqueuelen
    #关于网卡设备的缓冲队列长度,可通过ip 或 ifconfig来修改.
    ifconfig eth0 txqueuelen 10

  priomap:
    内核对会根据数据包的优先权将其对应到不同的频道.
    TCP报文中TOS字段如下:

      

    TOS值的含义 和 其对应的频道:

      

    对于以下服务推荐TOS设置:

      

  TBF(令牌桶过滤器):
    TBF是一个简单队列,它只允许数据包按照事先设定的速率通过,支持设置峰值流量,它很精确,
    且对网络和处理器的影响较小,因此比较常用.
  TBF的原理:
    它实现了一个缓冲器(即令牌桶),在这个桶里面会不断以特定速率往里面填充“令牌",token rate
      (令牌速率)是令牌桶比较重要的参数,它是桶的大小,也就是能存储令牌的数量.
    如:
    rate 200kbps:   它指 令牌桶最多存储200kbit个令牌,一个令牌1bit, 因为要通过1bit的数据,
          就需要一个令牌,因此发送速率若为200k bit每秒,则桶里面始终会有令牌,若超过
          则没有可用令牌,就会产生丢包,这也就是TBF对流量整型的过程; 若低于此速率
          则令牌桶可能会被装满,多余的令牌将丢失。
          另外它也隐含说明了,缓存队列的长度,即它最多能缓存多少bit的数据.
          理解: 因为令牌的产生是按照系统的时间解析度来产生的,系统时间解析度指
           多久为1个时间单位 或 多少HZ(赫兹)一个时间单位, 假如10ms为一个时间单位,
           那就是每隔10毫秒系统会生产一个令牌放到令牌桶中。
           假如在初始时 桶中当前只有1个令牌,按照200kbit/s的速率, 第一个bit进入,桶中
          有令牌取走,该bit通过,接下来的bit,就要等10ms(一个时间单位)后,才能得到下一个
          令牌,而第二个bit在等待时,第三个bit已经到了,依次类推,缓存队列最多能存200kbit
          数据,若超过了,后续的数据就丢失了,若不超过设定速率,这个队列始终不会被填满.

  TBF可用参数:
    limit 和 latency:
    limit: 允许最多有多少数据(字节数)在队列中等待可用令牌。
    latency: 设定一个数据包在缓存队列中等待发送的最长等待时间,若设置它,就相当于
      决定了桶的大小、速率和峰值速率,因为数据包大小范围:64~MTU kbit 。

    burst/buffer/maxburst:
      设置最多一次允许多少个令牌能被立即使用,即峰值速率。
    buffer: 设置令牌桶的大小,通常是管理的带宽越大,buffer就需要的越大.

    mpu: Minimum Packet Unit:最小分组单位, 它决定了令牌的最低消耗。
    rate:设置速率(缺省不限速)
    peakrate:设置峰值速率,即: 一个包通过后,下一个包要等多久才允许通过.
      如: Unix的时间解析度是10ms(2004年左右的参考值), 若平均包长为10kbit,
        则峰值速率最大为1Mbps,即 1秒=1000ms, 按10ms的解析度, 即100个
        时间单位,每个时间单位发送10kbit,就是100 X 10kbit = 1Mbps.
    mtu/minburst:
      mtu: 峰值速率 = mtu X 时间解析度.

      例:
        tc qdisc add dev ppp0 root tbf rate 220kbit latency 50ms burst 1540

  SFQ(Stochastic Fairness Queueing:随机公平队列):
    SFQ的精确度不如上面的算法,但它确能以很小的计算量,实现较高的公平数据发送。
    SFQ实现的公平是随机的, 因为它是针对一个TCP会话或UDP流,将它们通过散列的
    方式平均分配到有限的几个FIFO队列中,所以它们实际上是共享发包机会的,但为了
    让尽量公平,SFQ会每隔指定时间改变一次散列算法,以便让这种机制能让所有包都
    在几秒内发送出去。
   注:
    SFQ仅在网卡确实已经被挤满时,才会生效, 来创建队列并散列TCP或UDP数据包到不同
    队列中,进行公平调度。

  SFQ可用参数:
    perturb: 每隔多久改变一次散列算法,10秒是比较合适的值.
    quantum: 设置一个流至少传输多少字节后,切换到下一个队列中发送其中的数据包。
        建议使用默认值,即最大包长度(MTU). 此值不能设置数值小于MTU!!

    例:
    # tc qdisc add dev ppp0 root sfq perturb 10
    # tc -s -d qdisc ls
     qdisc sfq 800c: dev ppp0 quantum 1514b limit 128p flows 128/1024 perturb 10sec
     Sent 4812 bytes 62 pkts (dropped 0, overlimits 0)
    注:
      “ 800c:”这个号码是系统自动分配的句柄号
      “ limit”: 是这个队列中可以有 128 个数据包排队等待。
      “flows 128/1024”: 一共可以有 1024 个散列目标可以用于速率审计,
              而其中 128 个可以同时激活。
      perturb 10: 每隔 10 秒散列算法更换一次。

  以上队列何时使用最合适:
    1. 仅想限速,使用令牌桶过滤器(TBF):调整桶的配置后可用于控制很高的带宽。
    2. 若链路已被塞满, 使用SFQ,可避免某一会话独占出口带宽.
    3. 若你仅想看看网卡是否有较高的负载,可使用pfifo,而非pfifo_fast,因为pfifo内部
      频道可进行backlog统计。
    4.最后记住: 技术不能解决一切问题,社交还是需要的!

    TC的实现流量控制的大致框架流程如下:

    

   注:
    图中Ingress处就根据策略避免超过规定的数据包进入内核,这样可以
    减少CPU处理时间。 若数据包顺利进入内核,若它是进入本地进程的,
    就转给IP协议栈, 否则就交给egress分类器. 经过审查后,最终被放入
    若干队列规定中进行排队,此过程叫入队。如不进行任何配置,默认
    只有一个egress队列规定,即pfifo_fast. 当数据包入队后,等待内核处理
    并通过某网卡发出,这过程叫出队。

  队列规定: 即管理设备输入(ingress)或输出(egress)的算法.根据否能包含子类,
      它被分为无类和分类两种:
      无类队列规定: 一个内部不包含可配置子类的队列规定.
      分类队列规定: 一个分类的队列规定内可包含更多class(类),其中每个子类又
            进一步地包含一个分类 或 无类的队列规定。

  整形(策略):在数据包被发送前,跟据设定进行适当延迟,避免超过设定的最大速率.
      通常采用丢包来实现, 因为TCP的滑动窗口机制可以根据丢包来自动调整
      其发送数据包的速率,而UDP只能通过丢包来限制其速率。
    Work-Conserving: 对于work-conserving队列规定,若得到一个数据包,就立刻
      发送。即:只要网卡(egress队列规定)允许,它就不会延迟数据包发送.
  non-Work-Conserving: 有些队列,如TBF(令牌桶过滤器),可能需要暂时停止发包,
      以实现限制带宽,也就是说它们有时即时有数据包需要处理,也可能拒绝发送.

  过滤器: 对流量进行分类,如:网页流量,视频流量,游戏流量等进行过滤条件匹配,
    匹配出来后,交给分类器处理。
  分类器: 分类器可将不同的流量分发给 分类队列规定 中不同的子类来处理。

TC的队列规定家族:
  root, 句柄(handle), 兄弟节点 和 父节点

    

   注:
    句柄(handle): 节点引用标识,它的格式: MajorNumber:MinorNumber,其中父节点的次号码始终为0.
        root节点的handle为1:0(可简写为:"1:"), 它有一个子节点 1:1
        1:1这个子队列规定有两个父级的子队列规定分别是 10: 和 11:
        内核 仅和root qdisc 进行通信, 与物理网卡的通信也是有root qdisc来完成的,它们对应整体
        的队列规定家族是透明的,所有对外的接口只有root qdisc一个。
    在队列规定内部(我的理解如下):
      当内核发来入队请求时, root qdisc 会先调用过滤器来匹配数据包,若没有匹配就直接由分类器
        将其下发至子队列规定,它也是先过滤器匹配,然后分类器分发,假如过滤器发现数据包为游戏流量
     就将其送入11: 这个父级的子队列规定,接着11: 过滤器继续判断,发现是boos的游戏流量,就将其
        分发到11:1,在继续到11:1的过滤器,然后是分类器,完后入队等待发送。
      当内核发来出队请求时,root qdisc会向1:1发查询,1:1会分别向10: 和 11:发查询,接着10:会向
        其下的10:1 和 10:2发查询,直到11:1发现了要出队的数据包,它将数据包出队发给root qdisc,接着
     在内核的指引下,root qdisc将数据包发给网卡。【注: 出队要遍历全队列,所以队列不要太多哦~】

  队列规定:
    PRIO:它不对流量进行整形,它仅根据配置的过滤器将流量细分到不同的类中,若需要对流量进行整形处理,
      可以在这些子类中包含相应的队列,由它们来做整形。默认PRIO队列规定包含3个类,每个类下面包含
      一个FIFO队列。

     PRIO可以参数:
    bands : 指定创建的频道个数,一个频道就是一个类, 默认是3个频道.
    priomap: 为PRIO队列规定绑定一个过滤器,默认:根据TOS字段来匹配分类规则与pfifo_fast根据TOS
      字段分类一样。

    例:
     创建如下树:

      

         命令:
       #这个命令创建了三个类,1:1, 1:2, 1:3,因为默认bands为3.
          tc qdisc add dev eth0 root handle 1: prio
      #为第一个子类1:1创建了一个父级子类10:, 并制定内部队列为SFQ(随机公平队列)
          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
         tc qdisc add dev eth0 parent 1:3 handle 30: sfq

           tc -s qdisc ls dev eth0
        qdisc sfq 30: quantum 1514b
        Sent 0 bytes 0 pkts (dropped 0, overlimits 0)
        qdisc tbf 20: rate 20Kbit burst 1599b lat 667.6ms
        Sent 0 bytes 0 pkts (dropped 0, overlimits 0)
        qdisc sfq 10: quantum 1514b
        Sent 132 bytes 2 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 174 bytes 3 pkts (dropped 0, overlimits 0)

    测试:
    1. 尝试使用scp 复制文件到其它主机. 然后查看 队列统计信息。
    2. 书中说 10: 它的优先权最高,交互流量会优先选它, 30:的优先权最低,大量数据流量会优先走它.
        需要测试参考 TOS 标志位含义。

  CBQ(Class Based Queueing:基于类的队列):
    CBQ是根据链路平均空闲时间,来判断链路负载是否需要进行管制(即:整形),它有三种情况:
      avgidle = 0 : 则说明当前连路负载最佳,数据包能够精确按照预计时间间隔到达.
      avgidle < 0 : 则说明当前链路过载了, 若负值逐渐增大,则说明负载超限(Overlimit),
          CBQ将启动整形,开始丢包以禁止发包,禁止发包时长为 超限前计算
          出来的数据包平均发送间隔。
      avgidle > 0 : 则说明当前链路太空闲了, 若空闲超过几个小时,若此时有流量过来,CBQ
          将允许无限制的流量转发, 但这通常不是我期望的,因此需要设置maxidle,
          来限制avgidle的值不能太大.
      avgidle = 两个数据包平均发送间隔时长 减去 EWMA
          EWMA:Exponential Weighted Moving Average:指数加权移动均值,此算法是根据最近
            处理的数据包的权值比以前的数据包按指数增加。 【算法具体含义不清楚】
      简单理解: 最近数据包权值 = 前一个数据包权值^n+1
      另注: UNIX 的平均负载也是这样算出来的

  CBQ整形的参数:
    avpkt: 平均数据包大小,单位:字节. 它是计算maxidle的参数, maxidle从maxburst得出.
    bandwidth: 物理网卡的带宽, 用于计算链路空闲时间.
    cell: 它用于设置时间解析度(即:时间精度), 通常设为8,它必须是2的整数次幂。
    maxburst: 最大突发数据包的个数(原文: 在avgidle=0前,可允许有maxburst个数据包突发传输出去。)
        此值决定了maxidle计算使用的数据包个数【不是很理解】.
    minburst: 它是设置超限后CBQ进入禁止发包延时状态后,根据之前计算的空闲时间延迟值,
        结合系统调度处理程序离开CPU到下次调度它到CPU上执行的间隔,来适当设置禁止发包的
        时长,当处理程序调度到CPU上执行时,一次突发传输 minburst 个数据包.
        注: 大尺度时间上, minburst值越大,整形越精确;
         从毫秒级时间尺度上,就会有更多突发传输.
           禁止发包的等待时间叫: offtime
      minidle: 当avgidle < 0,发送越限后,CBQ进入禁止发包的等待状态,但为了避免解禁后,再次
        出现突发传输,导致avgidle超限更多,负值越大,导致更长的禁止状态,所以需要设置
        一个 minidle 来限制负值无限增大.
        注: minidle 10 : 表示avgidle被限制其越限最大值为 -10us (负10微秒)
      mpu: 数据包的最小大小.用于CBQ精确计算链路空闲时间
      rate: 预期想限制的最大传输速率.

    CBQ在数据包分类方面的参数:
      注: 这些参数是控制那些队列要参与计算,如:已知该队列中无数据包,就不让其参与调度计算,
        及那些队列要被惩罚性的降低优先级等。
      CBQ使用prio参数来设定每个类的优先级,值越小越优先; 数据包出队是按照WRR(Weighted
        Round Robin:加权轮询) 对root qdisc下每个子类进行轮询,优先级高的子类先被调度,从
        该子类中的队列中取数据,接着是次高的,直到全部子类遍历一遍,当然对于没有数据的
        子类将自动跳过. 每次从子类中取多少数据是根据 allot * weight 来决定的。

  WRR的相关参数:
    prio: 设置类的优先级,值越小越优先.
    allot: 设置一次发送多少数据量.
    weight: 允许多发多少数据的权重数(注: 建议weight=rate/10);假如有如下图:

      

   注:
    对于这个图, 1:0这个根类下有两个子类1:1和1:2, 1:1的prio值更小,因此它
    更优先被WRR调度;
      一级子类1:1它的发送数据的权重=0.2+0.5
      一级子类1:2它的发送数据的权重=0.3
      而对于1:1的子类来说:
       二级1:1发送数据的权重=0.2
         二级1:2发送数据的权重=0.5
         而2:1与此一样.

  CBQ兄弟类之间是否可以互相借用带宽:
    isolated / sharing:
    isolated: 不会和兄弟类出借暂时多余的带宽。
    sharing: 允许借用暂时多余的带宽.
    bounded / borrow:
    bounded: 不允许借
    borrow: 允许借

   例:
    这个配置把 WEB 服务器的流量控制为 5Mbps、 SMTP 流量控制在 3Mbps , 而且
    二者一共不得超过 6Mbps,互相之间允许借用带宽。我们的网卡是 100Mbps的。
    # 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:1物理网卡的最大带宽为100Mbit,设置最大速率为6Mbit,允许发送数据量的权重为0.6Mbit.
       一次发送数据量为1514(单位:不清楚),允许的最大突发20个数据包,平均包大小为1000字节,时间解析度为8,
       不借出带宽给兄弟节点,本例子类1:1没有同级兄弟节点,因此设置或不设置一样.

   # 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
      注:
      在子类1:1下有两个子类,它们是可以互相借用空闲带宽的,但他俩最大能使用的总带宽是6Mbit.
    Web能占用的带宽 = 6 X (0.5/(0.5+0.3)) Mbps
    SMTP能占用的带宽 = 6 X (0.3/(0.5+0.3)) Mbps

  # tc qdisc add dev eth0 parent 1:3 handle 30: sfq
  # tc qdisc add dev eth0 parent 1:4 handle 40: 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
  注:
       这是添加了两个过滤器,用于匹配Web和SMTP的流量,并将它们分别送入1:3和1:4中.
  对于没有匹配到的流量,1:0 即root队列规定将直接处理,它采用FIFO队列,不限制直接转发.

  注: 以上命令创建的结构如下图:

    

  
  CBQ的过滤器选项:
    split节点: 当你需要使用CBQ自带的过滤器 defmap时,定义defmap的类的父类就称为split节点.
    defmap: 它是通过与TCP的TOS(服务类型标志位) 做或运算来匹配特定TOS置位的数据包,并将
      这些数据包接入到匹配类中. 0:表示不匹配.

      例:
    # 1:1就是split节点
    # tc qdisc add dev eth1 root handle 1: cbq bandwidth 10Mbit allot 1514 cell 8 avpkt 1000 mpu 64
    # tc class add dev eth1 parent 1:0 classid 1:1 cbq bandwidth 10Mbit \
      rate 10Mbit allot 1514 cell 8 weight 1Mbit prio 8 maxburst 20 avpkt 1000

    # c0: 1100 0000, 它是匹配TOS的第7和6位,即交互和控制位 置位的数据包.
    # tc class add dev eth1 parent 1:1 classid 1:2 cbq bandwidth 10Mbit \
     rate 1Mbit allot 1514 cell 8 weight 100Kbit prio 3 maxburst 20 avpkt 1000 split 1:0 defmap c0

    # 3f:0011 1111, 它是匹配TOS的1~5位,也就是将剩余的所有数据包都匹配到本子类中.
    # tc class add dev eth1 parent 1:1 classid 1:3 cbq bandwidth 10Mbit \
     rate 8Mbit allot 1514 cell 8 weight 800Kbit prio 7 maxburst 20 avpkt 1000 split 1:0 defmap 3f

    root节点1:0接收到的数据包将被分配到1:3 和 1:2子类中的情况为:

      

      补充:
      # tc class change dev eth1 classid 1:2 cbq defmap 01/01
      # 这个change 可以给defmap提供一个mask(掩码),但是暂时不理解它是什么意思.
      # 这是原作者提供的 经过掩码计算后, 优先权值的变化:

      

    HTB(Hierarchical Token Bucket : 分层令牌桶)
   有一个固定速率的链路,希望分割给多种不同的用途使用,为每种用途做出带宽承诺并实现定量的带宽借用,
   这时你就需要使用HTB队列规则了,它配置相比于CBQ简单.

  HTB参数解释:
    rate: 设定期望的最大限制速率.
    burst: 设置突发流量在现有基础上,可以增大多少.
    ceil: 设置速率最高可达到多少. 此参数表明该子类可借用其兄弟类的空闲带宽。

    # tc qdisc add dev eth0 root handle 1: htb default 30
      注:
      default 30: 表明若过滤器没有匹配到的流量都将被分配到root qdisc的1: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
      注:
      1:10这个子类,它的最大速率为5Mbps,它不可用借用其兄弟类的带宽.
      但下面两个设置ceil ,表明它们可借用兄弟类空闲带宽,最大速率可达到6Mbps.
    # 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
    注:
    perturb: 设定SFQ(随机公平队列)每隔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

    以上命令创建的TC结构图:

      

     TC过滤器创建:
    # tc filter add dev 网卡名  parent  父类句柄  protocol  ip  prio   优先级值   u32 \
      [match [ip [[src |dst [IPAddr/CIDR Mask]] [sport |dport 端口号 Mask] | protocol 协议号 Mask]] | \
      handle FirewallMark fw] \
      flowid 前面父类的子类句柄
      注:
       protocol: 支持/etc/protocols中定义的协议号.

  创建基于端口的过滤器:
    # tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip dport 22 0xffff flowid 10:1
    # tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip sport 80 0xffff flowid 10:1
      注:
       上面两个是精确匹配80, 即: 80和0xffff或运算的值 必须与 目标端口 匹配.
         u32: 是一种根据协议内容做数据提取,与指定参数做匹配的参数.
    # tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 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
    # tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip src 1.2.3.4/32 flowid 10:1
    注:
        IP/32: 这是精确匹配主机IP. 若需要匹配网络地址,可使用指定CIDR值,如:192.168.0.0/24
    # tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 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

  基于协议号的过滤器:
    # tc filter add dev eth0 parent 10:0 protocol ip prio 1 u32 match ip protocol 1 0xff flowid 10:1

  基于防火墙标记的过滤器:
    # tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 6 fw flowid 1:1
    # iptables -A PREROUTING -t mangle -i eth0 -j MARK --set-mark 6

  基于TOS字段的过滤器:
    # tc filter add dev ppp0 parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff flowid 1:4

  高级过滤器:
    基于路由的过滤器:
    目的地址匹配:
    # ip route add 192.168.10.0/24 via 192.168.10.1 dev eth1 realm 10
    注:
     realm :用于定义一个realm号码,用于表示网络或主机路由.
    # tc filter add dev eth1 parent 1:0 protocol ip prio 100 route to 10 classid 1:10
     注:
      此命令定义节点 1:0 里添加了一个优先级是 100 的路由过滤器(或加分类器),
      当来自192.168.10.0/24网络的数据包到达这个节点时,就会查询路由表,
      若它要从eth1接口被路由出去,则匹配此路由,进而被发送到类1:10,并赋予优先级值为 100。

  源地址匹配:
    # ip route add 192.168.2.0/24 dev eth2 realm 2
    # tc filter add dev eth1 parent 1:0 protocol ip prio 100 route from 2 classid 1:2
     注:
      若匹配到从192.168.2.0/24网络过来的数据包,则将其送到1:2节点,并赋予优先级值为100.

  管理大量过滤器:
    注: 不建议使用,若真的有这类需求,可尝试使用ipset 和 mark结合
      当你需要管理大量过滤器时,为了避免大量过滤器对每一个数据包都做匹配,带来严重的系统性能问题,
      这里提供一种通过散列表来构建 多个链表,每个链表中仅有几条规则过滤器,以便高效匹配过滤器.
      下面的例子是对IP做散列表的示例:
        假如说你有 1024 个用户使用一个 Cable MODEM,IP 地址范围是 1.2.0.0 到 1.2.3.255,
        每个 IP 都需要不同过滤器来对待,最佳的做法如下:
      

      1. 首先创建一个root过滤器
       # tc filter add dev eth1 parent 1:0 prio 5 protocol ip u32

      2. 然后构建出一个256项的散列表
       # tc filter add dev eth1 parent 1:0 prio 5 handle 2: protocol ip u32 divisor 256

      3.然后我们向表项中添加一些规则:利用IP地址的后半段做为
         # tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: match ip src 1.2.0.123 flowid 1:1
         # tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: match ip src 1.2.1.123 flowid 1:2
         # tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: match ip src 1.2.3.123 flowid 1:3
         # tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 2:7b: match ip src 1.2.4.123 flowid 1:2
        注:
        这是第 123 项,包含了为 1.2.0.123、1.2.1.123、1.2.2.123 和 1.2.3.123 准备的匹配
        规则,分别把它们发给 1:1、1:2、1:3 和 1:2。注意,我们必须用 16 进制来表示
        散列表项,0x7b 就是 123

        4.然后创建一个“散列过滤器”,直接把数据包发给散列表中的合适表项:
      # tc filter add dev eth1 protocol ip parent 1:0 prio 5 u32 ht 800:: \
        match ip src 1.2.0.0/16 \
        hashkey mask 0x000000ff at 12 \
        link 2:
      注:
       “800::” 这表示创建一个散列表,所有的过滤都将从这里开始.
       at 12: 表示从IP头的第12位开始匹配 mask的长度, IP头的第12~15字节为源IP地址位.
       ”link 2:“ 表示匹配后,发送数据包发送到前面创建的第2个散列表项,即: 2:

  IMQ(Intermediate queueing device: 中介队列设备)
    若需要使用IMQ,需要对内核,netfilter,iptables打补丁后才能使用:
      https://blog.csdn.net/dayancn/article/details/45871523
    这篇文章详细讲解了如何给Linux-kernel2.6.18的内核打上IMQ补丁的详细步骤.
    在Linux中由于队列规定只能附加到网卡上,因此有两个局限:
    1. 虽可在入口做队列规定,但在上面实现分类队列规定可能性很小,所以相当于只支持出口整形.
    2. 一个队列规定只能处理一个网卡流量,无法全局限速.
    IMQ就是为解决这两个问题而诞生的,简单说: 你可往一个队列规定中放任何方向的流量, 我们可通过
    iptables将打了特定标记的数据包在netfilter的NF_IP_PRE_ROUTING和NF_IP_POST_ROUTING两个
    钩子函数处被拦截,并被送到附加在IMQ虚拟网卡上的队列规定中, 这样你就可对进入刚进入网卡的
    数据包打上标记做入口整形,或把所有网卡当成一个个类来对待,做全局整形控制。

TC学习总结的更多相关文章

  1. 虚拟化原理到K8s实践经验路线总结

    以下这些内容均为自行学习总结的内容,很多内容没有写概括介绍,看起来可能会有些突兀,但并不影响整体性,我自己的学习经验告诉我,这些内容还仅仅是最精简的核心部分,周边还有很多可扩展内容,主要是操作系统生态 ...

  2. Linux学习日记-使用EF6 Code First(四)

    一.在linux上使用EF 开发环境 VS2013+mono 3.10.0 +EF 6.1.0 先检测一下EF是不是6的 如果不是  请参阅 Linux学习日记-EF6的安装升级(三) 由于我的数据库 ...

  3. HTML5移动开发学习笔记之CSS3基础学习

    CSS回顾 在学CSS3之前首先巩固下CSS的基础知识. 1.CSS框模型 举例子: #box { width: 70px; margin: 10px; padding: 5px; } 这个代码将出现 ...

  4. knockout学习笔记10:demo

    前面已经介绍了ko的基本用法,结合官方文档,基本就可以实际应用了.本章作为ko学习的最后一篇,实现一个简单的demo.主要集中在ko,所以后台数据都是静态的.类似于博园,有一个个人文章的分类列表,一个 ...

  5. 【HTML5&CSS3进阶学习02】Header的实现·CSS中的布局

    前言 我们在手机上布局一般是这个样子的: 其中头部对整个mobile的设计至关重要,而且坑也很多: ① 一般来说整个header是以fixed布局,fixed这个产物在移动端来说本身坑就非常多 ② 在 ...

  6. Python爬虫学习(10):Selenium的好基友PhantomJS

    上一节中我们学习了selenium,用python来操作浏览器,在做网页自动化测试的时候最好不过了 .如果我们来做爬虫用一个带界面的浏览器似乎不太好吧,那可咋办呢?别着急,下来我们要介绍的就是一款不带 ...

  7. Android学习——windows下搭建Cygwin环境

    在上一篇博文<Android学习——windows下搭建NDK_r9环境>中,我们详细的讲解了在windows下进行Android NDK开发环境的配置,我们也讲到了在NDk r7以后,我 ...

  8. Android学习——windows下搭建NDK_r9环境

    1. NDK(Native Development Kit) 1.1 NDK简介 Android NDK是一套允许开发人员使用本地代码(如C/C++)进行Android APP功能开发的工具,通过这个 ...

  9. Java学习笔记(04)

    Java学习笔记(04) 如有不对或不足的地方,请给出建议,谢谢! 一.对象 面向对象的核心:找合适的对象做合适的事情 面向对象的编程思想:尽可能的用计算机语言来描述现实生活中的事物 面向对象:侧重于 ...

随机推荐

  1. [leetcode解题记录]Jump Game和Jump Game II

    Jump Game Given an array of non-negative integers, you are initially positioned at the first index o ...

  2. java 常量表达式

    原文地址:http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28 这是我翻译的,以备不时之用. 常量表达式是一个代 ...

  3. BZOJ 1042: [HAOI2008]硬币购物 容斥+背包

    1042: [HAOI2008]硬币购物 Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请 ...

  4. Codeforces Round #422 (Div. 2) C. Hacker, pack your bags! 排序,贪心

    C. Hacker, pack your bags!     It's well known that the best way to distract from something is to do ...

  5. 使用libcurl的包装库cpr发起http请求

    cpr GitHub地址https://github.com/whoshuu/cpr 简单示例:cpr_http_request.cpp #include <iostream> #incl ...

  6. Delphi如何实现多国语言

    Delphi里的多语言处理方法都一样, 都是通过资源DLL的形式进行加载处理. Delphi在加载form数据的时候会判断当前的系统语言,然后根据语言加载不同的资源dll, 来实现多国语言的功能. 下 ...

  7. 浏览器和服务器 对post get请求 url长度限制

    1. URL长度限制 2. Post数据的长度限制 3. Cookie的长度限制 1. GET  URL长度限制 在Http1.1协议中并没有提出针对URL的长度进行限制,RFC协议里面是这样描述的, ...

  8. POJ3436 ACM Computer Factory —— 最大流

    题目链接:https://vjudge.net/problem/POJ-3436 ACM Computer Factory Time Limit: 1000MS   Memory Limit: 655 ...

  9. CollectionView网格布局

    说句老实话,UICollectionView真的太强大了,而且要掌握高级部分是相当困难的.至少笔者是这么认为的,如果觉得自己比较厉害,可以轻而易举地掌握UICollectionView的使用的,希望可 ...

  10. 用mkdirs创建目录

    import java.io.*; class a { public static void main(String args[]) { createDir("c:/fuck"); ...