]>
git.ipfire.org Git - people/bonnietwin/ipfire-2.x.git/blob - config/qos/makeqosscripts.pl
442324b985cba427a7fa9fce22e2381283f0254e
2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2007-2021 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 @cake_options = ();
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 ;
64 my $QOS_INC_SKIP_MASK = $QOS_INC_MASK ;
65 my $QOS_OUT_SKIP_MASK = $QOS_OUT_MASK ;
67 & General
:: readhash
( "${General::swroot}/ethernet/settings" , \
%netsettings );
69 $qossettings { 'ENABLED' } = 'off' ;
70 $qossettings { 'EDIT' } = 'no' ;
71 $qossettings { 'OUT_SPD' } = '' ;
72 $qossettings { 'INC_SPD' } = '' ;
73 $qossettings { 'DEF_OUT_SPD' } = '' ;
74 $qossettings { 'DEF_INC_SPD' } = '' ;
75 $qossettings { 'DEFCLASS_INC' } = '' ;
76 $qossettings { 'DEFCLASS_OUT' } = '' ;
77 $qossettings { 'RED_DEV' } = `cat /var/ipfire/red/iface` ;
78 $qossettings { 'IMQ_DEV' } = 'imq0' ;
79 $qossettings { 'TOS' } = '' ;
80 $qossettings { 'VALID' } = 'yes' ;
82 & General
:: readhash
( "${General::swroot}/qos/settings" , \
%qossettings );
84 my $DEF_OUT_MARK = ( $qossettings { 'DEFCLASS_OUT' } << $QOS_OUT_SHIFT ) . "/ $QOS_OUT_MASK " ;
85 my $DEF_INC_MARK = ( $qossettings { 'DEFCLASS_INC' } << $QOS_INC_SHIFT ) . "/ $QOS_INC_MASK " ;
87 open ( FILE
, "< $classfile " ) or die "Unable to read $classfile " ;
90 open ( FILE
, "< $level7file " ) or die "Unable to read $level7file " ;
93 open ( FILE
, "< $portfile " ) or die "Unable to read $portfile " ;
96 open ( FILE
, "< $tosfile " ) or die "Unable to read $tosfile " ;
100 ############################################################################################################################
101 ############################################################################################################################
105 #################################################
106 # This is an autocreated QoS-Script for #
108 # Copyright by the IPFire Team (GPLv2) #
110 #################################################
113 # RED INTERFACE: $qossettings {'RED_DEV'}
114 # IMQ DEVICE: $qossettings {'IMQ_DEV'}
116 eval \$(/usr/local/bin/readhash /var/ipfire/main/settings)
117 if [ "\ $RRDLOG " == "" ]; then
127 tc -s qdisc show dev $qossettings {'RED_DEV'}
128 tc -s qdisc show dev $qossettings {'IMQ_DEV'}
133 tc -s class show dev $qossettings {'RED_DEV'}
134 tc -s class show dev $qossettings {'IMQ_DEV'}
139 tc -s filter show dev $qossettings {'RED_DEV'}
140 tc -s filter show dev $qossettings {'IMQ_DEV'}
145 iptables -t mangle -n -L QOS-OUT -v -x 2> /dev/null
146 iptables -t mangle -n -L QOS-INC -v -x 2> /dev/null
158 ### $qossettings {'RED_DEV'}
164 ### ADD HTB QDISC FOR $qossettings {'RED_DEV'}
165 tc qdisc del dev $qossettings {'RED_DEV'} root >/dev/null 2>&1
166 tc qdisc add dev $qossettings {'RED_DEV'} root handle 1: htb default $qossettings {'DEFCLASS_OUT'}
169 tc class add dev $qossettings {'RED_DEV'} parent 1: classid 1:1 htb rate $qossettings {'OUT_SPD'}kbit
171 ### CLASSES FOR $qossettings {'RED_DEV'}
174 foreach $classentry ( sort @classes )
176 @classline = split ( /\;/ , $classentry );
177 if ( $qossettings { 'RED_DEV' } eq $classline [ 0 ]) {
178 $qossettings { 'DEVICE' } = $classline [ 0 ];
179 $qossettings { 'CLASS' } = $classline [ 1 ];
180 $qossettings { 'PRIO' } = $classline [ 2 ];
181 $qossettings { 'RATE' } = $classline [ 3 ];
182 $qossettings { 'CEIL' } = $classline [ 4 ];
183 $qossettings { 'BURST' } = $classline [ 5 ];
184 $qossettings { 'CBURST' } = $classline [ 6 ];
185 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'} " ;
186 if (( $qossettings { 'BURST' } ne '' ) && ( $qossettings { 'BURST' } ne 0 )) {
187 print "burst $qossettings {'BURST'}k " ;
189 if (( $qossettings { 'CBURST' } ne '' ) && ( $qossettings { 'CBURST' } ne 0 )) {
190 print "cburst $qossettings {'CBURST'}k" ;
196 print " \n\t ### ATTACH QDISC TO LEAF CLASSES \n " ;
197 foreach $classentry ( sort @classes )
199 @classline = split ( /\;/ , $classentry );
200 if ( $qossettings { 'RED_DEV' } eq $classline [ 0 ]) {
201 $qossettings { 'DEVICE' } = $classline [ 0 ];
202 $qossettings { 'CLASS' } = $classline [ 1 ];
203 print " \t tc qdisc add dev $qossettings {'DEVICE'} parent 1: $qossettings {'CLASS'} handle $qossettings {'CLASS'}: cake @cake_options \n " ;
206 print " \n\t ### FILTER TRAFFIC INTO CLASSES \n " ;
207 foreach $classentry ( sort @classes )
209 @classline = split ( /\;/ , $classentry );
210 if ( $qossettings { 'RED_DEV' } eq $classline [ 0 ]) {
211 $qossettings { 'DEVICE' } = $classline [ 0 ];
212 $qossettings { 'CLASS' } = $classline [ 1 ];
213 print " \t tc filter add dev $qossettings {'DEVICE'} parent 1:0 prio 0 protocol ip" ;
214 printf ( " u32 match mark 0x %x 0x %x flowid 1: %d \n " , ( $qossettings { 'CLASS' } << $QOS_OUT_SHIFT ), $QOS_OUT_MASK , $qossettings { 'CLASS' });
220 ### ADD QOS-OUT CHAIN TO THE MANGLE TABLE IN IPTABLES
221 iptables -t mangle -N QOS-OUT
222 iptables -t mangle -A POSTROUTING -o $qossettings {'RED_DEV'} -j QOS-OUT
224 # If the packet is already marked, then skip the processing
225 iptables -t mangle -A QOS-OUT -m mark ! --mark 0/ $QOS_OUT_SKIP_MASK -j RETURN
230 foreach $tosruleentry ( sort @tosrules )
232 @tosruleline = split ( /\;/ , $tosruleentry );
233 $qossettings { 'CLASS' } = $tosruleline [ 0 ];
234 $qossettings { 'TOS' } = abs $tosruleline [ 2 ] * 2 ;
235 if ( $tosruleline [ 1 ] eq $qossettings { 'RED_DEV' } )
237 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 " ;
238 print " \t iptables -t mangle -A QOS-OUT -m tos --tos $qossettings {'TOS'} -j RETURN \n " ;
242 print " \n\t ### SET PORT-RULES \n " ;
243 foreach $portruleentry ( sort @portrules )
245 @portruleline = split ( /\;/ , $portruleentry );
246 if ( $portruleline [ 1 ] eq $qossettings { 'RED_DEV' } )
248 $qossettings { 'CLASS' } = $portruleline [ 0 ];
249 $qossettings { 'DEVICE' } = $portruleline [ 1 ];
250 $qossettings { 'PPROT' } = $portruleline [ 2 ];
251 $qossettings { 'QIP' } = $portruleline [ 3 ];
252 $qossettings { 'QPORT' } = $portruleline [ 4 ];
253 $qossettings { 'DIP' } = $portruleline [ 5 ];
254 $qossettings { 'DPORT' } = $portruleline [ 6 ];
255 print " \t iptables -t mangle -A QOS-OUT -m mark --mark 0/ $QOS_OUT_MASK " ;
256 if ( $qossettings { 'QIP' } ne '' ){
257 print "-s $qossettings {'QIP'} " ;
259 if ( $qossettings { 'DIP' } ne '' ){
260 print "-d $qossettings {'DIP'} " ;
262 print "-p $qossettings {'PPROT'} " ;
263 # if (($qossettings{'QPORT'} ne '') || ($qossettings{'DPORT'} ne '')){
264 # print "-m multiport ";
266 if ( $qossettings { 'QPORT' } ne '' ){
267 print "--sport $qossettings {'QPORT'} " ;
269 if ( $qossettings { 'DPORT' } ne '' ){
270 print "--dport $qossettings {'DPORT'} " ;
272 print "-j MARK --set-xmark " . ( $qossettings { 'CLASS' } << $QOS_OUT_SHIFT ) . "/ $QOS_OUT_MASK \n " ;
281 foreach $l7ruleentry ( sort @l7rules )
283 @l7ruleline = split ( /\;/ , $l7ruleentry );
284 if ( $l7ruleline [ 1 ] eq $qossettings { 'RED_DEV' } )
286 $qossettings { 'CLASS' } = $l7ruleline [ 0 ];
287 $qossettings { 'DEVICE' } = $l7ruleline [ 1 ];
288 $qossettings { 'L7PROT' } = $l7ruleline [ 2 ];
289 $qossettings { 'QIP' } = $l7ruleline [ 3 ];
290 $qossettings { 'DIP' } = $l7ruleline [ 4 ];
291 print " \t iptables -t mangle -A QOS-OUT -m mark --mark 0/ $QOS_OUT_MASK " ;
292 if ( $qossettings { 'QIP' } ne '' ){
293 print "-s $qossettings {'QIP'} " ;
295 if ( $qossettings { 'DIP' } ne '' ){
296 print "-d $qossettings {'DIP'} " ;
298 print "-m layer7 --l7dir /etc/l7-protocols/protocols --l7proto $qossettings {'L7PROT'} -j MARK --set-xmark " . ( $qossettings { 'CLASS' } << $QOS_OUT_SHIFT ) . "/ $QOS_OUT_MASK \n " ;
304 ### REDUNDANT: SET ALL NONMARKED PACKETS TO DEFAULT CLASS
305 iptables -t mangle -A QOS-OUT -m mark --mark 0/ $QOS_OUT_MASK -m layer7 ! --l7proto unset -j MARK --set-xmark $DEF_OUT_MARK
307 # Save mark in connection tracking
308 iptables -t mangle -A QOS-OUT -m mark ! --mark 0/ $QOS_OUT_MASK -j CONNMARK --save-mark --mask $QOS_OUT_MASK
311 ### $qossettings {'IMQ_DEV'}
314 tc qdisc del dev $qossettings {'RED_DEV'} ingress >/dev/null 2>&1
315 tc qdisc add dev $qossettings {'RED_DEV'} handle ffff: ingress
317 ### BRING UP $qossettings {'IMQ_DEV'}
318 if [ ! -d "/sys/class/net/ $qossettings {'IMQ_DEV'}" ]; then
319 ip link add name $qossettings {'IMQ_DEV'} type ifb
322 ip link set $qossettings {'IMQ_DEV'} up
324 ### Pass IPSec traffic without redirect
325 tc filter add dev $qossettings {'RED_DEV'} parent ffff: prio 1 protocol all basic \\
326 match "ipt(-m policy --pol ipsec --dir in)" \\
329 ### Restore connmark and send rest of the traffic to $qossettings {'IMQ_DEV'}
330 tc filter add dev $qossettings {'RED_DEV'} parent ffff: prio 2 protocol all u32 \\
333 action mirred egress redirect dev $qossettings {'IMQ_DEV'}
335 ### ADD HTB QDISC FOR $qossettings {'IMQ_DEV'}
336 tc qdisc del dev $qossettings {'IMQ_DEV'} root >/dev/null 2>&1
337 tc qdisc add dev $qossettings {'IMQ_DEV'} root handle 2: htb default $qossettings {'DEFCLASS_INC'}
340 tc class add dev $qossettings {'IMQ_DEV'} parent 2: classid 2:1 htb rate $qossettings {'INC_SPD'}kbit
342 ### CLASSES FOR $qossettings {'IMQ_DEV'}
345 foreach $classentry ( sort @classes )
347 @classline = split ( /\;/ , $classentry );
348 if ( $qossettings { 'IMQ_DEV' } eq $classline [ 0 ]) {
349 $qossettings { 'DEVICE' } = $classline [ 0 ];
350 $qossettings { 'CLASS' } = $classline [ 1 ];
351 $qossettings { 'PRIO' } = $classline [ 2 ];
352 $qossettings { 'RATE' } = $classline [ 3 ];
353 $qossettings { 'CEIL' } = $classline [ 4 ];
354 $qossettings { 'BURST' } = $classline [ 5 ];
355 $qossettings { 'CBURST' } = $classline [ 6 ];
356 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'} " ;
357 if (( $qossettings { 'BURST' } ne '' ) && ( $qossettings { 'BURST' } ne 0 )) {
358 print "burst $qossettings {'BURST'}k " ;
360 if (( $qossettings { 'CBURST' } ne '' ) && ( $qossettings { 'CBURST' } ne 0 )) {
361 print "cburst $qossettings {'CBURST'}k" ;
367 print " \n\t ### ATTACH QDISC TO LEAF CLASSES \n " ;
368 foreach $classentry ( sort @classes )
370 @classline = split ( /\;/ , $classentry );
371 if ( $qossettings { 'IMQ_DEV' } eq $classline [ 0 ]) {
372 $qossettings { 'DEVICE' } = $classline [ 0 ];
373 $qossettings { 'CLASS' } = $classline [ 1 ];
374 print " \t tc qdisc add dev $qossettings {'DEVICE'} parent 2: $qossettings {'CLASS'} handle $qossettings {'CLASS'}: cake @cake_options \n " ;
377 print " \n\t ### FILTER TRAFFIC INTO CLASSES \n " ;
378 foreach $classentry ( sort @classes )
380 @classline = split ( /\;/ , $classentry );
381 if ( $qossettings { 'IMQ_DEV' } eq $classline [ 0 ]) {
382 $qossettings { 'DEVICE' } = $classline [ 0 ];
383 $qossettings { 'CLASS' } = $classline [ 1 ];
384 print " \t tc filter add dev $qossettings {'DEVICE'} parent 2:0 prio 0 protocol ip" ;
385 printf ( " u32 match mark 0x %x 0x %x flowid 2: %d \n " , ( $qossettings { 'CLASS' } << $QOS_INC_SHIFT ), $QOS_INC_MASK , $qossettings { 'CLASS' });
390 ### ADD QOS-INC CHAIN TO THE MANGLE TABLE IN IPTABLES
391 iptables -t mangle -N QOS-INC
392 iptables -t mangle -A PREROUTING -i $qossettings {'RED_DEV'} -j QOS-INC
394 # If the packet is already marked, then skip the processing
395 iptables -t mangle -A QOS-INC -m mark ! --mark 0/ $QOS_INC_SKIP_MASK -j RETURN
400 foreach $tosruleentry ( sort @tosrules )
402 @tosruleline = split ( /\;/ , $tosruleentry );
403 $qossettings { 'CLASS' } = $tosruleline [ 0 ];
404 $qossettings { 'TOS' } = abs $tosruleline [ 2 ] * 2 ;
405 if ( $tosruleline [ 1 ] eq $qossettings { 'IMQ_DEV' } )
407 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 " ;
412 print " \n\t ### SET PORT-RULES \n " ;
413 foreach $portruleentry ( sort @portrules )
415 @portruleline = split ( /\;/ , $portruleentry );
416 if ( $portruleline [ 1 ] eq $qossettings { 'IMQ_DEV' } )
418 $qossettings { 'CLASS' } = $portruleline [ 0 ];
419 $qossettings { 'DEVICE' } = $portruleline [ 1 ];
420 $qossettings { 'PPROT' } = $portruleline [ 2 ];
421 $qossettings { 'QIP' } = $portruleline [ 3 ];
422 $qossettings { 'QPORT' } = $portruleline [ 4 ];
423 $qossettings { 'DIP' } = $portruleline [ 5 ];
424 $qossettings { 'DPORT' } = $portruleline [ 6 ];
425 print " \t iptables -t mangle -A QOS-INC -m mark --mark 0/ $QOS_INC_MASK " ;
426 if ( $qossettings { 'QIP' } ne '' ){
427 print "-s $qossettings {'QIP'} " ;
429 if ( $qossettings { 'DIP' } ne '' ){
430 print "-d $qossettings {'DIP'} " ;
432 print "-p $qossettings {'PPROT'} " ;
433 # if (($qossettings{'QPORT'} ne '') || ($qossettings{'DPORT'} ne '')){
434 # print "-m multiport ";
436 if ( $qossettings { 'QPORT' } ne '' ){
437 print "--sport $qossettings {'QPORT'} " ;
439 if ( $qossettings { 'DPORT' } ne '' ){
440 print "--dport $qossettings {'DPORT'} " ;
442 print "-j MARK --set-xmark " . ( $qossettings { 'CLASS' } << $QOS_INC_SHIFT ) . "/ $QOS_INC_MASK \n " ;
451 foreach $l7ruleentry ( sort @l7rules )
453 @l7ruleline = split ( /\;/ , $l7ruleentry );
454 if ( $l7ruleline [ 1 ] eq $qossettings { 'IMQ_DEV' } )
456 $qossettings { 'CLASS' } = $l7ruleline [ 0 ];
457 $qossettings { 'DEVICE' } = $l7ruleline [ 1 ];
458 $qossettings { 'L7PROT' } = $l7ruleline [ 2 ];
459 $qossettings { 'QIP' } = $l7ruleline [ 3 ];
460 $qossettings { 'DIP' } = $l7ruleline [ 4 ];
461 print " \t iptables -t mangle -A QOS-INC -m mark --mark 0/ $QOS_INC_MASK " ;
462 if ( $qossettings { 'QIP' } ne '' ){
463 print "-s $qossettings {'QIP'} " ;
465 if ( $qossettings { 'DIP' } ne '' ){
466 print "-d $qossettings {'DIP'} " ;
468 print "-m layer7 --l7dir /etc/l7-protocols/protocols --l7proto $qossettings {'L7PROT'} -j MARK --set-xmark " . ( $qossettings { 'CLASS' } << $QOS_INC_SHIFT ) . "/ $QOS_INC_MASK \n " ;
473 ### REDUNDANT: SET ALL NONMARKED PACKETS TO DEFAULT CLASS
474 iptables -t mangle -A QOS-INC -m mark --mark 0/ $QOS_INC_MASK -m layer7 ! --l7proto unset -j MARK --set-xmark $DEF_INC_MARK
476 # Save mark in connection tracking
477 iptables -t mangle -A QOS-INC -m mark ! --mark 0/ $QOS_INC_MASK -j CONNMARK --save-mark --mask $QOS_INC_MASK
479 ## STARTING COLLECTOR
480 /usr/local/bin/qosd $qossettings {'RED_DEV'} >/dev/null 2>&1
481 /usr/local/bin/qosd $qossettings {'IMQ_DEV'} >/dev/null 2>&1
483 for i in \$(ls \ $RRDLOG /class_*.rrd); do
484 rrdtool update \ $i \$(date + %s ): 2>/dev/null
487 echo "Quality of Service was successfully started!"
491 ### RESET EVERYTHING TO A KNOWN STATE
492 killall qosd >/dev/null 2>&1
495 tc qdisc del dev $qossettings {'RED_DEV'} root >/dev/null 2>&1
496 tc qdisc del dev $qossettings {'RED_DEV'} ingress >/dev/null 2>&1
497 INTERFACE=" $qossettings {'RED_DEV'}" ACTION="add" /lib/udev/network-aqm &>/dev/null
499 ip link set $qossettings {'IMQ_DEV'} down >/dev/null 2>&1
500 ip link del $qossettings {'IMQ_DEV'} >/dev/null 2>&1
502 # REMOVE & FLUSH CHAINS
503 iptables -t mangle --delete POSTROUTING -o $qossettings {'RED_DEV'} -j QOS-OUT >/dev/null 2>&1
504 iptables -t mangle --delete PREROUTING -i $qossettings {'RED_DEV'} -j QOS-INC >/dev/null 2>&1
505 iptables -t mangle --flush QOS-OUT >/dev/null 2>&1
506 iptables -t mangle --delete-chain QOS-OUT >/dev/null 2>&1
507 iptables -t mangle --flush QOS-INC >/dev/null 2>&1
508 iptables -t mangle --delete-chain QOS-INC >/dev/null 2>&1
510 for i in \$(ls \ $RRDLOG /class_*.rrd); do
511 rrdtool update \ $i \$(date + %s ):
514 echo "Quality of Service was successfully cleared!"
517 echo -n "Generating the QoS-Scripts..."
518 /usr/bin/perl /var/ipfire/qos/bin/makeqosscripts.pl > /var/ipfire/qos/bin/qos.sh
523 ### FIRST CLEAR EVERYTHING
534 ############################################################################################################################
535 ############################################################################################################################