论坛风格切换切换到宽版
  • 1642阅读
  • 9回复

[问题求助]Linux的高级路由和流量控制_第5章 隧道 [复制链接]

上一主题 下一主题
离线malawenwen.
 
发帖
2019
C币
-60527
威望
364
贡献值
1
银元
-1
铜钱
4523
人人网人气币
0
只看楼主 倒序阅读 使用道具 楼主  发表于: 2009-05-01
我认为这章的语.言基本上没问题了。等我全翻完后会给出HT.ML和PDF格式的文档。(广告)
------------.--------------------.-    美容
第5章 GRE 和其他隧道
L.inux有3种隧道。它们是: IP-in-IP 隧道、 GRE 隧道和非内.核隧道(如PPTP)。            杀毒
5.1. 关于隧道的几点注释
隧道可以用于实现很多非常不一般而有趣的功能。但如果你的配置有问题,却也会发生可怕的错误。除非你确切地知道你在做什么,否则不要把缺省路由指向一个隧道设备。而且,隧道会增加协议开销,因为它.需要一个额外的IP包头.。一般应该是每个包增加20个字节,所以如果一个网络的MTU是1500字节的话,使用隧道技术后,实际的IP.包长度最长只能有1480字节了.。这倒不是什么原则性的问题,但如果你想使用隧道技术构建一个比较大规模的网络的话,最好仔细研究一下关于IP包的分.片和汇聚的知识。哦,还有.,挖一个隧道最好的方法当然是同时从两头挖。--------------彩票
5.2.. IP-in-IP 隧道    外汇
这种隧.道在Linux上已经实现很长一段时间了。需要两个内核模.块:ipip.o 和 new_tunnel.o。--------------彩票
比如说你有3个网络:内部网A和B,中间网C(比如说:Inter.net)。.A网络的情况:外贸
网络地址        10..0.1.0教育
子网掩.码        255.255.255.0投资
路由器        1.0.0.1.1投资
路由器在C网络上的地.址是172.16.17.18。.
B网络的情况:
网络地.址        10.0.2.0外贸
子网掩码        255.255.255..0.
路由器        1.0.0.2.1--- 印刷
路由器在C网络上的IP地址.是 .172.19.20.21。虚拟主机
已知C网络已经连通,我们假定它.会将所有的数据包从A传到B,反之亦然。而且你可以随便使.用Internet。电脑
这就是你要做的:
首先,确认模块是否加载:
insmod ipip.o
insmod new_tunne.l.o(广告)
然后,在A网络的路由器上输入.:    健康
ifconfig tunl0. 10.0.1.1 pointopo.int 172.19.20.21.
route add -ne.t .10.0.2.0 netmask 255.255.255.0 dev tunl0虚拟主机
并且在B网络的路由器上输入:
ifconfig tunl0 10..0.2.1 .pointopoint 172.16.17.18             电子
route add -net 10.0.1.0 netma.sk 255.255..255.0 dev tunl0.
如果你想中止隧道,输入:
ifconfig tun.l0 down--------------彩票
简单之极!但是你不能通过IP-in-IP隧道转发广播或者IPv6数据包。你只是连接了两个一般情况下无法直接通讯的IPv4网络而.已。至于兼容性,这部分代码已经有很长一段历史了,它.的兼容性可以上溯到1.3版的内核。据我所知,Linux的IP.-in-IP 隧道不能与其他操作.系统或路由器互相通讯。它很简单,也很有效。需要它的时候尽管使用,否则就使用GRE。外贸
5.3. GRE 隧道
GRE是最初由CISCO开发出.来的隧道协议,能够做一些IP-in-IP隧道做.不到的事情。比如,你可以使用GRE隧道传输多播数据.包和IPv6数据包。在Linux下,你需要ip_gre.o模块。.
5.3.1. IPv4隧道
让我们先来做一做IPv4隧.道:              乙肝
比如说你有3个网络:内部网A和B,中间网C(比如说..:Internet)。A网络的情况:[成人用品]
网络地址        .10.0.1.0--------------彩票
子网掩码      .  255.255.255.0.
路由器  .      10.0.1.1服务器
路由器在C.网络上的地址是172.16.17.18。我们称之为ne.ta。.
B网络的情况:
网络地址     .   10.0.2.0    外汇
子网掩码        .255.255.255.0            杀毒
路由器    .    10.0.2.1电影
路由器在C网络上的..IP地址是 172.19.20.21。我们称之为netb。.
已知C网络已经连通,我们假定它会将所有的数据包从A传到.B,反之亦然。至于原因,我们不考虑。..
在A网络的路由器上,输入:
ip tunnel add. netb mode gre remote 172.19.20.2.1 local 172.16.17.18 ttl 255           鲜花
ip link s.et netb up    外汇
i.p ad.dr add 10.0.1.1 dev netb[成人用品]
ip. ro.ute add 10.0.2.0/24 dev netb外贸
让我们稍微讨论一下.。第1行,我们添加了一个隧道设备,并且称之为n.etb(为了能够表示出这个隧道通向哪里)。并且表示要使用GRE协议 (.mode gre),对端地址是172.19.20.21(另一端的路由器),我们的隧道数据包发源于172.16.17.18(以便当你的路由器在C网络中拥有多个地址的时候,你可以指定哪一个应用于隧道) 并且包的TTL字段应设置为255(ttl. 255.)。    外汇
第2行,启用该隧道。
第3行,我们给这个新生的网卡配置了一个IP:10.0.1.1。对于小网络来说足够了,但如果你网络中的隧道多得象无证.运营的.小煤窑一样,你可能就要考虑给你的隧道规划一个单独的IP地址范围(在本例中,你可以使用10.0.3..0)。外贸
第4行,我们为B网络设置.了一条路由。注意子网掩码的另一种表示方法。如果你不熟悉这种表示.,我就来解释一下:你把你的子网掩码写成二进制形式,数数里面由多少个1。如果你连这个也不会做,不妨就简单地记住.:255.0.0.0 就是 /8,255.255.0.0 就是 /16, 25.5.255.255.0 就是 /24。    健康
让我们再看看B网络的路由器。
ip tunnel add neta mode gre remote 172.16..17.18 local 172..19.20.21 ttl 255(        游戏          )
ip l.ink set neta up.
ip addr add 10.0.2..1 dev n.eta           建材
ip .rou.te add 10.0.1.0/24 dev neta.
如.果你想从A路由器中停止隧道,输入:          婚庆
ip link set netb. down.
ip tunnel. del netb.
当然,你.可以把netb换成neta,在B路由器.上操作。电影
5.3.2. IPv6隧道
关于IPv6地址,请参看第6章第1节。.<性病>
这就开始吧。
我.们假设你有如下的IPv6网络,你想把它连接到6b.one或者一个朋友那里。              乙肝
Network 3ffe:406:5.:1:5:a:2:.1/96(        游戏          )
你的IPv4地址是172.16.17.1.8,6bone 路.由器的IPv4地址是172.22.23.24。外贸
ip tunnel add sixbone mode sit remote 17.2.22.23.24 local. 172.16.17..18 ttl 255(广告)
ip .link set sixbone up服务器
ip addr add 3.ffe:406:5:1:5:a:2:1/9.6 dev sixbone[成人用品]
ip route .add 3ffe::/15 dev s.ixbone 电脑
让我们来讨论一下。我们创建了一个叫做sixbone的隧道设备。我们设置.它的模式是sit(也.就是在IPv4隧道中使用IPv6)并且告诉它对端(remote)和本端 (local)在哪里。TTL设置为最大,2.55。接着,我们激活了.这个设备(up)。然后.,我们添加了我们自己的网络地址,并添加了一条通过隧道去往3ffe::/15 (现在全部属于6bone)的路由。投资
GRE隧道是.现在最受欢迎的隧道技.术。它也广泛地应用于Linux世界之外并成为一个标准,是个好东西。           鲜花
5.4. 用户级隧道
在内核之外,还有很多.实现隧道的方法,最闻名的当然要数PPP和PPTP,但实际上还有很多(有.些是专有的,有些是安全的,有些甚至根本不用IP),但那远远超出了本.HOWTO所涉及的范围。             电子

评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
离线yufan163.
发帖
2164
C币
-60464
威望
407
贡献值
1
银元
-2
铜钱
4840
人人网人气币
0
只看该作者 沙发  发表于: 2010-04-13
Re:Linux的高级路由和流量控制_第5章
这种howto,网上的中文版已经有很多了,楼上的老兄精神可嘉.
我把6~18章的东西贴出来

离线zxlovest.
发帖
2235
C币
-60023
威望
421
贡献值
1
银元
-1
铜钱
5033
人人网人气币
0
只看该作者 板凳  发表于: 2010-04-13
Re:Linux的高级路由和流量控制_第5章
6. 用 Cisco 和/或 6bone 進行 IPv6 tunneling (IPv6 tunneling with Cisco and/or 6bone)
By Marco Davids <marco@sara.nl>;

維護者需知﹕

