QoS Advanced Routing for Linux
от ManiaX, Renegade 23:22:20, 10 Януари 2000

10x na Renegade (който даде идеята да напиша т'ва нещо и който доста ми помогна (например написа цялата traffic control част), Алексей Кузнецов (за прекрасното ръководство на ip командата, част от което съм превел тука).

    С новите ядра (v2.2.x) Linux започна да придобива мрежовите възможности на Cisco router (благодарение на Алексей Кузнецов).

    Тези възможности се включват от Network Options/Quality of Services и Network Options/Advanced routing". За да използваме тези възможности, ни е нужен пакета iproute2 (или iproute2+tc), достъпен от ftp.inr.ac.ru/ip-routing. В него се съдържат 2 основни програми - ip и tc. Първата служи за манипулация на интерфейси routing-таблици и т.н., а втората - за traffic control. За първата има дълго и подробно ръководство в пакета, а за втората е в процес на разработка. Тук ще опиша, доколкото ми е възможно, и двете команди.

Манипулация на интерфейси
    С командата ip могат да се модифицират следните типове обекти: link (модификации на параметрите на интерфейсите), route (модификации на routing-таблицата), rule (разширения на routing-таблицата с правила), address (задаване на адреси на интерфейсите), maddress (multicast адреси), mroute (multicast routing), tunnel (създаване на тунели, като например IPv6-in-IPv4), neighbour (ARP-таблица). Лесно се забелязва, че тази команда може да замени, ако не целия, то почти целия netbase. ip link има следните команди: ip link set или ip link show (по подразбиране). ip link show показва всички интерфейси с техните параметри, а на ip link set могат да се подадат следните параметри:
dev <device> интерфейс за манипулация
up или down дали е up (т.е. работещ) или down (т.е. не)
arp <on или off> дали интерфейсът да използва ARP или не (резулатът от ip link set arp off dev xxx, ако интерфейсът е up може да бъде много неприятен)
multicase <on или off> multicast поддръжка на интерфейса
name <name> сменя името на интерфейса (от eth0 на xxx0 например)
txqueuelen <ADDRESS> големина на transmit-опашката
mtu <mtu> сменя MTU-то (Maximum Transmit Unit) на интерфейса
address <ADDRESS> сменя link-layer-адреса (т.е. ethernet-адреса)
broadcast или brd или peer <ADDRESS> сменя broadcast или point-to-pointlink-layer-адреса на интерфейса.
    Също така на ip link show може да бъде подадена опция "-statistics", която да изведе статистика за интерфейса.

    Този пример за използването на ip link конфигурира eth0 с адрес 2.3.4.5, да използва ARP и да включи интерфейса.

ip link set dev eth0 address 2.3.4.5
ip link set dev eth0 arp on
ip link set dev eth0 up
    Този ред пък увеличава transmit-опашката на ppp0-интерфейса, правейки го като ethernet - удобно е за ppp-on-ethernet връзки, за да се използва пълноценно преносната среда.
ip link set dev ppp0 txqueuelen 100
    На ip route могат да се подават следните команди: add, change, replace, delete, show, flush и get.

    <[ * Кратка забележка: В linux-2.2.x типовете entry-та на routing-таблица са следните:

unicast описва истински път до определено място
unreachable адресът е недостъпен, връща се ICMP съобщение "host unreachable", програмата, изпратила пакета, получава грешка EHOSTUNREACH.
blackhole адресът е недостъпен, не се връща ICMP съобщение, програмата, изпратила пакета, получава грешка EINVAL.
prohibit адресът е недостъпен, връща се ICMP съобщение "communication administratively prohibited", програмата, генерирала пакета, получава грешка EACCES
local локален, всички пакети се връщат в локалната машина.
broadcast адресът е broadcast-адрес, пакетите се пращат като link broadcast-ове.
throw специален тип, използван с policy rules. Ако при lookup на таблицата се избере подобен път, lookup-ът се прекратява, като се казва, че няма подобен route в тая таблица (ако lookup-ът се прави с policy, а ако не е еквивалентно на липсата на route и се връща ICMP събщение "netork unreachable", а програмата изпратила пакета - грешка ENETUNREACH.
nat т.нар. "Network Address Translation", всички пакети с такъв source се маскират през адреса подаден с параметъра via.
anycast не е написан.....
multicast специален тип, използван в multicast routing-а. Не се среща в нормалните routing-таблици.
]>

ip route add, change и replace поддържат следните опции:

to <PREFIX> или to <TYPE> <PREFIX> Отсрещна точка. Ако TYPE не е зададен, ip подразбира тип unicast. PREFIX е IP или IPv6 адрес с опционална netmask-а. Също така има един специален PREFIX - "default", който е еквивалентен в IPv4 на "0/0" или на "::/0"в IPv6.
tos <TOS> или dsfield <TOS> Type of Service (ToS, Тип на услугата). Използва се, за да могат да се използват различни пътища за пакети с различни ToS полета.
metric <NUMBER> или preference <NUMBER> Приоритет/дължина на route. NUMBER е нормално 32-битово число.
table <TABLEID> Таблица в която да се включи този route. TABLEID може да е е число или стринг, указващ файл в /etc/iproute2/rt_tables. Ако този параметър го няма, ip подразбира таблицата main, с изключение на таблица local, broadcast и nat route-овете, в които влиза по подразбиране в таблицата local.
dev <NAME> име на изходното устройство.
via <ADDRESS> адреса на следващия router. Фактически, значението зависи от типа route. За нормални unicast route-ове или чистия следващ router, или адреса на интерфейс, през който да се прати, ако е адрес инсталиран в BSD. За NAT route-ове това е адреса на маскиране на минаващите връзки.
src <ADDRESS> Изходен адрес, от който да се пращат пакетите, попадащи в това routing правило.
realm <REALMID> realm, в който попада този route. REALMID може да е число или стринг от файла /etc/iproute2/rt_realms.
mtu <MTU> или mtu lock <MTU> MTU-то по пътя до отсрещния адрес. Ако не се използва lock, MTU-то може да променя от kernel-а с Path MTU Discovery. Ако се използва lock, няма да се използва Path MTU Discovery. Всички пакети ще се изпращат без DF-бита в IPv4 случая или fragmented-бита за IPv6.
window <NUMBER> маклималният TCP прозорец за позволяване до тези места в байтове. Ограничава максималния поток от данни, които могат да бъдат пратени до хоста по TCP.
rtt <NUMBER> началното RTT (Round Trip Time).

<[ * Бележка:Всъщност, в Linux-2.2.x (и 2.0.x) то не е точно RTT, а timeout-а при начало на TCP връзка. Kernel-а спира да го използва при първия получен валиден ACK. ]>

nexthop <NEXTHOP> Следващият hop на multipath route. NEXTHOP е комплексна стойност със синтаксис подобен на този на останалите параметри от типа на add:   
via <ADDRESS> следващият router
dev <NAME> >устройството
weight <NUMBER> "тежестта" или "стойността" на този route в multipath-а, базирана на скоростта или качеството.
 
scope <SCOPE_VAL> обхват (scope) от цели покривани от route-префикса. SCOPE_VAL може да е число или стринг от файла /etc/iproute2/rt_scopes. Ако този параметър се пропусне, ip приема обхвата global за всички unicast route-ове, минаващи през gateway-а, обхвата link за директни unicast route-ве и broadcast-и, както и обхват host за локалните route-ове.
protocol <RTPROTO> "routing"-протокол за този "route". RTPROTO може да е число или стринг от файла "/etc/iproute2/rt_protos". Ако не зададен такъв, "ip" приема протокол "boot" (т.е. такъв, добавен от някой, който не знае к'во прави). Няколко такива стойности имат фиксирано значение:   
redirect route, инсталиран от "ICMP redirect".
kernel route, иснталиран от kernel-а по време на автоматичната конфигурация.
boot route, инсталиран по време на boot-а. Ако бъде стартиран routing daemon, той би ги изтрил.
static route, инсталиран от администратора, за да прескочи динамичния routing. Routing daemon-а може би няма да ги закача и, може би, дори ще ги, препоръча на съседите си.
ra route, инсталиран от "Router Discovery Protocol".
Останалите стойности не са резервирани и администратора може да ги задава за различни протоколи. Най-малко, routing daemon-ите трябва да се погрижат да използват уникалниза системата възможности, като тези в rtnetlink.h или rt_protos.
online казва, че следващия hop е директно свързан за тази връзка, даже и ако не пасва на който и да е интерфейс.
equalize Позволява изравняване по произволен начин по multipath routes. Без тази опция route ще бъде определен до един следващ hop, така че разделянето на трафика ще се получава само на база трафик. equalize работи само на patch-нати kernel-и. (?)
Примери:

    Тук имаме машина с две мрежови карти, която има три адреса: 192.168.1.1 на eth1, и 192.168.0.4 и 193.200.17.103 на eth0. Това е Samba server на мрежата и, когато осъществява връзки до 192.168.x.x използва 192.168.x.x адресите си, а се свързва към реални адреси, използва реалния си адрес. Също така има два хоста, за които минава през друг router (193.200.17.98), а не през главния си (193.200.17.97), както и три машини, които са и на LAN-а:

ip route add 192.168.0.0/24 dev eth0 srv 192.168.0.4
ip route add 192.168.1.0/24 dev eth1
ip route add 193.200.17.97 dev eth0 src 193.200.17.103 onlink
ip route add 193.200.17.101 dev eth0 src 193.200.17.103 onlink
ip route add 193.200.17.98 dev eth0 src 193.200.17.103 onlink
ip route add 193.200.17.105 via 193.200.17.98 src 193.200.17.103
ip route add 193.200.17.102 via 193.200.17.98 src 193.200.17.103
ip route add default via 193.200.17.97 src 193.200.17.103
    Тук defaultroute се разделя между ppp0 и ppp1 поравно, т.е. прави се балансиране на натоварването (load balancing):
ip route add default scope global nexthop dev ppp0 nexthop dev ppp1
    Тук се постига същото като в горния пример, но се използва по-добрия начин - с IP адреси, защото имената на интерфейсите са динамични, и се използва изравняване:
ip route add defaulte equalize scope global nexthop via 193.200.17.98 nexthop via 193.200.17.99
ip route delete има подобни опции като ip route add, с тази разлика, че се изтрива route, който има същите опции, като тези подадени на командата, като обачене е задължително да се подадат докрай всички опции за този route, ако няма подобни на него в routing-таблицата.

ip route show също така има подобни опции, но с него се извеждат route-овете, които имат подобни параметри.

    Ето един пример:

eosnw:~# ip route show 193.200.17.97 dev eth0 scope link 193.200.17.98 dev eth0 scope link 193.200.17.101 dev eth0 scope link 193.200.17.102 via 193.200.17.98 dev eth0 src 193.200.17.103 193.200.17.105 via 193.200.17.98 dev eth0 src 193.200.17.103 192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.1 192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.4 default via 193.200.17.97 dev eth0 src 193.200.17.103
    Тук route-овете до 192.168.x.x са добавени от kernel-а, защото ifconfig при 2.2.x kernel-и автоматично добавя route към address/netmask през този интерфейс.

ip route flush пък се различава от ip route show само по това, че изтрива всички route-ове, които имат такива параметри като зададените на командата.

ip route get пък проверява през кой route ще мине пакет със свойства като тези, зададени на командата. (* Внимание! Това не е точно ip route show - при rules и т.н. резултатът може да е различен. ip route get повтаря действията на kernel-а при lookup в routing-таблиците.).

ip rule позволява да се задават правила, на база на които да се прави lookup в други routing-таблици - по този начин може да се прави routing, базиран не само на адреса на целта, но и на база на изходния адрес, на ToS, на входен интерфейс. ip rule има няколко възможни команди: add, delete и show.

    Тези правила могат да бъдат следните типове:  

unicast Връща route от routing-таблицата, към която сочи правилото.
blackhole Дропва пакетите директно.
unreachable Връща грешка "Network is unreachable".
prohibit Връща грешка "Communication is administratively prohibited".
nat Правилото транслира изходния адрес.
ip rule add има следните опции:  
type <TYPE> (по подразбиране) тип на правилото.
from <PREFIX> изходен адрес на пакета.
to <PREFIX> адрес на целта на пакета.
iif <NAME> избира входен интерфейс. Ако интерфейса е loopback-а, правилото обхваща само пакети, изпратени от този хост. По този начин могат да се направят routing-таблици за пакети, изпратени от хоста и за пренасочени пакети и така да се разделят изцяло двата трафика.
tos <TOS> или dsfield <TOS> самообясняващо се.
fwmark <MARK> за какъв fwmark да се отнася.

<[ * Бележка:fwmark в възможност с ipchains на определени пакети да се поставя т.нар. fwmark, т.е. да се прави routing на базата на ipchains правила .... ]>

priority <PREFERENCE> приоритет на правилото. Всяко правило би трябвало да има уникален зададен приоритет.

<[ * Бележка: Всъщност, по исторически причини ip rule add не изисква никакъв приоритет. Ако потребителят не зададе никакъв приоритет, kernel-а му избирасамо, а ако зададе с такъв приоритет, който не съществува, го поставя преди всички по-стари правила със същия приоритет. Както казва Кузнецов: "It is mistake in design, not more. And it will be fixed one day, so that do not rely on this feature, use explicit priorities.". ]>

table <TABLEID> routing-таблица, в която да се прави lookup, ако пакетът отговаря на правилото.
realms <FROM/TO> realm-ове, които да се използват, ако пакетът отговаря на правилото.
nat <ADDRESS> База на блок от IP адреси за транслиране на изходния адрес. ADDRESS може да е или началото на блок от IP-адреси, избрани от NAT route-ове, или локален адрес (или дори нула). В последния случай router-а не ги транслира, а ги маскира с този адрес.
Примери:

    Това routе-ира всичко от 192.203.80.0/24 през правилата на таблица 13:

ip rule add from 192.203.80.0/24 table 13 prio 220
    Това дропва всички пакети получени през eth0 от адреси 192.168.1.0/24:
ip rule add iif eth0 from 192.168.1.0/24 type blackhole prio 100
    Това изтрива предишното правило:
ip rule del iif eth0 prio 100
    С ip rule show се показва списък на правилата, дефинирани в момента.

Пример:

eosnw:~# ip rule show0: from all lookup local100: from 192.168.1.0/0 \
iif eth0 lookup main blackhole32766: from all lookup main32767: from all \
lookup 253
ip address позволява добавяне/премахване на адрес от интерфейс - това е, което позволяваше ip aliasing-а, но в много по-добър вид. Сега може да имате 10000 vhosta-а на машината си без нито един виртуален интерфейс. Командата има 4 възможни подкоманди: add, delete, show и flush.

ip address add/delete имат следните параметри:  

dev <NAME> устройство, на което да бъде добавен адреса.
local <ADDRESS> (по подразбиране) адрес на интерфейса. Форматът му зависи от това, дали е IPv4 или IPv6, и се записва по стандартните за тях начини. ADDRESS може да бъде следвано от "/" и число, което да задава директно цяла мрежа адреси на интерфейса.
peer <ADDRESS> адрес на отсрещната точка. Пак както и при local, може да се използва "/" и число, определящи netmask-ата на адреса. Ако се задава такъв адрес, локалния адрес не може да има "/xx".
broadcast <ADDRESS> broadcast-адрес за интерфейса. Възможно е да се използват "+" и "-" вместо самия адрес. В този случай, broadcast-адреса се смята, като се слагат/нулират битовете в host-частта на интерфейсния адрес.
label <NAME> На всеки адрес може да се определя отделно устройство. За да се поддържа съжместимостта с alias-ите на linux 2.0.x, този стринг трябва да съвпада с името на интерфейса или да бъде името на интерфейса, следвано от ":" и номер.
scope <SCOPE_VALUE> обхват (scope) на зоната, в която този адрес е валиден. Възможните обхвати са записани във файла /etc/iproute2/rt_scopes. Специални такива стойности са:   
global адресът е глобално валиден.
site (само за IPv6) Валиден е само в този сайт.
link Валиден е само за това устройство.
host Валиден е само за този хост.
 

Примери:

    Тук например се създават три логически мрежи върху една физическа и те могат да работят независимо една от друга, независимо да им се прави shaping и accounting и т.н.:

ip address add 192.168.0.1 dev eth0
ip address add 192.168.1.1 dev eth0
ip address add 192.168.2.1 dev eth0
ip route add 192.168.0.0/24 dev eth0 src 192.168.0.1
ip route add 192.168.1.0/24 dev eth0 src 192.168.1.1
ip route add 192.168.2.0/24 dev eth0 src 192.168.2.1
    Това дава primary-адрес на eth0 194.12.235.195 и създава alias eth0:0 с адрес 194.12.235.199:
ip address add 194.12.235.195 dev eth0
ip address add 194.12.235.199 dev eth0 name eth0:0
    ip address show/flush имат еднакви параметви, а се различават само по това, че едната команда показва адресите, съответстващи на критерия, подаден на командата, а другата ги изтрива. Възможните параметри са:
dev <NAME> (по подразбиране) име на интерфейса.
scope <SCOPE_VAL> само адресите в този обхват.
to <PREFIX> само адреси съвпадащи с PREFIX.
label <PATTERN> само адреси, чието име съвпада с PATTERN. PATTERN е нормален shell-ки модел ("eth*", "eth1:?" и т.н.)
dynamic илиpermanent (само за IPv6) само статични или динамични адреси.
tentative (само за IPv6) само адреси, които не прминават през duplicate address теста.
deprecated (само за IPv6) само безсмислени (ненужни) адреси.
primary илиsecondary само главни или вторични адреси.
Примери:

    Така се виждат всички интерфейси:

eosnw:~# ip address show1: lo: <LOOPBACK,UP> mtu 3924 qdisc noqueuelink/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo2: teql0: <NOARP> mtu 1500 qdisc noop qlen 100 link/generic3: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast qlen 100link/ether 00:20:af:3c:07:f7 brd ff:ff:ff:ff:ff:ff inet 192.168.0.4/24 brd 192.168.0.255 scope global eth0inet 193.200.17.103/32 scope global eth04: eth1: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100link/ether 00:20:af:3c:08:0f brd ff:ff:ff:ff:ff:ff inet 192.168.1.1/24 brd 192.168.1.255 scope global eth1
    А така само тези, които се казват "eth*":
eosnw:~# ip address show label "eth*"3: eth0: <BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast qlen 100link/ether 00:20:af:3c:07:f7 brd ff:ff:ff:ff:ff:ff inet 192.168.0.4/24 brd 192.168.0.255 scope global eth0 inet 193.200.17.103/32 scope global eth04: eth1: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100 link/ether 00:20:af:3c:08:0f brd ff:ff:ff:ff:ff:ff inet 192.168.1.1/24 brd 192.168.1.255 scope global eth1
    Друго, което може да се прави с командата komandata ip, е да се създадат т.нар. "тунели". Например от типа IPv6-in-IPv4 (които позволяват на мрежи/хостове, които имат пряка връзка с мрежи/хостове поддържащи само IPv4, да ползват IPv6 като минават през друго място, което поддържа IPv6).

    С ip tunnel се манипулират тези т.нар. тунели. Тази команда има следните подкоманди: add, change, delete, show.

ip tunnel add/change/delete има следните опции:

name <NAME> (по подразбиране) Задава име NAME на тунела.
mode <MODE> Задава тип на тунела. За момента съществуващи са ipip, sit и gre.

<[ * Бележка: IPIP-тунелите са стандартна енкапсулация на пакет в пакет. GRE-тунелите са прoизведение на CISCO, което е препоръчително да се използва, ако отсрещната точка е CISCO рутер, а и този протокол поддържа multicast вътре в самия тунел (а и все пак CISCO си остават специалистите в тази област ;)) ]>

remote <ADDRESS> Задава адрес на отсрещната точка в тунела.
local <ADDRESS> Задава фиксиран изходен адрес на изпращаните през тунела пакети. Този адрес трябва да бъде адрес на някой интерфейс на машината.
ttl <N> Задава фиксирано TTL за тунелираните пакети. N е число от 1 до 255. 0 е специална стойност значеща, че пакетите не променят TTL-а си.
tos <T> или dsfield <T> Задава фиксиран TOS <T> за тунелираните пакети. По подразбиране не се променя.
dev <NAME> Задължава тунела на ползва интерфейса NAME, така че пакетите да не минават през други интерфейси, ако routing-а се промени.
nopmtudisc Маха Path MTU Discovery-то за тунела, което е включено по подразбиране. Тази опция е несъвместима с фиксирания TTL: тунел с фиксиран TTL винаги прави Path MTU Discovery.
key <K>,ikey <K> иokey <K> (само за GRE тунели) да използва 'keyed' GRE с ключ K. K е или число, или IP адрес. Параметърът key задава ключа за използване в двете посоки, а ikey и okey - съотверно само за изходящи и само за входящи пакети.
csum,icsum иocsum (само за GRE тунели) checksum-проверка за тунелираните пакети. ocsum проверява само изходящите пакети, а icsum - само за входящите пакети. csum е еквивалентно на комбинацията от двата флага icsum и ocsum.
seq,iseq иoseq (само за GRE тунели) Да "сериализира" пакетите. Тук пак oseq/iseq включват тази опция съответно за входните и изходните пакети.

<[ * Бележка: Според Ал.Кузнецов, тази опция не работи или поне не е тествана. Не е и известно как точно трябва да работи и за какво точно са мислели да използват CISCO тази опция. ]>

    ip tunnel show показва съществуващите в момента тунели.

    <[Това по-надолу е произведение на Renegade в/у traffic control ]>

"Traffic Control"
    С това бих искал да хвърля малко светлина върху поддръжката на "Traffic Control", и "Quality of Service" в кернелите 2.2.x.

    За да се компилира кернела с тая поддръжка, трябва да се компилират в кернела, или като модули "Class Based Queueing (CBQ)", "Tocken Bucket Flow (TBF)", "Traffic Sharpers", както и RED. След това, необходима е iproute2, за да може да се използват тия функции на кернела. Тя може да се свали от ftp://ftp.sunet.se/pub/Linux/ip-routing. Принципът, на който работи "traffic control (tc)", е следния: входящите пакети се проверяват дали са за дадена точка, и, ако това е така, те се изпращат за обработка на по-висок слой. В противен случай се гледа routing-таблицата, за да се установи следващия hop за пакета. Също така, по-високия слой също може да генерира трафик, който да кара forwarding agent процесите да търсят следващия hop. Когато това стане, forwarding agent-а слага дадения пакет към изходния интерфейс за предаване. Именно тук Linux Traffic Control-а почва да върши работа.

Linux Traffic Control-а е базиран на три основни блока:

1. Queueing (опашки)

    Всеки интерфейс има начин за обработване на опашките, асоциирани към него. Най-простата е FIFO. Има няколко типа на queueing, които се поддържат в момента:

    Някои от тези дисциплини използват филтри, за да се квалифицират пакетите в различни класове, и да ги обработват спрямо това. Това позволява даден пакет да има приоритет над друг. Такива са например FIFO, CBQ. Queueing-дисциплините и класовете са вързани едно с друго. Присъствието на класове е фундаментална опция за queueing-дисциплината. Също така, филтрите могат да бъдат комбинирани със queueing-дисциплини и класове.

2. Класове

    Опашките и класовете са тясно свързани. Всеки клас има опашка. Класовете се индетифицират спрямо class ID и internal ID. Class ID-то се задава от потребителя, докато internal ID-то се задава от queueing-дисциплината. Class ID-то има структура "major:minor". Major-номера сочи инстанцията в queueing-дисциплината, от която зависи. Minor-номера идентифицира тоя клас в дадена дисциплина.

    За повече подробности може да се види include/net/pkt_sched.h.

"tc (Traffic Controller)"

Traffic Controller (tc) е потребителска програма, която е грубо казано frontend към създаването и асоциирането на опашки към дадени изходни интерфейси. Тя се използва за създаването на различни видове опашки и асоцииране на класове към всяка от тези опашки. Също така може да се използва за слагане на филтри базирани на routing-таблицата, u32-класификаторите, както и RSVP-класификаторите. Тя използва netlink socket-ите като механизъм за комуникиране с мрежовите функции на кернела.

tc се използва по следния начин:

tc [-s[tatistics]] [-d[etails]] [-r[aw]] < qdiscp | class | filter > { COMMAND | help }
, където:
-s[tatistics] статистика
-d[etails] детйлна информация
-r[aw] говори само за себе си
qdiscp queueing-дисциплина
class клас
filter филтър

Queuing-дисциплина:

    Синтаксиса за задаване на queueing-дисциплина е следния:

tc qdisc [ add | del | replace | change | get ] dev STRING [ handle QHANDLE ] [ root | parent CLASSID ] [ estimator INTERVAL TIME_CONSTANT ] [ [ QDISC_KIND ] [ help | OPTIONS ] ]
tc qdisc show [ dev STRING ]
, където:
QDISC_KIND може да има стойност pfifo, bfifo, tbf, prio, cbq, red или т.н., т.е. име на queueing-дисциплината
hande уникален handle, даден на дадената дисциплина от създателя. Не може да има две дисциплини с еднакъв handle.
root показва, че дадената дисциплина е root в sharing-йерархията.
parent показва родителя на дадената дисциплина.

    За да се създаде "class based queue (CBQ)":

tc qdisc [ add | del | replace | change | get ] dev STRING \
cbq bandwidth BPS [ avpkt BYTES ] [ mpu BYTES ] [ cell BYTES ] [ ewma LOG ]
, където:  
bandwidth максимална скорост на дадения интерфейс
mpu минимални байтове, които да се изпращат в даден пакет

Пример:

    tc qdisc add dev eth0 root handle 1: cbq bandwidth 10Mbit allot 1514 cell 8 avpkt 1000 mpu 64

    В дадения пример, Class Based Queue (CBQ) се създава и се връзва към eth0. handle-ът е 1: (което е 1:0). Общата възможна скорост е 10Mbit.

    Класове:
Синтаксисът за създаване на класове е следния:

tc class [ add | del | change | get ] dev STRING [ classid CLASSID ] [ root | parent CLASSID ] [ [ QDISC_KIND ] [ help | OPTIONS ] ]
tc class show [ dev STRING ] [ root | parent CLASSID ]
, където:  
QDISC_KIND QDISC_KIND може да бъде някоя от queueing-дисциплините, които поддържат класове (prio, cbq и т.н.).
classid представлява handle-ът, който е даден на тоя клас от създателя.
root показва, че тоя клас е root-клас в sharing-йерархията.
parent показва handle-ът на родителя на дадената  queueing-дисциплина.

3. Class Based Queue

    За да се създаде CBQ, синтаксисът е следния:

cbq bandwidth BPS rate BPS maxburst PKTS [ avpkt BYTES ] \
[ minburst PKTS ] [ bounded ] [ isolated ] \
[ allot BYTES ] [ mpu BYTES ] [ weight RATE ] \
[ prio NUMBER ] [ cell BYTES ] [ ewma LOG ] \
[ estimator INTERVAL TIME_CONSTANT ] \
[ split CLASSID ] [ defmap MASK/CHANGE ]
, където:
bandwidth показва максималната скорост, която е възможна за queueing-дисциплината от тоя клас.
rate представлява скоростта, която се дава на тоя клас.
avpkt представлява средния брой байтове в пакет, за тоя клас.
bounded показва, че тоя клас не може да "всзина назаем" неизползвана скорост от "parent"-класа си.
isolated показва, че класа няма да дели скорост с някой друг клас.
    В дадения пример се създава CBQ клас с handle - 1:2. Неговият родител се индентифицира с handle - 1:1. Средният размер на пакета е 1000 байта. Split-точката е 1:0, което показва root-а на sharing-процедурата.
tc class add dev eth1 parent 1:1 classid 1:2 cbq bandwidth 10Mbit \
rate 1Mbit allot 1514 cell 8 weight 100Kbit prio 3 maxburst 20 \
avpkt 1000 split 1:0 defmap c0
4. Филтри:

Синтаксисът за създаване на филтри е:

tc filter [ add | del | change | get ] dev STRING \
[ prio PRIO ] [ protocol PROTO ] [ root | classid CLASSID ] \
[ handle FILTERID ] [ [ FILTER_TYPE ] [ help | OPTIONS ] ] \

tc filter show [ dev STRING ] [ root | parent CLASSID ]
, където: FILTER_TYPE е типа на филтъра (rsvp, u32, fw, route и т.н.}, а форматът на FILTERID зависи от класификатора. prio показва приоритет на дадения филтер. Останалите опции бяха разгледани по-горе.

Route-класификаторите класифицират пакетите спрямо routing-таблицата. Синтаксисът е следния:

tc filter [add | del | change | get] dev STRING \
[parent PARENTID] [protocol PROTO] [prio PRIORITY] route
, където: PROTO е low-level протокола {ip, icmp или някой друг}

    Ето и един пример:

tc filter add dev eth0 parent 1:0 protocol ip prio 100 route
    За да се зададат правила към филтъра:
ip route add 129.237.125.150 via 129.237.125.146 dev eth0 flow 1:2
    Тук се зададе правило за IP 129.237.125.150 с Gateway 129.237.125.146, като целия трафик принадлежи към клас, чийто handle е 1:2.

    И най-накрая, след толкова изписани глупости, нека да разгледам един реален пример:

    Нека да имаме три компютъра: computer1, който е с IP 10.10.10.149. Нека средната големина на пакета да е 1000 байта. И да имаме два класа: един за трафика към машината с IP 10.10.10.146 (computer2), и трафика към машината 10.10.10.148 (computer3). Т.е. с една дума, да се ограничи трафика на машиниcomputer2 иcomputer3. Трафикът къмcomputer2 е с по-висок приоритет от  тоя къмcomputer3. Къмcomputer2 се пуска 1Mbps, а към computer3 - 5Mbps.

На computer1:
--------------

# Attach-ваме queueing-дисциплина към eth0. (там са вързани
# другите две машини). Максималната възможна скорост е 10Mbps.
tc qdisc add dev eth0 root handle 1: cbq bandwidth 10Mbit \
cell 8 avpkt 1000 mpu 64

# Дефинираме root-класа. Той има 10Mbps.
tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 10Mbit \
rate 10MBit allot 1514 cell 8 weight 1Mbit prio 8 maxburst 20 \
avpkt 1000

# Трафик към computer2. Приоритетът е 3, а скоростта е 1Mbps.
tc class add dev eth0 parent 1:1 classid 1:2 cbq bandwidth 10Mbit \
rate 1Mbit allot 1514 cell 8 weight 100Kbit prio 3 maxburst 20 \
avpkt 1000 split 1:0

# Трафик към computer3. Приоритетът е 7, а скоростта е 5Mbps.
tc class add dev eth0 parent 1:1 classid 1:3 cbq bandwidth 10Mbit \
rate 5Mbit allot 1514 cell 8 weight 800Kbit prio 7 maxburst 20 \
avpkt 1000 split 1:0

# Слагаме route класификатора
tc filter add dev eth0 parent 1:0 protocol ip prio 100 route
# Слагаме route и правила за computer2
ip route add 10.10.10.146 via 10.10.10.149 flow 1:2
# Слагаме route и правила за computer3
ip route add 10.10.10.148 via 10.10.10.149 flow 1:3

от ManiaX, Renegade 23:22:20, 10 Януари 2000
back