Linux QOS:Тестирование различных вариантов управленя траффиком: различия между версиями
Sirmax (обсуждение | вклад) |
Sirmax (обсуждение | вклад) |
||
(не показано 17 промежуточных версий этого же участника) | |||
Строка 1: | Строка 1: | ||
+ | [[Категория:Заготовка Статьи]] |
||
[[Категория:not_tested]] |
[[Категория:not_tested]] |
||
[[Категория:Linux]] |
[[Категория:Linux]] |
||
[[Категория:QOS]] |
[[Категория:QOS]] |
||
+ | [[Категория:shaper]] |
||
+ | [[Категория:tc]] |
||
+ | |||
+ | |||
+ | =Что почитать еще= |
||
+ | * http://comments.gmane.org/gmane.linux.network/289937 |
||
+ | * http://forum.nag.ru/forum/index.php?showtopic=105810&st=0&p=1151018&#entry1151018 |
||
+ | * http://net-labs.in/2014/05/02/qos-%D0%B2-linux-%D0%BF%D0%BE%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE-%D1%83%D0%BC%D0%BE%D0%BB%D1%87%D0%B0%D0%BD%D0%B8%D1%8E-pfifo_fast-mq/ |
||
+ | * http://net-labs.in/category/linux/linux-qos/ |
||
+ | * http://www.linuxplumbersconf.org/2012/wp-content/uploads/2012/09/2012-lpc-networking-qdisc-fastabend.pdf |
||
+ | |||
=Linux Shaper= |
=Linux Shaper= |
||
Эта тема всегда вызывала у меня некоторые затруднения и потому я решил систематизировать свои знания. |
Эта тема всегда вызывала у меня некоторые затруднения и потому я решил систематизировать свои знания. |
||
+ | |||
+ | |||
+ | |||
+ | |||
==Описание лаборатории== |
==Описание лаборатории== |
||
Строка 20: | Строка 36: | ||
* Алиасами добавлены адреса 192.168.1.3-100 |
* Алиасами добавлены адреса 192.168.1.3-100 |
||
− | ===node- |
+ | ===node-2=== |
* 192.168.2.2 |
* 192.168.2.2 |
||
− | * Алиасами добавлены адреса 192.168.2.3-100 |
+ | * Алиасами добавлены адреса 192.168.2.3-100 |
===Router0=== |
===Router0=== |
||
Строка 307: | Строка 323: | ||
=====Проверка предположения про burst===== |
=====Проверка предположения про burst===== |
||
− | Как я писал выше, предположение что установка огромного burst вызовет всплеск трафика в начале теста требует подтверждения: настраиваю следующим |
+ | Как я писал выше, предположение что установка огромного burst вызовет всплеск трафика в начале теста требует подтверждения: настраиваю следующим образом |
<PRE> |
<PRE> |
||
tc qdisc replace dev eth1 root tbf rate 40Mbit burst 159900000 latency 10s |
tc qdisc replace dev eth1 root tbf rate 40Mbit burst 159900000 latency 10s |
||
Строка 672: | Строка 688: | ||
[[Изображение:011_htb__rate___1Mbit__default_burst_1600_cburst_1600_quantum_sfq_perturb_1__limit_65536_flows_512__depth_127__divisor__16384.png|700px|thumb|center]] |
[[Изображение:011_htb__rate___1Mbit__default_burst_1600_cburst_1600_quantum_sfq_perturb_1__limit_65536_flows_512__depth_127__divisor__16384.png|700px|thumb|center]] |
||
− | ====HFSC==== |
+ | ===== HFSC ===== |
+ | Подробнее о настройке - в другом разделе, тут только пример жеского шефпера который просто ограничивает скорость |
||
− | * http://ace-host.stuart.id.au/russell/files/tc/doc/sch_hfsc.txt |
||
− | * http://linux-ip.net/articles/hfsc.en/ |
||
− | |||
<PRE> |
<PRE> |
||
+ | DEV=eth1 |
||
− | Tutorial |
||
− | ======== |
||
− | HFSC stands for Hierarchical Fair Service Curve. Unlike its cousins CBQ and HTB it has a rigorous mathematical foundation that delivers |
||
− | a guaranteed outcome. In practice that means it does a better job than either CBQ or HTB, both of which are essentially best effort guesses at solving |
||
+ | tc qdis del root dev ${DEV} |
||
− | what is a surprisingly complex problem. Both of them get it wrong in subtle ways which shows up as them not meeting their bandwidth and latency guarantees. |
||
+ | tc qdisc replace dev eth1 root handle 1:0 hfsc default 1 |
||
+ | tc class add dev ${DEV} parent 1:0 classid 1:1 hfsc rt m2 1Mbit m2 |
||
</PRE> |
</PRE> |
||
+ | ==QOS - обеспечение приоритетов одного трафика над другим== |
||
− | HFTC - это Иерархическая Честная Обслуживающая Кривая (что бы это ни значило). В отличии от своих двоюродных братьев CBQ и HTB у HFSC есть строгое математическое обоснование которое дает гарантированный результат. На практике это означает что HFSC делает работу лучше чем CBQ или HTB, которые по сути тратят услилия на решение неожиданно сложных проблем. Оба они (CBQ & HTB) делают это неправильно хитрыми способами что приводит к недополучению полосы пропускания или гарантированных задержек. |
||
+ | Так как планируется большое число тестов и большое число данных, то первым делом нужно подготовить автоматизацию. |
||
− | <PRE> |
||
+ | Для генерации трафика я буду использовать iperf с переменным числом потоков, для сбора статистики - скрипт на питоне. Для визуализации - GnuPlot |
||
+ | ===HFSC=== |
||
+ | * http://ace-host.stuart.id.au/russell/files/tc/doc/sch_hfsc.txt |
||
+ | * http://linux-ip.net/articles/hfsc.en/ |
||
+ | Перенесено --> http://wiki.sirmax.noname.com.ua/index.php/Linux_QOS_HFSC |
||
− | The Service Curve |
||
− | ----------------- |
||
− | Like CBQ and HTB, HFSC assumes the user has defined classes of traffic. One class might be "telnet traffic from customer A" which will be assured low latency, assuming it uses a low total bandwidth. HFSC expects you to use one of filters tc provides to decide which class each packet belongs to. |
||
− | </PRE> |
||
− | |||
− | Как и CBQ & HTB, HFSC предпологает что пользователь определил классы трафика. Один класс может быть "траффик телнета для пользователя А" который гарантирует низкую задержку пока этот класс использует малую полосу пропускания. HFTC ожидает что вы будетет использовать фильты которые предоставляет tc для того что бы определить к какому классу отнести пакет |
||
− | |||
− | |||
− | <PRE> |
||
− | HFSC provides three types of service to each class, or to put it another way HFSC provides three knobs you can use to define the behaviour of each class: |
||
− | </PRE> |
||
− | |||
− | HFSC предоставляет 3 типа обслуживания каждому классу, или если сказать это по-другому HFSC предоставляет рукоятки которые можно |
||
− | использовать для определния поведения каждого из классов: |
||
− | |||
− | <PRE> |
||
− | rt Real time. This gives a class a hard guarantees about its real time speed. |
||
− | </PRE> |
||
− | |||
− | Real time. Этот флаг (ручка? =) ) дает классу жесткие гарантии о его real time speed. (примечание: гарантированная скорость?) |
||
− | |||
− | <PRE> |
||
− | ls Link share. If the link has data queued up to be sent (ie it is backlogged), its share of the links capacity is in proportion to this speed. Every class must have a real time or link share definition. |
||
− | </PRE> |
||
− | Link share. Если у линка есть данные поставленные в очередь на отправку, емкость линка распределяется пропорционально этой скорости. |
||
− | Каждый класс должен быть определен как rt или ls (примечание: не помешал бы пример!) |
||
− | |||
− | |||
− | <PRE> |
||
− | ul Upper limit. The maximum speed link share can send at. It can only used if the class has a link share defined. |
||
− | </PRE> |
||
− | Upper limit. Максимальная скорость на котоой ls класс может посылать данные (примечание: ceil?) |
||
− | |||
− | <PRE> |
||
− | The two letter codes above, "rt", "ls", and "ul" is how you identify these three types of service to the tc command. There is |
||
− | a fourth one: "sc". "sc" is a shorthand for setting both "rt" and "ls" to the same thing. |
||
− | </PRE> |
||
− | Двухбуквенные коды выше "rt", "ls" и "ul" это описание как определить эти три уровня обслуживания для команды tc. Существует так же четвертый код: "sc". "sc" это сокращение от "setting both" - установка обоих "rt" и "ls" для одного (класса?) |
||
− | |||
− | <PRE> |
||
− | The speed allocated to each service is specified as a normal speed and an optional burst speed: |
||
− | |||
− | SERVICE [m1 BPS d SEC] m2 BPS |
||
− | </PRE> |
||
− | Скорость выделенная для каждого сервиса определяется как нормальная скорость и опционально - burst speed |
||
− | <PRE> |
||
− | Where: |
||
− | |||
− | SERVICE "ls", "rt", "ul" - ie whether this specifies the link sharing, real time or upper limit service. |
||
− | |||
− | m2 BPS This is the steady state speed, eg "m2 10kbps" means the steady state allowance for this service class is 10 kilo bytes/sec. |
||
− | |||
− | m1 BPS d SEC The burst speed. "m1 20kbps d 10ms" means this class is allowed a burst speed of 20kbps for 10ms, then it must run at its steady state speed. |
||
− | </PRE> |
||
− | Где |
||
− | * SERVICE "ls" "rt" "ul": - определяет тип сервиса |
||
− | * m2: это "скорость устойчивого состояния", например "m2 10kbps" означает разрешение устойчивого состояния этого класса в 10 кбит в сек. Измеряется в bps |
||
− | * m1 это burst speed "m1 20kbps d 10ms" означает что классу разрешено burst speed 20kbps на 10ms а затем должен использовать "скорость устойчивого состояни" |
||
− | <PRE> |
||
− | In the specification and tc call this is called a "service curve".It is a curve in the same sense that any mathematical function can be plotted as a curve. In the paper this curve is used as the basis for mathematical proofs about the performance of the scheduler. Unless you also want to do mathematical proofs avoid thinking avoid thinking of specification as a curve. It is a speed with an optional latency specification - nothing more. |
||
− | </PRE> |
||
− | В спецификации и вызовах tc это называют "сервисной кривой". Это кривая имеет тот же смысл что и математическая функция которая может быть изображена как кривая. Эта кривая используется как математическое доказательство производительности планировщика. Если вы не собираетесь делать математические доказательства не думайте о спецификации как о кривой - это скорость с дополнительной спецификацией задержки и ничего более. |
||
− | |||
− | <PRE> |
||
− | (There is another syntax supported which is documented in the reference section below - "umax BYTES dmax SEC rate BPS". "rate BPS" is identical in meaning to "m2 BPS". The definition of "m2 BPS" does *not* always express specify a burst rate and time. I have not found any other documentation of what it can yield, probably because it is so complex to explain. Such complexity is best avoided - don't use "umax ... dmax ...". The original terms came from the paper, but tc didn't follow the paper's definitions of them to the letter.) |
||
− | </PRE> |
||
− | ( |
||
− | Существует другой синтаксис который описан в секции ниже: "umax BYTES dmax SEC rate BPS". |
||
− | * "rate BPS" соответвует "m2 BPS" |
||
− | * "m2 BPS" не всегда выражает burst rate и время. Я не нашел другой документации что это означает - вероятно это сложно пояснить. Таких сложностей лучше всего избежать - не используйте "umax ... dmax ...". Оригинальные термины пришли с бумаги но tc не следовал этим определениям. |
||
− | ) |
||
− | |||
− | <PRE> |
||
− | Burst and Latency |
||
− | ----------------- |
||
− | |||
− | The term "burst" hides more than it reveals. Yes, it specifies bursts, but it is not used to control bursts of data. It is used to control latency. This is not some minor quibble about naming conventions. Wrapping your head around this is fundamental to understanding HFSC. |
||
− | </PRE> |
||
− | Термин burst скрывает больше чем поясняет. Да он определяет burst но он не используется для burst данных а используется для контроля latency. |
||
− | Это не каламбур - это фундамент для понимания HFSC |
||
− | <PRE> |
||
− | But before going on, there is an even more important corollary to it being about latency. Most traffic doesn't care about latency. Web traffic doesn't, email doesn't. The two classes of traffic it might matter to are real time (like VOIP and NTP), and interactive traffic (like telnet, ssh, VNC, RDP and gaming). If you don't care about these do yourself a favour: don't use burst and skip this |
||
− | section entirely. |
||
− | </PRE> |
||
− | Прежде чем продолжить есть еше более важное замечание касающееся latency. Большая часть трафика не чувствительна к задержкам. Например web и email - не чувствительны. Real time имеет значение для VOIP NTP и интерактивного трафика - если вы не беспокоитесь об этом не используйте burst. |
||
− | <PRE> |
||
− | And a caveat. Any effort to control latency will fail abysmally (as in be a complete and utter waste of your time and your CPU's cycles) unless class doing the controlling is the slowest link in the chain. The moment any hop between source and destination starts buffering packets HFSC's efforts to constraint latency will be overwhelmed by delays caused by the buffering. In case it isn't obvious, this means you can never control ingress latency. |
||
− | </PRE> |
||
− | И напротив любые попытки контролировать задержки не пройдут. Это будет пустой тратой времени и циклов процесора если класс не контролирует самый едленный линк в цеочке. В момент когда хоп (роутрер) начинает буферизировать пакеты HFSC перестает контролировать задержку. Это неявно означает что вы никогда не сможете контролировать входную задержку (эту секцию написал Капитан очевидность) |
||
− | <PRE> |
||
− | To see how the burst speed effects latency, imagine we have two |
||
− | classes, say ssh and web, which we are happy to devote 50% of the |
||
− | link to over the long term. |
||
− | |||
− | When the link is idle the HFSC scheduler is given a 1499 byte web packet and a 1500 byte ssh |
||
− | packet to send. HFSC must decide which one to send one first, and |
||
− | after it does the other will be a backlog, awaiting it's turn to |
||
− | be sent. |
||
− | It is only if the link will become backlogged that the |
||
− | burst speed comes into play, and even then it is only for a |
||
− | short while - the length of time being specified by the SEC in |
||
− | "m1 BPS d SEC". In effect all it does is determine which of these |
||
− | packets get sent first. And that is how we get to latency - |
||
− | because whichever is sent first, ssh or web, will be perceived to |
||
− | have the lower latency. |
||
− | </PRE> |
||
− | Что бы увидеть как burst speed отражается на задержке представьте у нас есть 2 класса, скажем ssh и web которым мы рады выделить 50% полосы пропускания на длительный срок. |
||
− | <BR>Когда линк простаивает и планировщик HFSC получает на отправку 1499 байтовый пакет от web и 1500 байтовый пакет от класса ssh и HFSC должен решить который из пакетов отправить первым и после отправки другой пакет будет отложен ожидая своей очереди на отправку. |
||
− | |||
− | Только если есть отложенные данные burst speed вступакет в игру и даже тогда только на кроткое время - на время которое было определено в SEC в "m1 BPS d SEC". Эфект который жто дает - это определение какой иэ этих пакетов был отправлен первым. И это как мы получаем задержку потому что (пакет) отправленный первым будь то ssh или web будет иметь меньшую задержку. |
||
− | |||
− | <PRE> |
||
− | To figure out which packet to send HFSC calculates how long each will take to send, and sends the one that will finish sending first. The twist is it doesn't use link's raw speed to calculate this time, it uses the speed for the service. All three services (link share, real time and upper limit) do their calculations independently. |
||
− | </PRE> |
||
− | Что бы определить какой пакет отправлять HFSC вычисляет как долго займет отправка каждого и отравляет тот, отправка которого завершитья раньше. |
||
− | Обман в том что скорость линка не используется для вычисоения этого времени, а используется скорость определнная для сервиса. Все три сервиса (link share, real time и upper limit) делают вычисления независимо |
||
− | <PRE> |
||
− | Some examples will hopefully make this clear. Lets allocate web to classid 1:1, and ssh to classid 1:2, and say we have a 1mbps link. |
||
− | </PRE> |
||
− | Несколько примеров которые надеюсь сделают это все более понятным. Давайте создадим класс web (1:1) и ssh (1:2) и скажем что у нас 1мбитный линк (тут пояснить!!!!) |
||
− | <PRE> |
||
− | Example 1. |
||
− | |||
− | tc class add dev eth0 parent 1:0 classid 1:1 hfsc \ |
||
− | ls m2 500kbps # web |
||
− | tc class add dev eth0 parent 1:0 classid 1:2 hfsc \ |
||
− | ls m2 500kbps # ssh |
||
− | </PRE> |
||
− | Примечание: |
||
− | |||
− | <PRE> |
||
− | |||
− | We haven't set a burst speed, so the time it takes to send the |
||
− | packets is: |
||
− | |||
− | web 1499 / 500000 = 0.002998 sec |
||
− | ssh 1500 / 500000 = 0.003000 sec |
||
− | |||
− | So in this example web takes the shortest time to send, so it |
||
− | will it be send first and have the lower latency. |
||
− | </PRE> |
||
− | |||
− | |||
− | <PRE> |
||
− | Example 2. |
||
− | |||
− | Many would prefer ssh traffic to have lower latency than web. |
||
− | This will achieve it: |
||
− | |||
− | tc class add dev eth0 parent 1:0 classid 1:1 hfsc \ |
||
− | ls m1 100kbps d 1.5ms m2 500kbps # web |
||
− | tc class add dev eth0 parent 1:0 classid 1:2 hfsc \ |
||
− | ls m1 900kbps d 1.5ms m2 500kbps # ssh |
||
− | |||
− | Since this is the start of a backlog period it also marks the |
||
− | start of a bust period, so the bust speed in in effect. Thus |
||
− | we do that same calculation as in Example 1, but with burst |
||
− | speeds: |
||
− | |||
− | web 1499 / 100000 = 0.014990 sec |
||
− | ssh 1500 / 900000 = 0.001667 sec |
||
− | |||
− | In this scenario ssh will be sent first and thus appear to have |
||
− | the lower latency, which is what we wanted. In fact it because |
||
− | of the ratios chosen (100kbps for web versus 900kbps for ssh) a |
||
− | ssh packet would have to be 10 times larger than a web packet |
||
− | before it got sent second. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | The burst must be long enough to send the entire packet. That is |
||
− | what determined the 1.5ms above. Our link runs at 1mbps, so it |
||
− | takes (1500 / 1000000 = 1.5ms) to send a Maximum Transmit Unit |
||
− | (MTU) sized packet, assuming the MTU is 1500 bytes. |
||
− | </PRE> |
||
− | |||
− | |||
− | <PRE> |
||
− | Also notice the burst speed for web doesn't look like a "burst" |
||
− | at all. It is far slower than the steady state speed web normally |
||
− | receives. This is because it really *is* being used to control |
||
− | latency, not to specify a burst. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | Example 3. |
||
− | |||
− | That worked, but not as well as you hoped. You recall TCP can |
||
− | send multiple packets before waiting for a reply and you would |
||
− | like them all sent before web gets to send it's first packet. |
||
− | You also estimate you have 10 concurrent users all doing the same |
||
− | thing. From a packet capture you decide 4 sending packets before |
||
− | waiting for a reply is typical. |
||
− | |||
− | 10 users by 4 packets each means 40 MTU sized packets. Thus you |
||
− | must adjust the burst speed, so ssh gets 40 times the speed of |
||
− | web and you must allow for 40 MTU sized packets in the burst |
||
− | time: |
||
− | |||
− | tc class add dev eth0 parent 1:0 classid 1:1 hfsc \ |
||
− | ls m1 24kbps d 60ms m2 500kbps # web |
||
− | tc class add dev eth0 parent 1:0 classid 1:2 hfsc \ |
||
− | ls m1 975kbps d 60ms m2 500kbps # ssh |
||
− | |||
− | Note that 975:24 is 40:1, and (40 * 1500 / 1mbps = 60). |
||
− | |||
− | If a class's burst speed is truly a burst (ie allowed it to send |
||
− | faster than it's normal steady state speed), it will only be |
||
− | allowed to do it if it has been sending at less than it's steady |
||
− | state speed for long enough to accrue the headroom required for the |
||
− | burst. To put it another way, a class will not be allowed a burst |
||
− | if over the long term it would mean it is running over it's steady |
||
− | state speed. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | On the other hand if a classes "burst" is really a "go slow" than |
||
− | (like web's) it can be have its bandwidth pinched at any time by a |
||
− | class (like ssh) that is allowed a burst, thus giving it truly bad |
||
− | latency. In this sense ssh's good latency doesn't come for free. |
||
− | It gains it at the expense of web having bad latency. This will |
||
− | always be true, and is conceptually no different to the trade off |
||
− | you make for bandwidth. If you guarantee web good bandwidth over |
||
− | the long term, then some traffic (eg email) must be getting bad |
||
− | bandwidth when web is using it. Similarly web's latency will be |
||
− | bad when ssh is making use of its latency advantage. However, |
||
− | because HFSC guarantees that ssh will not exceed it's steady state |
||
− | bandwidth over the long term web will still average at least the |
||
− | bandwidth you allocated it. In the HFSC paper, they say the |
||
− | latency and bandwidth specifications are decoupled, meaning over |
||
− | the long term one has no effect on the other. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | Finally, since HFSC favours packets that can be sent quickly it |
||
− | favours sending small packets before large ones. By happy |
||
− | coincidence this is generally what you want. VOIP, DNS, NTP, TCP |
||
− | startup and ACKs are all small. Since the advantage you get from |
||
− | giving a class a high burst is measured in milliseconds, not |
||
− | seconds, specifying a burst for link sharing often isn't worth the |
||
− | effort. |
||
− | </PRE> |
||
− | |||
− | |||
− | <PRE> |
||
− | The meaning of "real time" |
||
− | -------------------------- |
||
− | |||
− | tc-hfsc's web page follows the terminology in the paper and says |
||
− | "real time" gives guaranteed bandwidth. Web pages talking about |
||
− | HFSC take this to imply link share does not give guaranteed |
||
− | bandwidth. This is true, but misleading. The "guarantees" given |
||
− | by the alternatives (like CBQ and HTB) are no better. |
||
− | </PRE> |
||
− | |||
− | |||
− | <PRE> |
||
− | The real time gives you something nothing else does: a hard |
||
− | deadline. Link share's will latency will on occasion be out by a |
||
− | 100's of milliseconds, very occasionally seconds. But notice we |
||
− | are talking seconds and milliseconds here. If you do not have |
||
− | traffic that cares about millisecond delays then you don't care |
||
− | about real time. There are very few traffic classes that do care - |
||
− | only VOIP and maybe NTP spring to mind. In particular if you were |
||
− | a satisfied user of HTB or CBQ, you don't care about real time. If |
||
− | you don't care about real time do yourself a favour: don't use it, |
||
− | and stop reading this section. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | Real time's guarantees do not come for free, nor are they what they |
||
− | seem. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | The first issue is in order to give hard real time guarantees the |
||
− | real time service must take into account all data a class has sent |
||
− | since the link was brought up. If the class has has exceeded its |
||
− | real time steady state speed in the past (probably by using |
||
− | bandwidth when no one else wanted it) then it can be denied *any* |
||
− | bandwidth by the real time class until it gets under its long term |
||
− | steady state speed. In practice this probably won't be an issue, |
||
− | but being penalised for using bandwidth no one else wanted it |
||
− | usually thought of as "unfair" (yes this is a well defined term |
||
− | when dealing with quality of service), and thus the real time is an |
||
− | unfair allocator of bandwidth. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | The second issue is in order to provide it's guarantees, real time |
||
− | may have keep the link idle in case a high priority packet needs to |
||
− | be sent in order to maintain latency guarantees. Ego there may be |
||
− | times when a packet is waiting to be sent, but the link is idle, |
||
− | thus the link will be artificially constrained to below its rated |
||
− | capacity. A service that always takes advantage of the links rated |
||
− | capacity is called work preserving. Link share is work preserving. |
||
− | Real time isn't. There is a corollary to this. Because real time |
||
− | delays sending packets it's accuracy can depend on the resultion of |
||
− | the kernels timers. For example, if your hardware + kernel only |
||
− | supprts a 100hz timer, the best latency resolution you can get is |
||
− | 10 milliseconds. Common modern hardware provides very accurate |
||
− | timers, but it's worth your while checking if you are taking the |
||
− | road less travelled. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | The third issue is real time provides a hard latency guarantee in |
||
− | the sense that latency is bounded to an absolute maximum. However |
||
− | that absolute maximum isn't necessarily what you specified when you |
||
− | said "m1 12500 d 2ms". You might expect that guarantees a 250 |
||
− | byte packet will be sent within 2ms. It doesn't, unless you do not |
||
− | use link share or put any other qdisc between HFSC and the device. |
||
− | Recall that real time will deliberately hold the line idle in order |
||
− | to give it's guarantee. The issue is link share will sneak in and |
||
− | send a packet over that idle link while real time isn't watching. |
||
− | In practice this means real time's latency guarantees can be out by |
||
− | the time it takes to send one MTU sized packet. So the guarantee |
||
− | isn't 2ms. It's (2ms + time to send MTU sized packet). You can of |
||
− | course compensate for this by specifying the time as (2ms - time to |
||
− | send MTU sized packet), provided your link is fast enough to send |
||
− | MTU sized packet + 250 bytes within 2ms. |
||
− | </PRE> |
||
− | |||
− | </PRE> |
||
− | The fourth issue is real time says nothing about what to do with |
||
− | the links spare capacity. If you don't use link share as well, |
||
− | the guaranteed minimum also becomes a maximum. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | The fifth issue is unlike link share, the bandwidths you give |
||
− | to real time must be accurate, and their sum must be below the |
||
− | links capacity. This means the sum of the burst speeds must be |
||
− | below the links capacity, and the sum of the steady state speeds |
||
− | must also be below the links capacity. Ensuring this if don't you |
||
− | use the same value for "d" or "dmax" in every class requires |
||
− | solving multiple linear equations. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | The sixth issue is if you use up all your bandwidth with real time |
||
− | guarantees, then when the link is backlogged link share will get |
||
− | no share, as in will never send a packet and all that goes along |
||
− | with that - like TCP connections timing out and dieing. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | In summary, real time good for one thing: guaranteeing hard |
||
− | latencies. So specifying a real time service without a burst time |
||
− | is a waste of time. The converse is also true: real time is |
||
− | absolutely useless for anything but guaranteeing hard latencies. |
||
− | Everything else is better done using link share. |
||
− | </PRE> |
||
− | |||
− | |||
− | <PRE> |
||
− | Using link share and upper limit |
||
− | -------------------------------- |
||
− | |||
− | Under link share the speed a backlogged class can send depends on |
||
− | ratio of its speed to other backlogged classes. (If class isn't |
||
− | backlogged then by definition it's sending packets as fast as it |
||
− | wants, so link share doesn't need to arbitrate on it's behalf.) |
||
− | Link share does one thing: when the underlying device says its |
||
− | ready to send a packet, it looks at what classes that is furtherest |
||
− | away from the proportion of the link it should have, and sends its |
||
− | packet. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | An example. Lets say we have classes A, B and C, who have link |
||
− | share specifications of: |
||
− | |||
− | class A: hfsc ls rate 10kbps |
||
− | class B: hfsc ls rate 20kbps |
||
− | class C: hfsc ls rate 30kbps |
||
− | |||
− | A and B are sending packets as fast as they can, so they will be |
||
− | backlogged. C is idle. The ratio of the speeds ratio of the |
||
− | backlogged classes, A and B, is 10 to 20, ie 1 to 2. So link share |
||
− | ensures for every byte A sends, B sends 2. |
||
− | |||
− | It's so simple it's important to note what this calculation doesn't |
||
− | depend on: |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | A. It doesn't depend on the speed of the underlying link. Link |
||
− | share doesn't need to know what that speed is, and the numbers |
||
− | you give it need have no relationship to that speed. Only the |
||
− | ratios matter. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | B. This implies link share is immune to link speed changing during |
||
− | the day, as real internet connections often do. |
||
− | </PRE> |
||
− | |||
− | <PRE> |
||
− | C. Link share doesn't care who sends the packets - it or real |
||
− | time. They are all counted the same way. |
||
− | </PRE> |
||
− | |||
− | |||
− | There are some complications as well: |
||
− | |||
− | A. Link share will not give a class more than the upper limit. |
||
− | Real time does not respect upper limit, but since link share |
||
− | counts what real time sends going over the upper limit using |
||
− | real time will be penalised later by link share. |
||
− | |||
− | B. Link share only gets what's left over after real time sends |
||
− | it's packets. To link share the bandwidth used by real time |
||
− | looks like the link speed varying a bit faster than it would |
||
− | otherwise. |
||
− | |||
− | C. A class is allowed to exceed its steady state speed by using |
||
− | its burst speed when it first becomes backlogged. Once the |
||
− | burst allowance is exhausted it can not exceed the steady state |
||
− | speed until the backlog has been completely cleared. |
||
− | |||
− | And there is one negative. Link share will send packets as fast as |
||
− | the underlying device will let it. If the underlying device isn't |
||
− | the slowest thing between it and the destination link share won't |
||
− | be the thing controlling what packet gets sent next - it will |
||
− | be whatever scheduler is running on the slowest device. Typically |
||
− | on a Linux box the device HFSC is controlling is an Ethernet NIC |
||
− | that runs at giggabits per second. The slowest thing is probably |
||
− | the thing it is connected to - the modem, so unless do something |
||
− | the modem will managing traffic, not HFSC. If your Linux box isn't |
||
− | controlling an Ethernet NIC its most likely attempting to schedule |
||
− | traffic on a virtual device. Under Linux virtual network devices |
||
− | like tunnels, ifb (used for ingress scheduling), and tun/tap |
||
− | devices processing their packets as soon as they receive them. To |
||
− | a scheduler they appear to be infinitely fast. This means on a |
||
− | typical Linux setup not only will link share have absolutely no |
||
− | effect on the outgoing traffic, it's propensity to flood the link |
||
− | will destroys any chance real time had at controlling latency. |
||
− | |||
− | To fix this, you must limit the rate link share can send using |
||
− | upper limit. Remember, for link share to be effective the limit |
||
− | must be lower than the slowest link between the source and |
||
− | destination. Upper limit has one other use - constraining a |
||
− | customer to the bandwidth they paid for. |
||
− | |||
− | Finally, link share can't give hard latency guarantees. So its |
||
− | burst numbers don't mean "send an ssh packet within 10 |
||
− | milliseconds". Instead they mean "if ssh has been quiet for a |
||
− | while, briefly increase the ratio at which ssh can send packets, |
||
− | so it gets better latency than competing classes". That said, |
||
− | if you follow these rules link share will get reasonably close |
||
− | to the latency you ask for: |
||
− | |||
− | a. For classes that use real time, you use exactly the same |
||
− | link share specification. Recall "sc" does this. |
||
− | |||
− | b. The total bandwidth you allocate for link share doesn't |
||
− | exceed the links capacity or upper limit. This must be |
||
− | true for both burst and steady state speeds. |
||
− | |||
− | |||
− | The Class Hierarchy |
||
− | ------------------- |
||
− | |||
− | Like HTB and CBQ, HFSC allows you to create a hierarchy of classes. |
||
− | This is an example: |
||
− | |||
− | +1:0---------+ |
||
− | | qdisc | |
||
− | | 1500kbit | |
||
− | +------------+ |
||
− | / \ |
||
− | +-1:10------+ +-1:20------+ |
||
− | | User A | | User B | |
||
− | | 50% share | | 50% share | |
||
− | | Unlimited | | 1000kbit | |
||
− | +-----------+ +-----------+ |
||
− | / \ |
||
− | +-1:11-------+ +-1:12---------+ |
||
− | | Web | | VOIP | |
||
− | | 100% share | | 20ms Latency | |
||
− | | Unlimited | | 100kbit | |
||
− | +------------+ +--------------+ |
||
− | |||
− | Intuitively this does the following: |
||
− | |||
− | - User A can use all of the links bandwidth. |
||
− | - All User A's spare bandwidth goes towards web browsing. |
||
− | - User A has VOIP which must have low latency. |
||
− | - User B can use a maximum of 1000kbit. |
||
− | - User B gets 50/50 share of a congested link. |
||
− | |||
− | Up till now we have been discussed the leaf nodes sharing a common |
||
− | parent (inner node) interact. This is how the hierarchy effects |
||
− | each type HFSC service: |
||
− | |||
− | ls A parent enforces its link sharing allocation on its |
||
− | children. In other words the siblings get to fight over |
||
− | the proportion of the shared bandwidth allocated to their |
||
− | parent, and the parent and it's siblings get to fight over |
||
− | whatever their ancestors link sharing allocations are. |
||
− | |||
− | rt The hierarchy does not effect the bandwidth allocated by the |
||
− | real time service any way. rt specifications for inner nodes |
||
− | are ignored. |
||
− | |||
− | ul A parent enforces its upper limit allocation on its children. |
||
− | In other words the sum of the bandwidth used by children's |
||
− | link sharing service will never exceed any of their ancestors |
||
− | upper limits. |
||
− | |||
− | In practice, for most devices, you will need one class enforcing an |
||
− | upper limit so link share doesn't flood the link and thus destroy |
||
− | HFSC's ability to schedule. That class will be the root, of |
||
− | course. |
||
− | |||
− | With those definition in hand it this is how the above hierarchy |
||
− | is implemented: |
||
− | |||
− | # |
||
− | # Save typing when creating classes. |
||
− | # |
||
− | ca() { |
||
− | par=$1; class=$2; shift 2 |
||
− | tc class add dev eth0 parent 1:$par classid 1:$class hfsc "$@" |
||
− | } |
||
− | # |
||
− | # Create the qdisc. Send unclassified traffic to 1:11. |
||
− | # If "default" isn't given unclassified traffic is dropped. |
||
− | # |
||
− | tc qdisc add dev eth0 root handle 1:0 hfsc default 11 |
||
− | ca 0 1 ls m2 1500kbit ul m2 1500kbit # Stop link flooding |
||
− | # |
||
− | # Create classes representing each user. |
||
− | # |
||
− | ca 1 10 ls m2 750kbit # User A |
||
− | ca 1 20 ls m2 750kbit ul m2 1000kbit # User B |
||
− | # |
||
− | # User A's web traffic. |
||
− | # |
||
− | ca 10 11 ls m2 1500kbit # User A web |
||
− | # |
||
− | # VOIP. We said VOIP uses 100kbit, and required 20ms latency. |
||
− | # We also know that HFSC can break its rt latency guarantees |
||
− | # by one MTU packet. Assuming MTU is 1500 bytes, it takes: |
||
− | # |
||
− | # 1500 [byte] * 8 [bits/byte] / 100000 [bits/sec] = 12 msec |
||
− | # |
||
− | # to send an MTU sized packet. That means we must send the |
||
− | # VOIP packet within 8ms (= 20ms - 12ms) to meet the latency |
||
− | # requirements. |
||
− | # |
||
− | # The requirements didn't say how big a VOIP packet is, but given |
||
− | # it has to send a new packet every 20ms the biggest it could be |
||
− | # is: |
||
− | # 100000 [bit/sec] / 8 [bit/byte] * 0.02 [sec/pkt] = 250 byte/pkt |
||
− | # So, we have 8ms to send 250 bytes, which works out to be: |
||
− | # 250 [bytes] * 8 [bit/byte] / 0.008 [sec] = 250kbit |
||
− | # |
||
− | ca 10 12 rt m1 250kbit d 8ms m2 100kbit # User A VOIP |
||
− | |||
− | |||
− | |||
− | Reference |
||
− | |||
− | ========= |
||
− | |||
− | Qdisc Parameters |
||
− | ---------------- |
||
− | |||
− | default <CLASSID> |
||
− | Send unclassified packets to <classid>. If not supplied |
||
− | unclassified packets are dropped. |
||
− | |||
− | Class Parameters |
||
− | ---------------- |
||
− | |||
− | ls <SERVICE-CURVE> |
||
− | Apportions how much of a backlogged link's spare capacity |
||
− | should be allocated to this class and its children if a packet |
||
− | isn't being sent under the rt <SERVICE-CURVE>. The bandwidth |
||
− | allocated by <SERVICE-CURVE> of all sibling classes wanting to |
||
− | share the excess capacity is summed, then the ratio of the |
||
− | links capacity after real time to the total bandwidth consumed |
||
− | this class and all it's offspring is equal to the ratio the |
||
− | classes <SERVICE-CURVE> bandwidth to the sum. When calculating |
||
− | <SERVICE-CURVE>, <BURST-SEC> is measured from the last time |
||
− | this class was backlogged, ie had packets waiting to be |
||
− | transmitted. Every leaf class must have a ls or rt (or both) |
||
− | <SERVICE-CURVE> specified. Every inner class must be given an |
||
− | ls <SERVICE-CURVE>. |
||
− | |||
− | rt <SERVICE-CURVE> |
||
− | <SERVICE-CURVE> sets the amount of bandwidth a leaf class is |
||
− | guaranteed. rt is ignored for inner classes. This amount of |
||
− | bandwidth is always available to it regardless of the other |
||
− | classes use of the link or the maximum bandwidth allowed by |
||
− | this class or its parents. When calculating <SERVICE-CURVE>, |
||
− | the calculation of the start time of <BURST-BPS> is complex. |
||
− | Roughly, it is the last time the class was backlogged and was |
||
− | under the guaranteed rate. Every leaf class must have a ls or |
||
− | rt <SERVICE-CURVE> specified. |
||
− | |||
− | ul <SERVICE-CURVE> |
||
− | For classes with a ls curve, set the maximum bandwidth this |
||
− | class and its children are permitted to use. This only effects |
||
− | sending packets under the ls <SERVICE-CURVE>, but packets set |
||
− | under the rt curve are included in the bandwidth calculation. |
||
− | When calculating <SERVICE-CURVE>, <BURST-SEC> is measured from |
||
− | the last time this class was backlogged, ie had packets waiting |
||
− | to be transmitted. |
||
− | |||
− | <SERVICE-CURVE> |
||
− | --------------- |
||
− | |||
− | A service curve specifies how much bandwidth a class can use. It |
||
− | has an optional initial burst rate, followed by a steady state. |
||
− | The start time of the burst depends on the service type (rt, ul or |
||
− | ls). The are two syntaxes available for describing a service |
||
− | curve. In both you use the usual tc units to designate speed, |
||
− | data size and time. |
||
− | |||
− | [m1 <BURST-SPEED> d <BURST-SEC>] m2 <STEADY-SPEED> |
||
− | <BURST-SPEED> is the speed of the burst, and <BURST-SEC> is the |
||
− | length. Thereafter the class sends at <STEADY-SPEED>. |
||
− | |||
− | [umax <BURST-BYTES> dmax <BURST-DSEC>] rate <STEADY-SPEED> |
||
− | "rate" has an identical meaning to "m2" above, so it specifies |
||
− | the long term speed the class is entitled to. To determine what |
||
− | "umax ... dmax ..." means, an implied burst speed is calculated |
||
− | using "<BURST-BYTES> / <BURST-DSEC>". If this burst speed larger |
||
− | than <STEADY-SPEED> then this syntax is equivalent to "m1 |
||
− | (<BURST-BYTES> / <BURST-DESC>) d <BURST-DSEC> m2 <STEADY-SPEED>" |
||
− | where the stuff in (...) is calculated. If the implied burst |
||
− | speed is not greater than <STEADY-SPEED> then during the burst |
||
− | period effective specification becomes "m1 0 d (<BURST-DSEC> - |
||
− | <BURST-BYTES> / <STEADY-SPEED>) m2 <STEADY-SPEED>". This means |
||
− | the class is not allowed to send any data at all during the |
||
− | burst period. The burst period is the time left over after |
||
− | if <BURST-BYTES> were sent at <STEADY-SPEED>. |
||
− | |||
− | |||
− | Classes. Traffic is assigned to HFSC classes using a filter. |
||
− | |||
− | Scheduling. The HFSC scheduler sends packets required to meet |
||
− | guaranteed bandwidth specified by rt, but only if those requirements |
||
− | would be broken by not sending them. In that case it sends the |
||
− | packet that will complete sending closest to its deadline. If not |
||
− | forced to send packets required by rt it will send a packet according |
||
− | to the ls criteria, choosing the packet that will complete sending |
||
− | closest to its deadline. For both rt and ls, time is measured with a |
||
− | clock running at one tick per bit per second of bandwidth allocated |
||
− | by the <SERVICE-CURVE>. Thus specifications with higher bandwidth |
||
− | appear to have their deadlines arrive sooner, and packets appear to |
||
− | be waiting longer and thus are sent sooner in actual time. |
||
− | |||
− | Policing. HFSC discard packets that aren't classified unless |
||
− | the default classid is specified to the qdisc. |
||
− | |||
− | Rate Limiting. HFSC restricts classes to the rate limit imposed by |
||
− | the ul specification, and the rate limit imposed by its ancestor |
||
− | classes on their children. Classes that have exceeded their |
||
− | real time <SERVICE-CURVE> in the past may be rate limited during if |
||
− | they don't also have a link share and the link is backlogged. |
||
− | |||
− | Classifier. The HFSC queuing discipline does not classify packets. |
||
− | </PRE> |
||
==Источники== |
==Источники== |
||
Строка 1377: | Строка 728: | ||
* http://ace-host.stuart.id.au/russell/files/tc/doc/cls_u32.txt |
* http://ace-host.stuart.id.au/russell/files/tc/doc/cls_u32.txt |
||
* https://nuclearcat.com/mediawiki/index.php/U32_tips_tricks |
* https://nuclearcat.com/mediawiki/index.php/U32_tips_tricks |
||
+ | |||
+ | |||
+ | * http://lartc.org/howto/lartc.adv-filter.policing.html |
||
+ | * http://www.nestor.minsk.by/sr/2006/05/sr60516.html |
||
+ | |||
+ | |||
+ | SFQ |
||
+ | * http://stuff.onse.fi/man?program=tc-sfq§ion=8 |
||
+ | |||
+ | U32 |
||
+ | * http://ace-host.stuart.id.au/russell/files/tc/doc/cls_u32.txt |
Текущая версия на 14:22, 12 марта 2020
Что почитать еще
- http://comments.gmane.org/gmane.linux.network/289937
- http://forum.nag.ru/forum/index.php?showtopic=105810&st=0&p=1151018&#entry1151018
- http://net-labs.in/2014/05/02/qos-%D0%B2-linux-%D0%BF%D0%BE%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE-%D1%83%D0%BC%D0%BE%D0%BB%D1%87%D0%B0%D0%BD%D0%B8%D1%8E-pfifo_fast-mq/
- http://net-labs.in/category/linux/linux-qos/
- http://www.linuxplumbersconf.org/2012/wp-content/uploads/2012/09/2012-lpc-networking-qdisc-fastabend.pdf
Linux Shaper
Эта тема всегда вызывала у меня некоторые затруднения и потому я решил систематизировать свои знания.
Описание лаборатории
Для тестирования я использую лабу из 3 виртуальных машин, виртуалбокс. Базовая ОС - Мак Ос
|-------| |--------| |-------| |node-1 |-eth0-----eth1-|router0 |-eth2-----eth0-|node-2 | |-------| |--------| |-------| | eth0 | HOST
node-1
- 192.168.1.2
- Алиасами добавлены адреса 192.168.1.3-100
node-2
- 192.168.2.2
- Алиасами добавлены адреса 192.168.2.3-100
Router0
- eth1: 192.168.1.1
- eth2: 192.168.2.1
eth0 - служит для доступа к лабе и никак в тестах не участвует.
Все политики клсассы и прочее - только на транзитных интерфейсах eth1 и eth2
Базовое тестирование-ограничение скорости
Так как планируется большое число тестов и большое число данных, то первым делом нужно подготовить автоматизацию. Для генерации трафика я буду использовать iperf с переменным числом потоков, для сбора статистики - скрипт на питоне. Для визуализации - GnuPlot
Как тестируем
Тест проходит следующим образом:
- на node-1 запущены множество экземпляров iperf в режиме сервера
BASE_PORT=5000 for I in `seq 2 100` do let PORT=BASE_PORT+I echo ${PORT} iperf -s -l 32k -w 512k -u -p ${PORT} -D iperf -s -l 32k -w 512k -p ${PORT} -D done
- на node-2 запускается iperf в 30 потоков, каждый - на другой порт и на другой IP, для того что бы в дальнейших тестах проверять классы трафика и
для более равномерного распределения. sleep 30 - нужен для того что бы успеть запустить счетчики на ноде 1
В случае когда условия тестирования отличаются - я буду указывать отдельно
#!/bin/bash sleep 30 BASE_PORT=5000 for I in `seq 2 ${1}` do . IP=192.168.1.${I} let PORT=BASE_PORT+I #echo iperf -c ${IP} -b 100000M -i 1 -l 60K -t 120 -p ${PORT} -D iperf -c ${IP} -b 100000M -i 1 -l 60K -t 120 -p ${PORT} -D iperf -c ${IP} -b 100000M -i 1 -l 60K -t 120 -p ${PORT} -u -D done
- В процессе работы собираем траффик наколенном скриптом на питоне и складываем в лог, потом рисуем график используя GnuPLOT
import time import datetime as dt import sys stop_time=time.time()+300 iface='eth0' sleep_time=0.5 tx_data_file = open('/sys/class/net/'+iface+'/statistics/tx_bytes', 'r') rx_data_file = open('/sys/class/net/'+iface+'/statistics/rx_bytes', 'r') res_file = open(str(sys.argv[1]),'w') for l in rx_data_file: in_bytes_prev=int(l) for l in tx_data_file: out_bytes_prev=int(l) while True: try: rx_data_file.seek(0) tx_data_file.seek(0) for l in rx_data_file: in_bytes=int(l) for l in tx_data_file: out_bytes=int(l) in_bytes_diff=in_bytes-in_bytes_prev out_bytes_diff=out_bytes-out_bytes_prev in_bytes_prev=in_bytes out_bytes_prev=out_bytes time.sleep(sleep_time) res_file.write(str(time.time())+" "+str((in_bytes_diff)*8/sleep_time)+" "+str((out_bytes_diff)*8/sleep_time)+"\n") print str(time.time())+" "+str(in_bytes_prev)+" "+str(in_bytes)+" "+str((in_bytes_diff)*8)+" "+str(out_bytes_prev)+" "+str(out_bytes)+" "+str(out_bytes_diff)+" IN="+str((in_bytes_diff)*8/1024/1024/sleep_time)+" OUT="+str((out_bytes_diff)*8/1024/1024/sleep_time) if time.time()>stop_time: break except: break res_file.close()
Скрипт для GnuPlot - заготовка из кототорой на лету формируем awk то что надо - подставляя входной файл, имя графика и т.д.
#!/usr/bin/gnuplot -persist set terminal png size 1400,600 # Размер и формат графика. set output "/root/no_shaper.png" set title "no_shaper" # Заголовок set nokey # не знаю. Уточнить. set key top left # Расположение подписи set key box # Оформление (в рамке) подписи к графикам set xlabel "Date" # Метка по оси Х set xdata time # Описать что по оси Х время (формат ниже) set timefmt "%s" # Формат даты соответвует формату gnu date # В моем случае был удобен такой формат. set ylabel "Traffic" #set format y '%.0s%cB' set format y '%s' plot \ "/root/no_shaper.log" using 1:2 with lines title "IN, bit/s" smooth bezier, \ "/root/no_shaper.log" using 1:2 with lines title "IN, bit/s" , \ "/root/no_shaper.log" using 1:3 with lines title "OUT, bit/s" smooth bezier, \ "/root/no_shaper.log" using 1:3 with lines title "OUT, bit/s" [root@node-1 ~]# cat plot.sh #!/usr/bin/gnuplot -persist set terminal png size 1400,600 # Размер и формат графика. set output "___OUTPUT_FILE___" set title "___TITLE_OF_PLOT___" # Заголовок set nokey # не знаю. Уточнить. set key top left # Расположение подписи set key box # Оформление (в рамке) подписи к графикам set xlabel "Date" # Метка по оси Х set xdata time # Описать что по оси Х время (формат ниже) set timefmt "%s" # Формат даты соответвует формату gnu date # В моем случае был удобен такой формат. set ylabel "Traffic" #set format y '%.0s%cB' set format y '%s' plot \ "___INPUT_FILE___" using 1:2 with lines title "IN, bit/s" smooth bezier, \ "___INPUT_FILE___" using 1:2 with lines title "IN, bit/s" , \ "___INPUT_FILE___" using 1:3 with lines title "OUT, bit/s" smooth bezier, \ "___INPUT_FILE___" using 1:3 with lines title "OUT, bit/s"
Точка отсчета - без шейпера
Для того что бы получить некоторую точку отсчета (учитывая что лаба - это ВМки) делаю первый прогон без ограничения трафика.
Бесклассовые дисциплины
Я не буду рассматривать в этом разделе дисциплины без возможности ограничения трафика - по той причине что на неогруженных интерфейсах это не имеет практического смысла
RED
Отличная документация: "Подробнее с RED можно ознакомится в исходниках ядра"
TBF
Про TBF много пишут но я никогда ее не использовал. Соответственно - нужно тестировать.
Как и все бесклассовые дисциплины крепиться или к листу (leaf) или к интерфейсу.
Об этом напишу подробнее ниже.
Напомню что eth1 - интерфейс в сторону node-1
Удаляем текущую дисциплину
tc qdis del dev eth1 root
Убеждаемся что удалена (т е стоит по умолчанию pfifo_fast)
tc qdisc s dev eth1 qdisc pfifo_fast 0: root refcnt 2 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1 qdisc ingress ffff: parent ffff:fff1 ---------------- qdisc ingress ffff: parent ffff:fff1 ----------------
Второй раз удалить дисциплину по-умолчанию нельзя:
tc qdis del dev eth1 root RTNETLINK answers: No such file or directory
Добавляем дисциплину tbf:
tc qdisc add dev eth1 root tbf rate 180kbit latency 20ms buffer 1540
Проверяем:
tc qdisc s dev eth1 qdisc tbf 8002: root refcnt 2 rate 180000bit burst 1539b lat 20.0ms qdisc ingress ffff: parent ffff:fff1 ----------------
Описание параметров
После длительного гугления я так и не нашел внятного описания параметров. Потому попробую процитировать
- rate — ограничение скорости
- latency — максимальный "возраст"пакета в очереди
- burst — размер буфера. В байтах. (burst/buffer/maxburst - альтернативные названия что вносит некоторую путаницу)
Вот такое описание я нашел на Хабре, красным - мои вопросы
Дисциплина ТBF для своей работы использует механизм токенов. Токены генерируются системой с постоянной какой??? скоростью и помещаются в буфер(bucket). За каждый токен, вышедший из буфера с интерфейса уходит IP-пакет.А как насчет размера пакета? скорость передачи зависит от размера пакета
Если скорости передачи пакетов и генерации токенов совпадает, процесс передачи данных идет без задержки.
Если скорость передачи пакетов меньше чем скорость токенов, последние начинают накапливаться в буфере и затем могут использоваться для кратковременной передачи данных на скорости выше пороговой.
Если скорость передачи пакетов выше — токенов начинает не хватать. Пакеты данных ожидают новых токенов некоторое время Какое? думаю - пока не заполнится очередь заданая limit/latency, а затем начинают отбрасываться.
Прямым следствием из этого я вижу следующее - если задать бурст ОЧЕНЬ большим то можно ожидать всплеска траффика в начале теста.
Впрочем немного погуглив - найдено другое описание алгоритма
http://linux.die.net/man/8/tc-tbf
Результаты
Результаты (для меня) достаточно неожиданные
- Таки да - достаточно четко выставлена нужная скорость
- Явных потерь пингов я не наблюдаю
- Рост задержек явно не соответствует обещанным 20мс но и не запредельный
64 bytes from node-2 (192.168.2.2): icmp_seq=19 ttl=63 time=84.5 ms 64 bytes from node-2 (192.168.2.2): icmp_seq=20 ttl=63 time=84.6 ms 64 bytes from node-2 (192.168.2.2): icmp_seq=21 ttl=63 time=82.2 ms 64 bytes from node-2 (192.168.2.2): icmp_seq=28 ttl=63 time=86.0 ms 64 bytes from node-2 (192.168.2.2): icmp_seq=30 ttl=63 time=84.3 ms 64 bytes from node-2 (192.168.2.2): icmp_seq=37 ttl=63 time=84.1 ms
Epic Fail
tc qdisc replace dev eth1 root tbf rate 40Mbit burst 159900000000000000 latency 10s
Kernel panic
Судя по моим подсчетам - burst 159900000000000000 (который пересчитывается в байты при создании правила) израсходовал 1100Мб при том что на ВМке всего1 гиг - предположительная причина - перерасход памяти
Проверка предположения про burst
Как я писал выше, предположение что установка огромного burst вызовет всплеск трафика в начале теста требует подтверждения: настраиваю следующим образом
tc qdisc replace dev eth1 root tbf rate 40Mbit burst 159900000 latency 10s
Как можно видеть по графику - предположение полностью подтверждается, наблюдаем явный пик трафика и потом переход к "нормальной скорости"
Проверка влияния burst и latency на поведение алгоритма
Попробуем собрать более-менее полную статистику по burst и latency. Для этого я в цикле прогоняю тесты при этом в каждом следующем тесте я делаю burst=burst*N что бы обеспечить более-менее приемлемую скорость перебора. Аналогично - для latency. Все параметры теста вынесены в заголовок графика.
Выводы
Судя по тому что я вижу - TBF неплохо подходит для простых случаев; хорошо масштабируемый до скоростей порядка 100Мбит.
Задирание буферов до запредельных значений смысла не имеет как и увеличение latency.
Насколько я могу судить алгоритм достаточно точный - снимаемые с ноды значения соответвуют выставляемым на роутере.
Классовые дисциплины
Для простых случаев можно использовать и классовые дисциплины - при этом конструкции будут достаточно простые и понятные.
HTB
По-поводу HTB написано очень много - но вопросы с пониманием возникают постоянно. Потому я попробую собрать наиболее подробное и понятное описание из разных источников - такая компиляция.
Вот неплохое описание:
The Hierarchical Token Bucket (HTB) is an improved version of TBF that introduces the notion of classes. Each class is, in fact, a TBF-like qdisc, and classes are linked together as a tree, with a root and leaves. HTB introduces a number of features to improved the management of bandwidth, such as a the priority between classes, a way to borrow bandwidth from another class, or the possibility to plug another qdisc as an exit point (a SFQ for example).
Т.е. для начала считаем что HTB - это расширенная TBF с возможностью займа полосы и подключения к выходу других дисциплин.
Пробная настройка
У HTB много малопонятных параметров - я постараюсь описать их по возможности подробно.
ВАЖНО!!! Я НЕ использую никакую дисциплину в "листьях" - это тест ТОЛЬКО HTB
Первым делом создаем корневую дисциплину - у нее по сути есть всего 2 параметра
# tc qdisc add dev eth1 root handle 1: htb default 20
- default 20 — задаем класс по-умолчанию. В нем будут обрабатываться пакеты, не попавшие в другие классы дисциплины htb.
Если его не указать, то будет назначен “default 0” и весь не классифицированный (не попавший под фильтры) трафик будет отправляться со скоростью интерфейса. В моем случае когда надо ограничить весь трафик (базовый случай - аналог примера выше) это будет единственный класс и никаких фильтров применяться не будет. (примеры с фильтрами, приоритетами и деревьями классов - ниже, в другом разделе этого документа)
- r2q DRR quantums are computed as rate in Bps/r2q {10}
Есть несколько описаний но насколько я смог понять - это кванты трафика с которым работает HTB, очевидно что делать мелкие кванты при нынешних скоростях смысла нет. Приведу несколько описаний (автор - не я)
- Второй параметр R2Q используется для квантования трафика в классах. В случае малых скоростей рекомендуется значение = 1, что позволяет шейпать с точностью до 4kbit. Если не указан, то =10, что для скоростей >120Kbit.
- Сейчас стоит рассмотреть понятие квантов трафика. В процессе конкурентной передачи данных нескольких классов обслуживание каждого из них начинается после того, как обработано некоторое количество байт предыдущего класса. Это количество байт называется квантом (quantum). Когда несколько классов претендуют на канал родительского, они получают части канала пропорциональные их квантам. Важно знать, что расчёт распределения канала тем точнее, чем меньше размер кванта (но квант всё же должен быть не меньше величины MTU). Как правило нет необходимости задавать кванты вручную, поскольку HTB рассчитывает их самостоятельно. Размер кванта класса устанавливается (при создании или изменении класса) равным запрошенной скорости делённой на глобальный параметр r2q. По умолчанию r2q равен 10, что приемлемо для скоростей выше 15 kbps (120 kbit), поскольку обычно MTU равен 1500. Для меньших скоростей величина r2q равна 1; это подходит для скоростей от 12 kbit.При желании можно установить величину кванта вручную. В этом случае параметр r2q игнорируется. Будут выведены предупреждения о том, что установленная величина не верна, но ими можно пренебречь.
http://forum.nag.ru/forum/index.php?showtopic=48277&st=0&p=609502&#entry609502
- Еще одно хорошее описание:
Уверен, многие сталкивались с проблемами:
HTB: quantum of class 10001 is big. Consider r2q change или HTB: quantum of class 10001 is small. Consider r2q change.
Что делать вообще и как жить? На удивление информации нереально мало.
Но на форму nag.ru нашелся чудесный челвоек technolab, который дал следующие разъяснения:
MTU - максимальный размера блока в байтах который может быть передан.
Quantum - число байт, которые может передать поток перед переходом к следующему классу, по умолчанию = MTU интерфейса. Расчет распределения канала тем точнее, чем меньше это значение.
R2Q - глобальный параметр, по умолчанию R2Q = 10, если Quantum указан, то R2Q игнорируется.
Немного констант:
quantum = rate / r2q
mtu ≤ quantum ≤ 60000
Соответственно:
quantum is small => RATE / R2Q < MTU
quantum is big => RATE / R2Q > 60000
То есть, для шейпинга на скорсоти около 30 000 мегабит у нас интервал r2q лежит в районе 700-3000. Ограничения - нельзя делать делать меньше mtu и нельзя делать уж очень большим.
Вот этот момент не очень понятен - при больших скоростях r2q надо брать достаточно большим что бы получался большой квантум - но как вычислили значения - не понятно
Пример с форума НАГа:
для примера на канал 900 мегабит $TC->("qdisc add dev $dev root handle 1: htb r2q 37500"); автоматом будет посчитан quantum = 3000 ровно таким же макаром нужно считать для дочек
Сбивает с толку размерность
- mtu/mru - в байтах
- quantum - как производная от mtu - тоже в байтах
- rate/ceil тоже надо указывать в байтах соответвенно имеем:
(quantum=3000)*(r2q=37500) = (rate=112500000 Мбайт/с) = (rate= 112500000*8/1000/1000 = 900 Mbit)
Создаем класс и прикрепляем его к корню:
# tc class add dev eth1 parent 1: classid 1:20 htb rate 180kbit ceil 180kbit
прикрепляем к root qdisc класс с идентификатором 1:1. Тем самым ограничиваем скорость на интерфейсе до 180Кбайт/c.
- classid 1:10 — идентификатор класса.
- rate 180kbit — устанавливаем нижний порог пропускной способности для класса. (в нашем простейшем случае - значения равны )
- ceil 180kbit — устанавливаем верхний порог пропускной способности для класса.
- burst - не устанавливаю
- cburst - не устанавливаю
- prio 1 - приоритет, судя по документации классы работают в порядке приоритетов и пока есть трафик в классах с меньшим приоритетом классы с большим - не обрабатываются. Это утверждение требует проверки что будет сделано ниже - в классовых конфигурациях.
- quantum - не задаю, в базовом тесте полагаюсь на авторассчет
- mtu - я не нашел описание должен ли МТУ класса быть равным МТУ интерфейса или больше него - но много примеров устанавливают МТУ 1600 (против 1500 на интерфейсе)
Кстати, в документации указано, что по факту в HTB шейпинг трафика происходит только в краевых классах, в нашем случае 1:20. Что часто сбивает с толку. Но в нашем случае это не нужно.
Результаты
Результаты пробного теста достаточно интересны (хотя и предсказуемые)
- Связь с сервером на время работы теста практически отсутствует, однако открыт вопрос - в каких таких буферах пинги стояли столько времени?
В качестве ответа на вопрос - следующая цитата:
Within the one HTB instance many classes may exist. Each of these classes contains another qdisc, by default tc-pfifo(8).
Т.е. сужествует qdisc по умолчанию и это pfifo c огромными (судя по пингу) очередями
64 bytes from node-1 (192.168.1.2): icmp_seq=51 ttl=63 time=65415 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=55 ttl=63 time=65388 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=56 ttl=63 time=65325 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=74 ttl=63 time=64448 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=88 ttl=63 time=64280 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=94 ttl=63 time=64150 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=100 ttl=63 time=65329 ms From 192.168.2.1 icmp_seq=172 Destination Host Unreachable From 192.168.2.1 icmp_seq=173 Destination Host Unreachable From 192.168.2.1 icmp_seq=174 Destination Host Unreachable From 192.168.2.1 icmp_seq=175 Destination Host Unreachable 64 bytes from node-1 (192.168.1.2): icmp_seq=139 ttl=63 time=65715 ms
- Ограничение работает как и ожидалось
- burst и cburst имеют разумные для такой скорости значения по-умолчанию
tc -s c s dev eth1 class htb 1:20 root prio 0 rate 180000bit ceil 180000bit burst 1599b cburst 1599b Sent 4276815 bytes 3106 pkt (dropped 1977877, overlimits 0 requeues 0) rate 0bit 0pps backlog 0b 0p requeues 0 lended: 3090 borrowed: 0 giants: 0 tokens: 1081942 ctokens: 1081942
Повторное тестирование: разные скорости но настройки по-умолчанию
Для сбора статистики повторяем тест с разными скоростями
RATE=1 for I in `seq 1 7` do let RATE=RATE*2 tc qdis del root dev eth1 tc qdisc replace dev eth1 root handle 1:0 htb default 20 tc class add dev eth1 parent 1: classid 1:20 htb rate ${RATE}Mbit ceil ${RATE}Mbit ... done
Результат соответствует ожиданию - шейпер успешно отработал на скорости от 2Мбит до 128Мбит при автоматическом вычислении всех параметров, с ростом скоростей уменьшались только задержки пингов.
Приведу только 2 крайних примера:
- 2 Mbit
64 bytes from node-1 (192.168.1.2): icmp_seq=1 ttl=63 time=6007 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=3 ttl=63 time=5997 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=4 ttl=63 time=5995 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=5 ttl=63 time=5996 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=14 ttl=63 time=5982 ms
- 128Mbit
64 bytes from node-1 (192.168.1.2): icmp_seq=504 ttl=63 time=105 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=506 ttl=63 time=103 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=510 ttl=63 time=101 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=512 ttl=63 time=100 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=513 ttl=63 time=101 ms 64 bytes from node-1 (192.168.1.2): icmp_seq=514 ttl=63 time=101 ms
HTB
Burst cburst
- burst - это просто размер буффера в токенах и он должен быть достаточным, сверхбольшое его увеличение ничего не дает.
- cburst - аналог peack rate т.е. размер буфера токенов который будет использоваться при превышении над ceil.
Небольшая цитата:
Сетевое устройство может передавать только один пакет в один момент времени и только с определенной устройством скоростью. Программам разделения канала остается только использовать эти параметры для расчетов деления канала на полосы требуемого размера. Таким образом, текущая и максимальная скорости передачи данных не могут быть урегулированы мгновенно. Они рассчитываются на основании усредненных данных о скорости отсылки пакетов. В действительности передача данных с учетом заданных свойств классов происходит следующим образом: устройству передается некоторое количество пакетов одного класса (которые отправляются в сеть со скоростью, определенной устройством, то есть максимально возможной), после чего некоторое время обрабатываются пакеты остальных классов. Параметры класса burst и cburst определяют количество данных, которое можно передать на максимальной скорости (скорости оборудования), после чего переключиться на обслуживание других классов.
Чем меньше параметр cburst (в идеале он должен быть равен размеру одного пакета), тем лучше он сглаживает ускорение передачи данных, чтобы скорость передачи не превысила величину ceil. Так же действует параметр peakrate дисциплины TBF.
Если параметр burst родительского класса меньше, чем у какого-нибудь из потомков, можно ожидать, что передача данных этого класса иногда будет останавливаться (так как дочерний класс пытается создать большее ускорение, чем позволено родительскому). HTB помнит о неудачной попытке ускорения в течение минуты.
Возникает вопрос: для чего нужно регулировать ускорение? Дело в том, что это дешевый и простой способ улучшить время отклика на переполненных каналах. К резким колебания склонен, к примеру, веб-трафик. Вы запрашиваете страницу, создавая ускорение, потом читаете ее. За время чтения “накапливается энергия” для следующего ускорения.
Параметры burst и cburst всегда должны быть не меньше, чем такие же параметры дочерних классов.
Оперируя высокими скоростями на компьютере с низкой частотой таймера, необходимо минимизировать величины burst и cburst для всех классов. Интервал срабатывания таймера равен 10 ms для архитектуры i386 и 1 ms для Alpha. Минимальное эффективное ускорение рассчитывается по формуле (максимальная скорость)*(интервал таймера). Например, чтобы обеспечить скорость 10 mbit на компьютере i386 параметр burst должен быть равен 12kb.
Заниженная величина burst приведет к тому, что данные будут передаваться на скорости, которая ниже запрошенной параметром rate. Последние версии tc по умолчанию самостоятельно рассчитывают и устанавливают минимальное значение burst.
С моей точки зрения практически во всех случаях можно положиться на автоматический расчет burst
При задирании burst/cburst поведение ожидаемое
Отмечу что выстрелить себе в ногу htb не дает - burst нельзя поставить выше определенного (но мне неизвестного) значения и занять всю память - похоже что при превышении "лишние" знаки отбрасываются =)
HTB + TBF vs HTB + pfifo (default qdisc)
В этом тесте я пробую следующие конфигуации
- HTB с qdisc по-умолчанию (pfifo)
BASE_BUFFER=1540 BASE_LATENCY=20 RATE=1 BURST=1600
tc qdis del root dev eth1 tc qdisc replace dev eth1 root handle 1:0 htb default 20 tc class add dev eth1 parent 1: classid 1:20 htb rate ${RATE}Mbit ceil ${RATE}Mbit burst ${BURST} cburst ${BURST}
- HTB + TBF, скорость qdisc = скорости htb leaf class
tc qdis del root dev eth1 tc qdisc replace dev eth1 root handle 1:0 htb default 20 tc class add dev eth1 parent 1: classid 1:20 htb rate ${RATE}Mbit ceil ${RATE}Mbit burst ${BURST} cburst ${BURST} tc qdisc add dev eth1 parent 1:20 tbf rate ${RATE}Mbit buffer ${BASE_BUFFER} latency ${BASE_LATENCY}ms
- HTB + TBF, скорость qdisc в 2 раза больше скорости htb leaf class
tc qdis del root dev eth1 tc qdisc replace dev eth1 root handle 1:0 htb default 20 tc class add dev eth1 parent 1: classid 1:20 htb rate ${RATE}Mbit ceil ${RATE}Mbit burst ${BURST} cburst ${BURST} let RATE=RATE*2 tc qdisc add dev eth1 parent 1:20 tbf rate ${RATE}Mbit buffer ${BASE_BUFFER} latency ${BASE_LATENCY}ms
- HTB + TBF, скорость qdisc в 32 раза больше скорости htb leaf class
tc qdis del root dev eth1 tc qdisc replace dev eth1 root handle 1:0 htb default 20 tc class add dev eth1 parent 1: classid 1:20 htb rate ${RATE}Mbit ceil ${RATE}Mbit burst ${BURST} cburst ${BURST} let RATE=RATE*32 tc qdisc add dev eth1 parent 1:20 tbf rate ${RATE}Mbit buffer ${BASE_BUFFER} latency ${BASE_LATENCY}ms
tc qdis del root dev eth1 tc qdisc replace dev eth1 root handle 1:0 htb default 20 tc class add dev eth1 parent 1: classid 1:20 htb rate ${RATE}Mbit ceil ${RATE}Mbit burst ${BURST} cburst ${BURST} let RATE=RATE*128 tc qdisc add dev eth1 parent 1:20 tbf rate ${RATE}Mbit buffer ${BASE_BUFFER} latency ${BASE_LATENCY}ms
HTB + SFQ
SFQ ( как я ВНЕЗАПНО узнал ) имеет достаточно большое число параметров
http://stuff.onse.fi/man?program=tc-sfq§ion=8
- PARAMETERS
- divisor: Can be used to set a different hash table size, available from kernel 2.6.39 onwards. The specified divisor must be a power of two and cannot be larger than 65536. Default value: 1024.размер хеша, предположительно он должен быть не меньше числа flow
- limit: Upper limit of the SFQ. Can be used to reduce the default length of 127 packets. After linux-3.3, it can be raised.По сути - длинна буфера
- depth: Limit of packets per flow (after linux-3.3). Default to 127 and can be lowered.Этот параметр отвечает за то какая часть общего буфера определнного limit может быть отдана каждому flow
- perturb: Interval in seconds for queue algorithm perturbation. Defaults to 0, which means that no perturbation occurs. Do not set too low for each perturbation may cause some packet reordering or losses. Advised value: 60 This value has no effect when externalflow classification is used. Its better to increase divisor value to lower risk of hash collisions.как часто делать ре-хеш
- quantum: Amount of bytes a flow is allowed to dequeue during a round of the round robin process. Defaults to the MTU of the interface which is also the advised value and the minimum value.квантум - порция данных которыми оперировать - делать кратным МТУ
- flows: After linux-3.3, it is possible to change the default limit of flows. Default value is 127Число флоу
- headdrop: Default SFQ behavior is to perform tail-drop of packets from a flow. You can ask a headdrop instead, as this is known to pro-vide a better feedback for TCP flows.
- redflowlimit: Configure the optional RED module on top of each SFQ flow. Random Early Detection principle is to perform packet marks or drops in a probabilistic way. (man tc-red for details aboutRED). redflowlimit configures the hard limit on the real (not average) queue size per SFQ flow in bytes.
- min: Average queue size at which marking becomes a possibility. Defaults to max /3
- max: At this average queue size, the marking probability is maximal. Defaults to redflowlimit /4
- probability: Maximum probability for marking, specified as a floating point number from 0.0 to 1.0. Default value is 0.02
- avpkt: Specified in bytes. Used with burst to determine the time constant for average queue size calculations. Default value is 1000
- burst: Used for determining how fast the average queue size is influenced by the real queue size.Default value is : (2 * min + max) / (3 * avpkt)
- ecn: RED can either 'mark' or 'drop'. Explicit Congestion Notification allows RED to notify remote hosts that their rate exceeds the amount of bandwidth available. Non-ECN capable hosts can only be notified by dropping a packet. If this parameter is specified, packets which indicate that their hosts honor ECN will only be marked and not dropped, unless the queue size hits depth packets.
- harddrop: If average flow queue size is above max bytes, this parameter forces a drop instead of ecn marking.
- HTB + SFQ
Попробуем разные параметры
При установке flows=1 - получаем поведение FIFO с коротким буфером (depth не может быть больше 127)
Ожидаемое поведение - при нагрузке получим потери пинга близко к 100%
[root@router0 ~]# tc -s -d q s dev eth1 qdisc htb 1: root refcnt 2 r2q 10 default 20 direct_packets_stat 0 ver 3.17 Sent 28253598 bytes 19524 pkt (dropped 44841, overlimits 73764 requeues 0) backlog 0b 0p requeues 0 qdisc sfq 40: parent 1:20 limit 127p quantum 1514b depth 127 flows 1/1024 divisor 1024 perturb 10sec Sent 28253598 bytes 19524 pkt (dropped 44841, overlimits 0 requeues 0) backlog 0b 0p requeues 0
Собственно это мы и наблюдаем: даже АРП перестал ходить.
From router0 (192.168.2.1) icmp_seq=218 Destination Host Unreachable From router0 (192.168.2.1) icmp_seq=219 Destination Host Unreachable
Пробую указать divisor=1
Видно что flows=1 (что логично - нет смысла создавать неиспользуемые потоки)
[root@router0 ~]# tc -s -d q s dev eth1 qdisc htb 1: root refcnt 2 r2q 10 default 20 direct_packets_stat 0 ver 3.17 Sent 28419225 bytes 19618 pkt (dropped 201715, overlimits 240233 requeues 0) backlog 0b 0p requeues 0 qdisc sfq 40: parent 1:20 limit 127p quantum 1514b depth 127 flows 1/1 divisor 1 perturb 10sec Sent 28419225 bytes 19618 pkt (dropped 201715, overlimits 0 requeues 0) backlog 0b 0p requeues 0
Поведение отличается но не сильно:
245 packets transmitted, 60 received, +9 errors, 75% packet loss, time 246003ms
Вывод - для того что бы SFQ распределял полосу равномерно между потоками нужно создавать достаточное число потоков и при этом - не слишком много что бы буффер (limit) не был слишком большим - иначе время ожидания становится запредельным.
tc -s -d q s dev eth1 qdisc htb 1: root refcnt 2 r2q 10 default 20 direct_packets_stat 0 ver 3.17 Sent 48001878 bytes 33888 pkt (dropped 220259, overlimits 280718 requeues 0) backlog 0b 0p requeues 0 qdisc sfq 40: parent 1:20 limit 65024p quantum 1514b depth 127 flows 512/16384 divisor 16384 perturb 1sec Sent 48001878 bytes 33888 pkt (dropped 220259, overlimits 0 requeues 0) backlog 0b 0p requeues 0
HFSC
Подробнее о настройке - в другом разделе, тут только пример жеского шефпера который просто ограничивает скорость
DEV=eth1 tc qdis del root dev ${DEV} tc qdisc replace dev eth1 root handle 1:0 hfsc default 1 tc class add dev ${DEV} parent 1:0 classid 1:1 hfsc rt m2 1Mbit m2
QOS - обеспечение приоритетов одного трафика над другим
Так как планируется большое число тестов и большое число данных, то первым делом нужно подготовить автоматизацию. Для генерации трафика я буду использовать iperf с переменным числом потоков, для сбора статистики - скрипт на питоне. Для визуализации - GnuPlot
HFSC
- http://ace-host.stuart.id.au/russell/files/tc/doc/sch_hfsc.txt
- http://linux-ip.net/articles/hfsc.en/
Перенесено --> http://wiki.sirmax.noname.com.ua/index.php/Linux_QOS_HFSC
Источники
- http://www.opennet.ru/base/net/linux_traffic_qos.txt.html
- http://www.opennet.ru/base/net/htb_manual.txt.html
- http://wiki.linuxwall.info/doku.php/en:ressources:dossiers:networking:traffic_control#tbf_-_token_bucket_filter
- http://xgu.ru/wiki/QoS_%D0%B2_Linux
- http://ace-host.stuart.id.au/russell/files/tc/doc/cls_u32.txt
- https://nuclearcat.com/mediawiki/index.php/U32_tips_tricks
- http://lartc.org/howto/lartc.adv-filter.policing.html
- http://www.nestor.minsk.by/sr/2006/05/sr60516.html
SFQ
U32