模擬兩台 ubuntu 伺服器機器之間的慢速連接
我想模擬以下場景:假設我有 4 台 ubuntu 伺服器機器 A、B、C 和 D。我想將機器 A 和機器 C 之間的網路頻寬減少 20%,將 A 和 B 之間的網路頻寬減少 10%。如何使用網路模擬/節流工具來做到這一點?
為此,您可以
tc
單獨使用u32
過濾器或與iptables 標記結合使用(如果您不想學習複雜的過濾器語法,可能會更直接)。我將在下面的文章中詳細介紹前一種解決方案。模擬您的設置
例如,讓我們考慮執行 10 Mbit/s虛擬介面的 A、B、C 和 D。
你基本上想要:
- A <==> B : 9 Mbit/s出口整形
- A <==> C : 8 Mbit/s出口整形
為了模擬這一點,我將創建 4 個網路命名空間和插入網橋的虛擬乙太網介面。
當然,在您的情況下,您將使用真正的 NIC,而網橋將成為您的網關或交換機,具體取決於您的基礎架構。
因此,在我的模擬中,我們將在 10.0.0.0/24 網路中進行以下設置:
10.0.0.254 +-------+ | | | br0 | | | +---+---+ | | veth{A..D}.peer | +------------+------+-----+------------+ | | | | vethA | vethB | vethC | vethD | +---+---+ +---+---+ +---+---+ +---+---+ | | | | | | | | | A | | B | | C | | D | | | | | | | | | +-------+ +-------+ +-------+ +-------+ 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4
首先,設置階段,以便您了解它的構成,如果您不熟悉它,請跳過它,沒什麼大不了的。然而,您必須知道的是,該命令
ip netns exec <namespace> <command>
允許在網路命名空間中執行命令(即,在上一次繪製的方框之一中)。這也將在下一節中使用。# Create the bridge ip link add br0 type bridge # Create network namespaces and veth interfaces and plug them into the bridge for host in {A..D} ; do ip link netns add ${host} ip link add veth${host} type veth peer name veth${host}.peer ip link set dev veth${host}.peer master br0 ip link set dev veth${host} netns ${host} ip netns exec ${host} ip link set veth${host} up done # Assign IPs ip addr add 10.0.0.254/24 dev br0 ip netns exec A ip addr add 10.0.0.1/24 dev vethA ip netns exec B ip addr add 10.0.0.2/24 dev vethB ip netns exec C ip addr add 10.0.0.3/24 dev vethC ip netns exec D ip addr add 10.0.0.4/24 dev vethD
所以此時我們已經有了前面描述的設置。
塑造流量
是時候進入交通管制以獲得你想要的了。該
tc
工具允許您添加排隊規則:
- 對於 egress :一旦核心需要發送數據包並且在訪問 NIC 驅動程序之前。
- 對於入口:在訪問 NIC 驅動程序之後,核心常式在接收到的數據包上執行之前。
它帶有 3 個概念:qdisc、類和過濾器。這些概念可用於設置複雜的數據包流管理,並根據您想要的任何標準/標準對流量進行優先級排序。
簡而言之 :
- Qdiscs 是數據包最終將入隊/出隊的結構。
- 類是具有特定行為的 qdisc 的容器。
- 過濾器是在類之間路由數據包的方法,在處理過程中可以在同一個入口點上定義多個過濾器,並具有優先級。
所有這些通常作為一棵樹,其中葉子是 qdisc,類是節點。樹或子樹的根將被聲明為
<id>:
,子節點將被聲明為<parent_id>:<children_id>
。請記住此語法。對於您的情況,讓我們採用 A 並渲染您想要設置的樹
tc
:1: | | | 1:1 / | \ / | \ / | \ 1:10 1:20 1:30 | | | | | | :10 :20 :30
解釋 :
1:
是附加到設備 vethA 的根 qdisc,它將被明確地htb
用於 Hierarchy Token Bucket(設備的預設 qdisc 是pfifo
或pfifo_fast
取決於作業系統)。它特別適用於頻寬管理。與此級別定義的過濾器不匹配的數據包將被1:30
分類。1:1
將是一個htb
將設備的整個流量限制為 10 Mbit/s 的類。1:10
將是一個htb
將輸出流量限制為 9 Mbit/s(10 Mbit/s 的 90%)的類。1:20
將htb
輸出流量限制為 8 Mbit/s(10 Mbit/s 的 80%)的類。1:30
將是一個htb
將流量限制為 10 Mbit/s(回退)的類。:10, :20, :30
是sfq
隨機公平隊列的 qdisc。換句話說,這些 qdisc 將確保基於流的傳輸調度的公平性。整個事情是通過以下命令設置的:
ip netns exec A tc qdisc add dev vethA root handle 1: htb default 30 ip netns exec A tc class add dev vethA parent 1: classid 1:1 htb rate 10mbit burst 15k ip netns exec A tc class add dev vethA parent 1:1 classid 1:10 htb rate 9mbit burst 15k ip netns exec A tc class add dev vethA parent 1:1 classid 1:20 htb rate 8mbit burst 15k ip netns exec A tc class add dev vethA parent 1:1 classid 1:30 htb rate 10mbit burst 15k ip netns exec A tc qdsic add dev vethA parent 1:10 handle 10: sfq perturb 10 ip netns exec A tc qdisc add dev vethA parent 1:20 handle 20: sfq perturb 10 ip netns exec A tc qdisc add dev vethA parent 1:30 handle 30: sfq perturb 10
我們需要的最後一件事是添加過濾器,以便目標 IP 等於 B 的
1:10
IP 數據包進入類別,而目標 IP 等於 C 的 IP 數據包將進入1:20
類別:ip netns exec A tc filter add dev vethA parent 1: protocol ip prio 1 u32 match ip dst 10.0.0.2/32 flowid 1:10 ip netns exec A tc filter add dev vethA parent 1: protocol ip prio 2 u32 match ip dst 10.0.0.3/32 flowid 1:20
現在你明白了,你需要向
tc
B 和 C 添加類似的規則,這樣從這些鑽機到 A 的傳輸也被塑造了。測試
現在讓我們測試一下。為此,我個人習慣使用
iperf
它,它只包含一個二進製文件,可以作為客戶端或伺服器執行,並且會在兩個主機之間自動發送盡可能多的流量。在 A 和 B 之間:
$ ip netns exec B iperf -s -p 8001 ... $ ip netns exec A iperf -c 10.0.0.2 -p 8001 -t 10 -i 2 ------------------------------------------------------------ Client connecting to 10.0.0.2, TCP port 8001 TCP window size: 21.0 KByte (default) ------------------------------------------------------------ [ 5] local 10.0.0.1 port 58191 connected with 10.0.0.2 port 8001 [ ID] Interval Transfer Bandwidth [ 5] 0.0- 2.0 sec 2.38 MBytes 9.96 Mbits/sec [ 5] 2.0- 4.0 sec 2.12 MBytes 8.91 Mbits/sec [ 5] 4.0- 6.0 sec 2.00 MBytes 8.39 Mbits/sec [ 5] 6.0- 8.0 sec 2.12 MBytes 8.91 Mbits/sec [ 5] 8.0-10.0 sec 2.00 MBytes 8.39 Mbits/sec [ 5] 0.0-10.1 sec 10.8 MBytes 8.91 Mbits/sec
我們得到了9 Mbit/s 的頻寬限制。
在 A 和 C 之間:
$ ip netns exec C iperf -s -p 8001 ... $ ip netns exec A iperf -c 10.0.0.3 -p 8001 -t 10 -i 2 ------------------------------------------------------------ Client connecting to 10.0.0.3, TCP port 8001 TCP window size: 21.0 KByte (default) ------------------------------------------------------------ [ 5] local 10.0.0.1 port 58522 connected with 10.0.0.3 port 8001 [ ID] Interval Transfer Bandwidth [ 5] 0.0- 2.0 sec 2.25 MBytes 9.44 Mbits/sec [ 5] 2.0- 4.0 sec 1.75 MBytes 7.34 Mbits/sec [ 5] 4.0- 6.0 sec 1.88 MBytes 7.86 Mbits/sec [ 5] 6.0- 8.0 sec 1.88 MBytes 7.86 Mbits/sec [ 5] 8.0-10.0 sec 1.75 MBytes 7.34 Mbits/sec [ 5] 0.0-10.1 sec 9.62 MBytes 7.98 Mbits/sec
我們得到了8 Mbit/s 的頻寬限制。
在 A 和 D 之間:
$ ip netns exec D iperf -s -p 8001 ... $ ip netns exec A iperf -c 10.0.0.4 -p 8001 -t 10 -i 2 ------------------------------------------------------------ Client connecting to 10.0.0.4, TCP port 8001 TCP window size: 21.0 KByte (default) ------------------------------------------------------------ [ 5] local 10.0.0.1 port 40614 connected with 10.0.0.4 port 8001 [ ID] Interval Transfer Bandwidth [ 5] 0.0- 2.0 sec 2.62 MBytes 11.0 Mbits/sec [ 5] 2.0- 4.0 sec 2.25 MBytes 9.44 Mbits/sec [ 5] 4.0- 6.0 sec 2.38 MBytes 9.96 Mbits/sec [ 5] 6.0- 8.0 sec 2.25 MBytes 9.44 Mbits/sec [ 5] 8.0-10.0 sec 2.38 MBytes 9.96 Mbits/sec [ 5] 0.0-10.2 sec 12.0 MBytes 9.89 Mbits/sec
在這裡,我們達到了10 Mbit/s的虛擬介面全速。
請注意,
htb
通過調整適當的參數,可以在類中更好地處理每次執行的第一個測量的突發。打掃乾淨
去除 :
- 優先級為 1 的過濾器在
1:
:上tc filter del dev vethA parent 1: prio 1 u32
。- 所有過濾器
1:
:tc filter del dev vethA parent 1:
。- 班級
1:20
及其孩子:tc class del dev vethA parent 1:1 classid 1:20
。- 整棵樹:
tc qdisc del dev vethA
。清理模擬集:
# Remove veth pairs and network namespaces for host in {A..D} ; do ip link del dev veth${host}.peer ip netns del ${host} done # Remove the bridge ip link del dev br0