Để làm điều này, bạn có thể sử dụng tc
một mình với u32
các bộ lọc hoặc kết hợp với đánh dấu iptables (có thể đơn giản hơn nếu bạn không muốn tìm hiểu cú pháp bộ lọc phức tạp). Tôi sẽ trong bài viết sau đây chi tiết các giải pháp trước đây.
Mô phỏng thiết lập của bạn
Ví dụ, hãy xem xét A, B, C và D chạy các giao diện ảo 10 Mbit / s .
Về cơ bản bạn muốn:
- A <==> B: 9 Mbit / s định hình cho đi ra
- A <==> C: 8 Mbit / s định hình cho đi ra
Để mô phỏng điều này, tôi sẽ tạo 4 không gian tên mạng và giao diện ethernet ảo được cắm vào một cây cầu.
Tất nhiên, trong trường hợp của bạn, bạn sẽ làm việc với các NIC thực và cây cầu sẽ là cổng hoặc công tắc tùy thuộc vào cơ sở hạ tầng của bạn.
Vì vậy, trong mô phỏng của tôi, chúng tôi sẽ có thiết lập sau, trong mạng 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
Đầu tiên, hệ thống thiết lập để bạn có thể hiểu nó được làm từ gì, bỏ qua nếu bạn không quen với nó, không có vấn đề gì lớn. Tuy nhiên, điều bạn phải biết là lệnh ip netns exec <namespace> <command>
cho phép thực thi một lệnh trong không gian tên mạng (tức là trong một trong các ô của lần rút trước đó). Điều này cũng sẽ được sử dụng trong phần tiếp theo.
# 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
Vì vậy, tại thời điểm này chúng tôi có các thiết lập được mô tả trước đây.
Định hình giao thông
Đã đến lúc kiểm soát giao thông để có được những gì bạn muốn. Công tc
cụ cho phép bạn thêm các quy tắc xếp hàng:
- Đối với đầu ra: một khi kernel cần gửi các gói và trước khi truy cập trình điều khiển NIC.
- Đối với xâm nhập: sau khi truy cập trình điều khiển NIC và trước các thường trình kernel được chạy qua các gói nhận được.
Nó đi kèm với 3 khái niệm: qdisc , các lớp và bộ lọc . Những khái niệm này có thể được sử dụng để thiết lập quản lý luồng gói phức tạp và ưu tiên lưu lượng dựa trên bất kỳ tiêu chí / tiêu chí nào bạn muốn.
Tóm lại:
- Qdiscs là các cấu trúc trong đó các gói sẽ thực sự được xử lý / loại bỏ.
- Các lớp là các thùng chứa cho qdiscs hành động với các hành vi cụ thể.
- Bộ lọc là cách để định tuyến các gói giữa các lớp, nhiều trong số chúng có thể được xác định trên cùng một điểm nhập với các ưu tiên trong quá trình xử lý.
Tất cả những thứ này thường hoạt động như một cái cây trong đó lá là qdiscs và các lớp là các nút. Các gốc của cây hoặc cây con sẽ được khai báo là <id>:
và các nút con sẽ được khai báo là <parent_id>:<children_id>
. Hãy ghi nhớ cú pháp này.
Đối với trường hợp của bạn, hãy lấy A và kết xuất cây bạn muốn thiết lập tc
:
1:
|
|
|
1:1
/ | \
/ | \
/ | \
1:10 1:20 1:30
| | |
| | |
:10 :20 :30
Giải trình :
1:
là qdisc gốc được gắn vào thiết bị vethA, nó sẽ được lấy một cách rõ ràng như htb
đối với Phân cấp mã thông báo phân cấp (qdisc mặc định của thiết bị là pfifo
hoặc pfifo_fast
tùy thuộc vào HĐH). Nó đặc biệt thích hợp để quản lý bandwith. Các gói không khớp với các bộ lọc được xác định ở cấp độ này sẽ đến 1:30
lớp.
1:1
sẽ là một htb
lớp giới hạn toàn bộ lưu lượng của thiết bị ở mức 10 Mbit / s.
1:10
sẽ là một htb
lớp giới hạn lưu lượng đầu ra ở mức 9 Mbit / s (90% của 10 Mbit / s).
1:20
sẽ là một htb
lớp giới hạn lưu lượng đầu ra ở mức 8 Mbit / s (80% của 10 Mbit / s).
1:30
sẽ là một htb
lớp giới hạn lưu lượng đến 10 Mbit / s (dự phòng).
:10, :20, :30
là sfq
qdisc cho xếp hàng công bằng Stochastic. Nói cách khác, các qdiscs này sẽ đảm bảo sự công bằng trong lịch trình truyền phát dựa trên các luồng.
Toàn bộ điều này được thiết lập bởi các lệnh sau:
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
Điều cuối cùng chúng ta cần là thêm các bộ lọc để các gói IP có IP đích bằng B sẽ chuyển đến 1:10
lớp và các gói IP có IP đích bằng C sẽ đến 1:20
lớp:
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
Bây giờ bạn đã có ý tưởng, bạn sẽ cần thêm các tc
quy tắc tương tự vào B và C để việc truyền tới A từ các giàn khoan này cũng được định hình.
Kiểm tra
Bây giờ hãy kiểm tra nó. Đối với điều này, cá nhân tôi thường sử dụng để chơi iperf
, nó chỉ bao gồm một nhị phân duy nhất có thể chạy như một máy khách hoặc máy chủ và sẽ tự động gửi càng nhiều lưu lượng càng tốt giữa cả hai máy chủ.
Giữa A và 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
Chúng tôi nhận giới hạn băng thông 9 Mbit / s .
Giữa A và 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
Chúng tôi nhận được giới hạn băng thông 8 Mbit / s của chúng tôi .
Giữa A và 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
Ở đây chúng tôi có giao diện ảo tốc độ tối đa 10 Mbit / s đạt được.
Lưu ý rằng sự bùng nổ của số đo đầu tiên của mỗi lần chạy có thể được xử lý tốt hơn trong htb
các lớp bằng cách điều chỉnh tham số thích hợp.
Dọn dẹp
Để xóa:
- Bộ lọc ưu tiên 1 trên
1:
: tc filter del dev vethA parent 1: prio 1 u32
.
- Tất cả các bộ lọc trên
1:
: tc filter del dev vethA parent 1:
.
- Lớp
1:20
và con của nó : tc class del dev vethA parent 1:1 classid
1:20
.
- Toàn cây :
tc qdisc del dev vethA
.
Để dọn dẹp bộ mô phỏng:
# 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