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

tc filter c vlan на ядрах 4.4 с использованием хэша tc filter c vlan на ядрах 4.4 с использованием хэша

На ядре 2.6.Х работала следующая конструкция шейпера:

 

/sbin/tc qdisc del dev eth0 root

/sbin/tc qdisc add dev eth0 root handle 1 htb default 30 r2q 32

 

/sbin/tc class add dev eth0 parent 1: classid 1:2 htb rate 100Mbit

/sbin/tc filter add dev eth0 parent 1:0 prio 200 handle 2: protocol ip u32 divisor 256

 

/sbin/tc class add dev eth0 parent 1:2 classid 1:11 htb rate 20Mbit ceil 30Mbit burst 50k prio 3

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

/sbin/tc filter add dev eth0 parent 1:0 protocol ip prio 100 handle 11 fw classid 1:11

/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 200 u32 ht 2:0x05 match ip dst 192.168.0.5 flowid 1:11

 

/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 200 u32 ht 800:: match ip dst 192.168.0.0/24 hashkey mask 0x000000ff at 16 link 2:

 

Собрал новую машину на ядре 4.4.18 и вылезла неожиданная проблема с vlan интерфейсами.

Предыдущая конструкция работает только если указать в качестве интерфейся конкретный vlan - типа eth0.3 и только на карточке интел c MSI - похоже сама карточка тэг снимает. Только в этом случае теряется наследование класса. Нужно запустить фильтр на корневом интерфейсе eth0.

На форуме здесь http://forum.nag.ru/forum/index.php?showtopic=98225 нашел решение которое работает

С приведенным ниже конфигом все нормально работает на любой карточке:

 

/sbin/tc qdisc del dev eth0 root

/sbin/tc qdisc add dev eth0 root handle 1 htb default 30 r2q 32

 

/sbin/tc class add dev eth0 parent 1: classid 1:2 htb rate 100Mbit

/sbin/tc filter add dev eth0 parent 1:0 prio 200 handle 2: protocol ip u32 divisor 256

 

/sbin/tc filter add dev eth0 parent 1: protocol all handle 0x5 basic match 'meta (vlan eq 3 )' action ok

 

/sbin/tc class add dev eth0 parent 1:2 classid 1:11 htb rate 20Mbit ceil 30Mbit burst 50k prio 3

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

/sbin/tc filter add dev eth0 parent 1:0 protocol ip prio 100 handle 11 fw classid 1:11

/sbin/tc filter add dev eth0 parent 1: protocol all handle ::5 u32 match ip dst 192.168.0.5 flowid 1:11

 

/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 200 u32 ht 800:: match ip dst 192.168.0.0/24 hashkey mask 0x000000ff at 16 link 2:

 

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

Share this post


Link to post
Share on other sites

'protocol all' поставьте везде, хеши и не могут работать из-за оставленного protocol ip.

У меня "подобные конструкции" работают на любых картах и с разными ядрами, если запускать на интерфейсе(eth0.3) с protocol ip, если на корневом eth - то только с all, ибо трафик из-за смещений получается не IP.

Share this post


Link to post
Share on other sites