據我所知﹐目前這個 IPv6-IPv4 tunneling 並非由 GRE tunneling 定義。雖然﹐您可以用 GRE tunnel 設備進行 IPv6 over IPv4 的 tunnel (GRE 可在 IPv4 上作任何的 tunnel)﹐但在這裡使用的設備("sit"﹐僅對 IPv6 over IPv4 進行 tunnel 而已﹐因此或和其它技術有別。

6.1 IPv6 Tunneling
這是 Linux 在 tunneling 技術上的另一應用。這在已經使用 IPv6 的界面上很普遍﹐當然囉﹐您認為很前衛也未嘗不可。後面的 '實作' 範例絕對不是唯一的 IPv6 tunneling 方法。不過﹐它卻是在 Linux 與 Cisco IPv6 兼容路由器之間進行 tunnel 的最常用武器﹐而實驗證明許多人對此也趨之若騖。我不怕以一賠十和您賭一賭

關於 IPv6 的小秘訣

比較起 IPv4 位址﹐IPv6 位址顯如龐然大物﹕128 bits 對比 32 bits。這同時也只提供我們需要的事物﹕就是許多﹑許多的 IP 位址﹕340,282,266,920,938,463,463,374,607,431,768,211,465 是一個十分精確的例子。除此以外﹐ IPv6(或 IPng﹐也就是 IP Next Generation)﹐被認為可以在 Internet backbone 路由器上維護更小的路由表﹑更簡單的設備設定﹑更好的 IP 層級安全﹑以及更佳的 QoS 支援。

例如﹕2002:836b:9820:0000:0000:0000:836b:9886

每次寫這麼長的 IPv6 位址﹐事實上蠻累人的。因此﹐不妨參考如下規則來簡化一下﹕

不要以零開始(和 IPv4 一樣)。
用冒號來區隔這 16 個 bit (或兩個 byte)。
當遇到連續的零的時候﹐您可以這樣寫 :: ﹐但是只能在一個位址上做一次﹐而且位址數量一定要為 16 個 bit。
參考此規則﹐一個如 2002:836b:9820:0000:0000:0000:836b:9886 的位址﹐也可以寫成 2002:836b:9820::836b:9886﹐顯然簡潔得多。

用於 tunnels 上面

IPv6 一致被認為能夠取代 IPv4 的地位。由於它相對而言還是一種嶄新技術﹐目前尚難找到純 IPv6 的原始網路。為了讓我們更迅速的過渡﹐於是有了 6bone 的出現。

原始的 IPv6 網路聯結﹐是透過將 IPv6 協定封裝在 IPv4 封包中﹐然後利用現有的 IPv4 架構從一個 IPv6 站點送到其它站點去。

恰好﹐這正是 tunnels 切入之處。

為了使用 IPv6﹐我們必須要先有一個支援它的核心。目前已經有非常多的優秀文件告訴我們如何做到這點﹐不過﹐似乎全都不外乎這幾路板斧﹕

使用新的 Linux 版本﹐以及合適的 blibc。
然後抓取最新的核心原始碼。
如果您全都準備妥當﹐那您就可以繼續上路﹐編譯出一個 IPv6 兼容的核心﹕
轉到 /usr/src/linux 並輸入﹕
make menuconfig
選擇 "Networking Options"
選擇 "The IPv6 protocol",﹐"IPv6: enable EUI-64 token format"﹐"IPv6: disable provider based addresses"
提示﹕不要使用‘模組’的方式﹐這通常工作起來不很完善。

總而言之﹐將 IPv6 以 '內建' 方式編進核心就是了。然後您可以如常般將設定保存好﹐再繼續核心的編譯。

提示﹕在真正編譯之前﹐不妨修改一下 Makefie﹕ EXTRAVERSION = -x ; -->; ; EXTRAVERSION = -x-IPv6

關於核心的編譯和安裝﹐應該有很多優秀文件了﹐本文件就不再贅言。如果您在這裡碰到麻煩﹐請按照您自己的規格參考 Linux 核心編譯的相關文件。

/usr/src/linux/README 這個檔應該是個不錯的起點。等您過了這一關﹐再用新的核心重新啟動系統﹐然後您可以輸入 '/sbin/ifconfig -a' 命令﹐或許會發現一個全新的'sit0-device'。 SIT 就是 Simple Internet Transition 的意思。果真如此的話﹐不妨開香檳自我慶祝一番﹕您已經距離下一代的 IP 邁出了很大一步了

接下來﹐您或許想要將機器連接起來﹐或是甚至將整個網路連接到其它 IPv6 兼容網路去。而 "6bone" 正是應此運而生的。

假設您獲得一個這樣的的 IPv6 網路﹕3ffe:604:6:8::/64 ﹐而您想要連接 6bone ﹐或是您的朋友。請注意﹕那個 /64 子網標記的使用辦法參照常規的 IP 位址界定方式就可以了。

您的 IPv4 位址為 172.16.17.181﹐而 6bone 的 router 也有一個位址為 145.100.1.5。

# ip tunnel add sixbone mode sit remote 145.100.1.5 [local 145.100.24.181 ttl 225]
# ip link set sixbone up
# ip addr add 3FFE:604:6:7::2/126 dev sixbone
# ip route add 3ffe::0/16 dev sixbone


讓們研究一下上面的句子。第一行﹐我們建立了一個 tunnel 設備﹐叫做 sixbone。然後設定為 sit 模式(IPv6 in IPv4 tunneling)﹐並且要連到哪裡去 (remote)﹐還有從哪裡來 (local)。而 TTL 呢﹐已設到最高﹕255。

接下來﹐我們將設備跑起來 (up)。再下來﹐我們新增自己的網路位址﹐同時透過這個 tunnel 為 3ffe::/15 設定一個路由 (目前均為 6bone)。如果您目前的執行主機是您的 IPv6 網關的話﹐請增加如下數行﹕


# echo 1 >;/proc/sys/net/ipv6/conf/all/forwarding
# /usr/local/sbin/radvd

在最後面的 radvd 是一個路由器廣告程式(advertisement daemon) - like zebra -﹐以支援 IPv6 的自動設定功能。如果您有興趣﹐請用搜索引擎尋找它的相關資訊。您可以用如下命令來檢查一下﹕


# /sbin/ip -f inet6 addr


假如您已經在 IPv6 網關上將 radvd 跑起來﹐並在本地網路上啟動 IPv6 兼容的 Linux 機器﹐那您應該可以享受到 IPv6 的自動設定功能了﹕

# /sbin/ip -f inet6 addr
1: lo: <LOOPBACK,UP>; mtu 3924 qdisc noqueue inet6 ::1/128 scope host

3: eth0: <BROADCAST,MULTICAST,UP>; mtu 1500 qdisc pfifo_fast qlen 100
inet6 3ffe:604:6:8:5054:4cff:fe01:e3d6/64 scope global dynamic
valid_lft forever preferred_lft 604646sec inet6 fe80::5054:4cff:fe01:e3d6/10
scope link


您還可以進而用 bind 設定 IPv6 位址。原來的 A 記錄﹐在 IPv6 裡面為﹕AAAA。而 in-addr.arpa 則改為 ip6.int。呵﹐光是這個題目就有一大堆資料了。

越來越多的應用程式已經開始支援 IPv6 了﹐包括 secure shell﹑telnet﹑inetd﹑Mozilla 瀏灠器﹑Apache 網站伺服器﹑以及其它﹐數不勝數。不過﹐這些都不是本路由文件所要討論的啦

在 Cisco 那邊﹐設定檔或許會長得有點像下面的樣子﹕

!
interface Tunnel1
description IPv6 tunnel
no ip address
no ip directed-broadcast
ipv6 enable
ipv6 address 3FFE:604:6:7::1/126
tunnel source Serial0
tunnel destination 145.100.24.181
tunnel mode ipv6ip
!
ipv6 route 3FFE:604:6:8::/64 Tunnel1

但是﹐如果您沒有 Cisco 可供設定﹐那就嘗試找 Internet 上的眾多 IPv6 tunnel 經紀幫忙。相信他們都非常樂意在他們的 Cisco 上面為您設定額外的 tunnel 的。而且大部份都可以透過友善的 web 界面進行。您可以用搜索引擎找找 "ipv6 tunnel broker" 看。

发帖
2052
C币
-235233
威望
369
贡献值
1
银元
-4
铜钱
4636
人人网人气币
0
只看该作者 地板  发表于: 2010-04-13
Re:Linux的高级路由和流量控制_第5章
7. IPsec﹕ internet 上之安全 IP (IPsec: secure IP over the internet)
FIXME﹕編輯空缺。請參考﹕ The FreeS/WAN project。

发帖
2095
C币
-193313
威望
380
贡献值
1
银元
-1
铜钱
4709
人人网人气币
0
只看该作者 4楼 发表于: 2010-04-13
Re:Linux的高级路由和流量控制_第5章
9. 用 CBQ 進行頻寬管理 (Using Class Based Queueing for bandwidth management)
現階段由我來發掘這功能﹐委實是折殺小弟了。Linux 2.2 本身就自帶有許多頻寬管理辦法﹐其實已夠得上那些高級專屬的頻寬管理系統了。

Linux 所提供的﹐甚至比 Frame 及 ATM 還要更多。

流量控管的兩個基本單元是過濾器(filters) 和佇列(queues)。前者將流量安排至後者﹐後者則收集流量然後決定哪些要先送﹑哪些要晚送﹑或是丟棄掉(drop)。而兩者都各有其不同系列。

最常見的過濾器是 fwmark 和 u32﹐前者讓您可以使用 Linux netfilter 程式選擇流量﹔而後者則允許您依據任何標頭(header)選擇流量。至於最常聽到的佇列演算法就是 Class Based Queue 了。CBQ 可以說是一個 super-queue﹐在其裡面包含了其它佇列 (甚至其它 CBQs)。

或許﹐關於佇列演算法(queueing)在頻寬管理上的運用﹐一時間尚難一窺全豹﹐不過﹐它還真的不負眾望就是了。

作為我們的參考資料框架﹐我把目前這個章節套用在一個 ISP 模式之上﹐也就是我偷師學藝之所﹐暫且稱之為 Casema Internet in The Netherlands 吧。Casema﹐事實上是一家 cable 公司﹐他們的客戶和他們自己的辦公室都有 internet 的需求。大多數公司電腦都有 internet 的連線。實際上﹐他們有大把金錢可以花而不是用 Linux 來做頻寬管理的。

那讓我們看看我們的 ISP 是怎樣用 Linux 來管理其頻寬吧。

9.1 佇列演算法是什麼東東﹖(What is queueing?)
我們用佇列演算法來判定數據 被傳送 的順序。有一個很重要的概念我們要知道﹐就是我們只能處理那些我們要傳送的數據。那它又是如何影響傳送速度之判定順序呢﹖您可以想像為一位收款員每一分鐘可以處理 3 個客人。

然後要付款的客人就要跑到隊列的 '尾巴' 去排隊。這是所謂的 'FIFO quequeing' (First IN, First Out --- 先入先出)。不過﹐假設我們讓某些客人插入隊列中間﹐而不是排在最後﹐然後這些客人就可以花更少時間在隊列中﹐因而也可以更快的購物。

在 inetnet 的環境中﹐我們沒辦法直接控制別人要送什麼東西過來。這有點像您家中的(實體)信箱﹐您沒辦法影響全世界去修改他們要送信給您的數量﹐除非您有能力通知所有人。

然而﹐internet 賴以為繼的 TCP/IP﹐卻有某些功能可以協助我們的。TCP/IP 本身是沒辦法知道兩台主機之間的網路容量的﹐所以它會越來越快('剛開始很慢')的將數據送出去﹐而當封包開始丟失的時候﹐因為沒有空間將他們送出去了﹐然後就會開始減慢下來。

這情形﹐就有點像您還沒讀完一半信件的時候﹐會希望別人不要再寄信給您一樣。不同之處﹐這裡是在 internet 上面而已。

FIXME﹕解釋擁塞視窗 (congestion windows)


[The Internet] ---<E3, T3, whatever>;--- [Linux router] --- [Office+ISP]
                                      eth1          eth0


現在﹐我的 Linux router 有兩張界面﹐eth0 和 eth1。eth1 用來連接我們的 router﹐它負責將封包送至光纖線路以及將封包接收進來。

eth0 則用來連接另外一個 subnet﹐內有公司防火牆及我們的網路前端﹐我們透過它來連接客戶。

由於我們僅能限制送出的部份﹐我們需要兩套獨立但非常近似的規則。透過修改 eth0 的佇列﹐我們可以判定資訊要多快送至我們客戶那邊﹐因而要分配多少下傳(downstream) 頻寬給他們﹐所謂的‘下載速度’是也。

在 eth1 上面﹐我們判定數據要多快送給 Internet﹑多快給我們的使用者﹐而且公司內部和業務方面均需要上傳數據。

9.2 先搞定頻寬切割 (First attempt at bandwidth division)
CBQ 可以讓我們產生好些不同類別(classes)﹐甚至類別中的類別。至於更大的切割﹐或許可以稱為 '代理(agencies)'。而在這些類別裡面﹐或者可以找到諸如 'bulk' 或 'interactive' 之類的名稱。

例如﹐我們或有一條 10 megabit 的 'internet' 連線﹐以分享給我們的客戶及公司之需。但我們不能讓辦公室裡的少數同仁盜取大量的本來要賣給客戶的頻寬。

在另一邊﹐比方說我們的客戶﹐也不能佔用本來給我們的門市通往客戶資料庫的頻寬。

在過去﹐用來解決的辦法﹐莫過於使用 Frame Relay/ATM 或建立虛擬電路(Virtual Circuits)。這的確能解決問題﹐只不過 frame 並不容易十分細緻調整﹐而 ATM 在攜帶 IP 流量上的效能也非常差強人意﹐而且﹐兩者都未有標準法則以產生不同類型的流量進入不同的 VCs 。

不過﹐假如您真的使用 ATM 的話﹐Linux 同樣能架輕就熟的為您表演高難度的流量分類技巧。而另一方法是牽兩條獨立的線路﹐但似乎不怎麼實用﹐也不十分完善﹐且也不見得能完全解決您的所有問題。

這時候﹐您就要求助於 CBQ 這尊菩薩了。

顯而易見﹐我們這裡主要有兩個類別﹕ 'ISP' 和 'Office' 。剛開始的時候﹐我們真的不必十分講究他們頻寬的切割﹐所以我們就不再於其類別下細分了。

我們決定客戶的下傳流量必須保證在 8 megabits 的範圍﹐而我們的辦公室只有 2 megabits。

可以用 iproute2 之 tc 工具來設定起流量控管。

# tc qdisc add dev eth0 root handle 10: cbq bandwidth 10Mbit avpkt 1000


好了﹐這裡有一堆數字。究竟如何呢﹖我們已經設定起 eth0 的 '佇列戒律 (queueing discipline)' 了。我們以 'root' 來宣告這是頂層(root) discipline。我們還將其 handle 設為 '10'。因為我們這裡要做 CBQ﹐所以我們也同時在命令行中指明。我們告訴核心﹐它可以支配 10M bit ﹐同時平均封包體積大約為 1000 個 octet。

好﹐現在我們就產生我們的頂層類別﹐它凌架於其它的所有類別之上。

# tc class add dev eth0 parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate \
  10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000


哇﹐這裡的數字更多﹗Linux 的 CBQ 在實作上其實蠻具通用性的。我們用 'parent 10:0' 來指定此類別是源自我們剛纔產生的 qdisc handel '10:' 這個頂層類別而來的。而 'classid 10:1' 呢﹐則是我們授予這個類別的名稱。

我們這裡無須告訴核心更多資訊﹐單純產生一個類別以滿足可用設備就是了。我們同時還指定出 MTU(外加一些 overhead) 為 1514 個 octet。而且﹐我們量定此類別的 '比重(weight) ' 為 1Mbit﹐此為一個微調參數而已。

現在﹐再讓我們產生 ISP 類別吧﹕

# tc class add dev eth0 parent 10:1 classid 10:100 cbq bandwidth 10Mbit rate \
  8Mbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 \
  bounded


我們先撥出 8Mbit﹐同時用 'bounded' 參數來指定此類別一定不能超過此限制。否則此類別或會從其它類別那裡借用頻寬﹐我們後面將會討論到。

還是讓我們產生Office 之頂層類別﹐趕快收鑼吧﹕

# tc class add dev eth0 parent 10:1 classid 10:200 cbq bandwidth 10Mbit rate \
  2Mbit allot 1514 weight 200Kbit prio 5 maxburst 20 avpkt 1000 \
  bounded


為了幫助我們更好的理解﹐下面的圖示列出了所有的類別﹕


+-------------[10: 10Mbit]-------------------------+
|+-------------[10:1 root 10Mbit]-----------------+|
||                                                ||
|| +-----[10:100 8Mbit]---------+ [10:200 2Mbit]  ||
|| |                            | |            |  ||
|| |          ISP               | |   Office   |  ||
|| |                            | |            |  ||
|| +----------------------------+ +------------+  ||
||                                                ||
|+------------------------------------------------+|
+--------------------------------------------------+


好了﹐現在我們已經告訴核心有什麼類別存在﹐但還沒說要怎樣去管理佇列。我們不如馬上起而行﹐一次搞定兩個類別吧。


# tc qdisc add dev eth0 parent 10:100 sfq quantum 1514b perturb 15
# tc qdisc add dev eth0 parent 10:200 sfq quantum 1514b perturb 15


目前的範例中﹐我們安裝的是 Stochastic Fairness Queueing discipline (sfq)﹐雖然不是很貼切﹐不過它卻可以在不耗費更多 CPU 運轉之下﹐很好的處理大量頻寬。而我們通常使用的會是 The Token Bucket Filter。

到目前為止﹐我們僅剩一件事情要做而已﹐就是向核心解釋什麼樣的封包屬於什麼樣的類別。剛開始﹐我們純粹用 iproute2 來做就好﹐但是﹐配合 netfilter 雙劍合璧的話﹐更是如虎添翼。


# tc filter add dev eth0 parent 10:0 protocol ip prio 100 u32 match ip dst \
  150.151.23.24 flowid 10:200

# tc filter add dev eth0 parent 10:0 protocol ip prio 25 u32 match ip dst \
  150.151.0.0/16 flowid 10:100


這裡﹐我們假設辦公室網路躲在位址為 150.151.23.24 的防火牆之後﹐而我們其它 IP 位址則屬於 ISP 的。

使用 u32 比對(match) 更是容易﹐而用 netfilter 來標識封包也更能夠設定出精密的比對規則﹐然後我們可以在 tc 裡進行比對。

好了﹐現在我們已經將下傳頻寬切割完畢﹐同樣的﹐我們在上傳頻寬上面依樣畫葫蘆。為求簡捷﹐這次讓我們一鼓作氣﹕


# tc qdisc add dev eth1 root handle 20: cbq bandwidth 10Mbit avpkt 1000

# tc class add dev eth1 parent 20:0 classid 20:1 cbq bandwidth 10Mbit rate \
  10Mbit allot 1514 weight 1Mbit prio 8 maxburst 20 avpkt 1000

# tc class add dev eth1 parent 20:1 classid 20:100 cbq bandwidth 10Mbit rate \
  8Mbit allot 1514 weight 800Kbit prio 5 maxburst 20 avpkt 1000 \
  bounded

# tc class add dev eth1 parent 20:1 classid 20:200 cbq bandwidth 10Mbit rate \
  2Mbit allot 1514 weight 200Kbit prio 5 maxburst 20 avpkt 1000 \
  bounded

# tc qdisc add dev eth1 parent 20:100 sfq quantum 1514b perturb 15
# tc qdisc add dev eth1 parent 20:200 sfq quantum 1514b perturb 15

# tc filter add dev eth1 parent 20:0 protocol ip prio 100 u32 match ip src \
  150.151.23.24 flowid 20:200

# tc filter add dev eth1 parent 20:0 protocol ip prio 25 u32 match ip src \
  150.151.0.0/16 flowid 20:100


9.3 如何處理頻寬透支 (What to do with excess bandwidth)
在我們這個虛構範例中﹐我們發現一個現象﹐就是在 ISP 客戶大都離線的時候(比方說﹐早上 8 點)﹐我們的辦公室卻只有 2Mbit﹐顯然是極其浪費的。

如果將 'bounded' 敘述拿掉﹐那麼類別就能夠借取其它類別的頻寬來用。

而有些類別或許不願意將他們的頻寬外借﹐例如兩個租用同一線路的敵對 ISP﹐是絕對不會向對方進貢的。在那樣的狀況下﹐您可以在 'tc class add' 的句子後端﹐加上一個關鍵詞 'isolated' 即可。

9.4 類別再分 (Class subdivisions)
FIXME﹕此構思並沒經過測試﹗小心嘗試﹗

我們這裡還可精益求精。如果所有辦公室員工同時開啟他們的股票程式﹐還是有可能把資料庫的頻寬給吃掉的。所以﹐我們可以再建兩個子類別﹕'Human' 和 'Database'。

我們的資料庫永遠需要 500Kbit﹐所以就剩下 1.5M 給我們的員工來花費。

我們要在 Office 這個類別裡面再建兩個類別﹕

# tc class add dev eth0 parent 10:200 classid 10:250 cbq bandwidth 10Mbit rate \
  500Kbit allot 1514 weight 50Kbit prio 5 maxburst 20 avpkt 1000 \
  bounded

# tc class add dev eth0 parent 10:200 classid 10:251 cbq bandwidth 10Mbit rate \
  1500Kbit allot 1514 weight 150Kbit prio 5 maxburst 20 avpkt 1000 \
  bounded


FIXME﹕尚需範例﹗

9.5 多界面的負載分流 (Loadsharing over multiple interfaces)
有好些方法都可以做到這點。其中最簡單明了就是 'TEQL' --- "True" (or "trivial" link equalizer。和大多數用來做佇列的辦法一樣﹐負載分流也是雙向的。線路的兩端都需要參與﹐才能獲得完整的效果。

發揮一下想像力吧﹕


                 +-------+   eth1   +-------+
                 |       |==========|       |
'network 1' ----|   A   |          |   B   |---- 'network 2'
                 |       |==========|       |
                 +-------+   eth2   +-------+


A 和 B 都是路由器﹐而且﹐我們目前假設它們都是跑 Linux 的。如果流量從 network 1 送到 network 2 那邊﹐那麼 router A 就需要將封包分送至 B 的兩條線路去。而 router B 則需要設定為能夠接受這樣的安排。調過來也一樣﹐當封包從 network 2 流向 network 1﹐router B 也需要將封包分送至 eth1 和 eth2 去。

負責分送的部份﹐就是由 'TEQL' 設備來做的﹐參考如下劍訣(易如削蠟)﹕


# tc qdisc add dev eth1 root teql0
# tc qdisc add dev eth2 root teql0


這需要在兩邊的機器上做啦。那個 teql0 的設備﹐基本上以 roundrobin 的方式向 eth1 和 eth2 進行分送﹐來發送封包。數據並不是從 teql 設備進入的﹐僅僅以 'raw' 格式出現在 eth1 和 eth2 上面。

然而﹐我們現在只是把設備弄起來而已﹐我們還需要適當的路由。方法之一是用一個 /31 的網路給這兩條線路﹐另外一個 /31 網路給 teql0 設備﹕

FIXME: 不知道是否需要某些諸如 'nobroadcast' 的設定呢﹖用一個 /31 同時包含網路位址和廣播位址似乎太小了 --- 如果這個設計不可行﹐那就試用 /30 吧﹐然後相應的調整 IP 位址就是了。您或許甚至連 eth1 和 eth2 的 IP 位址也不想給呢﹗

On router A:

# ip addr add dev eth1 10.0.0.0/31
# ip addr add dev eth2 10.0.0.2/31
# ip addr add dev teql0 10.0.0.4/31


On router B:

# ip addr add dev eth1 10.0.0.1/31
# ip addr add dev eth2 10.0.0.3/31
# ip addr add dev teql0 10.0.0.5/31


現在﹐router A 應該可以在這 2 條真實線路和 1 個均衡設備上 ping 10.0.0.1﹑10.0.0.3﹑和 10.0.0.5 了。而 router B 也應該可以透過線路 ping 10.0.0.0﹑10.0.0.2﹑和 10.0.0.4 。

如果上面的都成功了﹐router A 要將 10.0.0.5 設定為連接 network 2 的路由﹐同時 router B 則要將 10.0.0.4 設為連接 network 1 的路由。在一些特殊環境中﹐例如 network 1 是您家中的網路﹐而 network 2 是 internet﹐那麼 router A 就要將 10.0.0.5 設定為預設網關了。

一些注意地方 (Caveats)
任何事情都是知易行難。在 router A 和 router B 雙方﹐它們的 eth1 和 eth2 都必須將返回路徑的過濾關閉﹐否則它們會將那些不是以它們本身為目標 IP 位址的封包丟棄掉﹕


# echo 0 >; /proc/net/ipv4/conf/eth1/rp_filter
# echo 0 >; /proc/net/ipv4/conf/eth2/rp_filter


然後﹐就是討厭的封包重排序的問題了。比方說﹐有 6 個封包需要從 A 送到 B 去 --- eth1 或會得到 1﹑3﹑和 5 ﹔而 eth2 或會得到 2﹑4﹑和 6 。假如一切理想﹐router B 會收到這樣的順序﹕1﹑2﹑3﹑4﹑5﹑6。不過﹐現實中有很大機會將會是﹐核心按這樣的順序接收﹕2﹑1﹑4﹑3﹑6﹑5。問題是這樣會讓 TCP/IP 感到困擾。透過線路攜帶多個不同的 TCP/IP 連線並不至於有什麼問題﹐然而您卻不能合併多條線路讓下載單一檔案的 FTP 變得大幅加快﹐除非您用來傳送和接收的作業系統都是 Linux﹐因為在某些簡單的重排序中﹐連線的交握並不容易處理。

不過﹐對許多應用程式而言﹐線路的負載分流的確是一個非常厲害的武器。

离线blueii.
发帖
1982
C币
-152858
威望
353
贡献值
1
银元
-2
铜钱
4430
人人网人气币
0
只看该作者 5楼 发表于: 2010-04-13
Re:Linux的高级路由和流量控制_第5章
10. 更多的 qdisc (More queueing disciplines)
其實 Linux 核心已經提供我們許多 queueing disciplines 了。到目前為止﹐最為廣泛應用的是 pfifo_fast 佇列演算法﹐也是預設使用的。這也解釋了為何這些進階功能如此強悍。他們除了只是 '另外的佇列' 以外﹐別無它物。

每一種佇列演算法都各有千秋。不過並非全部都經嚴密測試過的就是了。

10.1 pfifo_fast
望文生意﹐此佇列演算法就是先入先出(First In First Out)﹐接收到的封包﹐均一視同仁。這種佇列演算法有 3 個所謂的 'bands'。在每一個 band 中﹐均奉行 FIFO 的規則。然而﹐z只有在 band0 中的封包處理完之後﹐才輪到 band1 裡面的。在 band1 和 band2 之間﹐也是同樣的情形。

10.2 Stochastic Fairness Queueing
一如前述﹐SFQ 也不是放之四海皆準的﹐但(平均來說)還是可用的就是了。它主要的好處是它所佔用的 CPU 和記憶體都很少﹐而‘真正’的平等(fair) 佇列法需要核心追蹤所有運作中的連線。

在平等佇列演算法家族中﹐Stochastic Fairness Queueing (SFQ) 算是較為簡明的實作。雖然它不如其它演算法那麼精確﹐不過在保持相當平等的前提下﹐它所需要的運算也較少。

在 SFQ 中的關鍵詞是會談(conversation)(或曰流程(flow))﹐在一連串的數據封包中找到足夠的公約數﹐以區分出不同的 conversation。IP 封包裡面都帶有來源和目的位址﹐以及協定號碼﹐此情形下﹐這些參數就派得上用場了。

SFQ 由動態分配的 FIFO queues 組成﹐一個 queue 負責一個 conversation。而 discipline 則以 round-robin 的形式執行﹐每次從一個 FIFO 中送出一個封包﹐這就是為何稱之為平等(fair)的原因了。SFQ 的主要好處在於它讓不同的程式平等的分享連線﹐而避免頻寬被單一的客戶程式所佔據。然而﹐SFQ 卻不能從 bulk flows 中判定出互動(interactive)的部份 --- 這需要先於前面的 CBQ 進行篩選﹐然後才將 bulk 流量導入 SFQ 中。

10.3 Token Bucket Filter
Token Bucket Filter(TBF)是一種簡單的網路佇列演算法。當網路封包經過這個佇列時﹐就會受到一個預先設定的速率限制(封包數/時間)﹐利用這個﹐可以來減緩網路瞬增流量(buffer short bursts)所造成的網路效能降低。

至於 TBF 的實作﹐則由一個緩衝區(bucket) 構成﹐不斷的被一些虛擬資訊﹐稱為 tokens ﹐按特定的速率(token rate) 填充。而緩衝區的重要參數是其體積﹐也就是它所能存儲的 token 數目。

每一個抵達的 token 抵消一個離開佇列的傳入數據封包﹐然後從緩衝區中清掉。另外﹐有兩個流程(flow) 與此演算法息息相關的﹕ token 和 data﹐這一共會帶出三種狀況﹕


數據按 等於(equal) 傳入 token 速率抵達 TBF。此情形之下﹐每一個傳入封包都各自獲得其匹配的 token﹐同時無延遲的通過。
數據按 小於(smaller) token 速率抵達 TBF。每一個數據封包都自佇列送出﹐但只有一部分 token 在傳出時被刪除﹐因而 token 則會不斷的積累﹐直到填滿緩衝區的體積為止。而那些被存儲起來的 token ﹐則在瞬增流量(short data burst)出現的時候﹐以高於 token 的速率傳送數據。
數據按 大於(bigger) token 速率抵達 TBF。此情形下則會引致過濾器出現超負荷(filter overrun) --- 傳入數據只能在不丟失前提下送出﹐直到所有積累的 token 全數耗盡為止。然之後﹐超過限制的封包就會被丟棄。

最後一種情形千萬不能掉以輕心﹐因為這會強行將頻寬撥給數據﹐而通過過濾器。至於 token 的積聚﹐則允許超出限制之瞬增流量仍可不被遺失地通過﹐但其後的持續過載﹐均會導致封包被持續的丟棄。

(譯者註﹕這個 TBF 其實不難理解﹐就是 no token no data 原則。只有當 data 獲得相應的 token 才能通過﹐而 token 的載入速率則是固定的。)

Linux 核心看起來似乎超過此一規格﹐而且還允許我們限制瞬增流量的速度。然而﹐Alexey 警告我們說﹕


注意﹕TBF 的最高峰值(peak rate) 相當高﹕當 MTU 為 1500 的時候﹐P_crit = 150Kbytes/sec。所以﹐如果您需要更大的峰值﹐使用 HZ=1000 的 alpha 機器囉  

FIXME﹕不清楚是否仍有 TSC (pentium+) ﹖嗯﹐看來有那麼點兒

FIXME﹕若不然﹐要為提高的 HZ 另闢章節

10.4 Random Early Detect
RED 可算是身懷絕技。當一個 TCP/IP 連線建立起來的時候﹐連線兩端都不清楚到底頻寬會有多大。所以 TCP/IP 會先由低速開始然後逐漸加快腳步﹐最後受制於 ACKs 回應的延遲。

當一條線路滿載的時候﹐RED 就會開始丟棄封包﹐告知 TCP/IP 這條線路已達擁塞狀態﹐需要減低速度了。聰明之處在於 RED 會模擬真正的擁塞﹐同時在線路完全滿載之前開始丟棄封包。一旦線路完全飽和﹐它就擔當起交通警察的角色。

如需更詳細的資料﹐請參考 Backbone 那章。

10.5 Ingress policer qdisc
如果您不想借助於 router 或其它 Linux 機器﹐而想要限制特定的主機﹐那麼 Ingress qdisc 會是您的隨身暗器。當頻寬超過您所設定的比率的時候﹐您可以管制入向頻寬及丟棄封包。比方說﹐可以保護您的主機抵禦 SYN flood 的攻擊﹐而且也可以用來降低 TCP/IP 速度﹐也就是以丟棄封包的方法來減速。

FIXME﹕除了丟棄之外﹐我們是否可以將之分配給一個真實的 queue 呢﹖

FIXME﹕以丟棄封包來進行管制似乎並非上上之舉﹐倒不如用 token 緩衝區過濾器。不敢莽斷啦﹐Cisco CAR 也都用這個﹐而且人們似乎也受之若然。

請參考本文最後面的 IOS Committed Access Rate 。

簡而言之﹕您可以用之來限制您電腦下載檔案有多快﹐而騰出更多頻寬給其它用途。

請參考 幫貴主機抵禦 SYN floods 那章﹐那裡有一個例子告訴您它是如何做到的。

10.6 DSMARK
本章由 Esteve Camps <esteve@hades.udg.es>; 撰寫。

簡介 (Introduction)
首先﹐再首先﹐您最好先到 IETF DiffServ working Group web site 和 Werner Almesberger web site(在 Linux 支援 Differentiated Services 的程式正是由他寫的) ﹐讀一讀 RFC 文件(RFC2474﹑RFC2475﹑RFC2597﹑以及 RFC259。

Dsmark 是蝦米哇哥﹖ (What is Dsmark related to?)
Dsmark 是一種佇列演算戒律(discipline)﹐主要用於 Differentiated Services (也稱為 DiffServ 或簡稱 DS)。DiffServ 是兩種 actual QoS 架構之一 (另外一個叫做 Intergrated Services)﹐主要依靠 IP 封包標頭中的 DS 欄位所攜帶的數值進行判斷。

最早在 IP 設計上所提供的 QoS 層級解決方案﹐其中之一就是 IP 標頭中的 Type of Service 欄位(TOS byte)。改變這些數值﹐我們可以選擇一個 高/低 等級的吞吐量﹑延遲﹑或是可靠度。但是這並不能提供足夠的靈活性﹐以滿足較新服務(如 real-time 應用程式﹑互動程式﹑和其它)的需求。有鑒於此﹐新的架構出現了。其一就是 DiffSserv﹐它會保留 TOS bits ﹐同時重新命名 DS 欄位。

DiffServ 指南 (Differentiated Services guidelines)
DiffServ 是以群組為導向的(group-oriented)。我是說﹐我們無須知道流向(flows)是如何運作的(這是 Intergrated Services 的事情)﹔我們只知道流向聚集(flow aggregations)﹐以及根據封包所屬的聚集如何應用不同的行為特性。

當封包抵達一個邊緣節點(即 DiffServ domain 的入口節點)﹐並進入 DiffSer Domain 的時候﹐我們就需要建立一些原則(policy)﹐引導 和/或 標識這些封包(所謂標識﹐就是設定 DS 欄位的數值)。然後 DiffSer Domain 的內部/核心節點就檢查這些標識/數值 ﹐以判定應用什麼樣的行為特性或 QoS 等級。

正如您所推斷的﹐DiffServ 意味著一個應用到所有 DS 規則的 domain。事實上﹐您可以這樣想像"我們會對所有進入 domain 的封包進行分類。一旦它們進入 domain﹐它們就逮屬於分類所指定的規則﹐並且每一個穿越節點都會應用這個 QoS 等級"。

實際而言﹐您可以在本地 domains 裡面應用您自定的原則﹐但是﹐當您連接到其它 DS domains 的時候﹐就需要顧及到某些 服務等級協議(Service Level Agreements) 。

至此﹐您或許滿腹疑團吧。DiffServ 遠比我所解釋的要複雜得多。事實上﹐您不難想像﹐我可沒那能耐將 3 個以上的 RFC 壓縮在短短 50 行裡面哦

運用 Dsmark (Working with Dsmark)
根據 DiffServ 學科所指定﹐我們要區別出邊界(boundary)節點和內部(interior)節點。在流量路徑上有兩個關鍵點﹐兩者在封包到達的時候均會進行分類。在封包真正送出網路之前﹐其結果會在 DS 處理過程中的不同地方使用到。這是因為 DiffServ 程式提供了一個稱為 sk_buff 的機制﹐包括一個新的欄位﹐稱為 skb->;tc_index﹐用來儲存初始分類的結果﹐用於 DS 處理中的不同目的。

該 skb->;tc_index 數值會被 DSMARK qdisc 用來做初始設定﹐從每一個接收封包的 IP 標頭之 DS 欄位就可以獲得。另外﹐cls_tcindex 分類器會讀取全部或部份的 skb->;tcindex 數值﹐用來選擇等級(classes)。

然而﹐首先﹐請參閱一下 DSMARK qdisc 命令以及它的參數﹕

... dsmark indices INDICES [ default_index DEFAULT_INDEX ] [ set_tc_index ]

這些參數究竟代表什麼呢﹖
indices: 表格體積 (mask, value)﹐一對使用。最大值為 2^n﹐且 n>;=0。
Default_index: 如果分類器找不到符合的比對﹐則使用預設表格項目索引。
Set_tc_index: 指示 dsmark discipline 讀取 DS 欄位並將之存放於 skb->;tc_index 上面。

然後讓我們看看 DSMARK 的運作。

SCH_DSMARK 是如何工作的 (How SCH_DSMARK works.)
此 qdisc 的步驟如下﹕﹕

如果我們已在 qdisc 命令中宣告 set_tc_index 選項﹐DS 欄位就會被讀取並存放於 skb->;tc_index 變數中。
呼叫分類器。分類器會被執行﹐並返回一個 class ID﹐存放於 skb->;tc_index 變數中。假如沒有發現匹配的過濾器﹐那麼將以 default_index 選項作為 classID ﹐作為存放。假如 set_tc_index 或 default_index 都沒有被宣告﹐那後果就實在難料了。
當送至內部 qdisc (您可以於此重複使用過濾結果)之後﹐從內部 qdisc 所返回的 classid 將被存放於 skb->;tc_index 之內。以後我們還可以用這個數值來檢索 mask-value 表格。該封包獲得的最終分配結果﹐則取決於下一個運算的結果﹕
New_Ds_field = ( Old_DS_field & mask ) | value

這樣﹐新的數值由後面這些元素產生﹕ "anding" 這個 DS 欄位﹑mask values﹑還有這個 "ORed" 結果﹑以及數值參數。請參考下面這個圖例﹐以更好理解這個處理過程﹕
                         skb->;ihp->;tos
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >;
     |                                                       |     ^
     | -- If you declare set_tc_index, we set DS             |     |  <-----May change
     |    value into skb->;tc_index variable                  |     |O       DS field
     |                                                      A|     |R
   +-|-+      +------+    +---+-+    Internal   +-+     +---N|-----|----+
   | | |      | tc   |--->;|   | |-->;  . . .  -->;| |     |   D|     |    |
   | | |----->;|index |--->;|   | |     Qdisc     | |---->;|    v     |    |
   | | |      |filter|--->;| | | +---------------+ |   ---->;(mask,value) |
-->;| O |      +------+    +-|-+--------------^----+  /  |  (.  ,  .)    |
   | | |          ^         |                |       |  |  (.  ,  .)    |
   | | +----------|---------|----------------|-------|--+  (.  ,  .)    |
   | | sch_dsmark |         |                |       |                  |
   +-|------------|---------|----------------|-------|------------------+
     |            |         | <- tc_index ->; |       |
     |            |(read)   |    may change  |       |  <--------------Index to the
     |            |         |                |       |                    (mask,value)
     v            |         v                v       |                    pairs table
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->;
                         skb->;tc_index


那如何做標識呢﹖只需修改您想重新標識的分類(class)之 mask 和 value 就可以了。請參考下一行程式﹕

tc class change dev eth0 classid 1:1 dsmark mask 0x3 value 0xb8
這會改變那對存於雜湊表格內的 mask 和 value ﹐並重新將封包標識為屬於 class 1:1 。您必須 "修改" 這個數值﹐因為預設的數值 (mask, value) 會獲得初始值(看後面的表格)。

現在﹐我們將解釋一下 TC_INDEX 過濾器是如何工作的﹐以及如何滿足它的需求。另外﹐TCINDEX 過濾器還可以用在其它設定上﹐並不只限於 DS 服務之中。

TC_INDEX 過濾器 (TC_INDEX Filter)
宣告一個 TC_INDEX 過濾器的基本命令如下﹕

... tcindex [ hash SIZE ] [ mask MASK ] [ shift SHIFT ]
            [ pass_on | fall_through ]
            [ classid CLASSID ] [ police POLICE_SPEC ]

這裡﹐我們沿用過往例子解釋 TC_INDEX 的運算模式。請特別留意標為粗體的文字﹕

tc qdisc add dev eth0 handle 1:0 root dsmark indices 64 set_tc_index
tc filter add dev eth0 parent 1:0 protocol ip prio 1 tcindex mask 0xfc shift 2
tc qdisc add dev eth0 parent 1:0 handle 2:0 cbq bandwidth 10Mbit cell 8 avpkt 1000 mpu 64
# EF traffic class
tc class add dev eth0 parent 2:0 classid 2:1 cbq bandwidth 10Mbit rate 1500Kbit avpkt 1000 prio 1 bounded isolated allot 1514 weight 1 maxburst 10
# Packet fifo qdisc for EF traffic
tc qdisc add dev eth0 parent 2:1 pfifo limit 5
tc filter add dev eth0 parent 2:0 protocol ip prio 1 handle 0x2e tcindex classid 2:1 pass_on


(這個程式尚不完整。它僅僅是取材於 iproute2 套件中的 EFCBQ 範例而已)。

首先﹐假設我們收到一個標識為 EF 的封包。如果您讀過 RFC2598﹐那您應該看到 EF 流量的 DSCP 建議值為 101110。這表示 DS 欄位將會是 10111000 (要知道 TOS byte 中的次重要位元並不會用於 DS 中)﹐或是以十六進位表示為 0xb8 。


              TC INDEX
              FILTER
   +---+      +-------+    +---+-+    +------+                +-+    +-------+
   |   |      |       |    |   | |    |FILTER|  +-+    +-+    | |    |       |
   |   |----->;| MASK  | ->; |   | | ->; |HANDLE|->;| |    | | ->; | | ->; |       |
   |   |  .   | =0xfc |    |   | |    |0x2E  |  | +----+ |    | |    |       |
   |   |  .   |       |    |   | |    +------+  +--------+    | |    |       |
   |   |  .   |       |    |   | |                            | |    |       |
-->;|   |  .   | SHIFT |    |   | |                            | |    |       |-->;
   |   |  .   | =2    |    |   | +----------------------------+ |    |       |
   |   |      |       |    |   |       CBQ 2:0                  |    |       |
   |   |      +-------+    +---+--------------------------------+    |       |
   |   |                                                             |       |
   |   +-------------------------------------------------------------+       |
   |                          DSMARK 1:0                                     |
   +-------------------------------------------------------------------------+


封包抵達之後﹐將 DS 欄位設定為 0xb8。正如我們前面所解釋的﹐例中的 dsmark qdisc 被鑒定為 id 1:0 ﹐讀取 DS 欄位﹐並存放於 skb->;tc_index 變數之內。例中的下一步﹐相當於該 qdisc 關聯的過濾器(例中第 2 行)。這將進行下一個運算﹕

Value1 = skb->;tc_index & MASK
Key = Value1 >;>; SHIFT


例中﹐MASK=0xFC i SHIFT=2。

Value1 = 10111000 & 11111100 = 10111000
Key = 10111000 >;>; 2 = 00101110 ->; 0x2E in hexadecimal


所返回的數值就是 qdisc 內部過濾器之 handle(本例中為 identifier 2:0)。假如找到這個 ID 的過濾器﹐原則和測量條件就獲得確認 (本例中的過濾器就包括這個)﹐同時會返回 classid(本例中為﹕classid 2:1)﹐並且存放於 skb->;tc_index 變數裡面。

不過﹐假如找到任何帶此 ID 的過濾器﹐其結果將取決於 fall_through 旗標的宣告。然則﹐返回的 classid 則以數值鍵值(value key)為準。否則﹐將返回一個錯誤﹐同時處理程序將繼續剩餘的過濾器。小心哦﹐如果您使用 fall_through 旗標的話﹐假如 skb->;tc_index 變數之數值和 class id 之間存在一個簡單的關聯﹐即可完成。

最後要註解的參數是 hash 和 pass_on。前者關乎雜湊表格的體積﹔而 pass_on 則指示﹕如果沒有發現與該過濾器結果相等的 classid﹐則嘗試下一個過濾器。預設動作為 fall_through (看下一個表格)

最後﹐讓我們看看有哪些可能的數值﹐是可以用來設定全部 TCINDEX 數值的﹕

TC Name                 Value           Default
-----------------------------------------------------------------
Hash                    1...0x10000     Implementation dependent
Mask                    0...0xffff      0xffff
Shift                   0...15          0
Fall through / Pass_on  Flag            Fall_through
Classid                 Major:minor     None
Police                  .....           None


此類過濾器實在非常厲害。它必須探勘所有的可能性。另外﹐這個過濾器不僅可以用在 DiffServ 設定中﹐還可以應用在其它種類的過濾器上面。

我建議您抽空看看 iproute2 套件中的所有 DiffServ 範例。我向各位保證﹐我將會竭盡全力儘快完成文字的部份。另外﹐我所作的解釋全都是許許多多測試的結果。

离线lsl3325009.
发帖
2008
C币
-235911
威望
401
贡献值
1
银元
-2
铜钱
4606
人人网人气币
0
只看该作者 6楼 发表于: 2010-04-13
Re:Linux的高级路由和流量控制_第5章
11. 其它資訊(Other information)
Esteve Camps Chust <marvin@grn.es>;
本文取材於我的論文"QoS Support in Linux", September 2000.


源文件﹕


Draft-almesberger-wajhak-diffserv-linux-01.txt。
iptoute2 套件中的範例。
White Paper-QoS protocols and architectures 和 IP QoS Frequently Asked Questions。兩者均屬於 Quality of Service Forum。

11.1 WRR
此一 qdisc 並不包括在標準的核心裡面﹐但可以從 這裡 下載。目前來說﹐此 qdisc 僅在 Linux 2.2 核心上面測試過﹐應該也可以在 2.4 核心工作的。

WWR qdisc 將頻寬以 weighted round robin 的形式分配給各類別。也就是﹐像 CBQ qdisc 那樣﹐它將類別(classes)包含在可插入的多樣化 qdiscs 中。所有類別均有足夠的請求能力獲得頻寬﹐再均衡的按比重分配給相關類別。比重通常可以用 tc 程式來設定。但是它們(比重)能夠自動的降低﹐以讓給進行大量數據傳送的類別使用。

此 qdisc 內建有一個分類器(classifier)﹐將來自或送往不同機器的封包分配至不同的類別裡去。無論 MAC 還是 IP﹑不管來源還是目的位址﹐都可以使用。不過﹐MAC 位址只能在這台 Linux 主機作為 ethernet bridge 的時候﹐才能使用。所有類別均自動的依據所見封包分配給不同的機器。

在那些諸如宿舍那樣的站台﹐存在為數眾多且又互不相干的個體分享同一 Internet 連線環境中﹐此 qdisc 簡直是靈丹妙藥。透過一套 script﹐為這樣一個站台設定出一個恰如其分的運轉狀態﹐正是 WRR 套件的精髓所在。

发帖
1996
C币
-235513
威望
378
贡献值
1
银元
-2
铜钱
4490
人人网人气币
0
只看该作者 7楼 发表于: 2010-04-13
Re:Linux的高级路由和流量控制_第5章
12. Netfilter 與 iproute - 封包標識 (Netfilter & iproute - marking packets)
到目前為止﹐我們已經見識過 iproute 的能耐了﹐而 netfilter 也曾數度提及。現在是要好好的看看 Rusty's Remarkably Unreliable Guides 的時候了。而 netfilter 的芳蹤﹐可以從 這裡 覓得。

Netfilter 可以讓我們過濾封包﹐或是修改它們的標頭(headers)。其中一絕是我們可以用號碼將封包標識起來﹐用 --set-mark 就可以做到。

舉個例子﹐下面的命令將所有送給 port 25 的封包標﹐也就是外送郵件﹐給識起來﹕


# iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 25 \
-j MARK --set-mark 1


讓我們假設有多條連線﹐其中一個比較快(當然每一 magabyte 也較貴)﹐而另一個比較慢﹐但使用固定價格。我們理所應當想把外送郵件走那個較便宜的 router 。

我們已經將封包標識為 '1' 了﹐現在就指引路由原則資料庫做如下事情﹕


# echo 201 mail.out >;>; /etc/iproute2/rt_tables
# ip rule add fwmark 1 table mail.out
# ip rule ls
0:      from all lookup local
32764:  from all fwmark        1 lookup mail.out
32766:  from all lookup main
32767:  from all lookup default


現在我們產生 mail.out 表格﹐將個路由指向較慢但也較便宜的線路﹕

# /sbin/ip route add default via 195.96.98.253 dev ppp0 table mail.out


大功告成﹗假如我們想要網開一面﹐有很多辦法可以做到的。我們可以修改 netfilter 的敘述﹐將某些特定主機豁免出來﹐或是為那些豁免主機插入一條規則﹐使用較低的優先值指向 main 表格。

我們還可以運用此一絕技來實踐 TOS 位元(bits)﹐只需將封包以不同數字標識為不同等服務類型﹐同時建立規則將之跑起來即可。用此辦法﹐我們甚至指定一條 ISDN 線路給互動連線呢。

值得一提的是﹐此法在 NAT('masquerading') 主機上也同具功效哦。

非常重要﹕我們收到一個報告指出 MASQ 和 SNAT 至少和封包標識會有所抵觸。Rusty Russel 已在如下網頁作過解釋﹕ this posting。請關閉逆向路徑過濾功能﹐以解決此一問題。

請留意﹕您需要將某些核心選項打開才行﹕


IP: advanced router (CONFIG_IP_ADVANCED_ROUTER) [Y/n/?]
IP: policy routing (CONFIG_IP_MULTIPLE_TABLES) [Y/n/?]
  IP: use netfilter MARK value as routing key (CONFIG_IP_ROUTE_FWMARK) [Y/n/?]


另外﹐還請看看 Cookbook 中的 Transparent web-caching

离线yonglin.
发帖
1999
C币
-235781
威望
348
贡献值
1
银元
0
铜钱
4371
人人网人气币
0
只看该作者 8楼 发表于: 2010-04-13
Re:Linux的高级路由和流量控制_第5章
13. 更多的分類器 (More classifiers)
分類器(classifier)就是核心用來決定封包需要送入哪一個佇列的方法。有許多形形色色的分類器﹐各司其職。


fw
根據防火牆如何標識封包來作判斷。

u32
根據封包裡面的欄位作判斷 (例如﹕來源 IP 位址﹐等)。

route
根據封包之路由作判斷。

rsvp, rsvp6
根據目標(目的位址﹐協定)﹐或以來源作判斷。

tcindex
FIXME﹕有待補充


請注意﹐大體上您有多種辦法來分類封包﹐但會降低系統之整體執行效能。

一般而言﹐分類器都能接受不同參數。為方便起見﹐茲列如下﹕


protocol
分類器所能接受的協定。通常您可能只會接受 IP 流量。必須指定。

parent
為分類器指定接管(handle)﹐只能是已經存在的類別(class)。必須指定。

prio
分類器的優先等級。數值越高越快。

handle
指定不同事物到不同的過濾器去。

FIXME﹕增加選項


下面的章節均假設您要將流量引導至 HostA ﹐還假設頂層(root)類別已經設定為 1﹕﹐同時您要將挑選出來的流量送至 1:1 去。

13.1 "fw" 分類器 (The "fw" classifier)
"fw" 分類器要依靠防火牆把需要引導的封包標識起來。所以﹐我們必須先設定好防火牆﹐為它們打標籤。


# iptables -I PREROUTING -t mangle -p tcp -d HostA \
-j MARK --set-mark 1


好了﹐所有傳給該主機的封包都被標識為 1。現在我們建立規則﹐以真正引導封包﹐我們只要指定好被標識為 1 的封包要送到類別 1:1 那邊去。透過如下命令就可以﹕


# tc filter add dev eth1 protocol ip parent 1:0 prio 1 handle 1 fw classid 1:1


命令本身應該說得蠻清楚的了。附在 1:0 類別的過濾器獲得的優先值為 1﹐過濾那些被防火牆標識為 1 的封包﹐再送到類別 1:1 那邊去。注意﹐這裡的 handle 要如何使用﹐取決於封包如何標識。

不經寒徹骨﹐哪得梅花香﹖這已是較為簡單的方法了﹐至於其它方法﹐我覺得更為難懂。注意﹐您可以完全將防火牆程式的功能應用在此分類器上面﹐包括比對 MAC 位址﹑用戶身份﹑以及所有其它防火牆所能比對的事物。

13.2 "u32" 分類器 (The "u32" classifier)
U32 過濾器是目前實作中所能找到的最強勁的過濾器。它完全依靠雜湊表(hashing tables)﹐配合眾多過濾規則而變得扎實耐用。

最簡單的做法是﹐U32 過濾器有一整列的記錄(records)﹐各自包含兩個欄位﹕選擇器(selector)和動作(action)。選擇器(後面會介紹)﹐會與當前處理的 IP 封包做比較﹐當碰到第一個符合的封包﹐然後就作出相應的動作。最簡單的動作﹐是將封包送至指定的 CBQ 類別去。

我們可用 tc filter 命令程式去設定過濾器﹐一共有 3 個部份﹕過濾器的規格(specification)﹑選擇器﹑以及動作。過濾器規則可以如下定義﹕


tc filter add dev IF [ protocol PROTO ]
                     [ (preference|priority) PRIO ]
                     [ parent CBQ ]


其中的 protocol 欄位說明過濾器所適用的協定﹐我們這裡只就 ip 協定進行討論。至於 preference(偏好值) 欄位(也可以用priority 來代替)﹐設定當前過濾器的優先值。這很重要﹐因為您或許會有好幾個過濾器(規則列表)﹐各自擁有不同的優先值。每一列規則按照規則新增順序通過﹐然後才處理低優先值(高偏好值)的規則列。最後的 parent 欄位定義出過濾器所屬的 CBQ 樹頂(如 1:0)。

以上選項均適用於所有過濾器﹐非 U32 獨美。

U32 選擇器 (U32 selector)
U32 選擇器包含式樣(pattern)定義﹐以比對當前處理的封包。它一絲不苟的定義出哪些封包標頭的位元(bits) 要用來比對﹐心無旁騖﹐然卻四兩撥千斤。不如讓我們看看以下範例﹐直接取自一個複雜且真實的過濾器﹕


# filter parent 1: protocol ip pref 10 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:3 \
  match 00100000/00ff0000 at 0


我們暫時不用管第一行 --- 全部參數度是用來描述過濾器之雜湊表而已。且讓我們仔細看看關於選擇器那一行﹐也就是帶 match 關鍵字的那行。選擇器會比對第 2 個 byte 為 0x10(0010) 的 IP 標頭。或許您已猜到﹐那個 00ff 數字就是比對遮罩(mask)。目前為 0xff﹐所以﹐這個 byte 只能是 0x10。然後 at 關鍵字意思是說﹐這個比對是從指定的 offset(以 bytes 算)開始 --- 在目前範例中﹐在封包的一開始處。換成我們的人類語言來說的話﹐如果封包的 Type of Serice 欄位帶有 `low delay` 位元設定﹐那這個比對就符合了。讓我們在看看另一個規則吧﹕


# filter parent 1: protocol ip pref 10 u32 fh 800::803 order 2051 key ht 800 bkt 0 flowid 1:3 \
  match 00000016/0000ffff at nexthdr+0


此處﹐有一個 nexthdr 選項﹐代表 IP 封包裡面的下一個標頭﹐例如上層協定的標頭。這個比對也是從下一個標頭的一開始處進行。比對應該出現在標頭首 32-bit 中的第二個字(word)。在 TCP 和 UDP 協定裡﹐此欄位包含封包目的端埠口(port)。此數字以 big-endian 格式顯示﹐例如 older 位元排前面﹐所以我們只要將 0x0016 換成十進位就是 22 了﹐換而言之﹐如果這是 TCP 的話﹐那他就是 SSH 服務。正如您所猜的﹐如果離開相關承接(我們後面再述)﹐這個比對會變得不明所以。

當我們對前述都有一定了解之後﹐就會發現如下這個選擇器其實蠻好理解的﹕match c0a80100/ffffff00 at 16 。我們只要從 IP 標頭開始﹐比對第 17 個 byte 起的 3 個 byte 即可。這會比對所有目的地為網路 192.168.1/24 的封包。看過這些範例之後﹐然後讓我們將所學的歸納一下吧。

通用選擇器 (General selectors)
通用選擇器定義出式樣(pattern)﹑遮罩(mask)﹑還有封包內容裡關於比對式樣的 offsest。使用通用選擇器﹐您實際上可以比對 IP (或上層) 標頭裡的每一個單獨的位元(bit) 。比較後面介紹的特定選擇器﹐它們更難讀寫。通用選擇器的語法如下﹕


match [ u32 | u16 | u8 ] PATTERN MASK [ at OFFSET | nexthdr+OFFSET]


u32﹑u16﹑或 u8 這些關鍵字﹐各自指定位元裡的式樣長度。PATTERN 和 MASK 必須接在前面關鍵詞定義的長度後面。至於 OFFSET 參數﹐則以 byte 為單位﹐指定開始比對的 offset 所在。如果 nexthdr+ 有設定﹐那麼 offset 則相對的從上層協定標頭開始算起。

範例﹕


# tc filter add dev ppp14 parent 1:0 prio 10 u32 \
     match u8 64 0xff at 8 \
     flowid 1:4


如果存活期(TTL)為 64 的話﹐封包就符合比對。從 IP 標頭數起﹐第 8 個 byte 開始就是 TTL 欄位了。


# tc filter add dev ppp14 parent 1:0 prio 10 u32 \
     match u8 0x10 0xff at nexthdr+13 \
     protocol tcp \
     flowid 1:3 \


此規則僅比對帶 ACK 位元設定的 TCP 封包。這裡我們可以看到一個範例中使用兩個選擇器﹐最終結果則將兩個結果用 AND 邏輯運算得出。如果我們仔細的看看 TCP 標頭結構圖﹐我們會發現 ACK 位元﹐是 TCP 標頭第 14 個 byte 算起(at nexthdr+13)第 2 個 older 位元(0x10)。至於第二個選擇器﹐如果我們想試試克難的方法﹐不指定選擇器使用 protocol tcp﹐可這樣寫﹕ match u8 0x06 0xff at 9﹐因為 TCP 的協定號碼是 6﹐位於 IP 標頭的第 10 個 byte。相對而言﹐在此範例中﹐我們不能用特定選擇器來做第一個比對 --- 這是因為沒有特定選擇器可以比對 TCP ACK 位於之故。

特定選擇器 (Specific selectors)
如下表格列出了本章作者所從 tc 程式中發現的全部特定選擇器。他們幫您省掉許多工作﹐同時讓您的過濾器設定更具可讀性。

FIXME: 表格存放位置 --- 存於另外的檔案﹕selector.html。

FIXME: 只有波蘭語

FIXME: 有待轉成 sgml 格式。

範例:


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


以上規則會比對那些 TOS 欄位設為 0x10 的封包。TOS 欄位從封包的第 2 個 byte 開始﹐並佔一個 byte 的長度﹐這樣好比我們另寫一個相等的通用選擇器﹕match u8 0x10 0xff at 1。由此﹐我們就可以一窺 U32 過濾器的內裡乾坤 --- 特定規則都會被轉換為通用規則﹐同時以此形式存於核心記憶體之內。舉一反三 --- tcp 和 udp 選擇器也是如法泡制﹐這也是為何您不能用單獨的 match tcp dst 53 0xffff 選擇器﹐來比對那些送給特定埠口(port) 的 TCP 封包 --- 它們也同時比對送至此埠口的 UDP 封包。另外﹐您不要忘了指定協定哦﹐並且最後產生如下規則﹕


# tc filter add dev ppp0 parent 1:0 prio 10 u32 \
        match tcp dst 53 0xffff \
        match ip protocol 0x6 0xff \
        flowid 1:2


13.3 "route" 分類器 (The "route" classifier)
此分類過濾器根據路由表格(routing tables)而定。當一個封包穿越分類(classes)抵達被標識為 "route" 的過濾器之後﹐它會按照路由表格的資訊分離(split)這個封包。


# tc filter add dev eth1 parent 1:0 protocol ip prio 100 route


這裡﹐我們新增一個 route 分類器給上游節點(parent node) 1:0 ﹐其優先值為 100。當封包抵達這個節點後(因為這是頂層(root) 分類﹐所以馬上生效)﹐它會查詢路由表格﹐並且﹐如果有一個比對符合的話﹐就把它送給指定的分類﹐同時賦予 100 的優先值。最後﹐您增加一個恰當的路由記錄﹐交由動作(action)處理﹕

這裡的訣竅是﹐要根據目的(destination)或來源(source)來定義一個所謂的 'realm' ﹐參考如下﹕


# ip route add Host/Network via Gateway dev Device realm RealmNumber


比方說﹐我們可以定義目的網路 192.168.10.0﹐它的 realm 號碼是 10﹕


# ip route add 192.168.10.0/24 via 192.168.10.1 dev eth1 realm 10


在增加 route 過濾器之後﹐我們可以使用 realm 號碼來代表網路或主機﹐同時指定路由如何配對(match)過濾器。


# tc filter add dev eth1 parent 1:0 protocol ip prio 100 \
  route to 10 classid 1:10


以上規則是說﹐送給網路 192.168.10.0 的封包﹐會配對 class id 1:10。

Route 過濾器還可以用來比對源路由(source routes)。例如﹐有一個子網接到 Linux router 的 eth2 界面﹕


# 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 (realm 2) 的封包﹐就配對 class id 1:2 。

13.4 "rsvp" 分類器 (The "rsvp" classifier)
FIXME: 有待補充

13.5 "tcindex" 分類器 (The "tcindex" classifier)

离线lele521.
发帖
2033
C币
-60461
威望
412
贡献值
1
银元
-1
铜钱
4633
人人网人气币
0
只看该作者 9楼 发表于: 2010-04-13
Re:Linux的高级路由和流量控制_第5章
14. 核心網路參數 (Kernel network parameters)
核心有很多參數可以調節﹐以適用於不同的狀況。通常﹐ 99% 的安裝﹐使用預設參數就可以了﹐不過﹐與其這樣的話﹐此稱為 Advanced 的 HOWTO 就浪得虛名了﹗

有空請看看 /proc/sys/net﹐或有意外收穫哦。只是﹐剛開始的時候﹐並非所有東西都會寫在這裡﹐我們盡力而為就是了。

14.1 逆向路徑過濾 (Reverse Path Filtering)
預設情況下﹐router 會路由所有東西﹐就算該封包‘顯然’不屬於貴網路的。常見的例子﹐莫過於將私有 IP 泄漏到 internet 上去。假如您有一個界面﹐其上設定的路由為 195.96.96.0/24﹐那您不會預期來自 212.64.94.1 的封包會到達這裡。

許多人都想關閉此一功能﹐因此核心設計者也打開了方便之門。在 /proc 裡面有些檔案﹐透過它們您可以讓核心為您做到這點。此方法被稱為 "逆向路徑過濾(Reverse Path Filtering)"。基本上﹐假如對此封包作出的回應﹐不是循其進入的界面送出去﹐那它就被視之為一個 bogus 封包﹐而被置之不理。


# for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
{  echo 2 >; $i
} done


我們用上面的例子來看看﹐如果一個封包從 eth1 到達 Linux router﹐自稱來自 Office+ISP 這個 subnet﹐那它就會被丟棄。同樣地﹐如果封包來自 Office 這個 subnet﹐卻自稱來自防火牆外部﹐那它也同樣會被丟棄。

上面是完全(full) 逆向路徑過濾。預設是只根據直接相連網路的 IP 進行過濾﹐這時因為完全過濾會打斷所謂的非對稱路(asymmetric routing)情形 (也就是﹐封包從一端進入﹐而從另一端出去﹐例如衛星流量傳送﹐或是您的網路使用動態 (bgp﹑ospf﹑rip)路由。資料從衛星接受碟下傳進來﹐而回應則從正常的專線送回去)。

假如您屬於這種例外(您應該心中有數)﹐那您可以簡單的在衛星數據進入的界面上關閉 rp_filter。如果您想要看看封包是否真的會被丟棄﹐那可以透過同一目錄的 log_martians 檔案﹐告訴核心將之記錄到 syslog 上面去。


# echo 1 >;/proc/sys/net/ipv4/conf/<interfacename>;/log_martians


FIXME: 不清楚設定 conf/{default,all}/* 下面的檔案是否足夠﹖ --- martijn

14.2 尚不明確的設定 (Obscure settings)
嗯﹐太多參數其實都可以修改啦。我們會試著將它們儘數羅列出來﹐而且(部份)會寫在Documentation/ip-sysctl.txt 中。

其中有些設定的預設值會有不同﹐看您在編譯核心的時候﹐是否以 'Yes' 來回答 'Configure as router and not host' 囉。

一般的 ipv4 (Generic ipv4)
請留意﹐大多數的速率(rate)限制功能都不適用於 loopback 之上﹐所以請勿在本機上進行測試。這個限制受制於所謂的 'jiffies' ﹐且它們硬性的只能使用前述的 token bucket filter。

核心有一個內部時鐘﹐每秒跑 'HZ' 跳(或曰 'jiffies' )。在 intel 上面﹐'HZ' 大概為 100 (譯者註﹕我猜這裡指所謂的 '內頻' 而言吧﹖新的主機板大都支援 133 這個速度)。比方說﹐設定一個 *_rate 檔案為 50 好了﹐則可每秒處理 2 個封包。而 token bucket filter 也可以被設定為﹐如果有足夠的 tokens 存儲的話﹐能讓每一個 burst (瞬增流量)可達 6 個封包。

如下列表中的一些項目﹐拷貝自 /usr/src/linux/Documentation/networking/ip-sysctl.txt﹐由 Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>; and Andi Kleen <ak@muc.de>; 所撰寫。


/proc/sys/net/ipv4/icmp_destunreach_rate
如果核心認為它不能傳送某一封包﹐則將之丟棄﹐同時向封包來源送出一個 ICMP 告知其結果。

/proc/sys/net/ipv4/icmp_echo_ignore_all
對所有封包均不作出 echo 。請勿將預設值設為啟動﹐除非您被利用為一個 DoS 工具的跳站﹐那或許有用。

/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts [Useful]
如果您 ping 網路的廣播位址﹐那所有主機都會做出回應﹐這將是一個非常便利的 dinal-of-servie 工具。將這裡設定為 1 則會忽略這些廣播訊息。

/proc/sys/net/ipv4/icmp_echoreply_rate
送出 echo 回應至任意目的端之速率

/proc/sys/net/ipv4/icmp_ignore_bogus_error_responses
設定它會忽略因網路主機對那些送至理解為廣播位址之框包作出抵抗而引起的 ICMP 錯誤。

/proc/sys/net/ipv4/icmp_paramprob_rate
一個相對未知的 ICMP 信息﹐其發送是因損毀的 IP 或 TCP 標頭封包而引發的。透過這個檔﹐您可以控制其發送的速率。

/proc/sys/net/ipv4/icmp_timeexceed_rate
這可以成為導致 traceroute 出現 '星星(* * *)' 的主因。這裡限制送出 ICMP Time Exceeded 訊息的數目。

/proc/sys/net/ipv4/igmp_max_memberships
主機上所傾聽的最大 igmp (multicast) socket 數量。
FIXME: 不知道是否真的?

/proc/sys/net/ipv4/inet_peer_gc_maxtime
FIXME: 增加一個關於 inet peer storage 之簡短說明?
廢物收集(garbage collection)通過的最長間隔。這個間隔會影響到 pool 中記憶體的低位(或缺少)壓力(pressure )。 以 jiffies 測量。

/proc/sys/net/ipv4/inet_peer_gc_mintime
廢物收集(GC)通過的最短間隔。這個間隔會影響到 pool 中記憶體的高位壓力。 以 jiffies 測量。

(譯者註﹕不清楚上面兩個解釋是否正確﹐因為原文中﹐作者均解釋為"Minimum interval between garbage collection passes"﹐我這裡私自將第一個改為“最長間隔”。)

/proc/sys/net/ipv4/inet_peer_maxttl
最高存活期項目。在此期限到達之後﹐如果沒有在 pool 上構成記憶體壓力的話(例如﹐pool 中的項目數目非常少)﹐不使用的項目將會逾時。以 jiffies 測量。

/proc/sys/net/ipv4/inet_peer_minttl
最低存活期項目。在重組端必須要有足夠的碎片(fragment)存活期。這個最低存活期必須保證 pool 體積是否少於 inet_peer_threshold。以 jiffies 測量。

/proc/sys/net/ipv4/inet_peer_threshold
INET peer storage 的適當體積。由此出發點開始的項目都會被強制拋棄。此出發點還判定項目的存活期﹐以及廢物收集通過的時間間隔。項目越多﹐存活期越低﹐GC 間隔越短。

/proc/sys/net/ipv4/ip_autoconfig
如果主機透過 RARP﹑BOOTP﹑DHCP﹑或類似方式獲得其 IP 設定﹐這檔會設為 1﹐否則為 0。

/proc/sys/net/ipv4/ip_default_ttl
封包的存活期。設為 64 應是安全的。如果您的網路超大的﹐那就提昇此值。千萬不要隨便亂玩 --- 如遇到路由迴圈(routing loop)將導致更嚴重的災難。在某些情形之下﹐您甚至會降低此值。

/proc/sys/net/ipv4/ip_dynaddr
假如您要用動態界面位址做 dial-on-demand ﹐那就設定它。一旦您的請求界面起來之後﹐所有看不到回應的本地 TCP socket 都會重新捆綁(rebound)﹐以獲得正確的位址。假如遇到啟動界面的連線自己不工作﹐但再試一次卻又可以的情形﹐設定這個可解決這個問題。

/proc/sys/net/ipv4/ip_forward
是否要核心傳送封包。預設是關閉的。

/proc/sys/net/ipv4/ip_local_port_range
對外連線時所使用的本地埠口範圍。預設值事實上蠻小的﹕1024 到 4999。

/proc/sys/net/ipv4/ip_no_pmtu_disc
如果您要關閉 Path MTU discovery --- 一種在路徑上判定可接受的最大傳送單位(Maximum Transfer Unit)數值的技術﹐那就設定這裡。

/proc/sys/net/ipv4/ipfrag_high_thresh
IP 碎片重組所需的最大記憶體。當記憶體的 ipfrag_high_thresh bytes 因此目的獲得分配之後﹐碎片處理程序會擱置封包﹐直到達到 ipfrag_low_thresh 為止。

/proc/sys/net/ipv4/ip_nonlocal_bind
如果您想讓應用程式能夠捆綁到一個不屬於該系統的位址﹐就需要設定這裡。當機器使用非固定(或是動態)線路的時候﹐這功能就很有用了﹐因而﹐當您的線路斷掉之後﹐您的服務仍可啟動而且捆綁到特定的位址之上。

/proc/sys/net/ipv4/ipfrag_low_thresh
IP 碎片重組所需的最小記憶體。

/proc/sys/net/ipv4/ipfrag_time
IP 碎片保留在記憶體中的秒數。

/proc/sys/net/ipv4/tcp_abort_on_overflow
一個 boolean 旗標﹐處於大量進入連線的時候控制其行為特性。當打開之後﹐會讓核心在服務出現超載的時候主動送出 RST 封包。

/proc/sys/net/ipv4/tcp_fin_timeout
如果 socket 是有我們這端結束的﹐socket 保持 FIN-WAIT-2 狀態的時間。連線端或會掛斷且不會從它那端結束﹐或是甚至意外終結(died)。預設值為 60 秒。過去在 2.2 核心中是 180 秒﹐您可以復原它﹐但請記住﹐如果您的機器為一台盈負載(underloaded) 網頁伺服器﹐您可能要冒著記憶體被大量死亡封包填滿的風險﹐FIN-WAIT-2 sockets 的危險性低於 FIN-WAIT-1 ﹐因為它們最多只吃 1.5K 的記憶體﹐但是它們存在時間更長。另外參考 tcp_max_orphans。

/proc/sys/net/ipv4/tcp_keepalive_time
當 keepalive 打開之後﹐TCP 要多久送出 keepalive 信息。
預設為 2 小時。

/proc/sys/net/ipv4/tcp_keepalive_intvl
當一個探測(probe)沒有獲得確認之後﹐隔多久要被重送。
預設是 75 秒。

/proc/sys/net/ipv4/tcp_keepalive_probes
在決定掛斷連線之前﹐要送出多少個 keepalive 探測。
預設值為﹕9 。
再乘上 tcp_keepalive_intvl﹐就是在一條線路在送出 keepalive 之後﹐所允許的不回應時間。

/proc/sys/net/ipv4/tcp_max_orphans
對於那些沒有附屬於任何使用者檔案 handle 的 TCP sockets﹐系統所能處理的最大數量。假如超過這個數量﹐那麼這些無人看管的連線將會被立即重設(reset)﹐並同時顯示警告信息。之所以要設定這個限制﹐純粹為了抵禦那些簡單的 DoS 攻擊﹐千萬不要依賴這個或是人為的降低這個限制﹐不過﹐如果網路條件需要比預設值更多﹐而且調整網路服務獲得拖延並強制性砍掉這類狀態﹐則可以提高它(或許還要增加記憶體)。再提醒一次﹕每一個這樣的 orphan 都會吃掉  64K 不能置換的記憶體。

/proc/sys/net/ipv4/tcp_orphan_retries
在我們這端砍掉 TCP 連線之前﹐要進行多少次重試。預設是 7 個﹐相當於  50秒 - 16分鐘﹐視 RTO 而定。如果您機器為負載(loaded)網頁伺服器﹐您或許會打算降低這個數值﹐這類 sockets 可能會耗費大量的資源。另外參考 tcp_max_orphans 。

/proc/sys/net/ipv4/tcp_max_syn_backlog
對於那些依然還未獲得客戶端確認的連線請求﹐需要記憶的最大數目。對於超過 128Mb 記憶體的系統﹐預設值是 1024 ﹐低於 128Mb 的則為 128。如果伺服器經常出現過載﹐可以嘗試增加這個數字。警告﹗假如您將此值設為大於 1024﹐最好修改 include/net/tcp.h 裡面的 TCP_SYNQ_HSIZE ﹐以保持 TCP_SYNQ_HSIZE*16<=tcp_max_syn_backlog ﹐並且編進核心之內。

/proc/sys/net/ipv4/tcp_max_tw_buckets
系統在同一時間內所處理的最大 timewait sockets 數目。如果超過此數字的話﹐time-wait socket 會被立即砍除並且顯示警告信息。之所以要設定這個限制﹐純粹為了抵禦那些簡單的 DoS 攻擊﹐千萬不要人為的降低這個限制﹐不過﹐如果網路條件需要比預設值更多﹐則可以提高它(或許還要增加記憶體)。

/proc/sys/net/ipv4/tcp_retrans_collapse
針對某些損壞印表機的 bug-to-bug 兼容性。於重傳上嘗試送出更大的封包﹐以解決特定 TCP 堆疊中的臭蟲。

/proc/sys/net/ipv4/tcp_retries1
當某些事情不對勁而必須向網路層報告這個可疑狀況之前﹐需要進行多少次重試。最低的 RFC 數值是 3 ﹐這也是預設值﹐相當於  3秒 - 8分鐘﹐視 RTO 而定。

/proc/sys/net/ipv4/tcp_retries2
在砍掉存活 TCP 連線之前﹐需要進行多少次重試。RFC1122 裡面說﹐這個限制必須大於 100秒。此數字非常小。預設值為 15 ﹐相當於  13-30分鐘﹐視 RTO 而定。

/proc/sys/net/ipv4/tcp_rfc1337
這個 boolean 會啟動關於 'time-wait assassination hazards in tcp' 的修正﹐請參考 RFC 1337。如果被打開﹐會讓核心丟棄那些處於 time-wait 狀態 sockets 之 RST 封包。
預設為 0 。

/proc/sys/net/ipv4/tcp_sack
使用 Selective ACK﹐它可以用來找出特定的遺失封包 --- 因而有助於迅速復原。

/proc/sys/net/ipv4/tcp_stdurg
使用 TCP urg pointer 欄位中的主機請求詮釋功能。
大部份的主機都使用老舊的 BSD 詮釋﹐因而﹐如果您在 Linux 打開它﹐或會導致不能和它們正確溝通。
預設為﹕FALSE

/proc/sys/net/ipv4/tcp_syn_retries
對於一個新建連線﹐核心要送多少個 SYN 封包數才決定放棄。

/proc/sys/net/ipv4/tcp_synack_retries
為了與另一端建立連線﹐核心會連同 SYN 一起送出 ACK ﹐以確認收到上一個 SYN。這是所謂的三段交握( threeway handshake) 的第二個步驟。這裡決定核心在放棄連線之前所送出的 SYN+ACK 數目。

/proc/sys/net/ipv4/tcp_timestamps
Timestamps 用在其它一些東西中﹐可以防範那些偽造的 sequence 號碼。一條 1 gigabit 的線路或許會重遇到帶 out-of-line 數值的舊 sequence 號碼(假如它是由於上次產生的)。Timestamp 會讓它知道這是個 '舊封包'。

/proc/sys/net/ipv4/tcp_tw_recycle
啟動快速 TIME-WAIT sockets 回收。預設值是 1 。除非得到技術專家的建議或要求﹐請不要修改這個值。

/proc/sys/net/ipv4/tcp_window_scaling
正常來說﹐TCP/IP 可以接受大至 65535 byte 的 windows。對於高速網路﹐這或許還是不夠的。這個 windows scaling 選項則允許接近 gigabyte 的 windows﹐這將有助改善高頻寬延遲產品。


逐個設備設定 (Per device settings)
DEV 可以只代表一個真實界面﹐也可以是 '全部' 或 '預設值'。而預設值也或許會改變建立的界面設定。

/proc/sys/net/ipv4/conf/DEV/accept_redirects
如果 router 認為您在不適當的使用它(ie﹐需要在同一界面上重送封包)﹐那它就會送出一個 ICMP Redirect。這或許會造成輕度的安全風險﹐所以您最好關閉它﹐或是使用 secure redirects。

/proc/sys/net/ipv4/conf/DEV/accept_source_route
此功能並不常用。過去﹐您可以給出一個 IP 位址列表﹐讓它提供此功能。Linux 也可以實踐這個 IP 選項。

/proc/sys/net/ipv4/conf/DEV/bootp_relay
FIXME: 有待補充

/proc/sys/net/ipv4/conf/DEV/forwarding
FIXME: 有待補充

/proc/sys/net/ipv4/conf/DEV/log_martians
請參考逆向路徑過濾章節。

/proc/sys/net/ipv4/conf/DEV/mc_forwarding
是否在該界面上進行 multicast forwarding。

/proc/sys/net/ipv4/conf/DEV/proxy_arp
如果設為 1﹐那麼所有其它界面都會回應以此界面為目的之 arp 請求。當架設 'ip pseudo bridges' 時相當有用。啟用此功能之前﹐請確定您的 netmasks 要非常正確。

/proc/sys/net/ipv4/conf/DEV/rp_filter
請參考逆向路徑過濾章節。

/proc/sys/net/ipv4/conf/DEV/secure_redirects
FIXME: 有待補充

/proc/sys/net/ipv4/conf/DEV/send_redirects
是否要送出前面提到的 redirects。

/proc/sys/net/ipv4/conf/DEV/shared_media
FIXME: 有待補充

/proc/sys/net/ipv4/conf/DEV/tag
FIXME: 有待補充


鄰接原則 (Neighbor pollicy)
DEV 可以只代表一個真實界面﹐也可以是 '全部' 或 '預設值'。而預設值也或許會改變建立的界面設定。

/proc/sys/net/ipv4/neigh/DEV/anycast_delay
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/app_solicit
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/base_reachable_time
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/delay_first_probe_time
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/gc_stale_time
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/locktime
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/mcast_solicit
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/proxy_delay
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/proxy_qlen
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/retrans_time
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/ucast_solicit
FIXME: 有待補充

/proc/sys/net/ipv4/neigh/DEV/unres_qlen
FIXME: 有待補充


路由設定 (Routing settings)

/proc/sys/net/ipv4/route/error_burst
FIXME: 有待補充

/proc/sys/net/ipv4/route/error_cost
FIXME: 有待補充

/proc/sys/net/ipv4/route/flush
FIXME: 有待補充

/proc/sys/net/ipv4/route/gc_elasticity
FIXME: 有待補充

/proc/sys/net/ipv4/route/gc_interval
FIXME: 有待補充

/proc/sys/net/ipv4/route/gc_min_interval
FIXME: 有待補充

/proc/sys/net/ipv4/route/gc_thresh
FIXME: 有待補充

/proc/sys/net/ipv4/route/gc_timeout
FIXME: 有待補充

/proc/sys/net/ipv4/route/max_delay
FIXME: 有待補充

/proc/sys/net/ipv4/route/max_size
FIXME: 有待補充

/proc/sys/net/ipv4/route/min_adv_mss
FIXME: 有待補充

/proc/sys/net/ipv4/route/min_delay
FIXME: 有待補充

/proc/sys/net/ipv4/route/min_pmtu
FIXME: 有待補充

/proc/sys/net/ipv4/route/mtu_expires
FIXME: 有待補充

/proc/sys/net/ipv4/route/redirect_load
FIXME: 有待補充

/proc/sys/net/ipv4/route/redirect_number
FIXME: 有待補充

/proc/sys/net/ipv4/route/redirect_silence
FIXME: 有待補充
快速回复
限100 字节
如果您在写长篇帖子又不马上发表,建议存为草稿
 
上一个 下一个