]>
git.ipfire.org Git - people/mfischer/ipfire-2.x.git/blob - config/qos/makeqosscripts.pl
b1bb637b3574ed0816b4f4cc3775f00261e68090
2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2007-2013 IPFire Team <info@ipfire.org> #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
23 # enable only the following on debugging purpose
26 require '/var/ipfire/general-functions.pl' ;
27 require "${General::swroot}/lang.pl" ;
28 require "${General::swroot}/header.pl" ;
34 my $errormessage = "" ;
39 my $portruleentry = "" ;
40 my $tosruleentry = "" ;
50 my @portruleline = ();
53 my $classfile = "/var/ipfire/qos/classes" ;
54 my $level7file = "/var/ipfire/qos/level7config" ;
55 my $portfile = "/var/ipfire/qos/portconfig" ;
56 my $tosfile = "/var/ipfire/qos/tosconfig" ;
57 my $fqcodel_options = "limit 10240 quantum 1514" ;
59 # Define iptables MARKs
60 my $QOS_INC_MASK = 0x0000ff00 ;
61 my $QOS_INC_SHIFT = 8 ;
62 my $QOS_OUT_MASK = 0x000000ff ;
63 my $QOS_OUT_SHIFT = 0 ;
65 & General
:: readhash
( "${General::swroot}/ethernet/settings" , \
%netsettings );
67 $qossettings { 'ENABLED' } = 'off' ;
68 $qossettings { 'EDIT' } = 'no' ;
69 $qossettings { 'OUT_SPD' } = '' ;
70 $qossettings { 'INC_SPD' } = '' ;
71 $qossettings { 'DEF_OUT_SPD' } = '' ;
72 $qossettings { 'DEF_INC_SPD' } = '' ;
73 $qossettings { 'DEFCLASS_INC' } = '' ;
74 $qossettings { 'DEFCLASS_OUT' } = '' ;
75 $qossettings { 'RED_DEV' } = `cat /var/ipfire/red/iface` ;
76 $qossettings { 'IMQ_DEV' } = 'imq0' ;
77 $qossettings { 'TOS' } = '' ;
78 $qossettings { 'VALID' } = 'yes' ;
80 & General
:: readhash
( "${General::swroot}/qos/settings" , \
%qossettings );
82 my $DEF_OUT_MARK = ( $qossettings { 'DEFCLASS_OUT' } << $QOS_OUT_SHIFT ) . "/ $QOS_OUT_MASK " ;
83 my $DEF_INC_MARK = ( $qossettings { 'DEFCLASS_INC' } << $QOS_INC_SHIFT ) . "/ $QOS_INC_MASK " ;
85 open ( FILE
, "< $classfile " ) or die "Unable to read $classfile " ;
88 open ( FILE
, "< $level7file " ) or die "Unable to read $level7file " ;
91 open ( FILE
, "< $portfile " ) or die "Unable to read $portfile " ;
94 open ( FILE
, "< $tosfile " ) or die "Unable to read $tosfile " ;
98 ############################################################################################################################
99 ############################################################################################################################
103 #################################################
104 # This is an autocreated QoS-Script for #
106 # Copyright by the IPFire Team (GPLv2) #
108 #################################################
111 # RED INTERFACE: $qossettings {'RED_DEV'}
112 # IMQ DEVICE: $qossettings {'IMQ_DEV'}
114 eval \$(/usr/local/bin/readhash /var/ipfire/main/settings)
115 if [ "\ $RRDLOG " == "" ]; then
125 tc -s qdisc show dev $qossettings {'RED_DEV'}
126 tc -s qdisc show dev $qossettings {'IMQ_DEV'}
131 tc -s class show dev $qossettings {'RED_DEV'}
132 tc -s class show dev $qossettings {'IMQ_DEV'}
137 tc -s filter show dev $qossettings {'RED_DEV'}
138 tc -s filter show dev $qossettings {'IMQ_DEV'}
143 iptables -t mangle -n -L QOS-OUT -v -x 2> /dev/null
144 iptables -t mangle -n -L QOS-INC -v -x 2> /dev/null
156 ### $qossettings {'RED_DEV'}
162 ### ADD HTB QDISC FOR $qossettings {'RED_DEV'}
163 tc qdisc del dev $qossettings {'RED_DEV'} root >/dev/null 2>&1
164 tc qdisc add dev $qossettings {'RED_DEV'} root handle 1: htb default $qossettings {'DEFCLASS_OUT'}
167 tc class add dev $qossettings {'RED_DEV'} parent 1: classid 1:1 htb rate $qossettings {'OUT_SPD'}kbit
169 ### CLASSES FOR $qossettings {'RED_DEV'}
172 foreach $classentry ( sort @classes )
174 @classline = split ( /\;/ , $classentry );
175 if ( $qossettings { 'RED_DEV' } eq $classline [ 0 ]) {
176 $qossettings { 'DEVICE' } = $classline [ 0 ];
177 $qossettings { 'CLASS' } = $classline [ 1 ];
178 $qossettings { 'PRIO' } = $classline [ 2 ];
179 $qossettings { 'RATE' } = $classline [ 3 ];
180 $qossettings { 'CEIL' } = $classline [ 4 ];
181 $qossettings { 'BURST' } = $classline [ 5 ];
182 $qossettings { 'CBURST' } = $classline [ 6 ];
183 print " \t tc class add dev $qossettings {'DEVICE'} parent 1:1 classid 1: $qossettings {'CLASS'} htb rate $qossettings {'RATE'}kbit ceil $qossettings {'CEIL'}kbit prio $qossettings {'PRIO'} " ;
184 if (( $qossettings { 'BURST' } ne '' ) && ( $qossettings { 'BURST' } ne 0 )) {
185 print "burst $qossettings {'BURST'}k " ;
187 if (( $qossettings { 'CBURST' } ne '' ) && ( $qossettings { 'CBURST' } ne 0 )) {
188 print "cburst $qossettings {'CBURST'}k" ;
194 print " \n\t ### ATTACH QDISC TO LEAF CLASSES \n " ;
195 foreach $classentry ( sort @classes )
197 @classline = split ( /\;/ , $classentry );
198 if ( $qossettings { 'RED_DEV' } eq $classline [ 0 ]) {
199 $qossettings { 'DEVICE' } = $classline [ 0 ];
200 $qossettings { 'CLASS' } = $classline [ 1 ];
201 print " \t tc qdisc add dev $qossettings {'DEVICE'} parent 1: $qossettings {'CLASS'} handle $qossettings {'CLASS'}: fq_codel $fqcodel_options \n " ;
204 print " \n\t ### FILTER TRAFFIC INTO CLASSES \n " ;
205 foreach $classentry ( sort @classes )
207 @classline = split ( /\;/ , $classentry );
208 if ( $qossettings { 'RED_DEV' } eq $classline [ 0 ]) {
209 $qossettings { 'DEVICE' } = $classline [ 0 ];
210 $qossettings { 'CLASS' } = $classline [ 1 ];
211 print " \t tc filter add dev $qossettings {'DEVICE'} parent 1:0 prio 0 protocol ip" ;
212 printf ( " u32 match mark 0x %x 0x %x flowid 1: %d \n " , ( $qossettings { 'CLASS' } << $QOS_OUT_SHIFT ), $QOS_OUT_MASK , $qossettings { 'CLASS' });
218 ### ADD QOS-OUT CHAIN TO THE MANGLE TABLE IN IPTABLES
219 iptables -t mangle -N QOS-OUT
220 iptables -t mangle -A POSTROUTING -o $qossettings {'RED_DEV'} -j QOS-OUT
222 # If the packet is already marked, then skip the processing
223 iptables -t mangle -A QOS-OUT -m mark ! --mark 0/ $QOS_OUT_MASK -j RETURN
225 ### Don't change mark on traffic for the ipsec tunnel
226 iptables -t mangle -A QOS-OUT -m mark --mark 50 -j RETURN
231 foreach $tosruleentry ( sort @tosrules )
233 @tosruleline = split ( /\;/ , $tosruleentry );
234 $qossettings { 'CLASS' } = $tosruleline [ 0 ];
235 $qossettings { 'TOS' } = abs $tosruleline [ 2 ] * 2 ;
236 if ( $tosruleline [ 1 ] eq $qossettings { 'RED_DEV' } )
238 print " \t iptables -t mangle -A QOS-OUT -m tos --tos $qossettings {'TOS'} -j MARK --set-xmark " . ( $qossettings { 'CLASS' } << $QOS_OUT_SHIFT ) . "/ $QOS_OUT_MASK \n " ;
239 print " \t iptables -t mangle -A QOS-OUT -m tos --tos $qossettings {'TOS'} -j RETURN \n " ;
243 print " \n\t ### SET PORT-RULES \n " ;
244 foreach $portruleentry ( sort @portrules )
246 @portruleline = split ( /\;/ , $portruleentry );
247 if ( $portruleline [ 1 ] eq $qossettings { 'RED_DEV' } )
249 $qossettings { 'CLASS' } = $portruleline [ 0 ];
250 $qossettings { 'DEVICE' } = $portruleline [ 1 ];
251 $qossettings { 'PPROT' } = $portruleline [ 2 ];
252 $qossettings { 'QIP' } = $portruleline [ 3 ];
253 $qossettings { 'QPORT' } = $portruleline [ 4 ];
254 $qossettings { 'DIP' } = $portruleline [ 5 ];
255 $qossettings { 'DPORT' } = $portruleline [ 6 ];
256 print " \t iptables -t mangle -A QOS-OUT -m mark --mark 0/ $QOS_OUT_MASK " ;
257 if ( $qossettings { 'QIP' } ne '' ){
258 print "-s $qossettings {'QIP'} " ;
260 if ( $qossettings { 'DIP' } ne '' ){
261 print "-d $qossettings {'DIP'} " ;
263 print "-p $qossettings {'PPROT'} " ;
264 # if (($qossettings{'QPORT'} ne '') || ($qossettings{'DPORT'} ne '')){
265 # print "-m multiport ";
267 if ( $qossettings { 'QPORT' } ne '' ){
268 print "--sport $qossettings {'QPORT'} " ;
270 if ( $qossettings { 'DPORT' } ne '' ){
271 print "--dport $qossettings {'DPORT'} " ;
273 print "-j MARK --set-xmark " . ( $qossettings { 'CLASS' } << $QOS_OUT_SHIFT ) . "/ $QOS_OUT_MASK \n " ;
282 foreach $l7ruleentry ( sort @l7rules )
284 @l7ruleline = split ( /\;/ , $l7ruleentry );
285 if ( $l7ruleline [ 1 ] eq $qossettings { 'RED_DEV' } )
287 $qossettings { 'CLASS' } = $l7ruleline [ 0 ];
288 $qossettings { 'DEVICE' } = $l7ruleline [ 1 ];
289 $qossettings { 'L7PROT' } = $l7ruleline [ 2 ];
290 $qossettings { 'QIP' } = $l7ruleline [ 3 ];
291 $qossettings { 'DIP' } = $l7ruleline [ 4 ];
292 print " \t iptables -t mangle -A QOS-OUT " ;
293 if ( $qossettings { 'QIP' } ne '' ){
294 print "-s $qossettings {'QIP'} " ;
296 if ( $qossettings { 'DIP' } ne '' ){
297 print "-d $qossettings {'DIP'} " ;
299 print "-m layer7 --l7dir /etc/l7-protocols/protocols --l7proto $qossettings {'L7PROT'} -j MARK --set-xmark " . $qossettings { 'CLASS' } << $QOS_OUT_SHIFT . "/ $QOS_OUT_MASK \n " ;
300 print " \t iptables -t mangle -A QOS-OUT " ;
301 if ( $qossettings { 'QIP' } ne '' ){
302 print "-s $qossettings {'QIP'} " ;
304 if ( $qossettings { 'DIP' } ne '' ){
305 print "-d $qossettings {'DIP'} " ;
307 print "-m layer7 --l7dir /etc/l7-protocols/protocols --l7proto $qossettings {'L7PROT'} -j RETURN \n " ;
313 ### REDUNDANT: SET ALL NONMARKED PACKETS TO DEFAULT CLASS
314 iptables -t mangle -A QOS-OUT -m mark --mark 0/ $QOS_OUT_MASK -j MARK --set-xmark $DEF_OUT_MARK
316 # Save mark in connection tracking
317 iptables -t mangle -A QOS-OUT -m mark ! --mark 0/ $QOS_OUT_MASK -j CONNMARK --save-mark
320 ### $qossettings {'IMQ_DEV'}
323 tc qdisc del dev $qossettings {'RED_DEV'} ingress >/dev/null 2>&1
324 tc qdisc add dev $qossettings {'RED_DEV'} handle ffff: ingress
326 ### BRING UP $qossettings {'IMQ_DEV'}
327 if [ ! -d "/sys/class/net/ $qossettings {'IMQ_DEV'}" ]; then
328 ip link add name $qossettings {'IMQ_DEV'} type ifb
331 ip link set $qossettings {'IMQ_DEV'} up
333 tc filter add dev $qossettings {'RED_DEV'} parent ffff: protocol all u32 match u32 0 0 \\
334 action mirred egress redirect dev $qossettings {'IMQ_DEV'}
336 ### ADD HTB QDISC FOR $qossettings {'IMQ_DEV'}
337 tc qdisc del dev $qossettings {'IMQ_DEV'} root >/dev/null 2>&1
338 tc qdisc add dev $qossettings {'IMQ_DEV'} root handle 2: htb default $qossettings {'DEFCLASS_INC'}
341 tc class add dev $qossettings {'IMQ_DEV'} parent 2: classid 2:1 htb rate $qossettings {'INC_SPD'}kbit
343 ### CLASSES FOR $qossettings {'IMQ_DEV'}
346 foreach $classentry ( sort @classes )
348 @classline = split ( /\;/ , $classentry );
349 if ( $qossettings { 'IMQ_DEV' } eq $classline [ 0 ]) {
350 $qossettings { 'DEVICE' } = $classline [ 0 ];
351 $qossettings { 'CLASS' } = $classline [ 1 ];
352 $qossettings { 'PRIO' } = $classline [ 2 ];
353 $qossettings { 'RATE' } = $classline [ 3 ];
354 $qossettings { 'CEIL' } = $classline [ 4 ];
355 $qossettings { 'BURST' } = $classline [ 5 ];
356 $qossettings { 'CBURST' } = $classline [ 6 ];
357 print " \t tc class add dev $qossettings {'DEVICE'} parent 2:1 classid 2: $qossettings {'CLASS'} htb rate $qossettings {'RATE'}kbit ceil $qossettings {'CEIL'}kbit prio $qossettings {'PRIO'} " ;
358 if (( $qossettings { 'BURST' } ne '' ) && ( $qossettings { 'BURST' } ne 0 )) {
359 print "burst $qossettings {'BURST'}k " ;
361 if (( $qossettings { 'CBURST' } ne '' ) && ( $qossettings { 'CBURST' } ne 0 )) {
362 print "cburst $qossettings {'CBURST'}k" ;
368 print " \n\t ### ATTACH QDISC TO LEAF CLASSES \n " ;
369 foreach $classentry ( sort @classes )
371 @classline = split ( /\;/ , $classentry );
372 if ( $qossettings { 'IMQ_DEV' } eq $classline [ 0 ]) {
373 $qossettings { 'DEVICE' } = $classline [ 0 ];
374 $qossettings { 'CLASS' } = $classline [ 1 ];
375 print " \t tc qdisc add dev $qossettings {'DEVICE'} parent 2: $qossettings {'CLASS'} handle $qossettings {'CLASS'}: fq_codel $fqcodel_options \n " ;
378 print " \n\t ### FILTER TRAFFIC INTO CLASSES \n " ;
379 foreach $classentry ( sort @classes )
381 @classline = split ( /\;/ , $classentry );
382 if ( $qossettings { 'IMQ_DEV' } eq $classline [ 0 ]) {
383 $qossettings { 'DEVICE' } = $classline [ 0 ];
384 $qossettings { 'CLASS' } = $classline [ 1 ];
385 print " \t tc filter add dev $qossettings {'DEVICE'} parent 2:0 prio 0 protocol ip" ;
386 printf ( " u32 match mark 0x %x 0x %x flowid 2: %d \n " , ( $qossettings { 'CLASS' } << $QOS_INC_SHIFT ), $QOS_INC_MASK , $qossettings { 'CLASS' });
391 ### ADD QOS-INC CHAIN TO THE MANGLE TABLE IN IPTABLES
392 iptables -t mangle -N QOS-INC
393 iptables -t mangle -A PREROUTING -i $qossettings {'RED_DEV'} -j QOS-INC
395 # If the packet is already marked, then skip the processing
396 iptables -t mangle -A QOS-INC -m mark ! --mark 0/ $QOS_INC_MASK -j RETURN
401 foreach $tosruleentry ( sort @tosrules )
403 @tosruleline = split ( /\;/ , $tosruleentry );
404 $qossettings { 'CLASS' } = $tosruleline [ 0 ];
405 $qossettings { 'TOS' } = abs $tosruleline [ 2 ] * 2 ;
406 if ( $tosruleline [ 1 ] eq $qossettings { 'IMQ_DEV' } )
408 print " \t iptables -t mangle -A QOS-INC -m tos --tos $qossettings {'TOS'} -j MARK --set-xmark " . ( $qossettings { 'CLASS' } << $QOS_INC_SHIFT ) . "/ $QOS_INC_MASK \n " ;
413 print " \n\t ### SET PORT-RULES \n " ;
414 foreach $portruleentry ( sort @portrules )
416 @portruleline = split ( /\;/ , $portruleentry );
417 if ( $portruleline [ 1 ] eq $qossettings { 'IMQ_DEV' } )
419 $qossettings { 'CLASS' } = $portruleline [ 0 ];
420 $qossettings { 'DEVICE' } = $portruleline [ 1 ];
421 $qossettings { 'PPROT' } = $portruleline [ 2 ];
422 $qossettings { 'QIP' } = $portruleline [ 3 ];
423 $qossettings { 'QPORT' } = $portruleline [ 4 ];
424 $qossettings { 'DIP' } = $portruleline [ 5 ];
425 $qossettings { 'DPORT' } = $portruleline [ 6 ];
426 print " \t iptables -t mangle -A QOS-INC -m mark --mark 0/ $QOS_INC_MASK " ;
427 if ( $qossettings { 'QIP' } ne '' ){
428 print "-s $qossettings {'QIP'} " ;
430 if ( $qossettings { 'DIP' } ne '' ){
431 print "-d $qossettings {'DIP'} " ;
433 print "-p $qossettings {'PPROT'} " ;
434 # if (($qossettings{'QPORT'} ne '') || ($qossettings{'DPORT'} ne '')){
435 # print "-m multiport ";
437 if ( $qossettings { 'QPORT' } ne '' ){
438 print "--sport $qossettings {'QPORT'} " ;
440 if ( $qossettings { 'DPORT' } ne '' ){
441 print "--dport $qossettings {'DPORT'} " ;
443 print "-j MARK --set-xmark " . ( $qossettings { 'CLASS' } << $QOS_INC_SHIFT ) . "/ $QOS_INC_MASK \n " ;
452 foreach $l7ruleentry ( sort @l7rules )
454 @l7ruleline = split ( /\;/ , $l7ruleentry );
455 if ( $l7ruleline [ 1 ] eq $qossettings { 'IMQ_DEV' } )
457 $qossettings { 'CLASS' } = $l7ruleline [ 0 ];
458 $qossettings { 'DEVICE' } = $l7ruleline [ 1 ];
459 $qossettings { 'L7PROT' } = $l7ruleline [ 2 ];
460 $qossettings { 'QIP' } = $l7ruleline [ 3 ];
461 $qossettings { 'DIP' } = $l7ruleline [ 4 ];
462 print " \t iptables -t mangle -A QOS-INC -m mark --mark 0/ $QOS_INC_MASK " ;
463 if ( $qossettings { 'QIP' } ne '' ){
464 print "-s $qossettings {'QIP'} " ;
466 if ( $qossettings { 'DIP' } ne '' ){
467 print "-d $qossettings {'DIP'} " ;
469 print "-m layer7 --l7dir /etc/l7-protocols/protocols --l7proto $qossettings {'L7PROT'} -j MARK --set-xmark " . ( $qossettings { 'CLASS' } << $QOS_INC_SHIFT ) . "/ $QOS_INC_MASK \n " ;
474 ### REDUNDANT: SET ALL NONMARKED PACKETS TO DEFAULT CLASS
475 iptables -t mangle -A QOS-INC -m mark --mark 0/ $QOS_INC_MASK -m layer7 ! --l7proto unset -j MARK --set-xmark $DEF_INC_MARK
477 # Save mark in connection tracking
478 iptables -t mangle -A QOS-INC -m mark ! --mark 0/ $QOS_INC_MASK -j CONNMARK --save-mark
480 ## STARTING COLLECTOR
481 /usr/local/bin/qosd $qossettings {'RED_DEV'} >/dev/null 2>&1
482 /usr/local/bin/qosd $qossettings {'IMQ_DEV'} >/dev/null 2>&1
484 for i in \$(ls \ $RRDLOG /class_*.rrd); do
485 rrdtool update \ $i \$(date + %s ): 2>/dev/null
488 echo "Quality of Service was successfully started!"
492 ### RESET EVERYTHING TO A KNOWN STATE
493 killall qosd >/dev/null 2>&1
496 tc qdisc del dev $qossettings {'RED_DEV'} root >/dev/null 2>&1
497 tc qdisc del dev $qossettings {'RED_DEV'} ingress >/dev/null 2>&1
498 tc qdisc add root dev $qossettings {'RED_DEV'} fq_codel >/dev/null 2>&1
499 tc qdisc del dev $qossettings {'IMQ_DEV'} root >/dev/null 2>&1
500 tc qdisc del dev $qossettings {'IMQ_DEV'} ingress >/dev/null 2>&1
501 tc qdisc add root dev $qossettings {'IMQ_DEV'} fq_codel >/dev/null 2>&1
503 ip link set $qossettings {'IMQ_DEV'} down >/dev/null 2>&1
504 ip link del $qossettings {'IMQ_DEV'} >/dev/null 2>&1
506 # REMOVE & FLUSH CHAINS
507 iptables -t mangle --delete POSTROUTING -o $qossettings {'RED_DEV'} -j QOS-OUT >/dev/null 2>&1
508 iptables -t mangle --delete PREROUTING -i $qossettings {'RED_DEV'} -j QOS-INC >/dev/null 2>&1
509 iptables -t mangle --flush QOS-OUT >/dev/null 2>&1
510 iptables -t mangle --delete-chain QOS-OUT >/dev/null 2>&1
511 iptables -t mangle --flush QOS-INC >/dev/null 2>&1
512 iptables -t mangle --delete-chain QOS-INC >/dev/null 2>&1
514 rmmod sch_htb >/dev/null 2>&1
516 for i in \$(ls \ $RRDLOG /class_*.rrd); do
517 rrdtool update \ $i \$(date + %s ):
520 echo "Quality of Service was successfully cleared!"
523 echo -n "Generating the QoS-Scripts..."
524 /usr/bin/perl /var/ipfire/qos/bin/makeqosscripts.pl > /var/ipfire/qos/bin/qos.sh
529 ### FIRST CLEAR EVERYTHING
540 ############################################################################################################################
541 ############################################################################################################################