Перейти к содержимому
Калькуляторы

sc: скрипт для управления Linux-шейпером

или все IP в классе будут делить полосу?

скорее всего это. Если нужен индивидуальный шейп - нет смысла лепить несколько IP в один класс.

Изменено пользователем voron

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

"Несколько IP на один класс" - каждый IP будет шейпится индивидуально? или все IP в классе будут делить полосу?

Ну естественно, несколько IP на одну очередь будут делить одну полосу пропускания. С другой стороны, я не хочу сейчас включать эту возможность, т.к. она ломает некоторые команды (show, list, операции с базой), и их под это дело нужно будет полностью переписывать. К тому же, не стоит провоцировать внедрение этой неоптимальной политики QoS.

Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Из какого набора хэшей Ipset беруться данные для шейпера? Или создается несколько каждая под свой диапазон IP?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

ipset и iptables при использовании u32 вообще не нужны, т.к. можно просто создать tc filter с policy, блокирующий весь неклассифицированный трафик. classid и номера фильтров генерируются из списков сетей. Допускаются сети от /31 до /16 с одинаковыми последними октетами. Для классов суммарное количество хостов во всех подсетях не должно превышать ffff. В конфиге теперь это выглядит примерно так:

 

# сети для вычисления classid

network = 10.0.0.0/17 172.16.0.0/22 172.16.5.0/24 172.16.254.0/24

# для построения фильтров

filter_network = 10.0.0.0/17 172.16.0.0/16

 

При создании фильтров нужно использовать примерно тот же принцип, что и для route aggregation: одним хэш-фильтром для 172.16.0.0/16 можно классифицировать трафик для подсетей 172.16.0.0/22, 172.16.5.0/24 и 172.16.254.0/24.

Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Круто! Уже хочется скрипт посмотреть =) Реально очень сложная работа

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

ipset и iptables при использовании u32 вообще не нужны, т.к. можно просто создать tc filter с policy, блокирующий весь неклассифицированный трафик.

Куда нужно помещать правило которое будет отлавливать не классифицированные пакеты? Правило которое вычисляет ключ и направляет в нужный ht уже проматчит все пакеты.

 

filter parent 1: protocol ip pref 5 u32 fh 800: ht divisor 1
filter parent 1: protocol ip pref 5 u32 fh 800::800 order 2048 key ht 800 bkt 0 link 2:  (rule hit 2721032302 success 0)
  match 00000000/00000000 at 16 (success 2721032302 )
    hash mask 000000ff at 16

 

Остаётся вариант с добавлением правила с максимальным prio в каждую из 255 ht.

 

Я сейчас при матче в ht делаю маркировку пакета, а в iptables пропускаю пакеты с установленным fwmark, остальные дропаю.

 

filter parent 1: protocol ip pref 5 u32 fh 2:fd:2 order 2 key ht 2 bkt fd flowid 1:5c6  (rule hit 1093575 success 772508)
  match 0a310ffd/ffffffff at 12 (success 772508 )
        action order 72097: tablename: mangle  hook: NF_IP_POST_ROUTING
        target MARK xset 0x2/0xffffffff
        index 3754 ref 1 bind 1 installed 247061 sec used 39797 sec
        Action statistics:
        Sent 92823432 bytes 772508 pkt (dropped 0, overlimits 0 requeues 0)
        rate 0bit 0pps backlog 0b 0p requeues 0

Изменено пользователем shaytan

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

ipset и iptables при использовании u32 вообще не нужны, т.к. можно просто создать tc filter с policy, блокирующий весь неклассифицированный трафик. classid и номера фильтров генерируются из списков сетей

Это хорошо, однако лучше ipset все же оставить, т. к. удобно перенаправлять трафик ipt_netflow. А если не использовать ipset - будет попадать трафик из заблокированных сетей.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Куда нужно помещать правило которое будет отлавливать не классифицированные пакеты? Правило которое вычисляет ключ и направляет в нужный ht уже проматчит все пакеты.
Да, в default queue с полосой 1bps такой трафик уже не попадает, но можно пойти другим путем. Если в хэше нет краевого фильтра $ht:$key:800, указывающего на какой-то конкретный flowid 1:x, то пакет проходит по фильтрам дальше. И здесь его можно отбросить с помощью правила, добавленного в конец, и желательно с более высоким значением pref:

