TC學習總結


  帶寬管理:
  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虛擬網卡上的隊列規定中, 這樣你就可對進入剛進入網卡的
    數據包打上標記做入口整形,或把所有網卡當成一個個類來對待,做全局整形控制。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM