jablonka.czprosek.czf

freenet-router

Subversion Repositories:
[/] [trunk/] [freenet-router/] [etc/] [firewall/] [qos] - Blame information for rev 2

 

Line No. Rev Author Line
12simandl#! /bin/bash
2# Firewall nove generace pro Czela Debian 3.0
3# Autor: Mirek Slugen
4# Spoluatori: Michal Perlik, Michal Vondracek, Jan Chmelensky
5# Vytvoreno: 06.11.2006
6# Naposledy zmeneno: 08.03.2009
7# Tento skript muzete volne sirit a upravovat.
8 
9# implementace QoSu
10qos_start() {
11 # Před každým spuštěním QoSu musíme předchozí QoS ukončit, raději i pokud nebyl aktivní
12 qos_stop
13 
14 echo "Starting QoS..."
15 
16 # lokální proměnné
17 local I=""
18 local J=""
19 local QOS=""
20 local DEV=""
21 local DEV_2=""
22 local RATE=""
23 local DUPLEX=""
24 local DIRECTION=""
25 local COUNT="0"
26 local DEVS=""
27 local RATES=""
28 local DUPLEXS=""
29 local DIRECTIONS=""
30 local CLASS=""
31 local CLASS_DEV=""
32 local CLASS_MIN=""
33 local CLASS_MAX=""
34 local CLASSES=""
35 local RATE_MIN=""
36 
37 # Zjistime rozhrani, na kterych chceme mit spusteny QoS
38 I="0"
39 while [ "$I" -lt 20 ]; do
40 DEV=DEV${I}_IFACE
41 DEV=${!DEV}
42 
43 QOS=DEV${I}_QOS
44 QOS=${!QOS}
45 
46 RATE=DEV${I}_QOS_RATE
47 RATE=${!RATE}
48 
49 DUPLEX=DEV${I}_QOS_DUPLEX
50 DUPLEX=${!DUPLEX}
51 
52 DIRECTION=DEV${I}_QOS_DIRECTION
53 DIRECTION=${!DIRECTION}
54 
55 # inkrementujeme před continue
56 ((I++))
57 
58 [ "$DEV" == "" ] && continue
59 [ "$QOS" != "yes" ] && continue
60 [ "$RATE" == "" ] && continue
61 [ "$DUPLEX" == "" ] && continue
62 [ "$DIRECTION" == "" ] && continue
63 
64 DEVS[$COUNT]="$DEV"
65 RATES[$COUNT]="$RATE"
66 DUPLEXES[$COUNT]="$DUPLEX"
67 DIRECTIONS[$COUNT]="$DIRECTION"
68 
69 ((COUNT++))
70 done
71 
72 # skončíme pokud nejsou rozhraní na kterých bychom QoS spustili
73 if [ "$COUNT" -lt "1" ]; then
74 echo "there is no QoS interface!"
75 return 0
76 fi
77 
78 # Zavedeni modulu pro imq a ifb , v nové verzi už není třeba modul znovu zavádět, v kernelu 2.6.26
79 # a vyšším je problém s odstraněním modulu z paměti (rmmod), jednoduchý test problému:
80 # modprobe imq
81 # iptables -t mangle -A PREROUTING -i eth0 -j IMQ --todev 0
82 # ip link set imq0 up
83 # sleep 5
84 # ping www.seznam.cz -c 2
85 # iptables -t mangle -F
86 # ip link set imq0 down
87 # sleep 0.5
88 # rmmod imq
89 #
90 # Proto zavedeme imq a ifb s maximálním množstvím zařízení abychom ho nemuseli při změně počtu
91 # zařízení znovu zavádět. Nezavádíme imq modul, pokud už je zaveden!
92 if [ "$QOS_DEVICE" == "imq" ]; then
93 [ "`lsmod | awk '{print \$1}' | grep -x \"imq\"`" == "" ] && modprobe imq numdevs=16 &>/dev/null
94 elif [ "$QOS_DEVICE" == "ifb" ]; then
95 [ "`lsmod | awk '{print \$1}' | grep -x \"ifb\"`" == "" ] && modprobe ifb numifbs=16 &>/dev/null
96 fi
97 
98 # Nahození příslušních rozhraní, pro fungovaní QoSu je potřeba rozhraní nahodit
99 if [ "$QOS_DEVICE" == "imq" ] || [ "$QOS_DEVICE" == "ifb" ]; then
100 I="0"
101 while [ "$I" -lt "$COUNT" ]; do
102 $IP link set ${QOS_DEVICE}$I up
103 ((I++))
104 done
105 fi
106 
107 # Na zĂ­skanĂĄ rozhranĂ­ nasadĂ­me QoS
108 I="0"
109 for DEV in ${DEVS[@]}; do
110 RATE="${RATES[$I]}"
111 DIRECTION="${DIRECTIONS[$I]}"
112 DUPLEX="${DUPLEXES[$I]}"
113 
114 # Kontrola na minimĂĄlnĂ­ rychlost rozhranĂ­
115 if [ "$RATE" -lt 10 ]; then
116 echo "Rate on $DEV is too small!"
117 ((I++))
118 continue
119 fi
120 
121 # Pro HTB vypočítáme R2Q
122 if [ "$QOS_LIMIT_TYPE" == "htb" ]; then
123 if [ "$RATE" -lt 20 ]; then
124 echo "Rate on $DEV is too small for HTB R2Q, try set QOS_LIMIT_TYPE to HFSC!"
125 R2Q="1"
126 elif [ "$RATE" -lt 100 ]; then
127 R2Q="1"
128 else
129 R2Q="$[$RATE/100]"
130 fi
131 fi
132 
133 # speciální garantované třídy
134 CLASSES=""
135 RATE_MIN="0"
136 J="1"
137 while true; do
138 CLASS_DEV=CLASS_${J}_DEV
139 CLASS_DEV=${!CLASS_DEV}
140 
141 [ "$CLASS_DEV" == "" ] && break
142 if [ "$CLASS_DEV" != "$DEV" ] && [ "$CLASS_DEV" != "all" ]; then
143 ((J++))
144 continue
145 fi
146 
147 CLASS_MIN=CLASS_${J}_MIN
148 CLASS_MIN=${!CLASS_MIN}
149 
150 CLASS_MAX=CLASS_${J}_MAX
151 CLASS_MAX=${!CLASS_MAX}
152 
153 # garantovaná rychlost nemůže být větší než maximální rychlost na rozhraní
154 if [ "$CLASS_MIN" -ge "$RATE" ]; then
155 ((J++))
156 continue
157 fi
158 
159 CLASSES=$CLASSES"$J $CLASS_MIN $CLASS_MAX
160"
161 
162 RATE_MIN=$(($RATE_MIN + $CLASS_MIN))
163 
164 ((J++))
165 done
166 
167 # kontrola na překročení maximální rychlosti rozhraní, potřebujeme alespoň 10 kbitů navíc
168 if [ "$(($RATE - $RATE_MIN))" -lt "10" ]; then
169 echo "Byla vypoctena pozadovana garantovana rychlost $RATE_MIN, garantovana rychlost na"
170 echo "rozhrani $DEV muze byt maximalne $(($RATE - 10)), snizte garantovane rychlosti,"
171 echo "nebo nastavte garantovane tridy na konkretni rozhrani, misto rozhrani \"all\"."
172 echo ""
173 echo "Garantovane tridy pro rozhrani $DEV budou vynechany!"
174 echo ""
175 CLASSES=""
176 fi
177 
178 # PomocnĂĄ rozhranĂ­ jako IFB a IMQ
179 if [ "$QOS_DEVICE" != "" ]; then
180 DEV_2="${QOS_DEVICE}$I"
181 echo " $DEV rate ${RATE} kbit/s with $DEV_2 type $DUPLEX"
182 
183 if [ "$QOS_DEVICE" == "imq" ]; then
184 if [ "$DUPLEX" == "HD" ]; then
185 if [ "$DUMMY_IFACE" != "" ]; then
186 [ "$DUMMY_IP" == "" ] && DUMMY_IP="`$IP addr show $DUMMY_IFACE | grep inet | grep -v inet6 | awk '{print \$2}' | cut -d \"/\" -f1`"
187 $IPTABLES -t mangle -A POSTROUTING -o $DEV -s ! $DUMMY_IP -j IMQ --todev $I
188 else
189 $IPTABLES -t mangle -A POSTROUTING -o $DEV -j IMQ --todev $I
190 fi
191 $IPTABLES -t mangle -A PREROUTING -i $DEV -j IMQ --todev $I
192 DEV=""
193 else
194 $IPTABLES -t mangle -A PREROUTING -i $DEV -j IMQ --todev $I
195 fi
196 elif [ "$QOS_DEVICE" == "ifb" ]; then
197 # IFB neumí poloviční duplex
198 [ "$DUPLEX" == "HD" ] && echo "IFB does not support HD (half duplex), using FD (full duplex)!"
199 
200 # Kontrola na nåzev rozhraní ath, kterÊ indikuje atheros kartu, ta må problÊmy s IFB
201 if [ "${DEV:0:3}" == "ath" ]; then
202 # Test, jestli dojde ke kernel panicu na atheros kartĂĄch:
203 #modprobe ifb
204 #ip link set ifb0 up
205 #tc qdisc add dev ath0 ingress
206 #tc filter add dev ath0 parent ffff: protocol ip prio 10 u32 match u32 0 0 flowid 1:0 action mirred egress redirect dev ifb0
207 echo "IFB on atheros (madwifi) cards could cause kernel panic, try to use IMQ, or"
208 echo "disable QoS on atheros cards!"
209 DEV_2=""
210 else
211 $TC qdisc add dev $DEV ingress
212 $TC filter add dev $DEV parent ffff: protocol ip prio 10 u32 match u32 0 0 flowid 1:0 action mirred egress redirect dev $DEV_2
213 fi
214 fi
215 else
216 echo " $DEV rate ${RATE} kbit/s without ifb or imq"
217 DEV_2=""
218 fi
219 
220 # Na zĂĄkladnĂ­m i pomocnĂŠm rozhranĂ­ nasadĂ­me QoS
221 for DEV in $DEV $DEV_2; do
222 # QoS pro esfq, nebo sfq
223 if [ "$QOS_TYPE" == "esfq" ] || [ "$QOS_TYPE" == "layer7_esfq" ]; then
224 # Pro ESFQ musíme určit na základě typu rozhraní hash
225 if [ "$DIRECTION" == "WAN" ]; then
226 if [ "${DEV:0:3}" != "imq" ] && [ "${DEV:0:3}" != "ifb" ]; then
227 SFQ="esfq perturb 10 hash src"
228 else
229 SFQ="esfq perturb 10 hash dst"
230 fi
231 elif [ "$DIRECTION" == "NAT" ]; then
232 if [ "${DEV:0:3}" != "imq" ] && [ "${DEV:0:3}" != "ifb" ]; then
233 SFQ="esfq perturb 10 hash ctnatchg"
234 else
235 SFQ="esfq perturb 10 hash dst"
236 fi
237 else
238 if [ "${DEV:0:3}" != "imq" ] && [ "${DEV:0:3}" != "ifb" ]; then
239 SFQ="esfq perturb 10 hash dst"
240 else
241 SFQ="esfq perturb 10 hash src"
242 fi
243 fi
244 else
245 SFQ="sfq perturb 10"
246 fi
247 
248 # Základní nasazení tříd je pro všechny typy QoSu stejné
249 # Vytvoříme root qdisc
250 $TC qdisc add dev $DEV root handle 1:0 prio bands 3 priomap 2 2 2 2 2 2 0 0 2 2 2 2 2 2 2 2
251 
252 # V prvních dvou třídách nebudeme limitovat, pouze budeme rozdělovat pásmo pomocí sfq
253 $TC qdisc add dev $DEV parent 1:1 handle 11:0 $SFQ
254 $TC qdisc add dev $DEV parent 1:2 handle 12:0 $SFQ
255 
256 # Omarkované pakety roztřídíme do jednotlivých tříd, první třída bude mít prioritu 1,
257 # tj. cokoliv co do ní přejde už nezávisle na dalších pravidlech zpracuje, ostatní
258 # nemají prioritu udanou, tím se řadí na konec až za všechna ostatní pravidla.
259 $TC filter add dev $DEV parent 1:0 protocol ip prio 1 handle 1 fw flowid 1:1
260 $TC filter add dev $DEV parent 1:0 protocol ip handle 2 fw flowid 1:2
261 
262 # 3. třída je určena pro datového omezení
263 if [ "$QOS_LIMIT_TYPE" == "htb" ]; then
264 $TC qdisc add dev $DEV parent 1:3 handle 13:0 htb r2q $R2Q default 111
265 
266 # Zakladni htb tride dame plnou rychlost, dalsi budou mit rychlost sdilenou HTTP,mail, DC++,
267 $TC class add dev $DEV parent 13:0 classid 13:1 htb rate ${RATE}kbit
268 else
269 $TC qdisc add dev $DEV parent 1:3 handle 13:0 hfsc default 111
270 
271 # Zakladni hfsc tride dame plnou rychlost, dalsi budou mit rychlost sdilenou HTTP,mail, DC++,
272 $TC class add dev $DEV parent 13:0 classid 13:1 hfsc ls m2 ${RATE}kbit ul m2 ${RATE}kbit
273 fi
274 
275 # Pokročilé nasazení tříd podle typu
276 if [ "$QOS_TYPE" == "layer7" ] || [ "$QOS_TYPE" == "layer7_esfq" ]; then
277 if [ "$QOS_LIMIT_TYPE" == "htb" ]; then
278 $TC class add dev $DEV parent 13:1 classid 13:111 htb rate $[5*($RATE - $RATE_MIN)/10]kbit ceil ${RATE}kbit
279 $TC class add dev $DEV parent 13:1 classid 13:112 htb rate $[3*($RATE - $RATE_MIN)/10]kbit ceil ${RATE}kbit
280 $TC class add dev $DEV parent 13:1 classid 13:113 htb rate $[2*($RATE - $RATE_MIN)/10]kbit ceil ${RATE}kbit
281 else
282 $TC class add dev $DEV parent 13:1 classid 13:111 hfsc ls m2 $[5*($RATE - $RATE_MIN)/10]kbit ul m2 ${RATE}kbit
283 $TC class add dev $DEV parent 13:1 classid 13:112 hfsc ls m2 $[3*($RATE - $RATE_MIN)/10]kbit ul m2 ${RATE}kbit
284 $TC class add dev $DEV parent 13:1 classid 13:113 hfsc ls m2 $[2*($RATE - $RATE_MIN)/10]kbit ul m2 ${RATE}kbit
285 fi
286 
287 # V kazde tride jeste pouziji sfq
288 $TC qdisc add dev $DEV parent 13:111 handle 111:0 $SFQ
289 $TC qdisc add dev $DEV parent 13:112 handle 112:0 $SFQ
290 $TC qdisc add dev $DEV parent 13:113 handle 113:0 $SFQ
291 
292 # Další třídy zpracovávající pravidla z iptables
293 $TC filter add dev $DEV parent 13:0 protocol ip handle 3 fw flowid 13:111
294 $TC filter add dev $DEV parent 13:0 protocol ip handle 4 fw flowid 13:112
295 $TC filter add dev $DEV parent 13:0 protocol ip handle 5 fw flowid 13:113
296 else
297 # Nastavime maximalni ryhlost pro vse co jde do tridy 2 (3. skupina)
298 if [ "$QOS_LIMIT_TYPE" == "htb" ]; then
299 $TC class add dev $DEV parent 13:1 classid 13:111 htb rate $[($RATE - $RATE_MIN)]kbit ceil ${RATE}kbit
300 else
301 # Zakladni hfsc tride dame plnou rychlost
302 $TC class add dev $DEV parent 13:1 classid 13:111 hfsc ls m2 $[($RATE - $RATE_MIN)]kbit ul m2 ${RATE}kbit
303 fi
304 
305 # V kazde tride jeste pouziji sfq
306 $TC qdisc add dev $DEV parent 13:111 handle 111:0 $SFQ
307 
308 # I pokud nepouŞívåme layer7, můŞeme vyuŞít markovåní pomocí iptables
309 $TC filter add dev $DEV parent 13:0 protocol ip handle 3 fw flowid 13:111
310 fi
311 
312 # speciální třídy
313 IFS=$'\t\n'
314 for CLASS in $CLASSES; do
315 IFS=$' \t\n'
316 CLASS=( $CLASS )
317 # garantovaná rychlost nemůže být větší než maximální rychlost na rozhraní
318 [ "${CLASS[1]}" -ge "$RATE" ] && continue
319 # pokud nenĂ­ zadanĂĄ maximĂĄlnĂ­ rychlost, tak je maximum celkovĂ˝ rychlost rozhranĂ­
320 [ "${CLASS[2]}" == "" ] && CLASS[2]=$RATE
321 # pokud je maximĂĄlnĂ­ rychlost menĹĄĂ­ neĹž minimĂĄlnĂ­, tak je maximum rychlost rozhranĂ­
322 [ "${CLASS[2]}" -lt "${CLASS[1]}" ] && CLASS[2]=$RATE
323 # pokud je maximální rychlost větší, než maximální rychlost rozhraní, tak je maximum rychlost rozhraní
324 [ "${CLASS[2]}" -gt "$RATE" ] && CLASS[2]=$RATE
325 
326 if [ "$QOS_LIMIT_TYPE" == "htb" ]; then
327 $TC class add dev $DEV parent 13:1 classid 13:$((113 + ${CLASS[0]})) htb rate ${CLASS[1]}kbit ceil ${CLASS[2]}kbit
328 else
329 $TC class add dev $DEV parent 13:1 classid 13:$((113 + ${CLASS[0]})) hfsc ls m2 ${CLASS[1]}kbit ul m2 ${CLASS[2]}kbit
330 fi
331 
332 # Nasadíme sfq na dané třídy
333 $TC qdisc add dev $DEV parent 13:$((113 + ${CLASS[0]})) handle $((113 + ${CLASS[0]})):0 $SFQ
334 
335 # Garantované třídy nepotřebují speciální třídu, protože se markují jen pomocí tc rovnou do dané třídy
336 #$TC filter add dev $DEV parent 1:0 protocol ip handle $((5 + ${CLASS[0]})) fw flowid 13:$((113 + ${CLASS[0]}))
337 #$TC filter add dev $DEV parent 13:0 protocol ip handle $((5 + ${CLASS[0]})) fw flowid 13:$((113 + ${CLASS[0]}))
338 done
339 IFS=$' \t\n'
340 done
341 ((I++))
342 done
343 
344 # Protože markování na každém zařízení zvlášť by bylo velmi mnoho pravidel pro iptables,
345 # tak použijeme markování na všech zařízeních, i tak zavedení pravidel trvá cca 6 vteřin.
346 if [ "$QOS_TYPE" == "layer7" ] || [ "$QOS_TYPE" == "layer7_esfq" ]; then
347 # Markování musíme provádět již v preroutingu, jinak nejsme schopni označit všechny pakety.
348 # ICMP - vzdy
349 $IPTABLES -t mangle -I PREROUTING -p icmp -j MARK --set-mark 1
350 # OSPF - vzdy
351 $IPTABLES -t mangle -I PREROUTING -p ospf -j MARK --set-mark 1
352 # UDP - vzdy
353 $IPTABLES -t mangle -I PREROUTING -p UDP -j MARK --set-mark 2
354 # HTML - jiny nekorektni zpusob markovani http, ale mnohem mene narocny
355 #$IPTABLES -t mangle -I PREROUTING -p TCP --dport 80 -j MARK --set-mark 3
356 
357 # Označení paketů pomocí layer7 filtru, detekce některých protokolů zvyšuje odezvy
358 # 8.3.2009 - vyřazeny protokoly, které po cca 30 dnech měly nulové čítače
359 qos_mark_layer7 1 "bgp dhcp dns irc jabber snmp whois"
360 qos_mark_layer7 2 "quake-halflife worldofwarcraft"
361 # Do třídy 3 jdou všechna nezařazená data, takže jí není třeba označovat
362 qos_mark_layer7 3 ""
363 qos_mark_layer7 4 "ftp cvs biff h323 imap live365 pop3 rtsp shoutcast smtp ssl tftp"
364 qos_mark_layer7 5 "bittorrent directconnect edonkey http-itunes soulseek"
365 fi
366 
367 echo "done."
368 
369 # Označíme jednotlivé počítače v třídách
370 qos_guaranted_classes
371}
372 
373qos_stop() {
374 echo -n "Stopping QoS..."
375 
376 local I=""
377 local DEV=""
378 
379 # SmaĹžeme vĹĄechna pravidla v iptables
380 for I in `$IPTABLES -t mangle -L POSTROUTING -n -v --line-numbers | grep "set 0x" | awk '{print $1}' | sort -r -n`; do
381 $IPTABLES -t mangle -D POSTROUTING $I
382 done
383 
384 for I in `$IPTABLES -t mangle -L PREROUTING -n -v --line-numbers | grep "set 0x" | awk '{print $1}' | sort -r -n`; do
385 $IPTABLES -t mangle -D PREROUTING $I
386 done
387 
388 for I in `$IPTABLES -t mangle -L POSTROUTING -n -v --line-numbers | grep "todev" | awk '{print $1}' | sort -r -n`; do
389 $IPTABLES -t mangle -D POSTROUTING $I
390 done
391 
392 for I in `$IPTABLES -t mangle -L PREROUTING -n -v --line-numbers | grep "todev" | awk '{print $1}' | sort -r -n`; do
393 $IPTABLES -t mangle -D PREROUTING $I
394 done
395 
396 # SmaĹžeme vĹĄechny root qdisky
397 while true; do
398 DEV="`$TC qdisc | grep -v 0: | awk '{print \$5}' | sort -u | sed -n 1p`"
399 [ "$DEV" == "" ] && break
400 $TC qdisc del dev "$DEV" root &>/dev/null
401 $TC qdisc del dev "$DEV" ingress &>/dev/null
402 done
403 
404 # Deaktivujeme všechna ifb zařízení
405 while true; do
406 DEV="`$IP link show | grep ifb | grep UP | awk '{print \$2}' | sort -u | sed -n 1p`"
407 [ "$DEV" == "" ] && break
408 DEV="${DEV//:/}"
409 $IP link set "$DEV" down
410 done
411 
412 # Odstraníme ifb modul z paměti
413 #rmmod -f ifb &>/dev/null
414 
415 # Deaktivujeme všechna imq zařízení
416 while true; do
417 DEV="`$IP link show | grep imq | grep UP | awk '{print \$2}' | sort -u | sed -n 1p`"
418 [ "$DEV" == "" ] && break
419 DEV="${DEV//:/}"
420 $IP link set "$DEV" down
421 done
422 
423 # Odstraníme imq modul z paměti
424 #rmmod -f imq &>/dev/null
425 
426 echo "done."
427}
428 
429qos_stats() {
430 $TC -s qdisc
431}
432 
433# speciální garantované třídy
434qos_guaranted_classes() {
435 [ "${#CLASS_1[*]}" -lt "1" ] && return 0
436 
437 echo "Starting QoS guaranted classes..."
438 
439 # lokální proměnné
440 local I=""
441 local J=""
442 local CLASS_DEV=""
443 local CLASS_MIN=""
444 local CLASS_MAX=""
445 local CLASS_USERS=""
446 local CLASSES=""
447 local RATE_MIN="0"
448 local USER=""
449 
450 J="1"
451 while true; do
452 CLASS_DEV=CLASS_${J}_DEV
453 CLASS_DEV=${!CLASS_DEV}
454 
455 [ "$CLASS_DEV" == "" ] && break
456 
457 CLASS_MIN=CLASS_${J}_MIN
458 CLASS_MIN=${!CLASS_MIN}
459 
460 CLASS_MAX=CLASS_${J}_MAX
461 CLASS_MAX=${!CLASS_MAX}
462 
463 # klasické přiřazení nelze použít na pole
464 CLASS_USERS="CLASS_${J}[@]"
465 CLASS_USERS=( "${!CLASS_USERS}" )
466 
467 # Přeskočíme prázdné třídy
468 if [ "${#CLASS_USERS[*]}" -lt "1" ]; then
469 ((J++))
470 continue
471 fi
472 
473 # Pokud není zadána maximální rychlost třídy
474 [ "$CLASS_MAX" == "" ] && CLASS_MAX="interface maximum"
475 
476 echo "QoS class $J (dev: $CLASS_DEV, min: $CLASS_MIN kbit/s, max: $CLASS_MAX kbit/s):"
477 
478 IFS=$'\t\n'
479 for USER in ${CLASS_USERS[@]}; do
480 IFS=$' \t\n'
481 USER=( $USER )
482 I="2"
483 while [ "${USER[$I]}" != "" ]; do
484 if [ "${USER[$I]:2:1}" == ":" ]; then
485 echo -e " user ${USER[1]}\twith mac ${USER[$I]}\ton ${USER[0]}\tlimited!"
486 else
487 echo -e " user ${USER[1]}\twith ip ${USER[$I]}\t\ton ${USER[0]}\tlimited!"
488 fi
489 qos_guaranted_class_add_user "$J" "${USER[$I]}" "${USER[0]}"
490 ((I++))
491 done
492 done
493 IFS=$' \t\n'
494 
495 ((J++))
496 done
497 
498 echo "done."
499}
500 
501# formát: "třída" "ip, nebo mac" "rozhraní - nepovinné"
502qos_guaranted_class_add_user() {
503 ( [ "$1" == "" ] || [ "$2" == "" ] ) && return 0
504 
505 # rozhraní na kterých je aktivní qos, vŞdy pouŞívåme alespoň sfq
506 local TC_DEVS=`$TC qdisc | grep sfq | awk '{print $5}' | sort -u`
507 
508 # další lokální proměnné
509 local I=""
510 local DEV=""
511 local TC_DEV=""
512 local TC_DEVS_POM=""
513 local IMQ_DEV=""
514 local IFB_DEV=""
515 local DATA=""
516 local LINE=""
517 local IP="$2"
518 local MAC="`echo $2 | tr [:upper:] [:lower:]`"
519 local TC_NUM=""
520 local CLASS=""
521 
522 # pokud ip, nebo mac uĹž je zadanĂĄ, tak jĂ­ smaĹžeme na vĹĄech rozhranĂ­ch
523 qos_guaranted_class_del_user "$2"
524 
525 # zjistĂ­me jestli jde o MAC, nebo IP adresu
526 IFS=$'./\t\n'
527 IP=( $IP )
528 IFS=$':\t\n'
529 MAC=( $MAC )
530 IFS=$' \t\n'
531 
532 # Je-li zadané rozhraní, tak musíme najít přidružené IMQ, nebo IFB
533 if [ "$3" != "" ] && [ "$3" != "all" ]; then
534 # IMQ z PREROUTINGu, musíme použít awk, protože iptables posílá * a ta se nedá převést do pole!
535 DATA=`$IPTABLES -t mangle -L PREROUTING -n -v | grep todev | awk '{print $6" "$12}'`
536 
537 IFS=$'\t\n'
538 for LINE in $DATA; do
539 IFS=$' \t\n'
540 LINE=( ${LINE} )
541 if [ "${LINE[0]}" == "$3" ] && [ "${LINE[1]}" != "" ]; then
542 IMQ_DEV="imq${LINE[1]}"
543 break
544 fi
545 done
546 IFS=$' \t\n'
547 
548 # ifb zĂ­skĂĄme z tc
549 IFB_DEV="`$TC filter list dev $3 parent ffff: | grep ifb | awk '{print \$9}'`"
550 IFB_DEV="${IFB_DEV//)/}"
551 
552 for I in $TC_DEVS; do
553 [ "$3" == "$I" ] && TC_DEVS_POM=$TC_DEVS_POM" $I"
554 [ "$IFB_DEV" != "" ] && [ "$IFB_DEV" == "$I" ] && TC_DEVS_POM=$TC_DEVS_POM" $IFB_DEV"
555 [ "$IMQ_DEV" != "" ] && [ "$IMQ_DEV" == "$I" ] && TC_DEVS_POM=$TC_DEVS_POM" $IMQ_DEV"
556 done
557 
558 [ "$TC_DEVS_POM" == "" ] && return 0
559 
560 # MusĂ­me odstranit prvnĂ­ prĂĄzdnĂ˝ znak
561 TC_DEVS="${TC_DEVS_POM:1}"
562 fi
563 
564 # samotné zařazení do třídy
565 for DEV in $TC_DEVS; do
566 # smažeme nejprve třídy 1:0 a pak 13:0
567 for CLASS in "1:0" "13:0"; do
568 # musíme najít další číslo kam budeme přidávat záznam
569 TC_NUM=$((`$TC filter list dev $DEV parent $CLASS | awk '{print $5}' | grep -v "4915" | sort -ug | tail -n 1` + 1))
570 
571 if [ "${IP[3]}" != "" ]; then
572 $TC filter add dev $DEV parent $CLASS protocol ip prio $TC_NUM u32 match ip src $2 flowid 13:$((113 + $1))
573 $TC filter add dev $DEV parent $CLASS protocol ip prio $TC_NUM u32 match ip dst $2 flowid 13:$((113 + $1))
574 elif [ "${MAC[5]}" != "" ]; then
575 $TC filter add dev $DEV parent $CLASS protocol ip prio $TC_NUM u32 match u16 0x0800 0xffff at -2 match u32 0x${MAC[2]}${MAC[3]}${MAC[4]}${MAC[5]} 0xffffffff at -12 match u16 0x${MAC[0]}${MAC[1]} 0xffff at -14 flowid 13:$((113 + $1))
576 $TC filter add dev $DEV parent $CLASS protocol ip prio $TC_NUM u32 match u16 0x0800 0xffff at -2 match u16 0x${MAC[4]}${MAC[5]} 0xffff at -4 match u32 0x${MAC[0]}${MAC[1]}${MAC[2]}${MAC[3]} 0xffffffff at -8 flowid 13:$((113 + $1))
577 else
578 # nejednĂĄ se ani o ip ani o mac adresu
579 return 0
580 fi
581 done
582 done
583 
584 return 0
585}
586 
587# Pro mazání není třeba znát třídu ze které mažeme, protože by jedna ip, nebo mac
588# neměla být ve více třídách.
589#
590# formĂĄt: "ip, nebo mac"
591qos_guaranted_class_del_user() {
592 [ "$1" == "" ] && return 0
593 
594 # MaĹžeme na vĹĄech rozhranĂ­ch, kde je QoS
595 local TC_DEVS=`$TC qdisc | grep sfq | awk '{print $5}' | sort -u`
596 
597 # lokální proměnné
598 local I=""
599 local DEV=""
600 local DATA=""
601 local LINE=""
602 local LINE_1=""
603 local LINE_2=""
604 local IP="$1"
605 local MAC="`echo $1 | tr [:upper:] [:lower:]`"
606 local IP_HEX=""
607 local MAC_1=""
608 local MAC_2=""
609 local MAC_3=""
610 local CLASS=""
611 local PRIO=""
612 local PRIO_PREV=""
613 
614 # zjistíme jestli jde o MAC, nebo IP adresu, pro mac musíme převést velká písmena na malá
615 IFS=$'./\t\n'
616 IP=( $IP )
617 IFS=$':\t\n'
618 MAC=( $MAC )
619 IFS=$' \t\n'
620 
621 if [ "${IP[3]}" != "" ]; then
622 # převedeme ip do formátu, který používá tc
623 IP_HEX=`printf '%02x%02x%02x%02x\n' ${IP[0]} ${IP[1]} ${IP[2]} ${IP[3]}`
624 elif [ "${MAC[5]}" != "" ]; then
625 MAC_1="00000800"
626 MAC_2="${MAC[2]}${MAC[3]}${MAC[4]}${MAC[5]}"
627 MAC_3="0000${MAC[0]}${MAC[1]}"
628 else
629 # NejednĂĄ se ani o ip ani o mac adresu
630 return 0
631 fi
632 
633 # zkontrolujeme vĹĄechna rozhranĂ­
634 for DEV in $TC_DEVS; do
635 # smažeme nejprve třídy 1:0 a pak 13:0
636 for CLASS in "1:0" "13:0"; do
637 # načteme data z tc, kde jsou uloženy všechny zadané mac i ip adresy
638 IFS=$'\t\n'
639 DATA=( `$TC filter list dev $DEV parent $CLASS` )
640 IFS=$' \t\n'
641 
642 I="0"
643 PRIO=""
644 PRIO_PREV=""
645 
646 IFS=$'\t\n'
647 for LINE in ${DATA[@]}; do
648 # pro matchování nás nezajímá maska, proto masku oddělíme, platí jen v případě ip
649 IFS=$' /\t\n'
650 LINE=( $LINE )
651 IFS=$' \t\n'
652 
653 # inkrementovat musíme ještě před continue
654 ((I++))
655 
656 if [ "${LINE[3]}" == "pref" ]; then
657 PRIO=${LINE[4]}
658 continue
659 fi
660 # dĂĄle nĂĄs zajĂ­mĂĄ jen match
661 [ "${LINE[0]}" != "match" ] && continue
662 # pokud neznáme prioritu, tak pokračujeme
663 [ "$PRIO" == "" ] && continue
664 # pokud jsme již jednou tuto prioritu mazali, tak pokračujeme
665 [ "$PRIO" == "$PRIO_PREV" ] && continue
666 
667 # rozdělení podle ip, nebo mac
668 if [ "${IP[3]}" != "" ]; then
669 # pokud ip neodpovídá, tak pokračujeme
670 [ "${LINE[1]}" != "$IP_HEX" ] && continue
671 elif [ "${MAC[5]}" != "" ]; then
672 # jednotnĂ˝ match pro vĹĄechny mac adresy
673 [ "${LINE[1]}/${LINE[2]}" != "$MAC_1/0000ffff" ] && continue
674 # následující řádek musí obsahovat druhou část mac adresy, už nepoužíváme jako delimiter /
675 LINE_1=( ${DATA[$I]} )
676 [ "${LINE_1[1]}" != "$MAC_2/ffffffff" ] && continue
677 # další řádek musí obsahovat poslední část mac adresy
678 LINE_2=( ${DATA[$(($I + 1))]} )
679 [ "${LINE_2[1]}" != "$MAC_3/0000ffff" ] && continue
680 fi
681 
682 # DanĂĄ ip uĹž je matchovanĂĄ, proto pravidla smaĹžeme
683 $TC filter del dev $DEV parent $CLASS protocol ip prio $PRIO 2>/dev/null
684 
685 PRIO_PREV="$PRIO"
686 done
687 IFS=$' \t\n'
688 done
689 done
690 
691 return 0
692}
693 
694qos_mark_layer7() {
695 ( [ "$1" == "" ] || [ "$2" == "" ] ) && return 0
696 
697 # Lokální proměnné
698 local I=""
699 local O_DEV=""
700 local I_DEV=""
701 
702 [ "$3" != "" ] && O_DEV="-o $3"
703 [ "$4" != "" ] && I_DEV="-i $4"
704 
705 for I in $2; do
706 $IPTABLES -t mangle -I PREROUTING $O_DEV $I_DEV -m layer7 --l7proto $I -j MARK --set-mark $1
707 done
708 
709 return 0
710}

Powered by WebSVN 2.2.1