Попробовал как вы говорите - не работает. У меня на сутки еще только одно сообщение доступно :(

Возможно не сразу отвечу.

При добавлений правил ругани нет, но пакеты в фильтр не попадают. Что я делаю не так?

 

/sbin/tc qdisc del dev eth0 root

/sbin/tc qdisc add dev eth0 root handle 1 htb default 30 r2q 32

 

/sbin/tc class add dev eth0 parent 1: classid 1:2 htb rate 100Mbit

/sbin/tc filter add dev eth0 parent 1:0 handle 2: protocol all u32 divisor 256

 

/sbin/tc class add dev eth0 parent 1:2 classid 1:11 htb rate 20Mbit ceil 30Mbit burst 50k prio 3

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

/sbin/tc filter add dev eth0 parent 1:0 protocol all handle 11 fw classid 1:11

/sbin/tc filter add dev eth0 parent 1:0 protocol all u32 ht 2:0x05 match ip dst 192.168.0.5 flowid 1:11

 

/sbin/tc filter add dev eth0 parent 1:0 protocol all u32 ht 800:: match ip dst 192.168.0.0/24 hashkey mask 0x000000ff at 16

Share this post


Link to post
Share on other sites

Пробовал ip link set eth0.3 type vlan reorder_hdr on/off

На результат никак не влияет.

 

Пробовал

/sbin/tc filter add dev eth0 parent 1:0 protocol all u32 ht 800:: match ip dst 192.168.0.0/24 hashkey mask 0x000000ff at 20

в надежде, что 4 бита сработают, но нет.

Решения пока не нахожу. Ниже ссылки, но я уже окончательно запутался. Пробую разные варианты - никак не получается.

Ниже несколько ссылок по теме. Как я понимаю в новых ядрах поменяли что-то. Без хэшей мне удалось все запустить, но с хэш пока ника не получается.

Ссылка

Ссылка

До завтра мой лимит ссобщений исчерпан :(

Share this post


Link to post
Share on other sites

Попробуйте другое ядро.

На 3.18 у меня вообще qinq трафик(с 2 метками) шейпится прямо на bond1. Т.е. клиенты висят на bond1.100.200 etc. И все работает замечательно на разном железе и на ядрах 3.хх веток.

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

Share this post


Link to post
Share on other sites

Попробовал запустить без использования хэшей с указанием протокола all - работает!

 

/sbin/tc qdisc del dev eth0 root

/sbin/tc qdisc add dev eth0 root handle 1 htb default 30 r2q 32

 

/sbin/tc class add dev eth0 parent 1: classid 1:2 htb rate 100Mbit

 

/sbin/tc class add dev eth0 parent 1:2 classid 1:11 htb rate 20Mbit ceil 30Mbit burst 50k prio 3

/sbin/tc qdisc add dev eth0 parent 1:11 handle 11 esfq perturb 10 hash dst

/sbin/tc filter add dev eth0 parent 1:0 protocol all prio 200 handle 11 fw classid 1:11

/sbin/tc filter add dev eth0 parent 1:0 protocol all prio 100 u32 match ip dst 192.168.0.5 classid 1:11

 

Как только указываю использование хэш - ничего не работает. Пакеты в класс не направляются. Ниже пример:

 

/sbin/tc qdisc del dev eth0 root

/sbin/tc qdisc add dev eth0 root handle 1 htb default 30 r2q 32

 

/sbin/tc class add dev eth0 parent 1: classid 1:2 htb rate 100Mbit

/sbin/tc filter add dev eth0 parent 1:0 prio 200 handle 2: protocol all u32 divisor 256

 

/sbin/tc class add dev eth0 parent 1:2 classid 1:11 htb rate 20Mbit ceil 30Mbit burst 50k prio 3

/sbin/tc qdisc add dev eth0 parent 1:11 handle 11 esfq perturb 10 hash dst

/sbin/tc filter add dev eth0 parent 1:0 protocol all prio 100 handle 11 fw classid 1:11

/sbin/tc filter add dev eth0 protocol all parent 1:0 prio 200 u32 ht 2:0x05 match ip dst 192.168.0.5 flowid 1:11

 

/sbin/tc filter add dev eth0 protocol all parent 1:0 prio 200 u32 ht 800:: match ip dst 192.168.0.0/24 hashkey mask 0x000000ff at 16 link 2:

 

Выделил строки которые добавляются для хэша. С их появлением не работает. Подскажите - куда копать?

В ссылках которые я приводил есть упоминание: VLAN tag is stripped from skb in recent kernels и там же примеры.

Думаю проблемма именно в этом. Пока запустил без применения хэша, но хотелось бы уменьшить нагрузку на сервер.

Share this post


Link to post
Share on other sites

Nekto Думаю проблема со смещением. Советую в скрипте создать все 256 фильтров нижнего уровня и посмотреть в какой попадает трафик, а на основании этого сделать вывод, какое смещение нужно.

Share this post


Link to post
Share on other sites

Методам построчного ввода заметили, что команда вида:

/sbin/tc filter add dev eth0 protocol all parent 1:0 prio 200 u32 ht 2:0x05 match ip dst 192.168.0.5 flowid 1:11

не принимается - идет ругань на аргументы. Разобрались, что для запуска команды нужно указать протокол ip.

если есть значение ht 2:0x05 протокол all не срабатывает. Без протокола all тегированный трафик tc не видит.

аналогично с командой для субнета:

sbin/tc filter add dev eth0 protocol all parent 1:0 prio 200 u32 ht 800:: match ip dst 192.168.0.0/24 hashkey mask 0x000000ff at 16 link 2:

протокол нужно указать ip

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

Share this post


Link to post
Share on other sites

А если указать HT 2:5, без всяких хексов? Оно и так хексовое дефолтно..

Не получится. Нужно указать куда попадают данные из субнета - эта строка

tc filter add dev eth0 protocol ip parent 1:0 prio 200 u32 ht 800:: match ip dst 192.168.0.0/24 hashkey mask 0x000000ff at 16 link 2:

Последняя запись из субнета попадает в свой divisor на свой link, а в нем откусывается только последня циферка по маске.

правило с указателем protocol all не работает. tc не видит тэгированный трафик как ip

пробую указать вид протокола 802,1q - получаю ту же ошибку:

tc filter add dev eth0 protocol 802.1q parent 1:0 prio 200 u32 ht 800:: match ip dst 192.168.0.0/24 hashkey mask 0x000000ff at 16 link 2:

RTNETLINK answers: Invalid argument

We have an error talking to the kernel

Без этого правила работать ничего не будет. Каким образом указать, что ip протокол нужно смотреть в конкретном vlan я не понимаю.

Edited by Nekto

Share this post


Link to post
Share on other sites

Скажите, этот трафик во вланах маршрутизируется на данной железке, или загнаны в бридж? Может подойдет такой вариант:

 

ipset create shape-skb4 nethash family inet skbinfo

ipset add shape-skb4 192.168.0.5 skbprio 1:11

iptables -t mangle -I POSTROUTING -o vlan* -j SET --map-set shape-skb4 dst --map-prio

 

(создание класса 1:11 условно не показано)

 

Получается, что весь исходящий трафик по интефейсам vlan* будет классифицироваться через сет, с выставлением нужного поля, и потом попадает в нужный класс. По производительности данная схема идет на равне с хэшами, но имеет два серьезных преимущества перед хэшами tc: 1 - можно нарезать скорости для сеток произвольного размера; 2 - схема применима и для нарезки скоростей для ipv6

Share this post


Link to post
Share on other sites

Скажите, этот трафик во вланах маршрутизируется на данной железке, или загнаны в бридж?

 

Трафик маршрутизируется. Нарезка на исходящих интерфейсах. Уже копал в сторону ipset.

ПО мануалу tc последних версий его поддерживает из коробки. Пробовал правило приведенное ниже - не работает

tc filter add dev eth0 parent 1:0 protocol all prio 100 basic match ipset'(test dst)' classid 1:11

 

Что интересно, nmap на этой машине тоже не работает. Говорит, что все хосты с закрытыми портами. Это так к слову.

Пересобираю ядро на 3.18.42 по результатам отпишусь.

 

Относительно вашего примера - не хочу плодить кучу правил iptables.

Не копал на предмет skb ipset, но если ipset add shape-skb4 192.168.0.5 skbprio 1:11 загоняет трафик с ип прямо в нужный класс, то решение интересное.

Для экономии времени - в первом примере: ipset create shape-skb4 nethash family inet skbinfo в последнее значение skbinfo, что заносится? Или готовый пример с конкретными цифрами если не сложно. Я пока почитаю по ipset, направление интересное. И да я на этой машине сейчас использую ipset для hash:ip и hash:ip,port 2000 прежних правил iptables уместились в 10, сэкономив 10% нагрузки на проц. шапер без хэшей сожрал экономию и даж чуть поднажал, но пока терпимо. Ядро скомпилилось - пойду тестить.

Share this post


Link to post
Share on other sites

Для экономии времени - в первом примере: ipset create shape-skb4 nethash family inet skbinfo в последнее значение skbinfo, что заносится?

 

Это значение резервирует место в ipset для добавления fw mark, класса и/или hw queue в список. Потом в iptables -j SET можно устанавливать отдельно какую-либо величину, либо все вместе.

Share this post


Link to post
Share on other sites

Относительно вашего примера - не хочу плодить кучу правил iptables.

 

Цитирование сбилось, трудно понять о чем речь. В общем, https://www.altlinux.org/%D0%A8%D0%B5%D0%B9%D0%BF%D0%B5%D1%80%D0%94%D0%BB%D1%8F%D0%91%D0%BE%D0%BB%D1%8C%D1%88%D0%B8%D1%85%D0%A1%D0%B5%D1%82%D0%B5%D0%B9

Share this post


Link to post
Share on other sites

Ура - решение найдено. Заработало!

ipset create test hash:ip hashsize 64

ipset add test 192.168.0.5

 

tc qdisc add dev eth0 root handle 1 htb default 30 r2q 32

tc class add dev eth0 parent 1: classid 1:2 htb rate 100Mbit

tc class add dev eth0 parent 1:2 classid 1:11 htb rate 20Mbit ceil 30Mbit burst 50k prio 3

tc qdisc add dev eth0 parent 1:11 handle 11 esfq perturb 10 hash dst

tc filter add dev eth0 parent 1:0 protocol all prio 200 handle 11 fw classid 1:11

tc filter add dev eth0 parent 1:0 protocol all prio 100 basic match ipset'(test dst)' classid 1:11

 

Из ipset пакеты прямиком направляются в нужный класс шэйпера. Никаких промежуточных iptables не надо!

Я правильно смотрел в направлении ipset. Теперь собственно о граблях, почему у меня сразу не получилось.

Стояла стоковая версия ipset 6.20. Собрал 6.29, когда на skbinfo полезли ошибки - он после 6.22 включен.

По случаю я в это время работал на ядре 3.18.42 - все прекрасно запустилось. Перешел на версию 4.4.18 - получил облом.

На сегодняшний момент ядро 3.18.42 ipset 6.29 iproute2-4.7.0 - все работает на машине с vlan. У кого не используется vlan проблем скорее всего не возникнет с любым ядром. Осталось переписать скрипты под новый формат.

Edited by Nekto

Share this post


Link to post
Share on other sites

Погодите, в таком разрезе вы получите производиельность как без хэшей. По сути у вас будет портянка filters которую пакеты будут должны перебирать. В моем примере в одном правиле iptables сразу происходит присвоение нужного класса через хэширование в сете (то есть нет портянки линейных filters). В сет просто набиваются записи с указанием индивидуальных классов.

Share this post


Link to post
Share on other sites

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

В классическом использовании хэшей перебор идет по последнему знаку ип адреса, здесь перебор на уровне хэша выполнит ипсет и направит прямо в клас тц

Edited by Nekto

Share this post


Link to post
Share on other sites

Я там выше ссылку привел на описание.

 

цитата:

 

 

 

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
class add dev bondINT parent 1: classid 1:d44 est 1sec 8sec hfsc sc umax 1500b dmax 10ms rate 30720kbit ul rate 30720kbit
qdisc add dev bondINT parent 1:d44 handle d44: pfifo limit 200
class add dev bondEXT parent 1: classid 1:d44 est 1sec 8sec hfsc sc umax 1500b dmax 10ms rate 30720kbit ul rate 30720kbit
qdisc add dev bondEXT parent 1:d44 handle d44: pfifo limit 200

add shaper4 172.16.1.2/32 skbprio 1:d
add shaper4 172.16.1.5/32 skbprio 1:d
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
add shaper4 172.16.1.103/32 skbprio 1:d
add shaper4 172.16.1.128/32 skbprio 1:d
add shaper4 172.16.1.184/32 skbprio 1:d
add shaper4 172.16.2.115/32 skbprio 1:d
add shaper4 172.16.5.198/32 skbprio 1:d
add shaper4 172.16.6.38/32 skbprio 1:d
add shaper4 172.16.6.58/32 skbprio 1:d
add shaper4 172.16.6.69/32 skbprio 1:d
add shaper4 172.16.9.228/32 skbprio 1:d
add shaper4 172.16.10.208/32 skbprio 1:d
add shaper4 172.16.11.67/32 skbprio 1:d
add shaper4 172.16.11.68/32 skbprio 1:d
add shaper4 172.16.11.147/32 skbprio 1:d
add shaper4 172.16.15.213/32 skbprio 1:d
add shaper4 172.16.15.214/32 skbprio 1:d
add shaper4 172.16.17.75/32 skbprio 1:d
add shaper4 172.16.17.231/32 skbprio 1:d44
add shaper6 XXXX:4680:26:0:0:0:0:202/124 skbprio 1:d44

 

Итак, в этом примере на пачку адресов дается 20 мегабит, и делят они ее между собой как хотят, а вот для адреса 172.16.17.231 и префиксу сети ipv6 мы назначили скорость 30М.

 

Правило iptables одно.

Share this post


Link to post
Share on other sites

Не знал, что tc может сам в ipset заглядывать. Прикольно.

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

Share this post


Link to post
Share on other sites

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

 

А разве фильтр по classid выбирается линейным перебором списка? Или, все же, выбор идет по индексу id?

Share this post


Link to post
Share on other sites

tc filter add dev eth0 parent 1:0 protocol all prio 100 basic match ipset'(test dst)' classid 1:11

 

это просто случай расширенного линейного списка фильтров. Да, если нам в класс 1:11 надо запихать 100500 адресов по порядку или без, подсетями или россыпью, то будет весьма серьезный выигрыш. Но это фильтр, классифицирующий трафик для одного класса. Если классов 100500, то надо будет создавать 100500 (точнее 65536) линейных фильтров.

 

В моем примере в сете задается соотвествие IP и значения поля skbinfo, записей можно задавать сколько душа пожелает

 

ipset create shape-skb4 nethash family inet skbinfo

ipset add shape-skb4 192.168.0.5 skbprio 1:11

ipset add shaper4 172.16.1.2/32 skbprio 1:d

ipset add shaper4 172.16.17.231/32 skbprio 1:d44

 

А правило

iptables -t mangle -I POSTROUTING -o vlan* -j SET --map-set shaper4 dst --map-prio

 

Проверяет через обращение к сету есть ли для адреса в поле destination пакета запись, и если есть, то пакету проставляется соотвествующая служебная информация (как если бы пакет прошел соотвествующий tc filter), дальше с этой инофрмацией пакет попадет в нужный класс.

 

Боевой шейпер:

 

iptables -L POSTROUTING -nv -t mangle 
Chain POSTROUTING (policy ACCEPT 3920G packets, 3207T bytes)
pkts bytes target     prot opt in     out     source               destination
1556G  469T SET        all  --  *      bondEXT  0.0.0.0/0            0.0.0.0/0            map-set shaper4 src map-prio
2253G 2669T SET        all  --  *      bondINT  0.0.0.0/0            0.0.0.0/0            map-set shaper4 dst map-prio

tc class show dev bondEXT | wc -l
3784

ipset -L shaper4 | wc -l
4101

Share this post


Link to post
Share on other sites

Но это фильтр, классифицирующий трафик для одного класса. Если классов 100500, то надо будет создавать 100500 (точнее 65536) линейных фильтров.

 

А разве ограничение в 0xffff классов не связано с тем, что фильтры для класса ищутся по массиву индексов, а не линейным перебором списка? Просто лень смотреть сырцы. Или я что-то не так спрашиваю...

 

PS Если classid выставлять через ipset/iptables фильтры вообще не нужны.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.