Jump to content
Калькуляторы

tc - HTB + SFQ равное разделение канала с QoS Помогите....:(

Здравствуйте! Вообщем имеем:

Сервер на CentOS.

2 сетевые карты, eth0 смотрит в локальную сеть, eth1 в интернет.

Внутренняя сеть 10.0.10.0/24

Канал в интернет 100мб\сек, анлим.

Порядка 200 пользователей.

 

Задача: сделать равное разделение канала между пользователями с QoS внутри каждой выделенной полосы каждого пользователя. Проще всего объяснить на примере:

Есть абстрактный канал в 10 мегабит, и 5 пользователей.

 

Если 1 пользователь качает файл, а остальные 4 не делают ничего то этот 1 получает все 10 мегабит, если начинает качать еще 1 то поровну т.е. по 5 мегабит, если все качают то соответственно по 2 мегабита на пользователя. НО нужно чтобы так же работал QoS _внутри_ этих каналов по 2 мегабита. т.е. к примеру пользователь начинает качать торрент и занимает все свои 2 мегабита (остальные так же что-то качают поэтому сервер выделяет по 2 мегабита каждому), далее он решает сделать VOIP звонок, во время звонка сервер обрезает ему торент и отдает приоритет SIP-пу в результате пользователь качает торрент скажем со скоростью 1930 кб\сек и в то же время говорит через sip без проблем. Или к примеру он решает полазить в интернете и в тот момент когда он начинает загружать страничку весь приоритет из его 2 мегабит отается этому т.е. торент к примеру падает до 0 скорость, а http занимает все 2 мегабита....

 

 

 

То как конфиг файл выглядит сейчас:

 

 

 

#!/bin/bash
tc qdisc del dev eth0 root 2> /dev/null > /dev/null
tc qdisc del dev eth0 ingress 2> /dev/null > /dev/null

DL=90Mbit
# создает рут очередь и указывает default (весь IP трафик отловим дальше, тут дефолт для максимального приоритета ARP и остальных служебных запросов)
tc qdisc add dev eth0 root handle 1: htb default 10
tc class add dev eth0 parent 1: classid 1:1 htb rate $DL

# ACK\ARP etc...
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 1Mbit ceil $DL prio 0
# DNS\SSH\SIP CTRL\ICQ\Jabber\SMTP etc...
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 1Mbit ceil $DL prio 1
# WWW
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 1Mbit ceil $DL prio 2
# Torrent\bulk  traffic
tc class add dev eth0 parent 1:1 classid 1:40 htb rate 1Mbit ceil $DL prio 3


tc qdisc add dev eth0 parent 1:10 handle 2: sfq perturb 10
tc qdisc add dev eth0 parent 1:20 handle 3: sfq perturb 10
tc qdisc add dev eth0 parent 1:30 handle 4: sfq perturb 10
tc qdisc add dev eth0 parent 1:40 handle 5: sfq perturb 10

 

#А вот тут обавляем правила, чтобы разделять полосу по ИП адресам а не по соединениям (потокам). - правильно ли сделано ??

 

tc filter add dev eth0 parent 2: prio 1 protocol ip handle 2 flow hash keys dst divisor 1024
tc filter add dev eth0 parent 3: prio 1 protocol ip handle 3 flow hash keys dst divisor 1024
tc filter add dev eth0 parent 4: prio 1 protocol ip handle 4 flow hash keys dst divisor 1024
tc filter add dev eth0 parent 5: prio 1 protocol ip handle 5 flow hash keys dst divisor 1024

 

Тут матчим трафик...просто как пример...не знаю куда именно нужно прикрепить данные фильтры...

#WWW
tc filter add dev eth0 protocol ip parent 1: prio 2 u32 match ip dport 80 0xffff flowid 1:30
#SSH
tc filter add dev eth0 protocol ip parent 1: prio 2 u32 match ip dport 22 0xffff flowid 1:20
# Все остальное
tc filter add dev eth0 parent 1: prio 3 flowid 1:40

 

Подскажите пожалуйста - правильно ли написан конфиг, если нет то как нужно ?

п.с. в конфиге всего 3 фильтра просто чтобы понять принцип...

Edited by neyro

Share this post


Link to post
Share on other sites

Сейчас QoS делается как shaping+policing на одном интерфейсе. Это не очень удачное решение, лучше делать шейпинг на двух интерфейсах. Второе: вам нужно, чтобы несколько юзеров были в одном классе с полосой, которую они будут делить. Для этого надо использовать не flow, а хэш-фильтры u32, где можно явно указать номер класса. Т.е. вам надо на каждый канал создать по одному дочернему классу HTB с краевой дисциплиной SFQ. На самом деле, несколько юзеров на канал -- это тоже неудачное решение, лучше давать каждому IP по своей полосе, тогда управление правилами радикально упрощается. Третье: разные типы трафика (HTTP, SSH и т.п.) лучше приоритизировать не на шейпере, а на следующей за ним машине, иначе правила сильно усложняются и появляются проблемы с масштабированием.

Edited by photon

Share this post


Link to post
Share on other sites

Возможно я не совсем правильно объяснил...

Задача в том, чтобы канал в 100 мб\сек делился поровну между всеми пользователями. причем динамически т.е. если 2 юзера то каждому по 50 мб\сек, 10 - каждому по 10 мб\сек и т.д. и при этом нужно чтобы был QoS для каждого юзера отдельно внутри выделяемой для него полосы, чтобы он даже если качает торент на всю свою полосу мог без проблем смотреть www странички или говорить по сип телефону. Общий QoS делать смысла никакого нет т.к. как именно юзер использует свою выделенную динамически полосу - это его дело. Важно сделать так чтобы юзерам было удобно... не все ведь к примеру знают, что если качаешь торент то он забивает канал и у них начинает тормозить загрузка www страниц, прерывания в сип телефонах и т.п.

Share this post


Link to post
Share on other sites

Для деления поровну надо использовать drr, а для приоритизации трафика внутри пользовательских классов -- дисциплину prio. Но лучше делать приоритизацию на отдельной машине, тогда не надо будет настраивать prio для каждого пользовательского класса.

Edited by photon

Share this post


Link to post
Share on other sites

В принципе, в вопросе содержится ответ :)

