LINUX.ORG.RU

Распределение трафика в одном классе htb

 , , ,


1

2

Исходные данные: есть ограниченная полоса, для управления трафиком пользователей используется шейпер, созданный с помощью tc, дисциплина htb. Полоса делится на несколько классов с разными приоритетами. Для помещения трафика в каждый класс используется фильтрация по IP пользователя. В каждый класс помещается несколько пользователей. Распределение между классами замечательно работает.

Проблема: ожидается что в пределах одного класса полоса будет делиться между пользователями примерно равномерно. Т.е. классу в данный момент доступно, допустим, 12 мб/с, в нем три пользователя. Один пользователь может занять все 12, если работают двое - каждому достанется по 6, если трое - каждому по 4. По факту так не получается. Выделяемая полоса зависит от количества сессий. Один пользователь может запустить какой-нибудь торрент и съест практически всю полосу, выделенную классу, а двум другим, которые хотят, например, почитать почту, не остается почти ничего.

Пример создания класса:

#/sbin/tc class add dev eth0 parent 1:2 classid 1:20 htb rate 8000Kbit ceil 12000Kbit prio 1

# /sbin/tc qdisc add dev eth0 parent 1:20 handle 20 sfq perturb 10

# /sbin/tc filter add dev eth0 parent 1:0 protocol ip prio 100 u32 match ip dst 172.16.0.1/32 classid 1:20

# /sbin/tc filter add dev eth0 parent 1:0 protocol ip prio 100 u32 match ip dst 172.16.0.2/32 classid 1:20

# /sbin/tc filter add dev eth0 parent 1:0 protocol ip prio 100 u32 match ip dst 172.16.0.3/32 classid 1:20

Нужно, чтобы когда работают все трое (172.16.0.1, .2, .3) каждому доставалось примерно по 4 Мбит. А не так, чтобы 1 запустил 100 сессий и съел всё, а 2 и 3 запустили по одной сессии и ничего не получают. Предположительно здесь можно применить flow hash в filter, но пока не понимаю как. Мануалы читал, но в голове сумбур.

Отягчающие обстоятельства: По условиям эксплуатации сети приоритизация допустима только по IP пользователей, устраивать приоритизацию по типам сервисов (почта, серфинг, торрент и т.п.) - не предлагать. Создавать отдельный класс для каждого пользователя - выход, но плохой (наоборот, хочется от этого уйти по ряду причин).


гм. дык они у тебя все в одном классе.

сделай 3 подкласса с CEIL=12Mbit RATE=4Mbit и фильтрами загони каждого в свой класс.

а для большей равномерности в sfq/esfq рекомендовали типа «tc filter add dev XXXX parent 2: prio 1 protocol ip handle 2 flow hash keys dst divisor 1024»

vel ★★★★★ ()
Ответ на: комментарий от vel

гм. дык они у тебя все в одном классе.

именно. в этом и идея.

сделай 3 подкласса с CEIL=12Mbit RATE=4Mbit и фильтрами загони каждого в свой класс.

это решение простое и понятное, но, как я написал, именно его и хотелось бы избежать. это хорошо на примерах и на небольших списках пользовтаелей. а когда их реально много, то администрировать всё это становится затруднительно. достаточно долго это проходил, захотелось упростить конфигурацию.

а для большей равномерности в sfq/esfq рекомендовали типа

«tc filter add dev XXXX parent 2: prio 1 protocol ip handle 2 flow hash keys dst divisor 1024»

вот! про это и вопрос. в принципе эту запись я понимаю, но есть непонятки в частностях. а именно: что значат parent и handle в этой команде? Откуда надо брать их значения (понятно, что не с потолка, а с конкретной конфигурации)? и заодно - почему divisor 1024 ?

вот тут, например, я понимаю, что делает divisor и почему он такой:

filter parent 1: protocol ip pref 1 u32

filter parent 1: protocol ip pref 1 u32 fh 1: ht divisor 256

А с flow hash - не понимаю.

mik73 ()
Ответ на: комментарий от mik73

handle & parent - из «tc qdisc add dev eth0 parent 1:20 handle 20 sfq»

Но почему в «parent» используется только младшая часть - хз.

Размер дивизора может быть и меньше. Если в классе не много потоков, то можно уменьшить до 32-64.

vel ★★★★★ ()
Ответ на: комментарий от vel

так-так... может тогда, если класс 20, то должно быть

filter parent 20: prio 1 protocol ip handle 20 flow hash ...

handle тут. возможно, может быть любым - по аналогии с ht в фильтрах u32, это, скорее всего, ссылка на запись для дальнейшего оперирования ею.