tc filter add dev $DEV parent 1: protocol ip pref 30 u32 match u32 0x0 0x0 at 0 police mtu 1 action drop

 

Это хорошо, однако лучше ipset все же оставить, т.к. удобно перенаправлять трафик ipt_netflow. А если не использовать ipset - будет попадать трафик из заблокированных сетей.
Я полагаю, что шейпер по возможности лучше делать в виде простого моста, на чистом tc, чтобы не связываться с iptables и его проблемами с блокировками. А всевозможные Netflow и NAT делать на других машинах. В принципе, потом можно будет придумать какую-то опцию для совместного использования u32 и ipset, но сейчас главное получить правильно работающую функцию, которая отображает IP-адреса из указанных сетей на пространства классов и фильтров.
Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Предварительная версия скрипта, классифицирующего подсети с одинаковыми последними октетами с помощью u32 hashing filters: http://mercurial.intuxication.org/hg/sc/archive/tip.tar.gz

Теперь в конфиге нужно указывать подсети к которым принадлежат IP-адреса. Из-за вышеупомянутого фильтра, который блокирует весь трафик, сам шейпер будет иметь выход в Интернет только если для него тоже создан аккаунт. Наверное, стоит прикрутить добавление u32-фильтров для одиночных IP-адресов, чтобы в network и filter_network можно было указывать хосты с маской /32.

Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо, будем изучать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вопрос с генератором хэширующих фильтров решен. Я довел дело до релиза: http://sourceforge.net/projects/sc-tool/

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо, хорошая работа!

Результаты боевой эксплуатации отпишу после НГ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Кстати, а каким образом можно осуществить быструю загрузку большого кол-ва (от 10к) фильтров?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Исправил в версии 1.1.1 ошибку в фильтрах, возникающую если несколько раз подряд выполнить sc add <ip> <rate> для одного и того же IP-адреса.

 

Синтаксис tc для фильтра u32 довольно неоднозначен. Например, одинаковые с виду команды

tc filter replace dev eth1 parent 1: pref 20 handle 100:1 u32 ht 100:1: match ip src 10.0.0.2 flowid 1:3

tc filter replace dev eth1 parent 1: pref 20 handle 100:1:800 u32 ht 100:1: match ip src 10.0.0.2 flowid 1:3

tc filter replace dev eth1 parent 1: pref 20 u32 ht 100:1: match ip src 10.0.0.2 flowid 1:3

делают разные вещи.

Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

а удвоение скоростей есть? (типа ночью в два раза выше)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

да не, просто вопрос кто как это делает обычно... мне вот тоже не нравилось делать delete/add, наваял вот скриптец на баше

#/bin/bash

case $1 in
    "up" )
        for iface in $(echo "eth3 ifb0"); do
            tc class show dev $iface | awk -v iface=$iface '$5 ~ "1:4" || $5 ~ "1:5"  { match($14,/([0-9]*)([Aa-Zz]*)/,arr);
                system("tc class replace dev " iface " parent " $5 " classid " $3 " hfsc sc m1 0 d 1s m2 " arr[1]*2arr[2] " ul rate " arr[1]*2arr[2]) }'
        done
   ;;
    "down" )
        for iface in $(echo "eth3 ifb0"); do
            tc class show dev $iface | awk -v iface=$iface '$5 ~ "1:4" || $5 ~ "1:5" { match($14,/([0-9]*)([Aa-Zz]*)/,arr);
                system ("tc class replace dev " iface " parent " $5 " classid " $3 " hfsc sc m1 0 d 1s m2 " arr[1]/2arr[2] " ul rate " arr[1]/2arr[2]) }'
        done
   ;;
    * )
        echo "Error! What do you want to go today?!"
   ;;
esac

может кто красивее знает решение?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

да не, просто вопрос кто как это делает обычно... мне вот тоже не нравилось делать delete/add, наваял вот скриптец на баше

Очевидно, что красивое решение должно читать данные из базы для всех адресов за один раз и использовать tc -batch для перезагрузки правил, чтобы не было накладных расходов на создание процессов tc. И вместо shell с костылями лучше использовать Perl.

Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