Делаете корневой клас на скорости интерфейса. У него потомками идут классы пользователей. А у каждого из этих подклассов - набор своих подклассов для каждого типа QoS.

C QoS-же основная проблема состоит именно в классификации трафика.

Если пользователей много - то фильтры для 1-го уровня делать через хеширование.

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

Share this post


Link to post
Share on other sites

На сервере 2 интерфейса, eht0 смотрит в сторону пользователей т.е. он исходящий получается, eth1 в инет.

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

В инете много чего написанно про tc, но полезной информации кот наплакал...95% конфигов либо устарели либо впринципе неправильные...про офф ман где процентов 60% еще вообще нет промолчу...

Да и задачи с распределением полосы без жестких лимитов мало кто решал...соответсвенно под такие конфигурации примеров нет вообще(и уж темболее с QoS внутри полосы для каждого отдельного пользователя - насколько я понял такое никто и не пытался делать...).

 

 

 

Share this post


Link to post
Share on other sites

итак -- во первых нужно отталкиваться от того что задачка может решаться двумя разными способами

 

1. определить полосу на всех пользователей и отдельно для каждого создать подклассы

2. определить полосы под конкретные сервисы а остальное поделить на всех

 

ИМХО -- второй вариант проще

 

итого

создаём очереди для приоритетного трафика

 

подготовка

tc qdisc del root dev $interface
rmmod cls_flow
rmmod cls_u32
rmmod sch_htb
rmmod sch_sfq

insmod sch_sfq
insmod sch_htb
insmod cls_flow
insmod cls_u32

 

