TC的使用實例說明
下面我們提供一個利用TC來實現對在一個Linux服務器上的兩個虛擬主機實行不同的帶寬策略的例子。在該例中,我們將講述如何配置和測試TC。
編譯內核
至於如何編譯一個新的內核已經不屬於本章節討論的范圍,我們假設你已經知道如何重新編譯一個內核。
編譯內核時將以下幾個內核選項選中:"kernel/User netlink socket"和"Netlink device emulation"。這樣TC就可以利用netlink來與內核傳送信息。同時將所有的排隊算法選上,位於包括
"Fair queueing"
"CBQ packet scheduler"
"CSZ packet scheduler"
"the simples PRIO pseudoscheduler"
"RED queue"
"SFQ queue"
"TBF queue"
"QoS support"
"rate estimator"
"packet classifier API"
"routing-tables-based classifier"
"U32 classifier"
"special RSVP classifier and special RSVP classifier for IPv6"。
選中這些選項以後,按正常的編譯內核步驟編譯內核,然後安裝新內核,並用新內核重新啟動系統。
編譯TC軟件包
可以在下面的地址下載到我們需要的軟件,然後按照軟件包裡的說明編譯它:
FTP://linux.wauug.org/pub/net/ip-routing/iproute2-current.tar.gz
通常我們要做的只是簡單的輸入make就可以了。
TC 的設定
圖1. CBQ 樹圖
圖一是我們將配置的一個系統的簡單的樹形圖示范。兩個葉子節點從父節點分配帶寬,IP地址10.0.0.10(標識符1:1)和地址10.0.0.11(標識符1:2)是接口eth0上的IP別名,它們共同分享父節點(標識符1:0)的帶寬。這個例子裡面只涉及到了對一個接口上的流量控制,大家可以仿照這個例子構造自己感興趣的控制多個接口設備的配置。
配置QoS特性的第一步就是將qdisc加入到一個接口上,例如本例子:
qdisc add dev eth0 root handle 1: ...
然後定義你需要區別的類別。不同的類別對應不同的流量控制類型。我們的例子中,使用如下的語句:
tc class add dev eth0 parent 1:0 classid X:Y ...
我們的例子中只使用了一層深的類別樹。當然,我們可以構造多層深度的復雜的樹,基本的原則是一樣的:就是一個子節點(如圖1所示)繼承一個父節點的資源同時進一步根據類的定義去分配父節點的資源。例如,父類1:0擁有該設備的全部帶寬,那麼子節點1:1不可能獲得超過10Mbits的帶寬,當然本例子中是限制為1Mbps。
最後定義"IP分組--類別"的映射規則,用來告訴系統的分類器,經過路由器調度的某IP分組該對應什麼類型。首先,將一個分類器與輸出接口關聯起來:
filter add dev eth0 parent 1:0 protocol ip ...
然後,定義"IP分組--類別"的映射規則。本例子中,將利用IP分組的源地址來作為分類的關鍵詞。 下面的腳本完成了這個功能。關於腳本中TC等命令的參數,大家可以參考隨機的文檔,這裡限於篇幅,不做介紹了。
#! /bin/sh
#path to tc and the ip utilities;
#change to reflect yours.
TC=./iproute2/tc/tc
IP=./iproute2/ip/ip
##################################################
#Addresses to be aliased
#change or add more to reflect yours
#
ALIAS1=10.0.0.10
ALIAS2=10.0.0.11
##################################################
# add ip aliasing support
#uncomment if you want to use the ip utility to
#add ip-aliasing for you
#
#$IP addr add $ALIAS1 dev eth0
#$IP addr add $ALIAS2 dev eth0
##################################################
# Attaching a device queue discipline to an
# interface a device queue discipline is
# equivalent almost to a device manager
#
#Attach CBQ to eth0
#Things you might need to change:
# bandwidth -- the bandwidth of the eth0 device
# note it must match the devices real bandwidth
# allot -- it is safe to leave it at the MTU of
# the device
# avpkt -- the average packet size that you
# suspect will be seen safe to leave at 1000
# for Ethernet with MTU of 1514 bytes
# mpu -- minimum packet size
#
$TC qdisc add dev eth0 root handle 1: cbq
bandwidth 10Mbit allot 1514 cell 8 avpkt 1000
mpu 64
##################################################
# Attaching class queue disciplines
# bounded -- it is bound to the rate allocated;
# can borrow even if there is a lot of idle
# bandwidth just sitting there isolated -- cannot
# share its bandwidth to other classes prio is the
# priority assigned 0 being the highest and 7 the
# lowest weight -- safer to leave at 1
# queue discipline setup. Classid 1:1 will have a
# rate of 1Mbps which is bounded.
#
$TC class add dev eth0 parent 1:0 classid 1:1 cbq
bandwidth 10Mbit rate 1Mbit avpkt 1000 prio 5
bounded isolated allot 1514 weight 1 maxburst 21
#rate 1Mbit avpkt 1000 prio 5 bounded allot 1514
#weight 1 maxburst 21
# Classid 1:2 will have a rate of 3Mbps which is
# bounded.
$TC class add dev eth0 parent 1:0 classid 1:2 cbq
bandwidth 10Mbit rate 3Mbit avpkt 1000 prio 5
bounded allot 1514 weight 1 maxburst 21
##################################################
# Define the filter to be attached to eth0
# Create with hash table of 256 slots with ID 1:
#
$TC filter add dev eth0 parent 1:0 protocol ip
prio 5 handle 1: u32 divisor 256
##################################################
# define the criteria for mapping incoming packets
# to classes. Add to the 5th slot of hash table a
# rule to select virtual address ALIAS1 direct it
# to class 1:1
#
$TC filter add dev eth0 parent 1:0 prio 5 u32
ht 1:6: match ip src $ALIAS1 flowid 1:1
# Add to 6th slot of hash table rule to select
# ALIAS2 direct it to class 1:2
$TC filter add dev eth0 parent 1:0 prio 5 u32
ht 1:6: match ip src $ALIAS2 flowid 1:2
## Lookup hash table, if it is not fragmented
## frame. Use protocol as hash key
#
$TC filter add dev eth0 parent 1:0 prio 5 handle
::1 u32 ht 800:: match ip nofrag
offset mask 0x0F00 shift 6
hashkey mask 0x00ff0000 at 8 link 1:
#
#some more examples of how to use u32
# Add to 4th slot of hash table rule to select
# tcp/telnet to 193.233.7.75 direct it to class
# 1:4 and prescribe to fall to best effort,
# if traffic violates TBF (32kbit,5K)
#$TC filter add dev eth1 parent 1:0 prio 5 u32
# ht 1:4: match ip dst 193.233.7.75
# match tcp dst 0x17 0xffff
# flowid 1:4
# police rate 32kbit buffer 5kb/8 mpu 64
# mtu 1514 index 1
## Add to 1st slot of hash table rule to select
## icmp to 193.233.7.75 direct it to class 1:3
## and prescribe to fall to best effort,
## if traffic violate TBF (10kbit,5K)
#$TC filter add dev eth1 parent 1:0 prio 5 u32
# ht 1:4: match ip dst 193.233.7.75
# match tcp dst 0x17 0xffff
# flowid 1:4
# police rate 32kbit buffer 5kb/8 mpu 64
# mtu 1514 index 1
## Add to 1st slot of hash table rule to select
## icmp to 193.233.7.75 direct it to class 1:3
## and prescribe to fall to best effort,
## if traffic violate TBF (10kbit,5K)
#$TC filter add dev eth1 parent 1:0 prio 5 u32
# ht 1:: sample ip protocol 1 0xff
# match ip dst 193.233.7.75 flowid 1:3
# police rate 10kbit buffer 5kb/8 mpu 64
# mtu 1514 index 2
##################################################
#Look at all that we created:
#
echo "---- qdisc parameters ----------"
$TC qdisc ls dev eth0
echo "---- Class parameters ----------"
$TC class ls dev eth0
echo "---- filter parameters ----------"
$TC filter ls dev eth0
測試
我們的例子當中,是有在同一個Linux服務器上有兩個虛擬WWW
#Look at all that we created:
#
echo "---- qdisc parameters ----------"
$TC qdisc ls dev eth0
echo "---- Class parameters ----------"
$TC class ls dev eth0
echo "---- filter parameters ----------"
$TC filter ls dev eth0
測試
我們的例子當中,是有在同一個Linux服務器上有兩個虛擬WWW