#!/usr/bin/perl ############################################################################### # # # IPFire.org - A linux based firewall # # Copyright (C) 2010 IPFire Team # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program. If not, see . # # # ############################################################################### use strict; # enable only the following on debugging purpose # use warnings; require '/var/ipfire/general-functions.pl'; require "${General::swroot}/lang.pl"; require "${General::swroot}/header.pl"; my %qossettings = (); my %checked = (); my %netsettings = (); my $message = ""; my $errormessage = ""; my $c = ""; my $direntry = ""; my $classentry = ""; my $subclassentry = ""; my $l7ruleentry = ""; my $portruleentry = ""; my $tosruleentry = ""; my @tmp = (); my @classes = (); my @subclasses = (); my @l7rules = (); my @portrules = (); my @tosrules = (); my @tmpline = (); my @classline = (); my @subclassline = (); my @tosruleline = (); my @l7ruleline = (); my @portruleline = (); my @proto = (); my %selected= () ; my $classfile = "/var/ipfire/qos/classes"; my $subclassfile = "/var/ipfire/qos/subclasses"; my $level7file = "/var/ipfire/qos/level7config"; my $portfile = "/var/ipfire/qos/portconfig"; my $tosfile = "/var/ipfire/qos/tosconfig"; &General::readhash("${General::swroot}/ethernet/settings", \%netsettings); $qossettings{'ENABLED'} = 'off'; $qossettings{'EDIT'} = 'no'; $qossettings{'OUT_SPD'} = ''; $qossettings{'INC_SPD'} = ''; $qossettings{'DEF_OUT_SPD'} = ''; $qossettings{'DEF_INC_SPD'} = ''; $qossettings{'DEFCLASS_INC'} = ''; $qossettings{'DEFCLASS_OUT'} = ''; $qossettings{'ACK'} = ''; $qossettings{'MTU'} = '1492'; $qossettings{'RED_DEV'} = `cat /var/ipfire/red/iface`; $qossettings{'IMQ_DEV'} = 'imq0'; $qossettings{'TOS'} = ''; $qossettings{'VALID'} = 'yes'; $qossettings{'IMQ_MODE'} = 'PREROUTING'; &General::readhash("${General::swroot}/qos/settings", \%qossettings); open( FILE, "< $classfile" ) or die "Unable to read $classfile"; @classes = ; close FILE; open( FILE, "< $subclassfile" ) or die "Unable to read $subclassfile"; @subclasses = ; close FILE; open( FILE, "< $level7file" ) or die "Unable to read $level7file"; @l7rules = ; close FILE; open( FILE, "< $portfile" ) or die "Unable to read $portfile"; @portrules = ; close FILE; open( FILE, "< $tosfile" ) or die "Unable to read $tosfile"; @tosrules = ; close FILE; ############################################################################################################################ ############################################################################################################################ print < /dev/null iptables -t mangle -n -L QOS-INC -v -x 2> /dev/null iptables -t mangle -n -L QOS-TOS -v -x 2> /dev/null exit 0 ;; esac \$0 \$1 qdisc \$0 \$1 class \$0 \$1 filter \$0 \$1 iptables exit 0 ;; start) ### ### $qossettings{'RED_DEV'} ### ### INIT KERNEL modprobe sch_htb ### SET QUEUE LENGTH & MTU - has just to be tested!!! IMPORTANT ip link set dev $qossettings{'RED_DEV'} qlen $qossettings{'QLENGTH'} #ip link set dev $qossettings{'RED_DEV'} mtu $qossettings{'MTU'} ### ADD HTB QDISC FOR $qossettings{'RED_DEV'} tc qdisc add dev $qossettings{'RED_DEV'} root handle 1: htb default $qossettings{'DEFCLASS_OUT'} ### MAIN RATE LIMIT tc class add dev $qossettings{'RED_DEV'} parent 1: classid 1:1 htb rate $qossettings{'OUT_SPD'}kbit ### CLASSES FOR $qossettings{'RED_DEV'} END ; foreach $classentry (sort @classes) { @classline = split( /\;/, $classentry ); if ($qossettings{'RED_DEV'} eq $classline[0]) { $qossettings{'DEVICE'} = $classline[0]; $qossettings{'CLASS'} = $classline[1]; $qossettings{'PRIO'} = $classline[2]; $qossettings{'RATE'} = $classline[3]; $qossettings{'CEIL'} = $classline[4]; $qossettings{'BURST'} = $classline[5]; $qossettings{'CBURST'} = $classline[6]; print "\ttc class add dev $qossettings{'DEVICE'} parent 1:1 classid 1:$qossettings{'CLASS'} htb rate $qossettings{'RATE'}kbit ceil $qossettings{'CEIL'}kbit prio $qossettings{'PRIO'} "; if (($qossettings{'BURST'} ne '') && ($qossettings{'BURST'} ne 0)) { print "burst $qossettings{'BURST'}k "; } if (($qossettings{'CBURST'} ne '') && ($qossettings{'CBURST'} ne 0)) { print "cburst $qossettings{'CBURST'}k"; } print "\n"; } } foreach $subclassentry (sort @subclasses) { @subclassline = split( /\;/, $subclassentry ); if ($qossettings{'RED_DEV'} eq $subclassline[0]) { $qossettings{'DEVICE'} = $subclassline[0]; $qossettings{'CLASS'} = $subclassline[1]; $qossettings{'SCLASS'} = $subclassline[2]; $qossettings{'SPRIO'} = $subclassline[3]; $qossettings{'SRATE'} = $subclassline[4]; $qossettings{'SCEIL'} = $subclassline[5]; $qossettings{'SBURST'} = $subclassline[6]; $qossettings{'SCBURST'} = $subclassline[7]; print "\ttc class add dev $qossettings{'DEVICE'} parent 1:$qossettings{'CLASS'} classid 1:$qossettings{'SCLASS'} htb rate $qossettings{'SRATE'}kbit ceil $qossettings{'SCEIL'}kbit prio $qossettings{'SPRIO'} "; if ($qossettings{'SBURST'} > 0) { print "burst $qossettings{'SBURST'}k "; } if (($qossettings{'SCBURST'} ne '') && ($qossettings{'SCBURST'} ne 0)) { print "cburst $qossettings{'CBURST'}k"; } print "\n"; } } print "\n\t### ATTACH QDISC TO LEAF CLASSES\n"; foreach $classentry (sort @classes) { @classline = split( /\;/, $classentry ); if ($qossettings{'RED_DEV'} eq $classline[0]) { $qossettings{'DEVICE'} = $classline[0]; $qossettings{'CLASS'} = $classline[1]; print "\ttc qdisc add dev $qossettings{'DEVICE'} parent 1:$qossettings{'CLASS'} handle $qossettings{'CLASS'}: sfq perturb $qossettings{'SFQ_PERTUB'}\n"; } } foreach $subclassentry (sort @subclasses) { @subclassline = split( /\;/, $subclassentry ); if ($qossettings{'RED_DEV'} eq $subclassline[0]) { $qossettings{'DEVICE'} = $subclassline[0]; $qossettings{'SCLASS'} = $subclassline[2]; print "\ttc qdisc add dev $qossettings{'DEVICE'} parent 1:$qossettings{'SCLASS'} handle $qossettings{'SCLASS'}: sfq perturb $qossettings{'SFQ_PERTUB'}\n"; } } print "\n\t### FILTER TRAFFIC INTO CLASSES\n"; foreach $classentry (sort @classes) { @classline = split( /\;/, $classentry ); if ($qossettings{'RED_DEV'} eq $classline[0]) { $qossettings{'DEVICE'} = $classline[0]; $qossettings{'CLASS'} = $classline[1]; print "\ttc filter add dev $qossettings{'DEVICE'} parent 1:0 prio 0 protocol ip handle $qossettings{'CLASS'} fw flowid 1:$qossettings{'CLASS'}\n"; } } foreach $subclassentry (sort @subclasses) { @subclassline = split( /\;/, $subclassentry ); if ($qossettings{'RED_DEV'} eq $subclassline[0]) { $qossettings{'DEVICE'} = $subclassline[0]; $qossettings{'CLASS'} = $subclassline[1]; $qossettings{'SCLASS'} = $subclassline[2]; print "\ttc filter add dev $qossettings{'DEVICE'} parent 1:0 prio 0 protocol ip handle $qossettings{'SCLASS'} fw flowid 1:$qossettings{'SCLASS'}\n"; } } print < 0) { print "burst $qossettings{'SBURST'}k "; } if (($qossettings{'SCBURST'} ne '') && ($qossettings{'SCBURST'} ne 0)) { print "cburst $qossettings{'CBURST'}k"; } print "\n"; } } print "\n\t### ATTACH QDISC TO LEAF CLASSES\n"; foreach $classentry (sort @classes) { @classline = split( /\;/, $classentry ); if ($qossettings{'IMQ_DEV'} eq $classline[0]) { $qossettings{'DEVICE'} = $classline[0]; $qossettings{'CLASS'} = $classline[1]; print "\ttc qdisc add dev $qossettings{'DEVICE'} parent 2:$qossettings{'CLASS'} handle $qossettings{'CLASS'}: sfq perturb $qossettings{'SFQ_PERTUB'}\n"; } } foreach $subclassentry (sort @subclasses) { @subclassline = split( /\;/, $subclassentry ); if ($qossettings{'IMQ_DEV'} eq $subclassline[0]) { $qossettings{'DEVICE'} = $subclassline[0]; $qossettings{'SCLASS'} = $subclassline[2]; print "\ttc qdisc add dev $qossettings{'DEVICE'} parent 2:$qossettings{'SCLASS'} handle $qossettings{'SCLASS'}: sfq perturb $qossettings{'SFQ_PERTUB'}\n"; } } print "\n\t### FILTER TRAFFIC INTO CLASSES\n"; foreach $classentry (sort @classes) { @classline = split( /\;/, $classentry ); if ($qossettings{'IMQ_DEV'} eq $classline[0]) { $qossettings{'DEVICE'} = $classline[0]; $qossettings{'CLASS'} = $classline[1]; print "\ttc filter add dev $qossettings{'DEVICE'} parent 2:0 prio 0 protocol ip handle $qossettings{'CLASS'} fw flowid 2:$qossettings{'CLASS'}\n"; } } foreach $subclassentry (sort @subclasses) { @subclassline = split( /\;/, $subclassentry ); if ($qossettings{'IMQ_DEV'} eq $subclassline[0]) { $qossettings{'DEVICE'} = $subclassline[0]; $qossettings{'CLASS'} = $subclassline[1]; $qossettings{'SCLASS'} = $subclassline[2]; print "\ttc filter add dev $qossettings{'DEVICE'} parent 2:0 prio 0 protocol ip handle $qossettings{'SCLASS'} fw flowid 2:$qossettings{'SCLASS'}\n"; } } if ( $qossettings{'IMQ_MODE'} eq 'POSTROUTING' ) { print </dev/null 2>&1) & ( sleep 10 && /usr/local/bin/qosd $qossettings{'IMQ_DEV'} >/dev/null 2>&1) & for i in \$(ls \$RRDLOG/class_*.rrd); do rrdtool update \$i \$(date +%s): done echo "Quality of Service was successfully started!" exit 0 ;; clear|stop) ### RESET EVERYTHING TO A KNOWN STATE killall qosd >/dev/null 2>&1 (sleep 3 && killall -9 qosd &>/dev/null) & # DELETE QDISCS tc qdisc del dev $qossettings{'RED_DEV'} root >/dev/null 2>&1 tc qdisc del dev $qossettings{'IMQ_DEV'} root >/dev/null 2>&1 # STOP IMQ-DEVICE ip link set $qossettings{'IMQ_DEV'} down >/dev/null 2>&1 iptables -t mangle --delete POSTROUTING -i $qossettings{'RED_DEV'} -p ah -j RETURN >/dev/null 2>&1 iptables -t mangle --delete POSTROUTING -i $qossettings{'RED_DEV'} -p esp -j RETURN >/dev/null 2>&1 iptables -t mangle --delete POSTROUTING -i $qossettings{'RED_DEV'} -p ip -j RETURN >/dev/null 2>&1 iptables -t mangle --delete PREROUTING -i $qossettings{'RED_DEV'} -p ah -j RETURN >/dev/null 2>&1 iptables -t mangle --delete PREROUTING -i $qossettings{'RED_DEV'} -p esp -j RETURN >/dev/null 2>&1 iptables -t mangle --delete PREROUTING -i $qossettings{'RED_DEV'} -p ip -j RETURN >/dev/null 2>&1 iptables -t mangle --delete POSTROUTING -m mark ! --mark 0 ! -o $qossettings{'RED_DEV'} -j IMQ --todev 0 >/dev/null 2>&1 iptables -t mangle --delete PREROUTING -i $qossettings{'RED_DEV'} -j IMQ --todev 0 >/dev/null 2>&1 # rmmod imq # this crash on 2.6.25.xx # REMOVE & FLUSH CHAINS iptables -t mangle --delete POSTROUTING -o $qossettings{'RED_DEV'} -j QOS-OUT >/dev/null 2>&1 iptables -t mangle --delete POSTROUTING -o $qossettings{'RED_DEV'} -j QOS-TOS >/dev/null 2>&1 iptables -t mangle --flush QOS-OUT >/dev/null 2>&1 iptables -t mangle --delete-chain QOS-OUT >/dev/null 2>&1 iptables -t mangle --delete FORWARD -i $qossettings{'RED_DEV'} -j QOS-INC >/dev/null 2>&1 iptables -t mangle --delete FORWARD -i $qossettings{'RED_DEV'} -j QOS-TOS >/dev/null 2>&1 iptables -t mangle --delete PREROUTING -i $qossettings{'RED_DEV'} -j QOS-INC >/dev/null 2>&1 iptables -t mangle --delete PREROUTING -i $qossettings{'RED_DEV'} -j QOS-TOS >/dev/null 2>&1 iptables -t mangle --flush QOS-INC >/dev/null 2>&1 iptables -t mangle --delete-chain QOS-INC >/dev/null 2>&1 iptables -t mangle --flush QOS-TOS >/dev/null 2>&1 iptables -t mangle --delete-chain QOS-TOS >/dev/null 2>&1 # remove l7-filter iptables -t mangle --delete POSTROUTING -m layer7 --l7proto unset rmmod sch_htb >/dev/null 2>&1 for i in \$(ls \$RRDLOG/class_*.rrd); do rrdtool update \$i \$(date +%s): done echo "Quality of Service was successfully cleared!" ;; gen|generate) echo -n "Generateing the QoS-Scripts..." /usr/bin/perl /var/ipfire/qos/bin/makeqosscripts.pl > /var/ipfire/qos/bin/qos.sh echo ".Done!" exit 0 ;; restart) ### FIRST CLEAR EVERYTHING \$0 clear ### THEN START \$0 start ;; esac ### EOF END ; ############################################################################################################################ ############################################################################################################################