tc qdisc add dev $interface root handle 1: htb default 10
# r2q 3
#создаём очередь для высокоприоритетного трафика гарантированной шириной в 10мбит с расшарением до 20мбит и максимальным приоритетом
tc class add dev $interface parent 1:1 classid 1:5 htb rate 10Mbit ceil 10mbit rate 20mbit prio 0
#разрешаем использовать полосу нашей сети равномерно через netfilter-conntrack по хостам в нашей сети
в случае если conntrack не используется можно использовать ключ dst
tc filter add dev $interface parent 5: protocol ip handle 10 flow hash keys nfct-dst divisor 512

#то-же самое делаем для менее приоритетного трафика -- единственное отличие в приоритете
tc class add dev $interface parent 1:1 classid 1:10 htb rate 80mbit ceil 90mbit prio 6
tc qdisc add dev $interface parent 1:10 handle 10: sfq perturb 10

#устанавливаем фильтр, который как раз и отвечает за равномерное распределение, опять-же смотрим на ключ nfct-dst и заменяем его на dst если conntrack не используется
tc filter add dev $interface parent 5: protocol ip handle 5 flow hash keys nfct-dst divisor 512
tc filter add dev $interface parent 10: protocol ip handle 10 flow hash keys nfct-dst divisor 512
#divisor отвечает за то, сколько хостов в сети (максимальный дивизор на sfq равен 1024), в нашем случае сеть /24 - поэтому используем 512

#устанавливаем фильтры для типа трафика, в данном случае для всей нашей сети 10.0.10.0/24 будет использоваться только высокоприоритетная очередь, и амксимальная скорость соответственно будет 20мбит
tc filter add dev $interface parent 1: protocol ip prio 2 u32 match ip dst 10.0.10.0/24 flowid 1:5

#соответственно в данном случае для высокоприоритетного трафика (потому как он обычно разномастный) удобнее всего использовать выставление меток на уровне iptables -j MARK/CONNMARK с последующим просовыванием его в определённую очередь на основе этой метки

 

Share this post


Link to post
Share on other sites

Апаю тему! В общем сейчас скрипт выглядит так:

#!/bin/bash

#

int="eth2"

 

tc qdisc del dev $int root > /dev/null 2>&1

 

DL=95Mbit

 

tc qdisc add dev $int root handle 1: htb

tc class add dev $int parent 1: classid 1:1 htb rate $DL ceil $DL

 

tc class add dev $int parent 1:1 classid 1:10 htb rate 5kbit ceil $DL prio 2

tc class add dev $int parent 1:1 classid 1:20 htb rate 5kbit ceil $DL prio 3

tc class add dev $int parent 1:1 classid 1:30 htb rate 5kbit ceil $DL prio 4

 

tc qdisc add dev $int parent 1:10 handle 10: sfq perturb 10

tc qdisc add dev $int parent 1:20 handle 20: sfq perturb 10

tc qdisc add dev $int parent 1:30 handle 30: sfq perturb 10

 

###HIGH PRIO

#ICMP

tc filter add dev $int parent 1: protocol ip prio 1 u32 match ip protocol 1 0xff flowid 1:10 police rate 5kbit buffer 25k drop

#VOIP

tc filter add dev $int parent 1: protocol ip prio 1 u32 match ip tos 0x68 0xff match ip protocol 11 0xff flowid 1:10

tc filter add dev $int parent 1: protocol ip prio 1 u32 match ip tos 0xb8 0xff match ip protocol 11 0xff flowid 1:10

#TOS

tc filter add dev $int parent 1: protocol ip prio 10 u32 match ip tos 0x10 0xff flowid 1:10

#ACK

tc filter add dev $int parent 1: protocol ip prio 12 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33 flowid 1:10

#DNS

tc filter add dev $int parent 1: protocol ip prio 19 u32 match ip protocol 17 0xff match ip sport 53 0xffff flowid 1:10

 

###MED PRIO

#WWW

tc filter add dev $int parent 1: prio 5 protocol ip u32 match ip sport 80 0xffff flowid 1:20

 

###LOW PRIO

#All other stuff(torrent etc..)

tc filter add dev $int parent 1: prio 100 protocol ip u32 match ip src 0.0.0.0/0 flowid 1:30

 

tc filter add dev $int parent 10: protocol ip handle 100 flow hash keys dst divisor 1024

