FreeBSD traffic shaper - DUMMYNET

Petr Bezděk, xbezdek@fi.muni.cz


Obsah


Úvod

Možnost jednoduchého omezení provozu nabízí akce probability ( =pravděpodobnost) příkazu ipfw.

Př.:
# zahazovat 20% ICMP echo požadavků
ipfw add prob 0.8 allow icmp from any to any in icmptypes 8 
Komplexnější možnosti nabízí dummynet, jemuž se budu v tomto dokumentu věnovat.


DUMMYNET

Dummynet byl původně navžen pro testování síťových protokolů. Implementuje variantu Weighted Fair Queueingu tzv. WF2Q+ ( =Worst-case Fair Weighted Fair Queueing).

K omezování provozu slouží dvě struktury:
- pipe ( =roura) emuluje linku s určitou šířkou pásma, zpomalením, velikostí fronty, po jejímž přeplnění se pakety začnou zahazovat a dále pak ztrátovostí.

- queue ( =fronta) implementuje WF2Q+ (Worst-case Fair Weighted Fair Queueing). Jednotlivé fronty jsou napojeny na rouru. Každá fronta má svou váhu, tedy pakety jdoucí frontou s vyšší váhou mají v rouře přednost před pakety jdoucí přes frontu s nižší váhou. Dále každá fronta má svou velikost a ztrátovost. Fronty se také mohou vytvářet dynamicky podle zdrojové/cílové IP adresy, zdrojového/cílového portu nebo protokolu.

Přesun paketů z front struktur queue do fronty struktury pipe probíhá až když je ve frontě struktury pipe místo. Fronta struktury pipe se vyprazdňuje rychlostí danou její konfigurací.


Zprovoznění DUMMYNETu

Máme dvě možnosti:

1) Zavést modul dummynet.ko do jádra
$ kldload dummynet
Pozor: s modulem dummynet.ko se natáhne i modul ipfw.ko, takže jestliže pracujete vzdáleně, je potřeba to udělat nějak takto:
$ kldload dummynet && ipfw add allow all from any to any
jinak si pod sebou podřežete větev...

2) Kompilací jádra s podporou DUMMYNET
$ cd /usr/src/sys/i386/conf && vim JADRO

# podpora pro samotný IPFW
options IPFIREWALL 

# podpora pro DUMMYNET
options DUMMYNET 

$ /usr/sbin/config JADRO
$ cd ../../config/JADRO
$ make depend
$ make
$ make install
$ reboot 

Výpis a mazání rour a front

výpis rour a front
$ ipfw pipe show
$ ipfw queue show
smazání rour/front
$ ipfw pipe delete císlo_routy
$ ipfw queue delete císlo_fronty
smazání všech rour/front
$ ipfw pipe flush
$ ipfw queue flush

Konfigurace roury

$ ipfw pipe number config pipe-configuration
Možné nastavení roury:

bw bandwidth
Šířka pásma v [K|M]{bit/s|Byte/s}. Implicitní hodnota 0 ( =nula) značí neomezenou šířku pásma. Jednotka musí bezprostředně následovat číslo.

delay ms-delay
Zpoždění v milisekundách. Implicitní hodnota 0 znamená žádné zpoždění.

plr packet-loss-rate
Ztrátovost paketů udávající číslo v rozmezí 0 ( = bez ztráty) a 1 ( = 100% ztráta).

queue {slots | sizeKbytes}
Velikost fronty roury v slotech nebo KBytech. Implicitní hodnota je 50 slotů, což je běžná velikost fronty u ethernetových zařízení. Čím je menši kapacita linky tím menší by měla být fronta v konfiguraci roury (je-li fronta příliš velká, dochází k retransmisím, i když nebyl paket firewalem zahozen).

mask mask-specifier
Vytvoří se dynamická roura, která má stejné parametry jako roura originální. Možná kritéria jsou:
dst-ip mask, src-ip mask, dst-port mask, src-port mask, proto mask nebo all.

Poznámka: pro simulaci full duplex provozu je potřeba vydefinovat pipe i queue 2krát - pro oba směry samostatně, bude-li pipe jen jedna pro oba směry, potom simuluje half duplex provoz.

Dále je dobré nastavit
$ sysctl -w net.inet.ip.fw.one_pass=1
aby paket opouštějící rouru neprocházel firewallem znovu, ale pokračoval na dalším pravidle.


Konfigurace fronty

$ ipfw queue number config queue-configuration
Možné nastavení fronty:

pipe pipe_number
Napojí frontu na rouru s číslem pipe_number. Na jednu rouru může být napojeno několik front.

weight weight
Určuje váhu, která bude použita pro pakety jdoucí přes tuto frontu. weight je číslo v rozsahu 1-100, implicitní hodnota je 1.

plr packet-loss-rate
Ztrátovost paketů udávající číslo v rozmezí 0 ( = bez ztráty) a 1 ( = 100% ztráta).

queue {slots | sizeKbytes}
Velikost fronty roury v slotech nebo KBytech. Implicitní hodnota je 50 slotů, což je běžná velikost fronty u ethernetových zařízení. Čím je menši kapacita linky tím menší by měla být fronta v konfiguraci roury (je-li fronta příliš velká, dochází k retransmisím, i když nebyl paket firewalem zahozen).

mask mask-specifier
Vytvoří se dynamická fronta, která má stejné parametry jako fronta originální. Šířka pásma se sdílí pro danou rouru. Možná kritéria jsou:
dst-ip mask, src-ip mask, dst-port mask, src-port mask, proto mask nebo all.


Příklady

Omezení linky na 128Kbit/s full-duplex a její rovnoměrné rozdělení
# roury o šířce pásma 128Kbit/s s délkou fronty 16KBytů pro oba směry
ipfw pipe 1 config bw 128Kbps queue 16Kbytes
ipfw pipe 2 config bw 128Kbps queue 16Kbytes

# rovnoměrné rozdělení pásma rour podle zdrojové a cílové IP adresy
ipfw queue 1 config pipe 1 mask src-ip 0xffffffff queue 16Kbytes
ipfw queue 2 config pipe 2 mask dst-ip 0xffffffff queue 16Kbytes

ipfw add queue 1 ip from ... to ....
ipfw add queue 2 ip from ... to ....
Omezení linky na 256Kbit/s half-duplex a její dělení v poměru 2/3
# roura o šířce pásma 256Kbit/s s délkou fronty 32KBytů
ipfw pipe 1 config bw 256Kbit/s queue 32Kbytes

# fronty s váhami 40 a 60 = dělení v poměru 2/3
ipfw queue 1 config pipe 1 weight 40 queue 32Kbytes
ipfw queue 2 config pipe 1 weight 60 queue 32Kbytes

ipfw add queue 1 ip from ... to ....
ipfw add queue 2 ip from ... to ....

Odkazy

dummynet manuál
slidy z BSDConEurope 2001
ipfw - manuálové stránky
dummynet - manuálové stránky