On 10/24/2012 07:30 AM, Tom Eastep wrote:
On 10/24/2012 07:22 AM, Jason Wever wrote:
On Wed, Oct 24, 2012 at 10:17 AM, Tom Eastep <[email protected]> wrote:
Sorry -- I missed this last part when I responded earlier. There is
currently no way to use the statistic match for load-balancing over
several SNAT sources; it can only be used in Shorewall to load-balance
between uplinks.

So you will have to add those rules manually in your
/etc/shorewall/start file.

OK I'll take a look there and see what I can come up with.  Thanks for
the prompt response!


Note that the masq file has a MARK column, so it is only the mangle
table rules that you need to add manually.

I'll look at adding a statistic match capability to
/etc/shorewall/tcrules in the next Shorewall release.


Here is a lightly-tested patch.

For Jason's case, his entry in tcrules will be:

1-3:F   10.0.0.1        eth5    ; state=NEW

-Tom
--
Tom Eastep        \ When I die, I want to go like my Grandfather who
Shoreline,         \ died peacefully in his sleep. Not screaming like
Washington, USA     \ all of the passengers in his car
http://shorewall.net \________________________________________________
diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm
index 2c66c22..0d2c7c9 100644
--- a/Shorewall/Perl/Shorewall/Chains.pm
+++ b/Shorewall/Perl/Shorewall/Chains.pm
@@ -117,6 +117,7 @@ our %EXPORT_TAGS = (
 				       OPTIMIZE_RULESET_MASK
 				       OPTIMIZE_MASK
 
+				       state_match
 				       state_imatch
 				       initialize_chain_table
 				       copy_rules
@@ -3715,6 +3716,16 @@ sub port_count( $ ) {
 #
 # Generate a state match
 #
+sub state_match( $ ) {
+    my $state = shift;
+
+    if ( $state eq 'ALL' ) {
+	''
+    } else {
+	have_capability 'CONNTRACK_MATCH' ? ( "-m conntrack --ctstate $state " ) : ( "-m state --state $state " );
+    }
+}
+
 sub state_imatch( $ ) {
     my $state = shift;
 
diff --git a/Shorewall/Perl/Shorewall/Tc.pm b/Shorewall/Perl/Shorewall/Tc.pm
index c85226f..cfbf484 100644
--- a/Shorewall/Perl/Shorewall/Tc.pm
+++ b/Shorewall/Perl/Shorewall/Tc.pm
@@ -174,6 +174,12 @@ my $family;
 
 my $divertref; # DIVERT chain
 
+my %validstates = ( NEW                => 0,
+		    RELATED            => 0,
+		    ESTABLISHED        => 0,
+		    UNTRACKED          => 0,
+		    INVALID            => 0,
+		  );
 #
 # Rather than initializing globals in an INIT block or during declaration,
 # we initialize them in a function. This is done for two reasons:
@@ -199,14 +205,14 @@ sub initialize( $ ) {
 }
 
 sub process_tc_rule( ) {
-    my ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability , $dscp );
+    my ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability , $dscp , $state );
     if ( $family == F_IPV4 ) {
-	( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $probability, $dscp ) =
-	    split_line1 'tcrules file', { mark => 0, action => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, probability => 12 , dscp => 13 }, { COMMENT => 0, FORMAT => 2 } , 14;
+	( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $probability, $dscp, $state ) =
+	    split_line1 'tcrules file', { mark => 0, action => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, probability => 12 , dscp => 13, state => 14 }, { COMMENT => 0, FORMAT => 2 } , 15;
 	$headers = '-';
     } else {
-	( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability, $dscp ) =
-	    split_line1 'tcrules file', { mark => 0, action => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, headers => 12, probability => 13 , dscp => 14 },  { COMMENT => 0, FORMAT => 2 }, 15;
+	( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability, $dscp, $state ) =
+	    split_line1 'tcrules file', { mark => 0, action => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, headers => 12, probability => 13 , dscp => 14 , state => 15 },  { COMMENT => 0, FORMAT => 2 }, 16;
     }
 
     our @tccmd;
@@ -259,6 +265,7 @@ sub process_tc_rule( ) {
     my $cmd;
     my $rest;
     my $matches = '';
+    my $mark1;
 
     my %processtcc = ( sticky => sub() {
 			                  if ( $chain eq 'tcout' ) {
@@ -501,7 +508,7 @@ sub process_tc_rule( ) {
 
 	    $chain    = $tcsref->{chain}                       if $tcsref->{chain};
 	    $target   = $tcsref->{target}                      if $tcsref->{target};
-	    $mark     = "$mark/" . in_hex( $globals{TC_MASK} ) if $connmark = $tcsref->{connmark};
+	    $mark     = "$mark/" . in_hex( $globals{TC_MASK} ) if $connmark = $tcsref->{connmark} && $mark !~ m'/';
 
 	    require_capability ('CONNMARK' , "CONNMARK Rules", '' ) if $connmark;
 
@@ -584,15 +591,23 @@ sub process_tc_rule( ) {
 		}
 	    }
 
-	    validate_mark $mark;
-
-	    if ( $config{PROVIDER_OFFSET} ) {
-		my $val = numeric_value( $cmd );
-		fatal_error "Invalid MARK/CLASSIFY ($cmd)" unless defined $val;
-		my $limit = $globals{TC_MASK};
-		unless ( have_capability 'FWMARK_RT_MASK' ) {
-		    fatal_error "Marks <= $limit may not be set in the PREROUTING or OUTPUT chains when HIGH_ROUTE_MARKS=Yes"
-			if $cmd && ( $chain eq 'tcpre' || $chain eq 'tcout' ) && $val <= $limit;
+	    if ( $mark =~ /-/ ) {
+		( $mark, $mark1 ) = split /-/, $mark, 2;
+		validate_mark $mark;
+		fatal_error "Invalid mark range ($mark-$mark1)" if $mark =~ m'/';
+		validate_mark $mark1;
+		require_capability 'STATISTIC_MATCH', 'A mark range', 's';
+	    }  else {
+		validate_mark $mark;
+
+		if ( $config{PROVIDER_OFFSET} ) {
+		    my $val = numeric_value( $cmd );
+		    fatal_error "Invalid MARK/CLASSIFY ($cmd)" unless defined $val;
+		    my $limit = $globals{TC_MASK};
+		    unless ( have_capability 'FWMARK_RT_MASK' ) {
+			fatal_error "Marks <= $limit may not be set in the PREROUTING or OUTPUT chains when HIGH_ROUTE_MARKS=Yes"
+			    if $cmd && ( $chain eq 'tcpre' || $chain eq 'tcout' ) && $val <= $limit;
+		    }
 		}
 	    }
 	}
@@ -600,26 +615,81 @@ sub process_tc_rule( ) {
 
     fatal_error "USER/GROUP only allowed in the OUTPUT chain" unless ( $user eq '-' || ( $chain eq 'tcout' || $chain eq 'tcpost' ) );
 
-    if ( ( my $result = expand_rule( ensure_chain( 'mangle' , $chain ) ,
-				     $restrictions{$chain} | $restriction,
-				     do_proto( $proto, $ports, $sports) . $matches .
-				     do_user( $user ) .
-				     do_test( $testval, $globals{TC_MASK} ) .
-				     do_length( $length ) .
-				     do_tos( $tos ) .
-				     do_connbytes( $connbytes ) .
-				     do_helper( $helper ) .
-				     do_headers( $headers ) .
-				     do_probability( $probability ) .
-				     do_dscp( $dscp ) ,
-				     $source ,
-				     $dest ,
-				     '' ,
-				     $mark ? "$target $mark" : $target,
-				     '' ,
-				     $target ,
-				     '' ) )
-	  && $device ) {
+    if ( $state ne '-' ) {
+	my @state = split_list( $state, 'state' );
+	my %state = %validstates;
+
+	for ( @state ) {
+	    fatal_error "Invalid STATE ($_)"   unless exists $state{$_};
+	    fatal_error "Duplicate STATE ($_)" if $state{$_};
+	}
+    } else {
+	$state = 'ALL';
+    }
+
+    if ( $mark1 ) {
+	#
+	# A Mark Range
+	#
+	my $chainref = ensure_chain( 'mangle', $chain );
+	
+	( $mark1, my $mask ) = split( '/', $mark1 );
+
+	fatal_error "Invalid mark range ($mark-$mark1)" unless $mark < $mark1;
+
+	$mask = $globals{TC_MASK} unless supplied $mask;
+
+	$mask = in_hex $mask;
+	
+	my $marks = $mark1 - $mark + 1;
+
+	for ( my $packet = 0; $packet < $marks; $packet++, $mark++ ) {
+	    my $match = "-m statistic --mode nth --every $marks --packet $packet ";
+	    my $mrk = in_hex( $mark );
+
+	    expand_rule( $chainref, 
+			 $restrictions{$chain} | $restriction,
+			 $match .
+			 do_user( $user ) .
+			 do_test( $testval, $globals{TC_MASK} ) .
+			 do_test( $testval, $globals{TC_MASK} ) .
+			 do_length( $length ) .
+			 do_tos( $tos ) .
+			 do_connbytes( $connbytes ) .
+			 do_helper( $helper ) .
+			 do_headers( $headers ) .
+			 do_probability( $probability ) .
+			 do_dscp( $dscp ) .
+			 state_match( $state ) ,
+			 $source ,
+			 $dest ,
+			 '' ,
+			 "$target $mrk/$mask" ,
+			 '',
+			 $target ,
+			 '' );
+	}
+    } elsif ( ( my $result = expand_rule( ensure_chain( 'mangle' , $chain ) ,
+					  $restrictions{$chain} | $restriction,
+					  do_proto( $proto, $ports, $sports) . $matches .
+					  do_user( $user ) .
+					  do_test( $testval, $globals{TC_MASK} ) .
+					  do_length( $length ) .
+					  do_tos( $tos ) .
+					  do_connbytes( $connbytes ) .
+					  do_helper( $helper ) .
+					  do_headers( $headers ) .
+					  do_probability( $probability ) .
+					  do_dscp( $dscp ) .
+					  state_match( $state ) ,
+					  $source ,
+					  $dest ,
+					  '' ,
+					  $mark ? "$target $mark" : $target,
+					  '' ,
+					  $target ,
+					  '' ) )
+	      && $device ) {
 	#
 	# expand_rule() returns destination device if any
 	#
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_sfd2d_oct
_______________________________________________
Shorewall-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/shorewall-users

Reply via email to