tc filter add dev $int parent 20: protocol ip handle 101 flow hash keys dst divisor 1024

tc filter add dev $int parent 30: protocol ip handle 102 flow hash keys dst divisor 1024

Все работает хорошо т.е.: 1 пользователь качает торрент и занимает весь канал.....как только 2-й пользователь начинает так же качать торент они делят канал поровну...и так далее те всем поровну достается. Как только кто то начинает качать www он тут же получает приоритет и продавливает мгновенно торренты....казалось бы все отлично и все довольны.

НО!

Трафик делится поровну внутри одного приоритета..т.е. если всего доступно 30 мегабит и 3 пользователя качают торент то каждый получит ровно по 10 мегабит....а как только кто то начнет качать www то получит все 30 мегабит...

Хочется чтобы трафик делился поровну независимо от того что качает пользователь и при этом были приоритеты.

те например всего есть 30 мегабит

есть 3 пользователя и каждый качает торент на скорости 10 мегабит....и когда один решает сделать VOIP звонок и посмотреть www он должен не продавливать остальных пользователей а забрать нужную часть полосы из куска выделенного ему....т.е. чтобы остальные могли так же качать торент на скоростях по 10 мегабит, а он качал торент например на скорости 8 мегабит и со скоростью 2 качал www.

 

При этом нужно чтобы это работало с flow hash key dst тк те же хеш таблицы не позволяют динамически делить канал между всеми пользователями в зависимости от загруженности в каждую долю сек.

 

 

Т.е. нужно чтобы flow hash key dst делил какой то общий класс на всех поровну. а например какие нибудь дочерние классы делали QOS внутри выделенной полосы отдельно для каждого.

 

Помогите пожалуйста! Времени уже потратил огромнео колличество и ничего даже примерно не могу сообразить...

Share this post


Link to post
Share on other sites

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

Пример подобного - тут.

И да, траффик распределится пропорционально rate подклассов.

Share this post


Link to post
Share on other sites

Все бы хорошо, но вопрос в том, что хеш таблицы делят все статически....10 юзеров на 10 мегабит-каждому по 1....

А при использовании flow hash keys dst если 9 из 10 ничего не качают то оставшийся 1 получит все.

Или я что то не понимаю в работе хеш таблиц ?

Share this post


Link to post
Share on other sites

Хеш-таблицы - это фильтры. Которые ничего не делят. А только направляют траффик в нужный класс. Все. Остальное же зависит от того, как выстроено дерево классов.

Share this post


Link to post
Share on other sites

Но настроить класс с внешним классификатором (flow hash keys dst) с подклассами невозможно ведь...? Только если отдельный flow hash keys dst вешать на каждый подкласс и в итоге получим то, что я выше описывал....

Share this post


Link to post
Share on other sites

Посмотрите в конце концов пример реализации "невозможного"...

Share this post


Link to post
Share on other sites

Добрый день.

 

neyro писал

 

tc filter add dev $int parent 20: protocol ip handle 101 flow hash keys dst divisor 1024

 

Поясните пожалуйста, что эта срока означает и как она срабатывает.

 

Перечитал кучу литературы, даже поднял вполне рабочий шейпер, но такого фильтра не встречал.

 

Насколько я понял на дисциплину SFQ 20:0 вешается данный фильтр, который как то делит трафик по IP назначения. Что такое 101? Это MARK в iptables?

Share this post


Link to post
Share on other sites

Что такое 101? Это MARK в iptables?

Хэндл (идентификатор, имя) фильтра. Нужен в операциях удаления фильтра.

Share this post


Link to post
Share on other sites

tc filter add dev $int parent 10: protocol ip handle 100 flow hash keys dst divisor 1024

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

 

RTNETLINK answers: Invalid argument

We have an error talking to the kernel

 

в чем может быть проблема?

Share this post


Link to post
Share on other sites

В целом это выглядит вот так:

 

 

#!/bin/bash

DEV="eth1.2501"

 

tc qdisc del dev $DEV root >/dev/null 2>&1

tc qdisc del dev $DEV ingress >/dev/null 2>&1

 

