Для цього ви можете використовувати tc
окремо з u32
фільтрами або поєднувати їх із позначенням iptables (можливо, простіше, якщо ви не хочете вивчати синтаксис складних фільтрів). Я розповім у наступному дописі про колишнє рішення.
Моделювання налаштувань
Як приклад, розглянемо A, B, C і D з віртуальними інтерфейсами 10 Мбіт / с .
Ви в основному хочете:
- A <==> B: 9 Мбіт / с формуючи для виходу
- A <==> C: 8 Мбіт / с, формуючи для виходу
Для того, щоб імітувати це, я створити 4 простори мережі імен та віртуальний інтерфейс Ethernet, підключений до мосту.
Звичайно, у вашому випадку ви будете працювати з справжніми 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
Інструмент дозволяє додавати організації черг:
- Для виходу: раз ядро має надіслати пакети та перш ніж отримати доступ до драйвера NIC.
- Для вступу: після доступу до драйвера NIC та перед запуском процедур ядра над отриманими пакетами.
Він поставляється з 3 поняттями: qdisc , класи та фільтри . Ці поняття можна використовувати для налаштування складного управління потоком пакетів та пріоритетного трафіку на основі будь-якого критерію / критеріїв, які ви хочете.
Коротко :
- Qdiscs - це структури, в яких пакети будуть заздалегідь залучатися / відмінятися.
- Заняття є контейнерами для qdiscs, що діють із певною поведінкою.
- Фільтри - це способи маршрутизації пакетів між класами, декілька з них можна визначити в одній точці входу з пріоритетами під час обробки.
Все це зазвичай працює як дерево, де листя є qdiscs, а класи - вузлами. Корінь дерева або піддерева буде оголошено як, <id>:
а дочірні вузли будуть оголошені як <parent_id>:<children_id>
. Майте на увазі цей синтаксис.
Для вашого випадку давайте візьмемо A і зробимо дерево, яке ви хотіли б встановити tc
:
1:
|
|
|
1:1
/ | \
/ | \
/ | \
1:10 1:20 1:30
| | |
| | |
:10 :20 :30
Пояснення:
1:
це кореневий qdisc, приєднаний до пристрою vethA, він буде сприйматися явно, як htb
для ієрархічного токена Bucket (qdisc пристрою за замовчуванням є pfifo
або pfifo_fast
залежно від ОС). Це спеціально підходить для управління пропускною здатністю. Пакети, які не відповідають фільтрам, визначеним на цьому рівні, перейдуть до 1:30
класу.
1:1
буде htb
класом, що обмежує весь трафік пристрою до 10 Мбіт / с.
1:10
буде htb
класом, що обмежує вихідний трафік до 9 Мбіт / с (90% від 10 Мбіт / с).
1:20
буде htb
класом, що обмежує вихідний трафік до 8 Мбіт / с (80% від 10 Мбіт / с).
1:30
буде htb
класом, що обмежує трафік до 10 Мбіт / с (резервний).
:10, :20, :30
є sfq
дисципліною стохастичною Fairness черзі. Іншими словами, ці qdiscs забезпечать справедливість у плануванні передач на основі потоків.
Все це налаштовано такими командами:
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-пакети з IP-адресою призначення дорівнювали B, переходили до 1:10
класу, а IP-пакети з IP-адресою призначення дорівнювали C 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 Мбіт / с .
Між 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 Мбіт / с .
Між 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 Мбіт / с .
Зауважте, що вибух першої міри кожного запуску можна краще обробити в 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