From f69a7416910e4916d4083a4fc28e8a0d709f41b7 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Tue, 12 Jan 2010 17:01:20 -0800 Subject: [PATCH] Port Simplified TC to 4.4.6 Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Config.pm | 22 +++- Shorewall/Perl/Shorewall/Tc.pm | 185 ++++++++++++++++++++++++++++- Shorewall/lib.base | 8 +- Shorewall6/lib.base | 10 +- 4 files changed, 217 insertions(+), 8 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index d65250b72..cbb74dc0b 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -227,6 +227,7 @@ our %capdesc = ( NAT_ENABLED => 'NAT', KLUDGEFREE => 'Repeat match', MARK => 'MARK Target', XMARK => 'Extended Mark Target', + EXMARK => 'Extended Mark Target 2', MANGLE_FORWARD => 'Mangle FORWARD Chain', COMMENTS => 'Comments', ADDRTYPE => 'Address Type Match', @@ -330,7 +331,7 @@ sub initialize( $ ) { EXPORT => 0, UNTRACKED => 0, VERSION => "4.4.6-Beta1", - CAPVERSION => 40406 , + CAPVERSION => 40407 , ); # @@ -403,6 +404,7 @@ sub initialize( $ ) { RETAIN_ALIASES => undef, TC_ENABLED => undef, TC_EXPERT => undef, + TC_PRIOMAP => undef, CLEAR_TC => undef, MARK_IN_FORWARD_CHAIN => undef, CLAMPMSS => undef, @@ -534,6 +536,7 @@ sub initialize( $ ) { IP_FORWARDING => undef, TC_ENABLED => undef, TC_EXPERT => undef, + TC_PRIOMAP => undef, CLEAR_TC => undef, MARK_IN_FORWARD_CHAIN => undef, CLAMPMSS => undef, @@ -619,6 +622,7 @@ sub initialize( $ ) { KLUDGEFREE => undef, MARK => undef, XMARK => undef, + EXMARK => undef, MANGLE_FORWARD => undef, COMMENTS => undef, ADDRTYPE => undef, @@ -2122,6 +2126,7 @@ sub determine_capabilities( $ ) { if ( qt1( "$iptables -t mangle -A $sillyname -j MARK --set-mark 1" ) ) { $capabilities{MARK} = 1; $capabilities{XMARK} = qt1( "$iptables -t mangle -A $sillyname -j MARK --and-mark 0xFF" ); + $capabilities{EXMARK} = qt1( "$iptables -t mangle -A $sillyname -j MARK --set-mark 1/0xFF" ); } if ( qt1( "$iptables -t mangle -A $sillyname -j CONNMARK --save-mark" ) ) { @@ -2590,6 +2595,8 @@ sub get_configuration( $ ) { $globals{TC_SCRIPT} = $file; } elsif ( $val eq 'internal' ) { $config{TC_ENABLED} = 'Internal'; + } elsif ( $val eq 'simple' ) { + $config{TC_ENABLED} = 'Simple'; } else { fatal_error "Invalid value ($config{TC_ENABLED}) for TC_ENABLED" unless $val eq 'no'; $config{TC_ENABLED} = ''; @@ -2600,6 +2607,19 @@ sub get_configuration( $ ) { require_capability 'MANGLE_ENABLED', "TC_ENABLED=$config{TC_ENABLED}", 's'; } + if ( $val = $config{TC_PRIOMAP} ) { + my @priomap = split ' ',$val; + fatal_error "Invalid TC_PRIOMAP ($val)" unless @priomap == 16; + for ( @priomap ) { + fatal_error "Invalid TC_PRIOMAP entry ($_)" unless /[1-3]/; + $_--; + } + + $config{TC_PRIOMAP} = join ' ', @priomap; + } else { + $config{TC_PRIOMAP} = '1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1'; + } + default 'RESTOREFILE' , 'restore'; default 'IPSECFILE' , 'zones'; default 'DROP_DEFAULT' , 'Drop'; diff --git a/Shorewall/Perl/Shorewall/Tc.pm b/Shorewall/Perl/Shorewall/Tc.pm index ba947448c..8f1bcc86d 100644 --- a/Shorewall/Perl/Shorewall/Tc.pm +++ b/Shorewall/Perl/Shorewall/Tc.pm @@ -130,6 +130,7 @@ our %tcdevices; our @devnums; our $devnum; our $sticky; +our $ipp2p; # @@ -183,6 +184,7 @@ sub initialize( $ ) { @devnums = (); $devnum = 0; $sticky = 0; + $ipp2p = 0; } sub process_tc_rule( ) { @@ -409,6 +411,96 @@ sub process_flow($) { $flow; } +sub process_simple_device() { + my ( $device , $type , $bandwidth ) = split_line 1, 3, 'tcinterfaces'; + + my $devnumber; + + if ( $device =~ /:/ ) { + ( my $number, $device, my $rest ) = split /:/, $device, 3; + + fatal_error "Invalid NUMBER:INTERFACE ($device:$number:$rest)" if defined $rest; + + if ( defined $number ) { + $devnumber = hex_value( $number ); + fatal_error "Invalid interface NUMBER ($number)" unless defined $devnumber && $devnumber; + fatal_error "Duplicate interface number ($number)" if defined $devnums[ $devnumber ]; + $devnum = $devnumber if $devnumber > $devnum; + } else { + fatal_error "Missing interface NUMBER"; + } + } else { + $devnumber = ++$devnum; + } + + $devnums[ $devnumber ] = $device; + + my $number = in_hexp $devnumber; + + fatal_error "Duplicate INTERFACE ($device)" if $tcdevices{$device}; + fatal_error "Invalid INTERFACE name ($device)" if $device =~ /[:+]/; + + my $physical = physical_name $device; + my $dev = chain_base( $physical ); + + if ( $type ne '-' ) { + if ( lc $type eq 'external' ) { + $type = 'nfct-src'; + } elsif ( lc $type eq 'internal' ) { + $type = 'dst'; + } else { + fatal_error "Invalid TYPE ($type)"; + } + } + + $tcdevices{$device} = { number => $devnumber , + physical => physical_name $device , + type => $type , + in_bandwidth => $bandwidth = rate_to_kbit( $bandwidth ) , + }; + + push @tcdevices, $device; + + emit "if interface_is_up $physical; then"; + + push_indent; + + emit ( "${dev}_exists=Yes", + "qt \$TC qdisc del dev $physical root", + "qt \$TC qdisc del dev $physical ingress\n" + ); + + if ( $bandwidth ) { + emit ( "run_tc qdisc add dev $physical handle ffff: ingress", + "run_tc filter add dev $physical parent ffff: protocol all prio 10 u32 match ip src 0.0.0.0/0 police rate ${bandwidth}kbit burst 10k drop flowid :1\n" + ); + } + + emit "run_tc qdisc add dev $physical root handle $number: prio bands 3 priomap $config{TC_PRIOMAP}"; + + my $i = 0; + + while ( ++$i <= 3 ) { + emit "run_tc qdisc add dev $physical parent $number:$i handle ${number}${i}: sfq quantum 1500 limit 127 perturb 10"; + emit "run_tc filter add dev $physical protocol all parent $number: handle $i fw classid $devnum:$i"; + emit "run_tc filter add dev $physical protocol all prio 1 parent ${number}$i: handle ${number}${i} flow hash keys $type divisor 1024" if $type ne '-'; + emit ''; + } + + save_progress_message_short " TC Device $physical defined."; + + pop_indent; + emit 'else'; + push_indent; + + emit qq(error_message "WARNING: Device $physical is not in the UP state -- traffic-shaping configuration skipped"); + emit "${dev}_exists="; + pop_indent; + emit "fi\n"; + + progress_message " Simple tcdevice \"$currentline\" $done."; +} + sub validate_tc_device( ) { my ( $device, $inband, $outband , $options , $redirected ) = split_line 3, 5, 'tcdevices'; @@ -976,6 +1068,91 @@ sub process_tc_filter( ) { } +sub process_tc_priority() { + my ( $band, $proto, $ports , $address, $interface, $helper ) = split_line1 1, 6, 'tcpri'; + + if ( $band eq 'COMMENT' ) { + process_comment; + return; + } + + my $val = numeric_value $band; + + fatal_error "Invalid PRIORITY ($band)" unless $val && $val <= 3; + + my $rule = do_helper( $helper ) . "-j MARK --set-mark $band"; + + $rule .= join('', '/', in_hex( $globals{TC_MASK} ) ) if $capabilities{EXMARK}; + + if ( $interface ne '-' ) { + fatal_error "Invalid combination of columns" unless $address eq '-' && $proto eq '-' && $ports eq '-'; + + my $forwardref = $mangle_table->{tcfor}; + + add_rule( $forwardref , + join( '', match_source_dev( $interface) , $rule ) , + 1 ); + } else { + my $postref = $mangle_table->{tcpost}; + + if ( $address ne '-' ) { + fatal_error "Invalid combination of columns" unless $proto eq '-' && $ports eq '-'; + add_rule( $postref , + join( '', match_source_net( $address) , $rule ) , + 1 ); + } else { + add_rule( $postref , + join( '', do_proto( $proto, $ports, '-' , 0 ) , $rule ) , + 1 ); + + if ( $ports ne '-' ) { + my $protocol = resolve_proto $proto; + + if ( $proto =~ /^ipp2p/ ) { + fatal_error "ipp2p may not be used when there are tracked providers and PROVIDER_OFFSET=0" if @routemarked_interfaces && $config{PROVIDER_OFFSET} == 0; + $ipp2p = 1; + } + + add_rule( $postref , + join( '' , do_proto( $proto, '-', $ports, 0 ) , $rule ) , + 1 ) + unless $proto =~ /^ipp2p/ || $protocol == ICMP || $protocol == IPv6_ICMP; + } + } + } +} + +sub setup_simple_traffic_shaping() { + my $interfaces; + + save_progress_message "Setting up Traffic Control..."; + + my $fn = open_file 'tcinterfaces'; + + if ( $fn ) { + first_entry "$doing $fn..."; + process_simple_device, $interfaces++ while read_a_line; + } else { + $fn = find_file 'tcinterfaces'; + } + + my $fn1 = open_file 'tcpri'; + + if ( $fn1 ) { + first_entry sub { progress_message2 "$doing $fn1..."; + warning_message "There are entries in $fn1 but $fn was empty" unless $interfaces; + }; + process_tc_priority while read_a_line; + + clear_comment; + + if ( $ipp2p ) { + insert_rule1 $mangle_table->{tcpost} , 0 , '-m mark --mark 0/' . in_hex( $globals{TC_MASK} ) . ' -j CONNMARK --restore-mark --ctmask ' . in_hex( $globals{TC_MASK} ); + add_rule $mangle_table->{tcpost} , '-m mark ! --mark 0/' . in_hex( $globals{TC_MASK} ) . ' -j CONNMARK --save-mark --ctmask ' . in_hex( $globals{TC_MASK} ); + } + } +} + sub setup_traffic_shaping() { our $lastrule = ''; @@ -1185,8 +1362,10 @@ sub setup_tc() { if ( @routemarked_interfaces && ! $config{TC_EXPERT} ) { $mark_part = '-m mark --mark 0/' . in_hex( $globals{PROVIDER_MASK} ) . ' '; - for my $interface ( @routemarked_interfaces ) { - add_rule $mangle_table->{PREROUTING} , match_source_dev( $interface ) . "-j tcpre"; + unless ( $config{TRACK_PROVIDERS} ) { + for my $interface ( @routemarked_interfaces ) { + add_rule $mangle_table->{PREROUTING} , match_source_dev( $interface ) . "-j tcpre"; + } } } @@ -1205,6 +1384,8 @@ sub setup_tc() { append_file $globals{TC_SCRIPT}; } elsif ( $config{TC_ENABLED} eq 'Internal' ) { setup_traffic_shaping; + } elsif ( $config{TC_ENABLED} eq 'Simple' ) { + setup_simple_traffic_shaping; } if ( $config{TC_ENABLED} ) { diff --git a/Shorewall/lib.base b/Shorewall/lib.base index cb9b1085f..9ced599cd 100644 --- a/Shorewall/lib.base +++ b/Shorewall/lib.base @@ -4,7 +4,7 @@ # # This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt] # -# (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 - Tom Eastep (teastep@shorewall.net) +# (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007 - Tom Eastep (teastep@shorewall.net) # # Complete documentation is available at http://shorewall.net # @@ -30,7 +30,7 @@ # SHOREWALL_LIBVERSION=40406 -SHOREWALL_CAPVERSION=40406 +SHOREWALL_CAPVERSION=40407 [ -n "${VARDIR:=/var/lib/shorewall}" ] [ -n "${SHAREDIR:=/usr/share/shorewall}" ] @@ -813,6 +813,7 @@ determine_capabilities() { KLUDGEFREE= MARK= XMARK= + EXMARK= MANGLE_FORWARD= COMMENTS= ADDRTYPE= @@ -914,6 +915,7 @@ determine_capabilities() { if qt $IPTABLES -t mangle -A $chain -j MARK --set-mark 1; then MARK=Yes qt $IPTABLES -t mangle -A $chain -j MARK --and-mark 0xFF && XMARK=Yes + qt $IPTABLES -t mangle -A $chain -j MARK --set-mark 1/0xFF && EXMARK=Yes fi if qt $IPTABLES -t mangle -A $chain -j CONNMARK --save-mark; then @@ -1011,6 +1013,7 @@ report_capabilities() { report_capability "Repeat match" $KLUDGEFREE report_capability "MARK Target" $MARK [ -n "$MARK" ] && report_capability "Extended MARK Target" $XMARK + [ -n "$XMARK" ] && report_capability "Extended MARK Target 2" $EXMARK report_capability "Mangle FORWARD Chain" $MANGLE_FORWARD report_capability "Comments" $COMMENTS report_capability "Address Type Match" $ADDRTYPE @@ -1070,6 +1073,7 @@ report_capabilities1() { report_capability1 KLUDGEFREE report_capability1 MARK report_capability1 XMARK + report_capability1 EXMARK report_capability1 MANGLE_FORWARD report_capability1 COMMENTS report_capability1 ADDRTYPE diff --git a/Shorewall6/lib.base b/Shorewall6/lib.base index a82c5bef5..f309e6bdc 100644 --- a/Shorewall6/lib.base +++ b/Shorewall6/lib.base @@ -4,7 +4,7 @@ # # This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt] # -# (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 - Tom Eastep (teastep@shorewall.net) +# (c) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 - Tom Eastep (teastep@shorewall.net) # # Complete documentation is available at http://shorewall.net # @@ -33,7 +33,7 @@ # SHOREWALL_LIBVERSION=40406 -SHOREWALL_CAPVERSION=40406 +SHOREWALL_CAPVERSION=40407 [ -n "${VARDIR:=/var/lib/shorewall6}" ] [ -n "${SHAREDIR:=/usr/share/shorewall6}" ] @@ -722,6 +722,7 @@ determine_capabilities() { KLUDGEFREE= MARK= XMARK= + EXMARK= MANGLE_FORWARD= COMMENTS= ADDRTYPE= @@ -746,7 +747,7 @@ determine_capabilities() { fi qt $IP6TABLES -t mangle -L -n && MANGLE_ENABLED=Yes || MANGLE_ENABLED= - + qt $IP6TABLES -F $chain qt $IP6TABLES -X $chain if ! $IP6TABLES -N $chain; then @@ -822,6 +823,7 @@ determine_capabilities() { if qt $IP6TABLES -t mangle -A $chain -j MARK --set-mark 1; then MARK=Yes qt $IP6TABLES -t mangle -A $chain -j MARK --and-mark 0xFF && XMARK=Yes + qt $IP6TABLES -t mangle -A $chain -j MARK --set-mark 1/0xFF && EXMARK=Yes fi if qt $IP6TABLES -t mangle -A $chain -j CONNMARK --save-mark; then @@ -917,6 +919,7 @@ report_capabilities() { report_capability "Repeat match" $KLUDGEFREE report_capability "MARK Target" $MARK [ -n "$MARK" ] && report_capability "Extended MARK Target" $XMARK + [ -n "$XMARK" ] && report_capability "Extended MARK Target 2" $EXMARK report_capability "Mangle FORWARD Chain" $MANGLE_FORWARD report_capability "Comments" $COMMENTS report_capability "Address Type Match" $ADDRTYPE @@ -973,6 +976,7 @@ report_capabilities1() { report_capability1 KLUDGEFREE report_capability1 MARK report_capability1 XMARK + report_capability1 EXMARK report_capability1 MANGLE_FORWARD report_capability1 COMMENTS report_capability1 ADDRTYPE