freenet-router |
Subversion Repositories: |
Compare with Previous - Blame - Download
#! /bin/bash
# Firewall nove generace pro Czela Debian 3.0
# Autor: Mirek Slugen
# Spoluatori: Michal Perlik, Michal Vondracek, Jan Chmelensky
# Vytvoreno: 06.11.2006
# Naposledy zmeneno: 08.03.2009
# Tento skript muzete volne sirit a upravovat.
# implementace QoSu
qos_start() {
# PĹed kaĹždĂ˝m spuĹĄtÄnĂm QoSu musĂme pĹedchozĂ QoS ukonÄit, radÄji i pokud nebyl aktivnĂ
qos_stop
echo "Starting QoS..."
# lokĂĄlnĂ promÄnnĂŠ
local I=""
local J=""
local QOS=""
local DEV=""
local DEV_2=""
local RATE=""
local DUPLEX=""
local DIRECTION=""
local COUNT="0"
local DEVS=""
local RATES=""
local DUPLEXS=""
local DIRECTIONS=""
local CLASS=""
local CLASS_DEV=""
local CLASS_MIN=""
local CLASS_MAX=""
local CLASSES=""
local RATE_MIN=""
# Zjistime rozhrani, na kterych chceme mit spusteny QoS
I="0"
while [ "$I" -lt 20 ]; do
DEV=DEV${I}_IFACE
DEV=${!DEV}
QOS=DEV${I}_QOS
QOS=${!QOS}
RATE=DEV${I}_QOS_RATE
RATE=${!RATE}
DUPLEX=DEV${I}_QOS_DUPLEX
DUPLEX=${!DUPLEX}
DIRECTION=DEV${I}_QOS_DIRECTION
DIRECTION=${!DIRECTION}
#Â inkrementujeme pĹed continue
((I++))
[ "$DEV" == "" ] && continue
[ "$QOS" != "yes" ] && continue
[ "$RATE" == "" ] && continue
[ "$DUPLEX" == "" ] && continue
[ "$DIRECTION" == "" ] && continue
DEVS[$COUNT]="$DEV"
RATES[$COUNT]="$RATE"
DUPLEXES[$COUNT]="$DUPLEX"
DIRECTIONS[$COUNT]="$DIRECTION"
((COUNT++))
done
# skonÄĂme pokud nejsou rozhranĂ na kterĂ˝ch bychom QoS spustili
if [ "$COUNT" -lt "1" ]; then
echo "there is no QoS interface!"
return 0
fi
# Zavedeni modulu pro imq a ifb , v novĂŠ verzi uĹž nenĂ tĹeba modul znovu zavĂĄdÄt, v kernelu 2.6.26
# a vyĹĄĹĄĂm je problĂŠm s odstranÄnĂm modulu z pamÄti (rmmod), jednoduchĂ˝ test problĂŠmu:
# modprobe imq
# iptables -t mangle -A PREROUTING -i eth0 -j IMQ --todev 0
# ip link set imq0 up
# sleep 5
# ping www.seznam.cz -c 2
# iptables -t mangle -F
# ip link set imq0 down
# sleep 0.5
# rmmod imq
#
# Proto zavedeme imq a ifb s maximĂĄlnĂm mnoĹžstvĂm zaĹĂzenĂ abychom ho nemuseli pĹi zmÄnÄ poÄtu
# zaĹĂzenĂ znovu zavĂĄdÄt. NezavĂĄdĂme imq modul, pokud uĹž je zaveden!
if [ "$QOS_DEVICE" == "imq" ]; then
[ "`lsmod | awk '{print \$1}' | grep -x \"imq\"`" == "" ] && modprobe imq numdevs=16 &>/dev/null
elif [ "$QOS_DEVICE" == "ifb" ]; then
[ "`lsmod | awk '{print \$1}' | grep -x \"ifb\"`" == "" ] && modprobe ifb numifbs=16 &>/dev/null
fi
# NahozenĂ pĹĂsluĹĄnĂch rozhranĂ, pro fungovanĂ QoSu je potĹeba rozhranĂ nahodit
if [ "$QOS_DEVICE" == "imq" ] || [ "$QOS_DEVICE" == "ifb" ]; then
I="0"
while [ "$I" -lt "$COUNT" ]; do
$IP link set ${QOS_DEVICE}$I up
((I++))
done
fi
# Na zĂskanĂĄ rozhranĂ nasadĂme QoS
I="0"
for DEV in ${DEVS[@]}; do
RATE="${RATES[$I]}"
DIRECTION="${DIRECTIONS[$I]}"
DUPLEX="${DUPLEXES[$I]}"
# Kontrola na minimĂĄlnĂ rychlost rozhranĂ
if [ "$RATE" -lt 10 ]; then
echo "Rate on $DEV is too small!"
((I++))
continue
fi
# Pro HTB vypoÄĂtĂĄme R2Q
if [ "$QOS_LIMIT_TYPE" == "htb" ]; then
if [ "$RATE" -lt 20 ]; then
echo "Rate on $DEV is too small for HTB R2Q, try set QOS_LIMIT_TYPE to HFSC!"
R2Q="1"
elif [ "$RATE" -lt 100 ]; then
R2Q="1"
else
R2Q="$[$RATE/100]"
fi
fi
# speciĂĄlnĂ garantovanĂŠ tĹĂdy
CLASSES=""
RATE_MIN="0"
J="1"
while true; do
CLASS_DEV=CLASS_${J}_DEV
CLASS_DEV=${!CLASS_DEV}
[ "$CLASS_DEV" == "" ] && break
if [ "$CLASS_DEV" != "$DEV" ] && [ "$CLASS_DEV" != "all" ]; then
((J++))
continue
fi
CLASS_MIN=CLASS_${J}_MIN
CLASS_MIN=${!CLASS_MIN}
CLASS_MAX=CLASS_${J}_MAX
CLASS_MAX=${!CLASS_MAX}
# garantovanĂĄ rychlost nemĹŻĹže bĂ˝t vÄtĹĄĂ neĹž maximĂĄlnĂ rychlost na rozhranĂ
if [ "$CLASS_MIN" -ge "$RATE" ]; then
((J++))
continue
fi
CLASSES=$CLASSES"$J $CLASS_MIN $CLASS_MAX
"
RATE_MIN=$(($RATE_MIN + $CLASS_MIN))
((J++))
done
# kontrola na pĹekroÄenĂ maximĂĄlnĂ rychlosti rozhranĂ, potĹebujeme alespoĹ 10 kbitĹŻ navĂc
if [ "$(($RATE - $RATE_MIN))" -lt "10" ]; then
echo "Byla vypoctena pozadovana garantovana rychlost $RATE_MIN, garantovana rychlost na"
echo "rozhrani $DEV muze byt maximalne $(($RATE - 10)), snizte garantovane rychlosti,"
echo "nebo nastavte garantovane tridy na konkretni rozhrani, misto rozhrani \"all\"."
echo ""
echo "Garantovane tridy pro rozhrani $DEV budou vynechany!"
echo ""
CLASSES=""
fi
# PomocnĂĄ rozhranĂ jako IFB a IMQ
if [ "$QOS_DEVICE" != "" ]; then
DEV_2="${QOS_DEVICE}$I"
echo " $DEV rate ${RATE} kbit/s with $DEV_2 type $DUPLEX"
if [ "$QOS_DEVICE" == "imq" ]; then
if [ "$DUPLEX" == "HD" ]; then
if [ "$DUMMY_IFACE" != "" ]; then
[ "$DUMMY_IP" == "" ] && DUMMY_IP="`$IP addr show $DUMMY_IFACE | grep inet | grep -v inet6 | awk '{print \$2}' | cut -d \"/\" -f1`"
$IPTABLES -t mangle -A POSTROUTING -o $DEV -s ! $DUMMY_IP -j IMQ --todev $I
else
$IPTABLES -t mangle -A POSTROUTING -o $DEV -j IMQ --todev $I
fi
$IPTABLES -t mangle -A PREROUTING -i $DEV -j IMQ --todev $I
DEV=""
else
$IPTABLES -t mangle -A PREROUTING -i $DEV -j IMQ --todev $I
fi
elif [ "$QOS_DEVICE" == "ifb" ]; then
# IFB neumĂ poloviÄnĂ duplex
[ "$DUPLEX" == "HD" ] && echo "IFB does not support HD (half duplex), using FD (full duplex)!"
#Â Kontrola na nĂĄzev rozhranĂ ath, kterĂŠ indikuje atheros kartu, ta mĂĄ problĂŠmy s IFB
if [ "${DEV:0:3}" == "ath" ]; then
# Test, jestli dojde ke kernel panicu na atheros kartĂĄch:
#modprobe ifb
#ip link set ifb0 up
#tc qdisc add dev ath0 ingress
#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
echo "IFB on atheros (madwifi) cards could cause kernel panic, try to use IMQ, or"
echo "disable QoS on atheros cards!"
DEV_2=""
else
$TC qdisc add dev $DEV ingress
$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
fi
fi
else
echo " $DEV rate ${RATE} kbit/s without ifb or imq"
DEV_2=""
fi
# Na zĂĄkladnĂm i pomocnĂŠm rozhranĂ nasadĂme QoS
for DEV in $DEV $DEV_2; do
# QoS pro esfq, nebo sfq
if [ "$QOS_TYPE" == "esfq" ] || [ "$QOS_TYPE" == "layer7_esfq" ]; then
# Pro ESFQ musĂme urÄit na zĂĄkladÄ typu rozhranĂ hash
if [ "$DIRECTION" == "WAN" ]; then
if [ "${DEV:0:3}" != "imq" ] && [ "${DEV:0:3}" != "ifb" ]; then
SFQ="esfq perturb 10 hash src"
else
SFQ="esfq perturb 10 hash dst"
fi
elif [ "$DIRECTION" == "NAT" ]; then
if [ "${DEV:0:3}" != "imq" ] && [ "${DEV:0:3}" != "ifb" ]; then
SFQ="esfq perturb 10 hash ctnatchg"
else
SFQ="esfq perturb 10 hash dst"
fi
else
if [ "${DEV:0:3}" != "imq" ] && [ "${DEV:0:3}" != "ifb" ]; then
SFQ="esfq perturb 10 hash dst"
else
SFQ="esfq perturb 10 hash src"
fi
fi
else
SFQ="sfq perturb 10"
fi
# ZĂĄkladnĂ nasazenĂ tĹĂd je pro vĹĄechny typy QoSu stejnĂŠ
# VytvoĹĂme root qdisc
$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
# V prvnĂch dvou tĹĂdĂĄch nebudeme limitovat, pouze budeme rozdÄlovat pĂĄsmo pomocĂ sfq
$TC qdisc add dev $DEV parent 1:1 handle 11:0 $SFQ
$TC qdisc add dev $DEV parent 1:2 handle 12:0 $SFQ
# OmarkovanĂŠ pakety roztĹĂdĂme do jednotlivĂ˝ch tĹĂd, prvnĂ tĹĂda bude mĂt prioritu 1,
#Â tj. cokoliv co do nĂ pĹejde uĹž nezĂĄvisle na dalĹĄĂch pravidlech zpracuje, ostatnĂ
# nemajĂ prioritu udanou, tĂm se ĹadĂ na konec aĹž za vĹĄechna ostatnĂ pravidla.
$TC filter add dev $DEV parent 1:0 protocol ip prio 1 handle 1 fw flowid 1:1
$TC filter add dev $DEV parent 1:0 protocol ip handle 2 fw flowid 1:2
# 3. tĹĂda je urÄena pro datovĂŠho omezenĂ
if [ "$QOS_LIMIT_TYPE" == "htb" ]; then
$TC qdisc add dev $DEV parent 1:3 handle 13:0 htb r2q $R2Q default 111
# Zakladni htb tride dame plnou rychlost, dalsi budou mit rychlost sdilenou HTTP,mail, DC++,
$TC class add dev $DEV parent 13:0 classid 13:1 htb rate ${RATE}kbit
else
$TC qdisc add dev $DEV parent 1:3 handle 13:0 hfsc default 111
# Zakladni hfsc tride dame plnou rychlost, dalsi budou mit rychlost sdilenou HTTP,mail, DC++,
$TC class add dev $DEV parent 13:0 classid 13:1 hfsc ls m2 ${RATE}kbit ul m2 ${RATE}kbit
fi
# PokroÄilĂŠ nasazenĂ tĹĂd podle typu
if [ "$QOS_TYPE" == "layer7" ] || [ "$QOS_TYPE" == "layer7_esfq" ]; then
if [ "$QOS_LIMIT_TYPE" == "htb" ]; then
$TC class add dev $DEV parent 13:1 classid 13:111 htb rate $[5*($RATE - $RATE_MIN)/10]kbit ceil ${RATE}kbit
$TC class add dev $DEV parent 13:1 classid 13:112 htb rate $[3*($RATE - $RATE_MIN)/10]kbit ceil ${RATE}kbit
$TC class add dev $DEV parent 13:1 classid 13:113 htb rate $[2*($RATE - $RATE_MIN)/10]kbit ceil ${RATE}kbit
else
$TC class add dev $DEV parent 13:1 classid 13:111 hfsc ls m2 $[5*($RATE - $RATE_MIN)/10]kbit ul m2 ${RATE}kbit
$TC class add dev $DEV parent 13:1 classid 13:112 hfsc ls m2 $[3*($RATE - $RATE_MIN)/10]kbit ul m2 ${RATE}kbit
$TC class add dev $DEV parent 13:1 classid 13:113 hfsc ls m2 $[2*($RATE - $RATE_MIN)/10]kbit ul m2 ${RATE}kbit
fi
# V kazde tride jeste pouziji sfq
$TC qdisc add dev $DEV parent 13:111 handle 111:0 $SFQ
$TC qdisc add dev $DEV parent 13:112 handle 112:0 $SFQ
$TC qdisc add dev $DEV parent 13:113 handle 113:0 $SFQ
# DalĹĄĂ tĹĂdy zpracovĂĄvajĂcĂ pravidla z iptables
$TC filter add dev $DEV parent 13:0 protocol ip handle 3 fw flowid 13:111
$TC filter add dev $DEV parent 13:0 protocol ip handle 4 fw flowid 13:112
$TC filter add dev $DEV parent 13:0 protocol ip handle 5 fw flowid 13:113
else
# Nastavime maximalni ryhlost pro vse co jde do tridy 2 (3. skupina)
if [ "$QOS_LIMIT_TYPE" == "htb" ]; then
$TC class add dev $DEV parent 13:1 classid 13:111 htb rate $[($RATE - $RATE_MIN)]kbit ceil ${RATE}kbit
else
# Zakladni hfsc tride dame plnou rychlost
$TC class add dev $DEV parent 13:1 classid 13:111 hfsc ls m2 $[($RATE - $RATE_MIN)]kbit ul m2 ${RATE}kbit
fi
# V kazde tride jeste pouziji sfq
$TC qdisc add dev $DEV parent 13:111 handle 111:0 $SFQ
# I pokud nepouĹžĂvĂĄme layer7, mĹŻĹžeme vyuĹžĂt markovĂĄnĂ pomocĂ iptables
$TC filter add dev $DEV parent 13:0 protocol ip handle 3 fw flowid 13:111
fi
# speciĂĄlnĂ tĹĂdy
IFS=$'\t\n'
for CLASS in $CLASSES; do
IFS=$' \t\n'
CLASS=( $CLASS )
# garantovanĂĄ rychlost nemĹŻĹže bĂ˝t vÄtĹĄĂ neĹž maximĂĄlnĂ rychlost na rozhranĂ
[ "${CLASS[1]}" -ge "$RATE" ] && continue
# pokud nenĂ zadanĂĄ maximĂĄlnĂ rychlost, tak je maximum celkovĂ˝ rychlost rozhranĂ
[ "${CLASS[2]}" == "" ] && CLASS[2]=$RATE
# pokud je maximĂĄlnĂ rychlost menĹĄĂ neĹž minimĂĄlnĂ, tak je maximum rychlost rozhranĂ
[ "${CLASS[2]}" -lt "${CLASS[1]}" ] && CLASS[2]=$RATE
# pokud je maximĂĄlnĂ rychlost vÄtĹĄĂ, neĹž maximĂĄlnĂ rychlost rozhranĂ, tak je maximum rychlost rozhranĂ
[ "${CLASS[2]}" -gt "$RATE" ] && CLASS[2]=$RATE
if [ "$QOS_LIMIT_TYPE" == "htb" ]; then
$TC class add dev $DEV parent 13:1 classid 13:$((113 + ${CLASS[0]})) htb rate ${CLASS[1]}kbit ceil ${CLASS[2]}kbit
else
$TC class add dev $DEV parent 13:1 classid 13:$((113 + ${CLASS[0]})) hfsc ls m2 ${CLASS[1]}kbit ul m2 ${CLASS[2]}kbit
fi
# NasadĂme sfq na danĂŠ tĹĂdy
$TC qdisc add dev $DEV parent 13:$((113 + ${CLASS[0]})) handle $((113 + ${CLASS[0]})):0 $SFQ
# GarantovanĂŠ tĹĂdy nepotĹebujĂ speciĂĄlnĂ tĹĂdu, protoĹže se markujĂ jen pomocĂ tc rovnou do danĂŠ tĹĂdy
#$TC filter add dev $DEV parent 1:0 protocol ip handle $((5 + ${CLASS[0]})) fw flowid 13:$((113 + ${CLASS[0]}))
#$TC filter add dev $DEV parent 13:0 protocol ip handle $((5 + ${CLASS[0]})) fw flowid 13:$((113 + ${CLASS[0]}))
done
IFS=$' \t\n'
done
((I++))
done
# ProtoĹže markovĂĄnĂ na kaĹždĂŠm zaĹĂzenĂ zvlĂĄĹĄĹĽ by bylo velmi mnoho pravidel pro iptables,
# tak pouĹžijeme markovĂĄnĂ na vĹĄech zaĹĂzenĂch, i tak zavedenĂ pravidel trvĂĄ cca 6 vteĹin.
if [ "$QOS_TYPE" == "layer7" ] || [ "$QOS_TYPE" == "layer7_esfq" ]; then
# MarkovĂĄnĂ musĂme provĂĄdÄt jiĹž v preroutingu, jinak nejsme schopni oznaÄit vĹĄechny pakety.
# ICMP - vzdy
$IPTABLES -t mangle -I PREROUTING -p icmp -j MARK --set-mark 1
# OSPF - vzdy
$IPTABLES -t mangle -I PREROUTING -p ospf -j MARK --set-mark 1
# UDP - vzdy
$IPTABLES -t mangle -I PREROUTING -p UDP -j MARK --set-mark 2
# HTML - jiny nekorektni zpusob markovani http, ale mnohem mene narocny
#$IPTABLES -t mangle -I PREROUTING -p TCP --dport 80 -j MARK --set-mark 3
# OznaÄenĂ paketĹŻ pomocĂ layer7 filtru, detekce nÄkterĂ˝ch protokolĹŻ zvyĹĄuje odezvy
# 8.3.2009 - vyĹazeny protokoly, kterĂŠ po cca 30 dnech mÄly nulovĂŠ ÄĂtaÄe
qos_mark_layer7 1 "bgp dhcp dns irc jabber snmp whois"
qos_mark_layer7 2 "quake-halflife worldofwarcraft"
# Do tĹĂdy 3 jdou vĹĄechna nezaĹazenĂĄ data, takĹže jĂ nenĂ tĹeba oznaÄovat
qos_mark_layer7 3 ""
qos_mark_layer7 4 "ftp cvs biff h323 imap live365 pop3 rtsp shoutcast smtp ssl tftp"
qos_mark_layer7 5 "bittorrent directconnect edonkey http-itunes soulseek"
fi
echo "done."
# OznaÄĂme jednotlivĂŠ poÄĂtaÄe v tĹĂdĂĄch
qos_guaranted_classes
}
qos_stop() {
echo -n "Stopping QoS..."
local I=""
local DEV=""
# SmaĹžeme vĹĄechna pravidla v iptables
for I in `$IPTABLES -t mangle -L POSTROUTING -n -v --line-numbers | grep "set 0x" | awk '{print $1}' | sort -r -n`; do
$IPTABLES -t mangle -D POSTROUTING $I
done
for I in `$IPTABLES -t mangle -L PREROUTING -n -v --line-numbers | grep "set 0x" | awk '{print $1}' | sort -r -n`; do
$IPTABLES -t mangle -D PREROUTING $I
done
for I in `$IPTABLES -t mangle -L POSTROUTING -n -v --line-numbers | grep "todev" | awk '{print $1}' | sort -r -n`; do
$IPTABLES -t mangle -D POSTROUTING $I
done
for I in `$IPTABLES -t mangle -L PREROUTING -n -v --line-numbers | grep "todev" | awk '{print $1}' | sort -r -n`; do
$IPTABLES -t mangle -D PREROUTING $I
done
# SmaĹžeme vĹĄechny root qdisky
while true; do
DEV="`$TC qdisc | grep -v 0: | awk '{print \$5}' | sort -u | sed -n 1p`"
[ "$DEV" == "" ] && break
$TC qdisc del dev "$DEV" root &>/dev/null
$TC qdisc del dev "$DEV" ingress &>/dev/null
done
# Deaktivujeme vĹĄechna ifb zaĹĂzenĂ
while true; do
DEV="`$IP link show | grep ifb | grep UP | awk '{print \$2}' | sort -u | sed -n 1p`"
[ "$DEV" == "" ] && break
DEV="${DEV//:/}"
$IP link set "$DEV" down
done
# OdstranĂme ifb modul z pamÄti
#rmmod -f ifb &>/dev/null
# Deaktivujeme vĹĄechna imq zaĹĂzenĂ
while true; do
DEV="`$IP link show | grep imq | grep UP | awk '{print \$2}' | sort -u | sed -n 1p`"
[ "$DEV" == "" ] && break
DEV="${DEV//:/}"
$IP link set "$DEV" down
done
# OdstranĂme imq modul z pamÄti
#rmmod -f imq &>/dev/null
echo "done."
}
qos_stats() {
$TC -s qdisc
}
# speciĂĄlnĂ garantovanĂŠ tĹĂdy
qos_guaranted_classes() {
[ "${#CLASS_1[*]}" -lt "1" ] && return 0
echo "Starting QoS guaranted classes..."
# lokĂĄlnĂ promÄnnĂŠ
local I=""
local J=""
local CLASS_DEV=""
local CLASS_MIN=""
local CLASS_MAX=""
local CLASS_USERS=""
local CLASSES=""
local RATE_MIN="0"
local USER=""
J="1"
while true; do
CLASS_DEV=CLASS_${J}_DEV
CLASS_DEV=${!CLASS_DEV}
[ "$CLASS_DEV" == "" ] && break
CLASS_MIN=CLASS_${J}_MIN
CLASS_MIN=${!CLASS_MIN}
CLASS_MAX=CLASS_${J}_MAX
CLASS_MAX=${!CLASS_MAX}
# klasickĂŠ pĹiĹazenĂ nelze pouĹžĂt na pole
CLASS_USERS="CLASS_${J}[@]"
CLASS_USERS=( "${!CLASS_USERS}" )
# PĹeskoÄĂme prĂĄzdnĂŠ tĹĂdy
if [ "${#CLASS_USERS[*]}" -lt "1" ]; then
((J++))
continue
fi
# Pokud nenĂ zadĂĄna maximĂĄlnĂ rychlost tĹĂdy
[ "$CLASS_MAX" == "" ] && CLASS_MAX="interface maximum"
echo "QoS class $J (dev: $CLASS_DEV, min: $CLASS_MIN kbit/s, max: $CLASS_MAX kbit/s):"
IFS=$'\t\n'
for USER in ${CLASS_USERS[@]}; do
IFS=$' \t\n'
USER=( $USER )
I="2"
while [ "${USER[$I]}" != "" ]; do
if [ "${USER[$I]:2:1}" == ":" ]; then
echo -e " user ${USER[1]}\twith mac ${USER[$I]}\ton ${USER[0]}\tlimited!"
else
echo -e " user ${USER[1]}\twith ip ${USER[$I]}\t\ton ${USER[0]}\tlimited!"
fi
qos_guaranted_class_add_user "$J" "${USER[$I]}" "${USER[0]}"
((I++))
done
done
IFS=$' \t\n'
((J++))
done
echo "done."
}
# formĂĄt: "tĹĂda" "ip, nebo mac" "rozhranĂ - nepovinnĂŠ"
qos_guaranted_class_add_user() {
( [ "$1" == "" ] || [ "$2" == "" ] ) && return 0
# rozhranĂ na kterĂ˝ch je aktivnĂ qos, vĹždy pouĹžĂvĂĄme alespoĹ sfq
local TC_DEVS=`$TC qdisc | grep sfq | awk '{print $5}' | sort -u`
# dalĹĄĂ lokĂĄlnĂ promÄnnĂŠ
local I=""
local DEV=""
local TC_DEV=""
local TC_DEVS_POM=""
local IMQ_DEV=""
local IFB_DEV=""
local DATA=""
local LINE=""
local IP="$2"
local MAC="`echo $2 | tr [:upper:] [:lower:]`"
local TC_NUM=""
local CLASS=""
# pokud ip, nebo mac uĹž je zadanĂĄ, tak jĂ smaĹžeme na vĹĄech rozhranĂch
qos_guaranted_class_del_user "$2"
# zjistĂme jestli jde o MAC, nebo IP adresu
IFS=$'./\t\n'
IP=( $IP )
IFS=$':\t\n'
MAC=( $MAC )
IFS=$' \t\n'
# Je-li zadanĂŠ rozhranĂ, tak musĂme najĂt pĹidruĹženĂŠ IMQ, nebo IFB
if [ "$3" != "" ] && [ "$3" != "all" ]; then
# IMQ z PREROUTINGu, musĂme pouĹžĂt awk, protoĹže iptables posĂlĂĄ * a ta se nedĂĄ pĹevĂŠst do pole!
DATA=`$IPTABLES -t mangle -L PREROUTING -n -v | grep todev | awk '{print $6" "$12}'`
IFS=$'\t\n'
for LINE in $DATA; do
IFS=$' \t\n'
LINE=( ${LINE} )
if [ "${LINE[0]}" == "$3" ] && [ "${LINE[1]}" != "" ]; then
IMQ_DEV="imq${LINE[1]}"
break
fi
done
IFS=$' \t\n'
# ifb zĂskĂĄme z tc
IFB_DEV="`$TC filter list dev $3 parent ffff: | grep ifb | awk '{print \$9}'`"
IFB_DEV="${IFB_DEV//)/}"
for I in $TC_DEVS; do
[ "$3" == "$I" ] && TC_DEVS_POM=$TC_DEVS_POM" $I"
[ "$IFB_DEV" != "" ] && [ "$IFB_DEV" == "$I" ] && TC_DEVS_POM=$TC_DEVS_POM" $IFB_DEV"
[ "$IMQ_DEV" != "" ] && [ "$IMQ_DEV" == "$I" ] && TC_DEVS_POM=$TC_DEVS_POM" $IMQ_DEV"
done
[ "$TC_DEVS_POM" == "" ] && return 0
# MusĂme odstranit prvnĂ prĂĄzdnĂ˝ znak
TC_DEVS="${TC_DEVS_POM:1}"
fi
# samotnĂŠ zaĹazenĂ do tĹĂdy
for DEV in $TC_DEVS; do
# smaĹžeme nejprve tĹĂdy 1:0 a pak 13:0
for CLASS in "1:0" "13:0"; do
# musĂme najĂt dalĹĄĂ ÄĂslo kam budeme pĹidĂĄvat zĂĄznam
TC_NUM=$((`$TC filter list dev $DEV parent $CLASS | awk '{print $5}' | grep -v "4915" | sort -ug | tail -n 1` + 1))
if [ "${IP[3]}" != "" ]; then
$TC filter add dev $DEV parent $CLASS protocol ip prio $TC_NUM u32 match ip src $2 flowid 13:$((113 + $1))
$TC filter add dev $DEV parent $CLASS protocol ip prio $TC_NUM u32 match ip dst $2 flowid 13:$((113 + $1))
elif [ "${MAC[5]}" != "" ]; then
$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))
$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))
else
# nejednĂĄ se ani o ip ani o mac adresu
return 0
fi
done
done
return 0
}
# Pro mazĂĄnĂ nenĂ tĹeba znĂĄt tĹĂdu ze kterĂŠ maĹžeme, protoĹže by jedna ip, nebo mac
# nemÄla bĂ˝t ve vĂce tĹĂdĂĄch.
#
# formĂĄt: "ip, nebo mac"
qos_guaranted_class_del_user() {
[ "$1" == "" ] && return 0
# MaĹžeme na vĹĄech rozhranĂch, kde je QoS
local TC_DEVS=`$TC qdisc | grep sfq | awk '{print $5}' | sort -u`
# lokĂĄlnĂ promÄnnĂŠ
local I=""
local DEV=""
local DATA=""
local LINE=""
local LINE_1=""
local LINE_2=""
local IP="$1"
local MAC="`echo $1 | tr [:upper:] [:lower:]`"
local IP_HEX=""
local MAC_1=""
local MAC_2=""
local MAC_3=""
local CLASS=""
local PRIO=""
local PRIO_PREV=""
# zjistĂme jestli jde o MAC, nebo IP adresu, pro mac musĂme pĹevĂŠst velkĂĄ pĂsmena na malĂĄ
IFS=$'./\t\n'
IP=( $IP )
IFS=$':\t\n'
MAC=( $MAC )
IFS=$' \t\n'
if [ "${IP[3]}" != "" ]; then
# pĹevedeme ip do formĂĄtu, kterĂ˝ pouĹžĂvĂĄ tc
IP_HEX=`printf '%02x%02x%02x%02x\n' ${IP[0]} ${IP[1]} ${IP[2]} ${IP[3]}`
elif [ "${MAC[5]}" != "" ]; then
MAC_1="00000800"
MAC_2="${MAC[2]}${MAC[3]}${MAC[4]}${MAC[5]}"
MAC_3="0000${MAC[0]}${MAC[1]}"
else
# NejednĂĄ se ani o ip ani o mac adresu
return 0
fi
# zkontrolujeme vĹĄechna rozhranĂ
for DEV in $TC_DEVS; do
# smaĹžeme nejprve tĹĂdy 1:0 a pak 13:0
for CLASS in "1:0" "13:0"; do
# naÄteme data z tc, kde jsou uloĹženy vĹĄechny zadanĂŠ mac i ip adresy
IFS=$'\t\n'
DATA=( `$TC filter list dev $DEV parent $CLASS` )
IFS=$' \t\n'
I="0"
PRIO=""
PRIO_PREV=""
IFS=$'\t\n'
for LINE in ${DATA[@]}; do
# pro matchovĂĄnĂ nĂĄs nezajĂmĂĄ maska, proto masku oddÄlĂme, platĂ jen v pĹĂpadÄ ip
IFS=$' /\t\n'
LINE=( $LINE )
IFS=$' \t\n'
# inkrementovat musĂme jeĹĄtÄ pĹed continue
((I++))
if [ "${LINE[3]}" == "pref" ]; then
PRIO=${LINE[4]}
continue
fi
# dĂĄle nĂĄs zajĂmĂĄ jen match
[ "${LINE[0]}" != "match" ] && continue
# pokud neznĂĄme prioritu, tak pokraÄujeme
[ "$PRIO" == "" ] && continue
# pokud jsme jiĹž jednou tuto prioritu mazali, tak pokraÄujeme
[ "$PRIO" == "$PRIO_PREV" ] && continue
# rozdÄlenĂ podle ip, nebo mac
if [ "${IP[3]}" != "" ]; then
# pokud ip neodpovĂdĂĄ, tak pokraÄujeme
[ "${LINE[1]}" != "$IP_HEX" ] && continue
elif [ "${MAC[5]}" != "" ]; then
# jednotnĂ˝ match pro vĹĄechny mac adresy
[ "${LINE[1]}/${LINE[2]}" != "$MAC_1/0000ffff" ] && continue
# nĂĄsledujĂcĂ ĹĂĄdek musĂ obsahovat druhou ÄĂĄst mac adresy, uĹž nepouĹžĂvĂĄme jako delimiter /
LINE_1=( ${DATA[$I]} )
[ "${LINE_1[1]}" != "$MAC_2/ffffffff" ] && continue
# dalĹĄĂ ĹĂĄdek musĂ obsahovat poslednĂ ÄĂĄst mac adresy
LINE_2=( ${DATA[$(($I + 1))]} )
[ "${LINE_2[1]}" != "$MAC_3/0000ffff" ] && continue
fi
# DanĂĄ ip uĹž je matchovanĂĄ, proto pravidla smaĹžeme
$TC filter del dev $DEV parent $CLASS protocol ip prio $PRIO 2>/dev/null
PRIO_PREV="$PRIO"
done
IFS=$' \t\n'
done
done
return 0
}
qos_mark_layer7() {
( [ "$1" == "" ] || [ "$2" == "" ] ) && return 0
#Â LokĂĄlnĂ promÄnnĂŠ
local I=""
local O_DEV=""
local I_DEV=""
[ "$3" != "" ] && O_DEV="-o $3"
[ "$4" != "" ] && I_DEV="-i $4"
for I in $2; do
$IPTABLES -t mangle -I PREROUTING $O_DEV $I_DEV -m layer7 --l7proto $I -j MARK --set-mark $1
done
return 0
}