Traffic Control. Шейпинг трафика в Linux

Date August 25th, 2010 Author Vitaly Agapov

Закон на всех уровнях бытия — один и тот же: свой следущий мир мы выбираем посредством знания, обретённого здесь. И если здесь мы предпочли невежество, и знание наше осталось прежним, — следующий наш мир ничем не будет отличаться от нынешнего, все его ограничения сохранятся.

— «Чайка Джонатан Ливингстон»

Так уж получается, что те или иные задачи возникают иногда неожиданно, я бы даже сказал: спонтанно. Не всегда возможно быть готовым к мгновенному решению – частенько надо почитать мануалы, погуглить, почесать репу и разобраться. Ещё частенько для решения совсем маленькой и проходной подзадачи  требуется умение пользоваться некоторыми инструментами, создававшимися для более вдумчивого, комплексного и “профессионального” использования. Так было, например, с netfilter/iptables. Так случилось и с утилитой tc для управления трафиком в ядре Linux. Возникла задача (в рамках более крупной) ограничить сетевой трафик между двумя серверами некоторой полосой. Сделать это надо было как можно более просто, прозрачно и быстро. Задача была решена, а заодно выявилась необходимость набросать ещё одну памятку на будущее.

Итак, управляем сетевым трафиком в Linux.

tc

Утилита tc в Linux применяется для управления трафиком. Она позволяет ограничивать или сглаживать исходящий трафик, обеспечивать гарантированную полосу определённому виду трафика, применять разные политики ко входящему трафику и не умеет разве что грабить корованы. Замечательно, что tc написан нашим соотечественником Алексеем Кузнецовым и включён в ядро Linux, начиная с версии 2.2.

В этой области “правят бал” несколько понятий. Это:

qdisc (queueing discipline) – фактически очередь для конкретного сетевого интерфейса, из которого выбираются пакеты перед отправкой драйверу сетевой карты.

class – классы внутри очередей, в которые входят другие очереди. Разбиение по классам позволяет создавать приоритеты для обслуживания разных видов трафика. Класс всегда имеет одного родителя-qdisc.

filter – фильтры для определения, в очередь какого класса помещать тот или иной исходящий пакет.

Все очереди, классы и фильтры должны иметь идентификатор (который, впрочем, может назначаться автоматически). Идентификатор состоит обычно из двух чисел, разделенных двоеточием. Qdisc, потенциально могущий иметь классы-наследники, обычно имеет идентификатор только из старшего числа с двоеточием – handle. Классы наследуют это старшее число, которое вместе с младшим (например 1:10), образует classid.

Для всех объектов tc доступен набор команд, смысл, которых в основном ясен из их названия: add, remove, change, replace.

Очереди

Существуют несколько видов очередей, соответствующих моделям из теории массового обслуживания и телетрафика:

CBQ (Class-Based Queueing) – Очередь, основанная на классах. Позволяет создавать иерархию классов с приоритетами. Управление производится в зависимости от общей пропускной способности и загруженности канала.

HTB (Hierarchical Token Bucket) – Алгоритм дырявого ведра. Позволяет ограничивать пропускную способность независимо от общей пропускной способности канала. Поддерживает приоритеты.

PRIO – очередь, не влияющая на пропускную способность. Пакеты более низких приоритетов уходят на сетевую карту только при отсутствии в очереди пакетов полее высоких приоритетов.

Ещё есть несколько бесклассовых видов очередей:

[P|B]FIFO – First In, First Out с ограничением в пакетах или байтах.

RED (Random Early Detection) – имитирует физические заторы, отбрасывая пакеты при приближении к выделенной полосе пропускания.

SFQ (Stochastic Fairness Queueing) – равномерное распределение пакетов из разных сессий внутри очереди. Трафик разбивается на большое количество FIFO очередей, которые получают доступ к сетевой карте в режиме round-robin. Параметры: perturb – время, через которое будет меняться алгоритм распределения пакетов (обычно ставят 10 с), quantum – объем данных, выпускааемых из потока за один раз (по умолчанию MTU).

