Mindezen okfejtés után most már ideje, hogy megvalósítsuk a sávszélesség-gazdálkodást Linuxon.
A DSL modemhez aktuálisan küldött adatok mértékének korlátozása nem olyan egyszerű, mint amilyennek látszik. A legtöbb DSL modem igazából csak egy ethernet híd, amik továbbítják az adatokat oda-vissza a Linux gép és a szolgáltatónál lévő gateway között. A legtöbb DSL modem ATM-et használ adatátviteli csatolófelületként. Az ATM mindig 53 bájtos cellákban küldi az adatokat. Ezekből 5 bájt a fejléc információ, és 48 bájt marad az adatoknak. Még ha csak 1 bájt adatot küldesz is, a teljes 53 bájt sávszélességet foglal, mivel az ATM cellák mindig 53 bájt hosszúak. Ez azt jelenti, hogy ha egy tipikus TCP ACK csomagot küldesz, ami 0 bájt adatot + 20 bájt TCP fejlécet + 20 bájt IP fejlécet + 18 bájt Ethernet fejlécet tartalmaz. Valójában, még ha a kiküldött ethernet csomagnak csak 40 bájtnyi "hasznos terhe" van is (TCP és IP fejléc), a legkisebb méret egy Ethernet csomagnál 46 bájtnyi adat, így a maradék 6 bájt 0-val töltődik ki. Ez azt jelenti, hogy az Ethernet csomag plusz a fejléc információk aktuális hossza 18 + 46 = 64 bájt. Az ATM-mel 64 bájt átküldéséhez két ATM cellát kell küldened, ami 106 bájt sávszélességet foglal. Vagyis minden TCP ACK csomagnál 42 bájt sávszélességet vesztesz. Ez rendben van, ha a Linux figyelembe veszi a DSL modem által használt csomag-beágyazást, de ehelyett a Linux csak a TCP és IP fejlécet és 14 bájtos MAC címet jegyzi (a Linux nem számolja a 4 bájtos CRC-t, mivel ezt a hardver szint kezeli). A Linux nem számol a 46 bájtos minimális Ethernet csomagmérettel, sem a fix méretű ATM cellával.
Mindez azt jelenti, hogy a kimenő sávszélességet valamivel kisebbre kell állítani, mint a valós kapacitás (amíg nem találunk egy csomag-időzítőt, ami jegyzi a különböző típusú csomag-beágyazásokat). Azt találhatod, hogy sikerült egy jó értékre beállítani a sávszélességet, de amikor egy nagy fájlt töltesz le, a lappangás felszökik 3 másodperc fölé. Ez legvalószínűbben amiatt van, mivel a Linux rosszul számítja ki a bizonyos kis ACK csomagok által igényelt sávszélességet.
Néhány hónapot dolgoztam ennek a problémának a megoldásán, és majdnem lezártam a dolgot egy olyan megoldással, amit hamarosan közreadok további tesztelésre. A megoldás egy felhasználói szintű várakozósor használatát mutatja be a Linux QoS-e helyett a csomagok korlátozására. Alapvetően egy egyszerű HTB sort alkalmaztam, ami a Linux felhasználói szintű sorait használja. Ez a megoldás (eddig) képes volt a kimenő forgalom OLYAN JÓ korlátozására, hogy még egy masszív letöltés (több szálon) és ugyanilyen feltöltés (gnutella, több szálon) alatt is, a lappangás 400 ms CSÚCSÉRTÉKET ért csak el a névleges, forgalom nélküli 15 ms-hoz képest. További információért erről a QoS módszerről, iratkozz fel a frissítések levelezőlistájára vagy később nézd meg ennek a HOGYANnak a frissebb változatait.
A következőkben egy általam a Linux útválasztón a sávszélesség korlátozására használt szkript listája található. Ez több, a dokumentumban foglalt koncepciót is felhasznál. A kimenő forgalom a 7 típustól függő várósor egyikébe kerül. A bejövő forgalom két sorba kerül, a TCP csomagokat (alacsonyabb prioritásúak) előbb eldobjuk, ha a bejövő adatok a mérték fölöttiek. A szkriptben megadott ráták úgy tűnik, jól működnek az én beállításomban, de az eredmények változhatnak.
#!/bin/bash
#
# myshaper - DSL/kabelmodem kimeno forgalmanak szabalyozasa.
# Az ADSL/Cable wondershaper (www.lartc.org) szkripten alapszik.
#
# Irta: Dan Singletary (8/7/02)
#
# FIGYELEM: a szkript feltetelezi, hogy a kernelt megfoltoztuk a megfelelo HTB
# sor és IMQ foltokkal, amik hozzaferhetok itt (megj.: az ujabb kerneleknel
# lehet, hogy nem kell folt):
#
# http://luxik.cdi.cz/~devik/qos/htb/
# http://luxik.cdi.cz/~patrick/imq/
#
# Konfiguracios beallitasok:
# DEV - ethX-re allitsuk, ami kapcsolodik a DSL/kabelmodemhez
# RATEUP - allitsuk valamivel kisebbre, mint a modem kimeno savszelessege.
# Nekem 1500/128 DSL vonalam van, es a RATEUP=90 jol mukodik a
# 128 kbps-os feltoltessel. De ahogy jonak latod.
# RATEDN - allitsd valamivel kisebbre, mint a bejovo savszelesseg.
#
#
# Teoria az imq hasznalatarol a bejovo forgalom alakitasahoz:
#
#
# BEJOVO TCP KAPCSOLATOK BEFOLYASOLASAT. Ennek ertelmeben minden nem-TCP
# forgalmat egy magas prioritasu osztalyba kell sorolnunk, mivel egy nem-TCP
# csomag eldobasa valoszinuleg a csomag ujrakuldeset okozza. Ez semmi mast nem
# jelent, csak a savszelesseg szuksegtelen lefoglalasat, hogy specifikusan
# valaszthatunk: NEM dobunk el bizonyos tipusu csomagokat, amiket magasabb
# prioritasu tarolokba helyezunk el (ssh, telnet stb). Ez azert van, mert a
# csomagok mindig az alacsonyabb prioritasu osztalybol jonnek elo azzal a
# kikotessel, hogy a csomagok meg minden osztalybol egyforman egy minimalis
# mertekben jonnek ki (ebben a szkriptben minden tarolo legalabb a tisztesseges
# 1/7 savszelessegnyivel A TCP csomag eldobasa egy kapcsolaton belul a fogadas
# alacsonyabb mertekehez vezet, a torlodas-elkerulo algoritmus miatt.
#
# * Semmit nem nyerunk a nem-TCP csomagok eldobasaval. Valojaban, ha
# fontosak voltak, ugyis ujra elkuldik oket, igy megprobaljuk azt, hogy
# sosem dobjuk el oket. Ez azt jelenti, hogy a telitett TCP kapcsolatok nem
# befolyasoljak negativan azokat a protokollokat, amelyeknel nincs a
# TCP-hez hasonlo beepitett ujrakuldes.
#
# * A TCP kapcsolatok lelassitasa ugy, hogy a teljes bejovo rata kevesebb,
# mint az eszkoz valos kapacitasa AZT OKOZHATJA, hogy keves vagy egyetlen
# csomag sem all varakozosorba a szolgaltatoi oldalon (DSLAM,
# kabel-koncentrator stb). Mivel ezek a sorok kepesek megtartani 4
# masodpercnyi adatot 1500Kbps sebessegen vagy 6 megabitnyi adatot, ha egy
# csomag sem all sorba, az alacsonyabb lappangast okoz.
#
# Kikotesek (kerdesfeltevesek a teszteles elott):
# * A bejovo forgalom ezen a modon valo korlatozasa gyenge TCP-teljesítmenyt ad?
# - Az elozetes valsz: nem! Ugy nez ki, hogy az ACK csomagok prioritasanak
# beallitasa (kicsi <64b) anelkul maximaljuk a kimeno telesitmenyt, hogy
# nem vesztunk savszelesseget a mar meglevo ujrakuldott csomagok miatt.
# Megjegyzes: a kovetkezo konfiguracio jol mukodik az en beallitasaimmal:
# 1.5M/128K ADSL a Pacific Bell Internet-en keresztul (SBC Global Services)
DEV=eth0
RATEUP=90
RATEDN=700 # Figyeld meg, hogy ez jelntosen kisebb mint az 1500-as kapacitas.
# Emiatt nem kell a bejovo forgalom korlatozasaval torodnod, amig
# nem hasznalhatunk jobb megvalositast, mint például a TCP ablak
# manipulacioja.
#
# konfiguracios beallitasok vege
#
if [ "$1" = "status" ]
then
echo "[qdisc]"
tc -s qdisc show dev $DEV
tc -s qdisc show dev imq0
echo "[class]"
tc -s class show dev $DEV
tc -s class show dev imq0
echo "[filter]"
tc -s filter show dev $DEV
tc -s filter show dev imq0
echo "[iptables]"
iptables -t mangle -L MYSHAPER-OUT -v -x 2> /dev/null
iptables -t mangle -L MYSHAPER-IN -v -x 2> /dev/null
exit
fi
# Mindent visszaalitunk alapallapotba (torlunk)
tc qdisc del dev $DEV root 2> /dev/null > /dev/null
tc qdisc del dev imq0 root 2> /dev/null > /dev/null
iptables -t mangle -D POSTROUTING -o $DEV -j MYSHAPER-OUT 2> /dev/null > /dev/null
iptables -t mangle -F MYSHAPER-OUT 2> /dev/null > /dev/null
iptables -t mangle -X MYSHAPER-OUT 2> /dev/null > /dev/null
iptables -t mangle -D PREROUTING -i $DEV -j MYSHAPER-IN 2> /dev/null > /dev/null
iptables -t mangle -F MYSHAPER-IN 2> /dev/null > /dev/null
iptables -t mangle -X MYSHAPER-IN 2> /dev/null > /dev/null
ip link set imq0 down 2> /dev/null > /dev/null
rmmod imq 2> /dev/null > /dev/null
if [ "$1" = "stop" ]
then
echo "Shaping removed on $DEV."
exit
fi
###########################################################
#
# Kimeno korlatozas (a teljes savszelesseg RATEUP-ra allitva)
# a varakozosor meretet ugy allitjuk be, hogy kb. 2 mp lappangas legyen az alacsony
# prioritasu csomagoknal
ip link set dev $DEV qlen 30
# a kimeno eszkozon MTU-t allitunk. Az MTU csokkentese alacsonyabb lappangast
# ad, de valamivel kisebb kimeno teljesitmenyt is az IP es TCP protokoll
# felulvezerlese miatt
ip link set dev $DEV mtu 1000
# a HTB-t gyoker qdisc-nek allitjuk be
tc qdisc add dev $DEV root handle 1: htb default 26
# hozzaadjuk a fobb korlatozo osztalyokat
tc class add dev $DEV parent 1: classid 1:1 htb rate ${RATEUP}kbit
# hozzadjuk az alosztalyokat - garantaljuk minden osztalynak LEGALABB a
# "tisztesseges" osztozast a savszelessegen. Emiatt egy osztalyt sem fog egy
# masik kieheztetni. Ezenkivul mindegyik osztaly hasznalhatja a rendelkezesre
# allo savszelesseget, ha a tobbi nem hasznalja.
tc class add dev $DEV parent 1:1 classid 1:20 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 0
tc class add dev $DEV parent 1:1 classid 1:21 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 1
tc class add dev $DEV parent 1:1 classid 1:22 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 2
tc class add dev $DEV parent 1:1 classid 1:23 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 3
tc class add dev $DEV parent 1:1 classid 1:24 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 4
tc class add dev $DEV parent 1:1 classid 1:25 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 5
tc class add dev $DEV parent 1:1 classid 1:26 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 6
# az alosztalyokhoz qdisc-eket adunk - SFQ-t adunk minden osztalyhoz. Az SFQ
# biztositja, hogy minden osztalyon belul a kapcsolatokat (majdnem) egyenloen
# kezeljuk.
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev $DEV parent 1:21 handle 21: sfq perturb 10
tc qdisc add dev $DEV parent 1:22 handle 22: sfq perturb 10
tc qdisc add dev $DEV parent 1:23 handle 23: sfq perturb 10
tc qdisc add dev $DEV parent 1:24 handle 24: sfq perturb 10
tc qdisc add dev $DEV parent 1:25 handle 25: sfq perturb 10
tc qdisc add dev $DEV parent 1:26 handle 26: sfq perturb 10
# az fwmark-kal szurjuk osztalyokba a forgalmat - itt a csomagon beallitott
# fwmark-nak megfeleloen iranyitjuk a forgalmat az osztalyokba (az fwmark-ot az
# iptables segitsegevel kesobb allitjuk be). Figyeld meg, hogy fentebb az
# alapertelmezett prioritasu osztalyt 1:26-ra allitottuk, igy a nem jelolt
# csomagok (vagy a nem ismert ID-ju csomagok) alapertelmezesben az alacsonyabb
# prioritasu osztalyba mennek.
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 22 fw flowid 1:22
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 23 fw flowid 1:23
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 24 fw flowid 1:24
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 25 fw flowid 1:25
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 26 fw flowid 1:26
#
# a MYSHAPER-OUT lanc hozzadasa az iptables "mangle" tablajahoz - ez beallitja
# azt a tablat, amit a csomagok szuresehez es megjelolesehez hasznalunk.
iptables -t mangle -N MYSHAPER-OUT
iptables -t mangle -I POSTROUTING -o $DEV -j MYSHAPER-OUT
# a fwmark ertekek beallitasa a kulonbozo tipusu forgalomhoz - a fwmark-ot 20-26
# kozottire allitjuk a kivant osztalynak megfeleloen. A 20 a legmagasabb prioritas.
iptables -t mangle -A MYSHAPER-OUT -p tcp --sport 0:1024 -j MARK --set-mark 23 # Alapertek az
# alacsony portokon zajlo forgalomhoz
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 0:1024 -j MARK --set-mark 23 # ""
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 20 -j MARK --set-mark 26 # ftp-data port, alacsony prioritas
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport 5190 -j MARK --set-mark 23 # aol instant messenger
iptables -t mangle -A MYSHAPER-OUT -p icmp -j MARK --set-mark 20 # ICMP (ping) - magas prioritas, baratok ismertetojegye
iptables -t mangle -A MYSHAPER-OUT -p udp -j MARK --set-mark 21 # DNS nevfeloldas (kis csomagok)
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport ssh -j MARK --set-mark 22 # secure shell
iptables -t mangle -A MYSHAPER-OUT -p tcp --sport ssh -j MARK --set-mark 22 # secure shell
iptables -t mangle -A MYSHAPER-OUT -p tcp --dport telnet -j MARK --set-mark 22 # telnet (ew...)
iptables -t mangle -A MYSHAPER-OUT -p tcp --sport telnet -j MARK --set-mark 22 # telnet (ew...)
iptables -t mangle -A MYSHAPER-OUT -p ipv6-crypt -j MARK --set-mark 24 # IPSec - viszont nem tudjuk, mi a "hasznos teher"...
iptables -t mangle -A MYSHAPER-OUT -p tcp --sport http -j MARK --set-mark 25 # helyi webszerver
iptables -t mangle -A MYSHAPER-OUT -p tcp -m length --length :64 -j MARK --set-mark 21 # kis csomagok (valoszinuleg csak ACK-k)
iptables -t mangle -A MYSHAPER-OUT -m mark --mark 0 -j MARK --set-mark 26 # redundans- jeloljunk minden nem jelolt csomagot 26-tal (alacsony prioritas)
# vegeztunk a kimeno korlatozassal
#
####################################################
echo "Outbound shaping added to $DEV. Rate: ${RATEUP}Kbit/sec."
# tavolitsd el a megjegyzest a kovetkezo sor elol, ha csak kimeno forgalomszabalyozast akarsz
# exit
####################################################
#
# Bejovo korlatozas (a teljes savszelesseg RATEDN-re allitva)
# megnezzuk, hogy az imq modul betoltodott-e
modprobe imq numdevs=1
ip link set imq0 up
# a qdisc hozzadasa - alapertelmezett alcsony prioritasu 1:21-es osztaly
tc qdisc add dev imq0 handle 1: root htb default 21
# a fo korlatozo osztalyok hozzaadasa
tc class add dev imq0 parent 1: classid 1:1 htb rate ${RATEDN}kbit
# alosztalyok hozzaadasa - TCP forgalom a 21-ben, nem-TCP forgalom a 20-ban
#
tc class add dev imq0 parent 1:1 classid 1:20 htb rate $[$RATEDN/2]kbit ceil ${RATEDN}kbit prio 0
tc class add dev imq0 parent 1:1 classid 1:21 htb rate $[$RATEDN/2]kbit ceil ${RATEDN}kbit prio 1
# az alosztalyokhoz qdisc-eket adunk - SFQ-t adunk minden osztalyhoz. Az SFQ
# biztositja, hogy minden osztalyon belul a kapcsolatokat (majdnem) egyenloen
# kezeljuk.
tc qdisc add dev imq0 parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev imq0 parent 1:21 handle 21: red limit 1000000 min 5000 max 100000 avpkt 1000 burst 50
# az fwmark-kal szurjuk osztalyokba a forgalmat - itt a csomagon beallitott
# fwmark-nak megfeleloen iranyitjuk a forgalmat az osztalyokba (az fwmark-ot az
# iptables segitsegevel kesobb allitjuk be). Figyeld meg, hogy fentebb az
# alapertelmezett prioritasu osztalyt 1:21-re allitottuk, igy a nem jelolt
# csomagok (vagy a nem ismert ID-ju csomagok) alapertelmezesben az alacsonyabb
# prioritasu osztalyba kerulnek.
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21
# a MYSHAPER-IN lanc hozzadasa az iptables "mangle" tablajahoz - ez beallitja azt a tablat,
# amit a csomagok szuresehez es megjelolesehez hasznalunk.
iptables -t mangle -N MYSHAPER-IN
iptables -t mangle -I PREROUTING -i $DEV -j MYSHAPER-IN
# a fwmark ertekek beallitasa a kulonbozo tipusu forgalomhoz - a fwmark-ot 20-26 kozottire
# allitjuk a kivant osztalynak megfeleloen. A 20 a legmagasabb prioritas.
iptables -t mangle -A MYSHAPER-IN -p ! tcp -j MARK --set-mark 20 # A nem-tcp csomagokat a legnagyobb prioritasura allitja
iptables -t mangle -A MYSHAPER-IN -p tcp -m length --length :64 -j MARK --set-mark 20 # rovid TCP csomagok, valoszinuleg ACK-k
iptables -t mangle -A MYSHAPER-IN -p tcp --dport ssh -j MARK --set-mark 20 # secure shell
iptables -t mangle -A MYSHAPER-IN -p tcp --sport ssh -j MARK --set-mark 20 # secure shell
iptables -t mangle -A MYSHAPER-IN -p tcp --dport telnet -j MARK --set-mark 20 # telnet (ew...)
iptables -t mangle -A MYSHAPER-IN -p tcp --sport telnet -j MARK --set-mark 20 # telnet (ew...)
iptables -t mangle -A MYSHAPER-IN -m mark --mark 0 -j MARK --set-mark 21 # redundans- minden nem jelolt csomagot 21-el jelolunk (alacsony prioritas)
# vegul utasitjuk ezeket a csomagokat, hogy menjenek keresztul a fent beallitott imq0-on
iptables -t mangle -A MYSHAPER-IN -j IMQ
# vegeztunk a bejovo forgalommal
#
####################################################
echo "Inbound shaping added to $DEV. Rate: ${RATEDN}Kbit/sec."
|
| Előző | Tartalomjegyzék | Következő |
| Hogyan működik? | Az új várakozósor tesztelése |