а parent 20 - это тогда как раз из какого flowid направлять поток в этот фильтр.

а если у меня будет класс 1:30, например, то для него дисциплина

tc qdisc add dev eth0 parent 1:30 handle 30 sfq

трафик в него будет направляться командой типа

tc filter add .... classid 1:30

а правила хэширования потоков задаваться как

tc filter parent 30: prio 1 protocol ip handle 30 flow hash ...

вроде похоже на правду?

mik73 ()
Ответ на: комментарий от vel

что-то сомневаюсь. что к root handle если у класса есть подклассы (а у рутового класса они точно есть), то направляй в него что-то фильтром, не направляй - толку не будет. шейпятся только краевые классы. подозреваю, что здесь та же логика. цепяать это за не краевой класс - должно быть бессмысленно. надо стендик строить и пробовать.

mik73 ()
Ответ на: комментарий от mik73

Нашел у себя интересную закладку с хабра (https://habrahabr.ru/post/133076/)

# tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip dport 25 0xffff flowid 1:3

parent 1: — фильтр может крепиться только к дисциплине и вызывается из нее же.
На основе срабатывания фильтра дисциплина решает в каком классе продолжится обработка пакета.

Стенд нужно собрать и посмотреть :(

Для классификации логично цеплять к корню. А для flow - к краевой.

vel ★★★★★ ()
Последнее исправление: vel (всего исправлений: 3)
Ответ на: комментарий от vel

Докладываю:

Действительно проблема распределения трафика в пределах одного класса решается фильтром flow hash keys.

На https://www.opennet.ru/openforum/vsluhforumID1/85691.html:

по умолчанию потоки в sfq разбиваются так:
tc filter add .... flow hash keys src,dst,proto,proto-src,proto-dst divisor 1024

Т.е. доступная классу скорость делится внутри него по всем признакам - входящий/исходящий IP, протокол, сессия (протокол+порт назначения/отправления). Соответственно, если у кого-то много сессий, то им отдается много от общей полосы класса, а остальным не достается.Чтобы разбивать только по желаемому признаку (в моем случае по адресу получателя), надо ограничить набор параметров, по которому разбиваются потоки. Т.е. добавить в фильтры правило вида

tc filter add dev eth0 protocol ip pref 1 parent x: handle y flow hash keys dst divisor 1024

если нужно распределять потоки не по адресу назначения, а по другим признакам, то, соотвествующие keys - scr, proto, proto-scr, proto-dst.

Было непонятно, что такое x и y. По итогам экспериментов - parent x: - это номер дисциплины для которой мы это делаем (в моем примере 20:), а handle y - это что-то произвольное (например для определенности тоже 20), указатель по которому потом можно этим правилом в управлять (изменять, удалять). В результате выделенная классу полоса практически ровно делится между всеми пользователями в классе, чего и хотелось достичь.

Спасибо vel за подтверждение мыслей и обсуждение, наведшее на решение.

примечания: 1. если у нас несколько классов (и дисциплин), то для каждого надо применить аналогичное правило в фильтрах. 2. дисциплины и фильтры для htb имеют смысл только в краевых классах.

mik73 ()
Ответ на: комментарий от fet4

И если пытаешься удалить этот же фильтр.

tc filter del dev eth0 protocol ip pref 1 parent x: handle y flow hash keys dst divisor 1024
tc filter del dev eth0 handle y flow hash keys dst divisor 1024

Пишет

RTNETLINK answers: No such file or directory
We have an error talking to the kernel

fet4 ()
Ответ на: комментарий от fet4

Ребята такой вопрос

https://www.altlinux.org/ШейперДляБольшихСетей

В данном способе в ipset заносятся ip адреса с одинаковым классом 

add shaper4 172.16.1.10/32 skbprio 1:d
add shaper4 172.16.1.12/32 skbprio 1:d
add shaper4 172.16.1.14/32 skbprio 1:d
add shaper4 172.16.1.31/32 skbprio 1:d

Разве эти Ip не будут делить скорость между собой в пределах одного класса?

Насколько я понял это классы тарифов

class add dev bondINT parent 1: classid 1:d est 1sec 8sec hfsc sc umax 1500b dmax 5ms rate 20480kbit ul rate 20480kbit
qdisc add dev bondINT parent 1:d handle d: pfifo limit 200
class add dev bondEXT parent 1: classid 1:d est 1sec 8sec hfsc sc umax 1500b dmax 5ms rate 20480kbit ul rate 20480kbit
qdisc add dev bondEXT parent 1:d handle d: pfifo limit 200

Или я ошибаюсь?

fet4 ()