許多發行版都爲內核提供了模塊化或總體式的流量控制(QOS)。自定義的內核可能不會支持這些特性。html
對內核編譯不瞭解或經驗很少的用戶建議閱讀Kernel-HOWTO。對於熟練的內核編譯者在瞭解流量控制以後就能夠肯定須要開啓以下哪些選項。linux
例1.內核的編譯選項shell
# # QoS and/or fair queueing # CONFIG_NET_SCHED=y CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m CONFIG_NET_SCH_CSZ=m CONFIG_NET_SCH_PRIO=m CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m CONFIG_NET_SCH_TEQL=m CONFIG_NET_SCH_TBF=m CONFIG_NET_SCH_GRED=m CONFIG_NET_SCH_DSMARK=m CONFIG_NET_SCH_INGRESS=m CONFIG_NET_QOS=y CONFIG_NET_ESTIMATOR=y CONFIG_NET_CLS=y CONFIG_NET_CLS_TCINDEX=m CONFIG_NET_CLS_ROUTE4=m CONFIG_NET_CLS_ROUTE=y CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m CONFIG_NET_CLS_POLICE=y
使用如上選項編譯的內核能夠爲本文討論的全部場景提供模塊化支持。用戶在使用一個給定的特性前可能須要執行modprobe *module
*。網絡
iproute2是一個命令行套件,能夠用於管理一臺機器上與IP網絡配置有關的內核結構。若是要查看這些工具技術文檔,能夠參閱iproute2 文檔,若是要了解更具探討性的內容,請參閱linux-ip.net上的文檔。在iproute2工具包中,二進制的tc是惟一用於流量控制的工具。本文檔將忽略其餘工具。框架
因爲tc須要與內核交互來建立,刪除和修改流量控制結構,所以在編譯tc時須要支持全部指望的qdisc
。實際上,在iproute2上游包中還不支持HTB qdisc。更多信息參見Section 7.1, 「HTB, Hierarchical Token Bucket」 。socket
tc工具會執行支持流量控制所須要的全部內核結構配置。因爲它的用法多種多樣,其命令語法也是晦澀難懂的。該工具將三個Linux流量控制組件(qdisc、class或filter)中的一個做爲其第一個必選參數。tcp
例2.tc命令的用法模塊化
[root@leander]# tc Usage: tc [ OPTIONS ] OBJECT { COMMAND | help } where OBJECT := { qdisc | class | filter } OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] }
每一個對象均可以接收其餘不一樣的選項,本文後續將會進行完整的描述。下例展現了tc命令行語法的多種用法。更多用法能夠參見 LARTC HOWTO。若是要更好地瞭解tc,能夠參閱內核和iproute2源碼。函數
例3.tc qdisc工具
[root@leander]# tc qdisc add \ <1> > dev eth0 \ <2> > root \ <3> > handle 1:0 \ <4> > htb <5>
del
root
。另一個qdisc的功能是受限的,ingress qdisc能夠附加到相同的設備上major
:minor
格式指定的用戶自定義號。當使用隊列規則句柄時,次號必須爲0。qdisc句柄能夠簡寫爲"1:"(等同於"1:0"),若是沒有指定,則次號默認爲0上述展現了使用tc工具將一個隊列規則添加到一個設備的用法。下面是使用tc給現有的父類添加類的用法:
例4.tc 類
[root@leander]# tc class add \ <1> > dev eth0 \ <2> > parent 1:1 \ <3> > classid 1:6 \ <4> > htb \ <5> > rate 256kbit \ <6> > ceil 512kbit <7>
del
例5. tc過濾器
[root@leander]# tc filter add \ <1> > dev eth0 \ <2> > parent 1:0 \ <3> > protocol ip \ <4> > prio 5 \ <5> > u32 \ <6> > match ip port 22 0xffff \ <7> > match ip tos 0x10 0xff \ <8> > flowid 1:6 \ <9> > police \ <10> > rate 32000bps \ <11> > burst 10240 \ <12> > mpu 0 \ <13> > action drop/continue <14>
添加一個過濾器,動做也能夠爲del
指定附加的新過濾器的設備
指定附加的新過濾器的父句柄
該參數是必須的
prio
參數容許給定的過濾器優先於另外一個過濾器
這是一個分類器,是每一個tc過濾器命令中必需的部分。
flowid
指定了目標類(或qdisc)的句柄,匹配的過濾器應該將選定的數據包發送到該類。
這是一個策略器,這是每一個tc過濾器命令可選的部分
策略器會在速率達到某一個值後執行一個動做,並在速率低於某一值時執行另外一個動做
突發與HTB中的突發相似(突發是桶的概念)。
最小的策略單元,爲了計算全部的流量,使用的mpu
爲0
action表示當rate
與策略器的屬性匹配時將會執行那些操做。第一個字段指定了當超過策略器後的動做,第二個字段指定了其餘狀況下的動做
如上所示,即便對於上述簡單的例子來講,tc命令行工具的語法也是晦澀難懂的,若是說存在一種更簡單的方法來配置Linux流量控制,對於讀者來講,應該不會感到驚訝。參見下一節Section 5.3, 「tcng, Traffic Control Next Generation」。
參見 Traffic Control using tcng and HTB HOWTO 以及 tcng 文檔。
下一代流量控制(tcng)爲Linux提供了全部流量控制的能力。
Netfilter 是Linux內核提供的一個框架,容許使用自定義的格式來實現各類與網絡有關的操做。Netfilter 爲報文過濾、網絡地址轉換、端口轉換等提供了多種功能和操做,這些功能包括在網絡中重定向報文所需的功能,以及提供禁止報文到達計算機網絡中的敏感位置的功能。
Netfilter 爲一組Linux內核鉤子,容許特定的內核模塊將回調函數註冊到內核的網絡棧上。這些函數一般會用於流量的過濾和規則的修改,當報文通過網絡棧的各個鉤子時都會調用這些函數。
iptables是一個用戶空間的應用程序,容許系統管理員配置由Linux內核防火牆(由不一樣的Netfilter 實現)提供的表以及其保存的鏈和規則。不一樣的內核模塊和程序目前用於不一樣的協議,iptables用於IPv4,ip6tables用於IPv6,arptables用於ARP,ebtables用於以太幀。
iptables須要提高到特權才能運行,而且必須由root用戶執行,不然沒法運行。在大多數Linux系統上,iptables安裝在/usr/sbin/iptables 下,且有對應的man
文檔。此外iptables安裝還可能安裝在/sbin/iptables下,但相比於一個基本的二進制可執行文件,iptables更像一個服務,所以最好將其保留在/usr/sbin下面。
術語iptables也一般用於指內核級的組件。x_tables是內核模塊的名稱,其中包含四個模塊所使用的共享代碼部分,這些模塊還提供了用於擴展的API。後來,Xtables或多或少被用來指整個防火牆(v四、v六、arp和eb)體系結構。
Xtables 容許系統管理員定義包含處理報文的規則的表。每一個表都與一個不一樣類型的報文處理相關聯。報文會按照順序經過鏈中的規則來處理。鏈中的一個規則可能會跳轉到另一個鏈,經過這種方式能夠作到任意級別的嵌套。每一個到達或離開計算機的報文都會通過至少一個鏈。
報文的源能夠決定該報文首先進入哪一個鏈。iptables中預約義了五個鏈(對應五個Netfilter 鉤子),但不是每一個表都包含全部的鏈。
預約義的鏈都有一個策略,如DROP,即當報文到達鏈尾時會執行丟棄動做。系統管理員能夠按照須要建立任意多的鏈,新建立的鏈並無任何策略,當報文到達鏈尾時,會返回到調用該鏈的位置。一個鏈也多是空的。
PREROUTING:
報文在進行路由處理前會進入該鏈。INPUT:
報文會上送到本地,它與本地打開的socket沒有任何關係。本地上送的邏輯由"本地上送"路由表控制。可使用ip route show table local
命令查看FORWARD:
全部已經路由到非本地的報文將會通過該鏈OUTPUT:
本機發送的報文會通過該鏈POSTROUTING:
在完成路由決策後,報文傳遞給硬件以前進入這個鏈鏈中的每一個規則都包含報文匹配的規範,還有可能包含目標(target ,用於擴展)或斷定(verdict ,內置決策之一)。當一個報文進入一條鏈後,會按照順序逐一檢查鏈中的每條規則,若是這條規則不匹配,則檢查下一條規則。若是一個規則匹配報文,那麼就會按照規則中的目標/斷定指定的動做來處理該報文,執行的結果可能會容許或拒絕繼續在鏈中處理報文。因爲匹配包含了報文檢測的條件,所以其佔了規則集的絕大部分。這些匹配場景可能發生在OSI模型的任何層,例如——mac-source和-p tcp——dport參數,此外也能夠包含獨立於協議的匹配規則,如-m時間。
報文會繼續在鏈中處理,直到發生下面任意一種狀況:
ACCEPT
或DROP
),或使用了一個決定報文最終命運的模塊。RETURN
,致使處理返回到調用鏈目標也會返回相似ACCEPT(NAT模塊會這麼作)或DROP(如REJECT模塊)的斷定,但也可能會暗示CONTINUE(如LOG模塊;CONTINUE是一個內部名稱)來繼續處理下一個規則(若是沒有指定任何目標/斷定)。
中間隊列設備並非qdisc,但它的用法與qdiscs緊密相關。在Linux中,qdisc會附加到網絡設備上,任何要進入設備的報文,首先會進入qdisc,而後纔會進入驅動隊列。從這個觀點看,會有兩個限制:
IMQ用於解決這兩大限制。簡單地說,能夠將任意選定的內容放到一個qdisc中。特殊標記的報文會在netfilter NF_IP_PRE_ROUTING 和NF_IP_POST_ROUTING 鉤子中被攔截,並經過附加的qdisc傳遞給imq設備。iptables目標能夠用於標記報文。
這種方式容許對ingress流量進行整流,只要標記來自某處的報文,並/或將接口看成類來設置全局的限制。此外作不少其餘的事情,好比把http流量放到qdisc中,把新的鏈接請求放到qdisc中等。
下面使用ingress整流來受權一個高帶寬。對其餘接口的配置相似:
tc qdisc add dev imq0 root handle 1: htb default 20 tc class add dev imq0 parent 1: classid 1:1 htb rate 2mbit burst 15k tc class add dev imq0 parent 1:1 classid 1:10 htb rate 1mbit tc class add dev imq0 parent 1:1 classid 1:20 htb rate 1mbit tc qdisc add dev imq0 parent 1:10 handle 10: pfifo tc qdisc add dev imq0 parent 1:20 handle 20: sfq tc filter add dev imq0 parent 10:0 protocol ip prio 1 u32 match \ ip dst 10.0.0.230/32 flowid 1:10
本例使用u32來分類。此外還可使用其餘分類器,後續的流量將會被選擇並打上標記,最後入隊列到imq0。
iptables -t mangle -A PREROUTING -i eth0 -j IMQ --todev 0 ip link set imq0 up
在iptables的mangle表的PREROUTING 和POSTROUTING 鏈中能夠配置IMQ目標。語法爲:
IMQ [ --todev n ] n : number of imq device
也支持ip6tables目標。
注意,流量不是在目標被匹配時進入隊列,而是在匹配以後。當流量進入imq設備以後的具體位置取決於流量的方向(進/出)。這些位置由iptables預約義的netfilter 鉤子決定。
enum nf_ip_hook_priorities { NF_IP_PRI_FIRST = INT_MIN, NF_IP_PRI_CONNTRACK = -200, NF_IP_PRI_MANGLE = -150, NF_IP_PRI_NAT_DST = -100, NF_IP_PRI_FILTER = 0, NF_IP_PRI_NAT_SRC = 100, NF_IP_PRI_LAST = INT_MAX, };
對於ingress流量,imq會使用NF_IP_PRI_MANGLE + 1
的優先級,意味着在處理完PREROUTING 鏈以後,報文會直接進入imq設備。
對於使用NF_IP_PRI_LAST 的egress流量,意味着,被過濾表丟棄的報文將不會佔用帶寬。
ethtool 命令用於控制以太接口的驅動隊列大小。ethtool 也提供了底層接口的信息以及啓用/禁用IP棧和驅動特性的能力。
ethtool 的-g標誌能夠展現驅動隊列(ring)的參數:
$ethtool -g eth0 Ring parameters for eth0: Pre-set maximums: RX: 16384 RX Mini: 0 RX Jumbo: 0 TX: 16384 Current hardware settings: RX: 512 RX Mini: 0 RX Jumbo: 0 TX: 256
能夠看到該NIC的驅動的輸出隊列爲256個描述符。爲了減小延遲,一般建議下降驅動隊列的大小。在引入BQL(假設NIC驅動支持)以後,就不須要修改驅動隊列了。
ethtool還能夠管理如 TSO, UFO 和GSO這樣的優化特性。-k
表示展現了當前設置的卸載,可使用-K
進行修改。
$ethtool -k eth0 Offload parameters for eth0: rx-checksumming: off tx-checksumming: off scatter-gather: off tcp-segmentation-offload: off udp-fragmentation-offload: off generic-segmentation-offload: off generic-receive-offload: on large-receive-offload: off rx-vlan-offload: off tx-vlan-offload: off ntuple-filters: off receive-hashing: off
因爲TSO, GSO, UFO和GRO一般會增長驅動隊列中的報文字節數,若是須要優化延遲(而非吞吐量),建議關閉這些特性。除非系統正在處理很是高速率的數據,不然禁用這些特性時,可能不會注意到任何CPU影響或吞吐量降低。