From 4a9a8534e3500fcc6534ef3e311692e82e2dc380 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Sat, 2 May 2009 16:01:48 -0700 Subject: [PATCH] Finish fast per-IP classifier --- Shorewall/Perl/Shorewall/Tc.pm | 40 ++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Tc.pm b/Shorewall/Perl/Shorewall/Tc.pm index de098b281..5341f8675 100644 --- a/Shorewall/Perl/Shorewall/Tc.pm +++ b/Shorewall/Perl/Shorewall/Tc.pm @@ -616,6 +616,7 @@ sub validate_tc_class( $$$$$$ ) { flow => '' , pfifo => 0, occurs => 1, + src => 1, }; $tcref = $tcref->{$classnumber}; @@ -649,17 +650,18 @@ sub validate_tc_class( $$$$$$ ) { } elsif ( $option eq 'pfifo' ) { fatal_error "The 'pfifo'' option is not allowed with 'flow='" if $tcref->{flow}; $tcref->{pfifo} = 1; - } elsif ( $option =~ /^occurs=(.+)$/ ) { + } elsif ( $option =~ /^occurs=(\d+([ds]?))$/ ) { my $val = $1; $occurs = numeric_value($val); - fatal_error "Invalid 'occurs' ($val)" unless defined $occurs && $occurs > 0; + $tcref->{src} = 0 if $2 eq 'd'; + fatal_error "Invalid 'occurs' ($val)" unless defined $occurs && $occurs > 0 && $occurs <= 256; fatal_error "Invalid 'occurs' ($val)" if $occurs > ( $config{WIDE_TC_MARKS} ? 8191 : 255 ); fatal_error "Duplicate 'occurs'" if $tcref->{occurs} > 1; if ( $occurs > 1 ) { - fatal_error "The 'occurs' option is not valid with 'classify'" if $devref->{classify}; fatal_error "The 'occurs' option is not valid with 'default'" if $devref->{default} == $classnumber; fatal_error "The 'occurs' option is not valid with 'tos'" if @{$tcref->{tos}}; } + $tcref->{occurs} = $occurs; } else { fatal_error "Unknown option ($option)"; } @@ -678,7 +680,7 @@ sub validate_tc_class( $$$$$$ ) { rate => $tcref->{rate} , ceiling => $tcref->{ceiling} , priority => $tcref->{priority} , - mark => ++$markval , + mark => $tcref->{classify} ? 0 : ++$markval , flow => $tcref->{flow} , pfifo => $tcref->{pfifo}, }; @@ -712,7 +714,9 @@ sub process_tc_filter( $$$$$$ ) { $tcref = $tcref->{$classnum}; - fatal_error "Unknown CLASS ($devclass)" unless $tcref; + fatal_error "Unknown CLASS ($devclass)" unless $tcref && $tcref->{occurs}; + + my $occurs = $tcref->{occurs}; my $rule = "filter add dev $device protocol ip parent $devnum:0 prio 10 u32"; @@ -731,15 +735,33 @@ sub process_tc_filter( $$$$$$ ) { unless ( $proto eq '-' ) { $protonumber = resolve_proto $proto; fatal_error "Unknown PROTO ($proto)" unless defined $protonumber; - + fatal_error "PROTO not permitted in this rule" unless $occurs == 1; $rule .= "\\\n match ip protocol $protonumber 0xff" if $protonumber; } if ( $portlist eq '-' && $sportlist eq '-' ) { - emit( "\nrun_tc $rule\\" , - " flowid $devref->{number}:$class" , - '' ); + if ( $occurs == 1 ) { + emit( "\nrun_tc $rule\\" , + " flowid $devref->{number}:$class" , + '' ); + } else { + my $offset = $tcref->{src} ? 12 : 16; + my $tnum = $devref->{tablenumber}++; + my $bucket; + + emit( "\nrun_tc filter add dev $device parent $devnum:0 protocol ip prio 10 handle $tnum: u32 divisor $occurs" ); + + for ( my $i = 0; $i < $occurs; $i++ ) { + $class = in_hexp $classnum++; + $bucket = in_hexp $i; + emit( "run_tc filter add dev $device protocol ip parent $devnum:0 prio 10 u32 ht $tnum:$bucket match u32 0x00000000 0x000000 at 12 flowid $devref->{number}:$class" ); + } + + emit( "\nrun_tc $rule\\", + " link $tnum: hashkey mask ff at $offset\\" ); + } } else { + fatal_error "Ports may not be specified without a PROTO" unless $protonumber; our $lastrule; our $lasttnum; #