для меня перл с модулями - костыль :) городить его везде... шелл есть везде, авк тоже. имхо решение должно использовать текущее состояние шейпера, иначе можно напороться на какой нить косяк в стиле в базе нет, а в шейпере есть и наоборот, либо предварительно делать синхронизацию... кстате, наверно можно переделать скрипт чтобы вначале выгружал tc show в файл, скрипт генерит batch-файл с удвоенными скоростями и потом заливает... надо попробовать :) спасибо за наводку :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Простые вещи, вроде тех, что делают shell, awk и sed, на Perl решаются без модулей. Он для этого и был задуман. При этом не нужно использовать временные файлы, т.к. там можно работать с пайпами как с обычными файлами, а не только строить цепочки из них:

open my $FH, "tc class show dev eth1 |";
my @out = <$FH>;
close $FH;
open my $FH2, "| tc -batch";
print $FH2 "class replace ...\n";
close $FH2;

Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Это у меня глюк, что при sc init отваливается сервер от сети (при filter_method = u32)?

Детально пока еще не изучал, да и tc с хэшем только в теории понимаю.

Изменено пользователем vadislaus

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

sc dbadd <shaper-ip>

и загружайте правила с помощью sc load. sc init -- команда только для тестовых целей, она создает корневые классы и дисциплины, не загружая аккаунты из базы.

Изменено пользователем photon

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

"Несколько IP на один класс" - каждый IP будет шейпится индивидуально? или все IP в классе будут делить полосу?
Ну естественно, несколько IP на одну очередь будут делить одну полосу пропускания. С другой стороны, я не хочу сейчас включать эту возможность, т.к. она ломает некоторые команды (show, list, операции с базой), и их под это дело нужно будет полностью переписывать. К тому же, не стоит провоцировать внедрение этой неоптимальной политики QoS.

Подскажите, как включить эту возможность? Работа с базой не нужна, после трех дней изучения понял, что моих навыков в PERL не хватает для правки :( Хотелось бы указывать несколько IP на класс, в качестве идентификатора использовать первый IP либо строку (логин), что предпочтительнее. Например вызывать

 

sc add 192.168.1.12 1024

sc add 192.168.1.30 1024 192.168.1.12

sc add 192.168.1.31 1024 192.168.1.12

 

либо

 

sc add 192.168.1.12 1024 login_1

sc add 192.168.1.30 1024 login_1

sc add 192.168.1.31 1024 login_1

 

Дополнение: все-таки удалось запустить, сделал небольшой патч, реализующий первый предложенный мной вариант:

 

--- sc.save     2010-03-15 15:11:46.000000000 +0300
+++ sc  2010-03-15 15:38:49.000000000 +0300
@@ -82,7 +82,7 @@
                # database handler (optional)
                'dbhandler' => \&cmd_dbadd,
                # arguments (optional)
-               'arg' => '<ip> <rate>',
+               'arg' => '<ip> <rate> <parent_ip>',
                # command description
                'desc' => 'add rules',
                # check root privileges before execution (optional)
@@ -1465,12 +1465,18 @@

sub cmd_add
{
-       my ($ip, $rate) = @_;
+       my ($ip, $rate, $parent_ip) = @_;
+       my $cid;

        arg_check(\&is_ip, $ip, 'IP');
        $rate = arg_check(\&is_rate, $rate, 'rate');
-       my $cid = ip_classid($ip);
-       return $rul_add->($ip, $cid, $rate);
+       if($parent_ip){
+           $parent_ip = arg_check(\&is_ip, $parent_ip, 'parent_ip');
+           $cid = ip_classid($parent_ip);
+       } else {
+           $cid = ip_classid($ip);
+       }
+       return $rul_add->($ip, $cid, $rate, $parent_ip);
}

sub cmd_del

Изменено пользователем a0d75

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Дополнение: чтобы не было "кто первый встал - того и тапки" поставил leaf_qdisc = 'sfq perturb 10'. Все работает отлично, однако почему-то

команды типа "/sbin/tc qdisc replace dev ifb0 parent 1:800e handle 800e:0 sfq perturb 10" отрабатывают с ошибкой для каждого последующего IP адреса, добавляемого к первому. Если сделать сначала del вместо replace - все работает как нужно. Хотя это не принципиально в моем случае.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Join the conversation

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

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.