TBF (Token Bucket Filter) – замедляет трафик по точно заданному лимиту. Параметры следующие: rate – нужная скорость, latency – максимальное время в очереди, burst – размер “ведра” в байтах.

Если подвести итог, то TBF хорошо подходит, если надо замедлить весь исходящий трафик от узла на конкретном интерфейсе, а HTB – для построения иерархии классов и шейпинга трафика в соответствии с этой иерархией. При этом CBQ требует учитывания ряда дополнительных параметров, которые придётся для каждого конкретного случая получать эмпирическим путём, поэтому используется редко.

Приступим

Для начала определим корневую дисциплину для конкретного сетевого интерфейса и набор классов-наследников:

tc qdisc add dev eth0 root handle 1:  htb default 3
tc class add dev eth0 parent 1: classid 1:1 htb rate 64kbit
tc class add dev eth0 parent 1: classid 1:2 htb rate 4mbit burst 15k
tc class add dev eth0 parent 1: classid 1:3 htb rate 4mbit ceil 100mbit

Здесь мы создали корневой qdisc с идентификатором 1: , дисциплиной обслуживания HTB, сетевым интерфейсом eth0 и классом по умолчанию 1:3. И для него 3 класса: один с постоянной полосой 64kbit, второй с постоянной полосой 4mbit и максимальным объемом данных, который может быть передан через сетевую карту без переключения на другие классы, 15k, и, наконец, третий с гарантированной скоростью 4mbit и выше.

Для каждого класса при необходимости можно прописать отдельную дисциплину, например:

tc qdisc add dev eth0 parent 1:1 red min 1600 max 3210 burst 2 limit 32100 avpkt 1000
tc qdisc add dev eth0 parent 1:2  sfq perturb 10

После создания иерархии классов и набора дисциплин нам останется только распределить трафик по классам. Сделать это можно несколькими способами.

Способ первый – tc filter. В зависимости от некоторых условий направляем пакеты в класс 1:1

tc filter add dev eth0 protocol ip parent 1: prio 1 u32 match ip dst 192.168.0.1 flowid 1:1

В данном случае это пакеты, получателем у которых указан ip 192.168.0.1.

Способ второй – пометка пакетов с помощью iptables

iptables -A OUTPUT -t mangle -p tcp  -d 192.168.0.2 --dport 80 -j MARK --set-mark 20
tc filter add dev eth0 protocol ip parent 1: prio 2 handle 20 fw classid 1:2

Способ третий – установка класса сразу с помощью iptables

iptables -t mangle -A POSTROUTING -p tcp -d 192.168.0.3 -j CLASSIFY --set-class 1:3

Резюме

Задачу по ограничению исходящего трафика в направлении определенного хоста можно выполнить, например, следующими тремя командами:

tc qdisc add dev eth0 root handle 1:  htb default 1
tc class add dev eth0 parent 1: classid 1:1 htb rate 1mbit
iptables -t mangle -A POSTROUTING -p tcp -d 192.168.0.3 -j CLASSIFY  --set-class 1:1

Напоследок

Полезными могут оказаться знания о том, как проверить маркировку пакетов в iptables:

iptables -L -n -v -t mangle

Вот так можно удалить все правила:

tc qdisc del dev eth0 root
iptables -t mangle -F

А еще очень пригодится утилита iftop. С её помощью можно смотреть входящий и исходящий трафик по всем направлениям. Например, команда iftop -n -F 10.0.1.132/32 покажет в реальном режиме времени очень подробную информацию:

Ссылки

Memento iptables

Tags: ,
Category: Linux | 2 Comments »

Comments

2 комментариев на “Traffic Control. Шейпинг трафика в Linux”

  1. Дмитрий

    А как быть с входящим трафиком? То, что Вы описали, работает толко на исходящий, верно я понимаю?

  2. Дмитрий

    Совсем забыл, ещё бы логи скидывать, кто куда на какие сайты ходил.

Leave a comment

 Comment Form