tc qdisc add dev $DEV root handle 1: htb default 100

 

tc class add dev $DEV parent 1: classid 1:1 htb rate 7900kbit ceil 8000kbit

tc class add dev $DEV parent 1:1 classid 1:10 htb rate 64kbit ceil 7900kbit quantum 1500

tc class add dev $DEV parent 1:1 classid 1:11 htb rate 64kbit ceil 7900kbit quantum 1500

tc class add dev $DEV parent 1:1 classid 1:12 htb rate 256kbit ceil 7900kbit

tc class add dev $DEV parent 1:1 classid 1:13 htb rate 256kbit ceil 7900kbit

tc class add dev $DEV parent 1:1 classid 1:14 htb rate 2048kbit ceil 7900kbit

tc class add dev $DEV parent 1:1 classid 1:100 htb rate 5212kbit ceil 7900kbit

 

tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip protocol 1 0xff flowid 1:10

tc filter add dev $DEV protocol ip parent 1:0 prio 2 u32 match ip sport 53 0xffff flowid 1:11

tc filter add dev $DEV protocol ip parent 1:0 prio 3 u32 match ip sport 22 0xffff flowid 1:12

tc filter add dev $DEV protocol ip parent 1:0 prio 4 u32 match ip sport 23 0xffff flowid 1:12

tc filter add dev $DEV protocol ip parent 1:0 prio 5 u32 match ip sport 143 0xffff flowid 1:13

tc filter add dev $DEV protocol ip parent 1:0 prio 6 u32 match ip sport 993 0xffff flowid 1:13

tc filter add dev $DEV protocol ip parent 1:0 prio 7 u32 match ip sport 80 0xffff flowid 1:14

tc filter add dev $DEV protocol ip parent 1:0 prio 8 u32 match ip sport 8080 0xffff flowid 1:14

tc filter add dev $DEV protocol ip parent 1:0 prio 9 u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33 flowid 1:10

 

#tc filter add dev $DEV parent 10: protocol ip handle 10 flow hash keys nfct-dst divisor 1024

#tc filter add dev $DEV parent 11: protocol ip handle 20 flow hash keys nfct-dst divisor 1024

#tc filter add dev $DEV parent 12: protocol ip handle 30 flow hash keys nfct-dst divisor 1024

#tc filter add dev $DEV parent 13: protocol ip handle 40 flow hash keys nfct-dst divisor 1024

#tc filter add dev $DEV parent 14: protocol ip handle 50 flow hash keys nfct-dst divisor 1024

#tc filter add dev $DEV parent 100: protocol ip handle 70 flow hash keys nfct-dst divisor 1024

 

 

tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10

tc qdisc add dev $DEV parent 1:11 handle 11: sfq perturb 10

tc qdisc add dev $DEV parent 1:12 handle 12: sfq perturb 10

tc qdisc add dev $DEV parent 1:13 handle 13: sfq perturb 10

tc qdisc add dev $DEV parent 1:14 handle 14: sfq perturb 10

tc qdisc add dev $DEV parent 1:100 handle 100: sfq perturb 10

 

 

 

 

tc -s -d qdisc show dev $DEV

 

tc -s -d class show dev $DEV

 

 

вроде как все правильно

Share this post


Link to post
Share on other sites

Все я разобрался, номера handle изменил

Share this post


Link to post
Share on other sites

здравствуйте!

 

у меня есть похожая задача, но осложняется тем что ceil для root величина НЕпостоянная (dvb2/acm).

в связи с этим возможно глупый вопрос: можно ли в принципе обеспечить равномерное деление полосы для пользователей в данных условиях средствами tc\htb\sfq?

Edited by p0c0b0r

Share this post


Link to post
Share on other sites

Кстати у меня такой же вопрос. Как правильно всех расшейпить на негарантированном канале? Скажем емкость может снизиться в 2 раза.

 

Желательное поведение, чтобы приоритетный трафик например UDP, SSH и др. шел первым, а следом уже второстепенный. Можно решить эту задачу как-то через tc?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this