forked from extern/shorewall_code
Initial working version of IFB support with tc filters
git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@8295 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
parent
1fd17db3ca
commit
6e3469ee89
@ -6,5 +6,5 @@
|
|||||||
# See http://shorewall.net/traffic_shaping.htm for additional information.
|
# See http://shorewall.net/traffic_shaping.htm for additional information.
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#INTERFACE MARK RATE CEIL PRIORITY OPTIONS
|
#INTERFACE:CLASS MARK RATE CEIL PRIORITY OPTIONS
|
||||||
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
|
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
|
||||||
|
@ -6,6 +6,6 @@
|
|||||||
# See http://shorewall.net/traffic_shaping.htm for additional information.
|
# See http://shorewall.net/traffic_shaping.htm for additional information.
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#INTERFACE IN-BANDWITH OUT-BANDWIDTH OPTIONS REDIRECTED
|
#NUMBER: IN-BANDWITH OUT-BANDWIDTH OPTIONS REDIRECTED
|
||||||
# INTERFACES
|
#INTERFACE INTERFACES
|
||||||
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
|
#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE
|
||||||
|
@ -56,6 +56,7 @@ our %EXPORT_TAGS = ( internal => [ qw( create_temp_object
|
|||||||
finalize_object
|
finalize_object
|
||||||
numeric_value
|
numeric_value
|
||||||
in_hex
|
in_hex
|
||||||
|
in_hex8
|
||||||
emit
|
emit
|
||||||
emit_unindented
|
emit_unindented
|
||||||
save_progress_message
|
save_progress_message
|
||||||
@ -528,6 +529,10 @@ sub in_hex( $ ) {
|
|||||||
sprintf '0x%x', $_[0];
|
sprintf '0x%x', $_[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub in_hex8( $ ) {
|
||||||
|
sprintf '0x%08x', $_[0];
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Write the arguments to the object file (if any) with the current indentation.
|
# Write the arguments to the object file (if any) with the current indentation.
|
||||||
#
|
#
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#
|
#
|
||||||
package Shorewall::IPAddrs;
|
package Shorewall::IPAddrs;
|
||||||
require Exporter;
|
require Exporter;
|
||||||
use Shorewall::Config qw( :DEFAULT split_list require_capability );
|
use Shorewall::Config qw( :DEFAULT split_list require_capability in_hex8);
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
|
|
||||||
@ -39,6 +39,7 @@ our @EXPORT = qw( ALLIPv4
|
|||||||
|
|
||||||
validate_address
|
validate_address
|
||||||
validate_net
|
validate_net
|
||||||
|
decompose_net
|
||||||
validate_host
|
validate_host
|
||||||
validate_range
|
validate_range
|
||||||
ip_range_explicit
|
ip_range_explicit
|
||||||
@ -63,6 +64,40 @@ use constant { ALLIPv4 => '0.0.0.0/0' , ICMP => 1, TCP => 6, UDP => 17 , SCTP =>
|
|||||||
|
|
||||||
our @rfc1918_networks = ( "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16" );
|
our @rfc1918_networks = ( "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16" );
|
||||||
|
|
||||||
|
our @vlsm_to_mask = ( '0x00000000' ,
|
||||||
|
'0x80000000' ,
|
||||||
|
'0xC0000000' ,
|
||||||
|
'0xE0000000' ,
|
||||||
|
'0xF0000000' ,
|
||||||
|
'0xF8000000' ,
|
||||||
|
'0xFC000000' ,
|
||||||
|
'0xFE000000' ,
|
||||||
|
'0xFF000000' ,
|
||||||
|
'0xFF800000' ,
|
||||||
|
'0xFFC00000' ,
|
||||||
|
'0xFFE00000' ,
|
||||||
|
'0xFFF00000' ,
|
||||||
|
'0xFFF80000' ,
|
||||||
|
'0xFFFC0000' ,
|
||||||
|
'0xFFFE0000' ,
|
||||||
|
'0xFFFF0000' ,
|
||||||
|
'0xFFFF8000' ,
|
||||||
|
'0xFFFFC000' ,
|
||||||
|
'0xFFFFE000' ,
|
||||||
|
'0xFFFFF000' ,
|
||||||
|
'0xFFFFF800' ,
|
||||||
|
'0xFFFFFC00' ,
|
||||||
|
'0xFFFFFE00' ,
|
||||||
|
'0xFFFFFF00' ,
|
||||||
|
'0xFFFFFF80' ,
|
||||||
|
'0xFFFFFFC0' ,
|
||||||
|
'0xFFFFFFE0' ,
|
||||||
|
'0xFFFFFFF0' ,
|
||||||
|
'0xFFFFFFF8' ,
|
||||||
|
'0xFFFFFFFC' ,
|
||||||
|
'0xFFFFFFFE' ,
|
||||||
|
'0xFFFFFFFF' );
|
||||||
|
|
||||||
sub valid_address( $ ) {
|
sub valid_address( $ ) {
|
||||||
my $address = $_[0];
|
my $address = $_[0];
|
||||||
|
|
||||||
@ -96,23 +131,6 @@ sub validate_address( $$ ) {
|
|||||||
defined wantarray ? wantarray ? @addrs : $addrs[0] : undef;
|
defined wantarray ? wantarray ? @addrs : $addrs[0] : undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub validate_net( $$ ) {
|
|
||||||
my ($net, $vlsm, $rest) = split( '/', $_[0], 3 );
|
|
||||||
my $allow_name = $_[1];
|
|
||||||
|
|
||||||
fatal_error "Missing address" if $net eq '';
|
|
||||||
fatal_error "An ipset name ($net) is not allowed in this context" if substr( $net, 0, 1 ) eq '+';
|
|
||||||
|
|
||||||
if ( defined $vlsm ) {
|
|
||||||
fatal_error "Invalid VLSM ($vlsm)" unless $vlsm =~ /^\d+$/ && $vlsm <= 32;
|
|
||||||
fatal_error "Invalid Network address ($_[0])" if defined $rest;
|
|
||||||
fatal_error "Invalid IP address ($net)" unless valid_address $net;
|
|
||||||
} else {
|
|
||||||
fatal_error "Invalid Network address ($_[0])" if $_[0] =~ '/' || ! defined $net;
|
|
||||||
validate_address $net, $_[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub decodeaddr( $ ) {
|
sub decodeaddr( $ ) {
|
||||||
my $address = $_[0];
|
my $address = $_[0];
|
||||||
|
|
||||||
@ -139,6 +157,33 @@ sub encodeaddr( $ ) {
|
|||||||
$result;
|
$result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub validate_net( $$ ) {
|
||||||
|
my ($net, $vlsm, $rest) = split( '/', $_[0], 3 );
|
||||||
|
my $allow_name = $_[1];
|
||||||
|
|
||||||
|
fatal_error "Missing address" if $net eq '';
|
||||||
|
fatal_error "An ipset name ($net) is not allowed in this context" if substr( $net, 0, 1 ) eq '+';
|
||||||
|
|
||||||
|
if ( defined $vlsm ) {
|
||||||
|
fatal_error "Invalid VLSM ($vlsm)" unless $vlsm =~ /^\d+$/ && $vlsm <= 32;
|
||||||
|
fatal_error "Invalid Network address ($_[0])" if defined $rest;
|
||||||
|
fatal_error "Invalid IP address ($net)" unless valid_address $net;
|
||||||
|
} else {
|
||||||
|
fatal_error "Invalid Network address ($_[0])" if $_[0] =~ '/' || ! defined $net;
|
||||||
|
validate_address $net, $_[1];
|
||||||
|
$vlsm = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( defined wantarray ) {
|
||||||
|
fatal_error "Internal Error in validate_net()" if $allow_name;
|
||||||
|
if ( wantarray ) {
|
||||||
|
( decodeaddr( $net ) , $vlsm );
|
||||||
|
} else {
|
||||||
|
"$net/$vlsm";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub validate_range( $$ ) {
|
sub validate_range( $$ ) {
|
||||||
my ( $low, $high ) = @_;
|
my ( $low, $high ) = @_;
|
||||||
|
|
||||||
@ -178,6 +223,17 @@ sub ip_range_explicit( $ ) {
|
|||||||
@result;
|
@result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub decompose_net( $ ) {
|
||||||
|
my $net = $_[0];
|
||||||
|
|
||||||
|
return ( qw/0x00000000 0x00000000/ ) if $net eq '-';
|
||||||
|
|
||||||
|
( $net, my $vlsm ) = validate_net( $net , 0 );
|
||||||
|
|
||||||
|
( in_hex8( $net ) , $vlsm_to_mask[ $vlsm ] );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
sub validate_host( $$ ) {
|
sub validate_host( $$ ) {
|
||||||
my ( $host, $allow_name ) = $_[0];
|
my ( $host, $allow_name ) = $_[0];
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
package Shorewall::Tc;
|
package Shorewall::Tc;
|
||||||
require Exporter;
|
require Exporter;
|
||||||
use Shorewall::Config qw(:DEFAULT :internal);
|
use Shorewall::Config qw(:DEFAULT :internal);
|
||||||
|
use Shorewall::IPAddrs;
|
||||||
use Shorewall::Zones;
|
use Shorewall::Zones;
|
||||||
use Shorewall::Chains qw(:DEFAULT :internal);
|
use Shorewall::Chains qw(:DEFAULT :internal);
|
||||||
use Shorewall::Providers;
|
use Shorewall::Providers;
|
||||||
@ -119,17 +120,21 @@ our @deferred_rules;
|
|||||||
#
|
#
|
||||||
# %tcdevices { <interface> -> {in_bandwidth => <value> ,
|
# %tcdevices { <interface> -> {in_bandwidth => <value> ,
|
||||||
# out_bandwidth => <value> ,
|
# out_bandwidth => <value> ,
|
||||||
# number => <ordinal> ,
|
# number => <number>,
|
||||||
# default => <default class mark value> }
|
# default => <default class mark value> }
|
||||||
#
|
#
|
||||||
our @tcdevices;
|
our @tcdevices;
|
||||||
our %tcdevices;
|
our %tcdevices;
|
||||||
|
our @devnums;
|
||||||
|
our $devnum;
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# TCClasses Table
|
# TCClasses Table
|
||||||
#
|
#
|
||||||
# %tcclasses { device => <device> ,
|
# %tcclasses { device => <device> ,
|
||||||
# mark => <mark> ,
|
# mark => <mark> ,
|
||||||
|
# number => <number> ,
|
||||||
# rate => <rate> ,
|
# rate => <rate> ,
|
||||||
# ceiling => <ceiling> ,
|
# ceiling => <ceiling> ,
|
||||||
# priority => <priority> ,
|
# priority => <priority> ,
|
||||||
@ -141,8 +146,6 @@ our %tcdevices;
|
|||||||
our @tcclasses;
|
our @tcclasses;
|
||||||
our %tcclasses;
|
our %tcclasses;
|
||||||
|
|
||||||
our $prefix;
|
|
||||||
|
|
||||||
our %restrictions = ( tcpre => PREROUTE_RESTRICT ,
|
our %restrictions = ( tcpre => PREROUTE_RESTRICT ,
|
||||||
tcpost => POSTROUTE_RESTRICT ,
|
tcpost => POSTROUTE_RESTRICT ,
|
||||||
tcfor => NO_RESTRICT ,
|
tcfor => NO_RESTRICT ,
|
||||||
@ -163,7 +166,8 @@ sub initialize() {
|
|||||||
%tcdevices = ();
|
%tcdevices = ();
|
||||||
@tcclasses = ();
|
@tcclasses = ();
|
||||||
%tcclasses = ();
|
%tcclasses = ();
|
||||||
$prefix = '1';
|
@devnums = ();
|
||||||
|
$devnum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT {
|
INIT {
|
||||||
@ -321,8 +325,29 @@ sub calculate_quantum( $$ ) {
|
|||||||
sub validate_tc_device( $$$$$ ) {
|
sub validate_tc_device( $$$$$ ) {
|
||||||
my ( $device, $inband, $outband , $options , $redirected ) = @_;
|
my ( $device, $inband, $outband , $options , $redirected ) = @_;
|
||||||
|
|
||||||
fatal_error "Duplicate device ($device)" if $tcdevices{$device};
|
my $devnumber;
|
||||||
fatal_error "Invalid device name ($device)" if $device =~ /[:+]/;
|
|
||||||
|
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 = numeric_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;
|
||||||
|
|
||||||
|
fatal_error "Duplicate INTERFACE ($device)" if $tcdevices{$device};
|
||||||
|
fatal_error "Invalid INTERFACE name ($device)" if $device =~ /[:+]/;
|
||||||
|
|
||||||
my $classify = 0;
|
my $classify = 0;
|
||||||
|
|
||||||
@ -336,24 +361,20 @@ sub validate_tc_device( $$$$$ ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$inband = rate_to_kbit( $inband );
|
|
||||||
|
|
||||||
my @redirected = ();
|
my @redirected = ();
|
||||||
|
|
||||||
@redirected = split_list( $redirected , 'device' ) if defined $redirected && $redirected ne '-';
|
@redirected = split_list( $redirected , 'device' ) if defined $redirected && $redirected ne '-';
|
||||||
|
|
||||||
fatal_error "IN-BANDWIDTH must be zero for IFB devides" if @redirected && $inband;
|
|
||||||
|
|
||||||
for my $rdevice ( @redirected ) {
|
for my $rdevice ( @redirected ) {
|
||||||
fatal_error "Invalid device name ($rdevice)" if $rdevice =~ /[:+]/;
|
fatal_error "Invalid device name ($rdevice)" if $rdevice =~ /[:+]/;
|
||||||
my $rdevref = $tcdevices{$rdevice};
|
my $rdevref = $tcdevices{$rdevice};
|
||||||
fatal_error "REDIRECTED device ($rdevice) has not been defined in this file" unless $rdevref;
|
fatal_error "REDIRECTED device ($rdevice) has not been defined in this file" unless $rdevref;
|
||||||
fatal_error "IN-BANDWIDTH must be zero for REDIRECTED devices" if $rdevref->{in_bandwidth} ne '0kbit';
|
fatal_error "IN-BANDWIDTH must be zero for REDIRECTED devices" if $rdevref->{in_bandwidth} ne '0kbit';
|
||||||
fatal_error "IFB may not be redirected" if @{$rdevref->{redirected}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$tcdevices{$device} = { in_bandwidth => $inband . 'kbit' ,
|
$tcdevices{$device} = { in_bandwidth => rate_to_kbit( $inband ) . 'kbit' ,
|
||||||
out_bandwidth => rate_to_kbit( $outband ) . 'kbit' ,
|
out_bandwidth => rate_to_kbit( $outband ) . 'kbit' ,
|
||||||
|
number => $devnumber,
|
||||||
classify => $classify ,
|
classify => $classify ,
|
||||||
redirected => \@redirected };
|
redirected => \@redirected };
|
||||||
|
|
||||||
@ -375,8 +396,27 @@ sub convert_rate( $$ ) {
|
|||||||
"${rate}kbit";
|
"${rate}kbit";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub dev_by_number( $ ) {
|
||||||
|
my $dev = $_[0];
|
||||||
|
my $devnum = numeric_value( $dev );
|
||||||
|
my $devref;
|
||||||
|
|
||||||
|
if ( defined $devnum ) {
|
||||||
|
$dev = $devnums[ $devnum ];
|
||||||
|
fatal_error "Undefined INTERFACE number ($_[0])" unless defined $dev;
|
||||||
|
$devref = $tcdevices{$dev};
|
||||||
|
fatal_error "Internal Error in dev_by_number()" unless $devref;
|
||||||
|
} else {
|
||||||
|
$devref = $tcdevices{$dev};
|
||||||
|
fatal_error "Unknown INTERFACE ($dev)" unless $devref;
|
||||||
|
}
|
||||||
|
|
||||||
|
( $dev , $devref );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
sub validate_tc_class( $$$$$$ ) {
|
sub validate_tc_class( $$$$$$ ) {
|
||||||
my ( $device, $mark, $rate, $ceil, $prio, $options ) = @_;
|
my ( $devclass, $mark, $rate, $ceil, $prio, $options ) = @_;
|
||||||
|
|
||||||
my %tosoptions = ( 'tos-minimize-delay' => 'tos=0x10/0x10' ,
|
my %tosoptions = ( 'tos-minimize-delay' => 'tos=0x10/0x10' ,
|
||||||
'tos-maximize-throughput' => 'tos=0x08/0x08' ,
|
'tos-maximize-throughput' => 'tos=0x08/0x08' ,
|
||||||
@ -384,25 +424,61 @@ sub validate_tc_class( $$$$$$ ) {
|
|||||||
'tos-minimize-cost' => 'tos=0x02/0x02' ,
|
'tos-minimize-cost' => 'tos=0x02/0x02' ,
|
||||||
'tos-normal-service' => 'tos=0x00/0x1e' );
|
'tos-normal-service' => 'tos=0x00/0x1e' );
|
||||||
|
|
||||||
my $devref = $tcdevices{$device};
|
my $classnumber = 0;
|
||||||
fatal_error "Unknown Device ($device)" unless $devref;
|
my $devref;
|
||||||
|
my $device = $devclass;
|
||||||
|
|
||||||
|
if ( $devclass =~ /:/ ) {
|
||||||
|
( $device, my ($number, $rest ) ) = split /:/, $device, 3;
|
||||||
|
fatal_error "Invalid INTERFACE:CLASS ($devclass)" if defined $rest;
|
||||||
|
|
||||||
|
( $device , $devref) = dev_by_number( $device );
|
||||||
|
|
||||||
|
if ( defined $number ) {
|
||||||
|
if ( $devref->{classify} ) {
|
||||||
|
$classnumber = numeric_value( $number );
|
||||||
|
fatal_error "Invalid interface NUMBER ($number)" unless defined $classnumber && $classnumber;
|
||||||
|
fatal_error "Duplicate interface/class number ($number)" if defined $devnums[ $classnumber ];
|
||||||
|
} else {
|
||||||
|
warning_message "Class NUMBER ignored -- INTERFACE $device does not have the 'classify' option";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fatal_error "Missing interface NUMBER";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
($device, $devref ) = dev_by_number( $device );
|
||||||
|
fatal_error "Missing class NUMBER" if $devref->{classify};
|
||||||
|
}
|
||||||
|
|
||||||
my $full = rate_to_kbit $devref->{out_bandwidth};
|
my $full = rate_to_kbit $devref->{out_bandwidth};
|
||||||
|
|
||||||
$tcclasses{$device} = {} unless $tcclasses{$device};
|
$tcclasses{$device} = {} unless $tcclasses{$device};
|
||||||
my $tcref = $tcclasses{$device};
|
my $tcref = $tcclasses{$device};
|
||||||
|
|
||||||
|
my $markval;
|
||||||
|
|
||||||
fatal_error "Invalid Mark ($mark)" unless $mark =~ /^([0-9]+|0x[0-9a-f]+)$/ && numeric_value( $mark ) <= 0xff;
|
if ( $mark ne '-' ) {
|
||||||
|
if ( $devref->{classify} ) {
|
||||||
|
warning_message "INTERFACE $device has the 'classify' option - MARK value ($mark) ignored";
|
||||||
|
} else {
|
||||||
|
fatal_error "Invalid Mark ($mark)" unless $mark =~ /^([0-9]+|0x[0-9a-f]+)$/ && numeric_value( $mark ) <= 0xff;
|
||||||
|
|
||||||
my $markval = numeric_value( $mark );
|
$markval = numeric_value( $mark );
|
||||||
fatal_error "Duplicate Mark ($mark)" if $tcref->{$markval};
|
fatal_error "Duplicate MARK ($mark)" if $tcref->{$classnumber};
|
||||||
|
$classnumber = $devnum + $mark;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fatal_error "Missing MARK" unless $devref->{classify};
|
||||||
|
fatal_error "Duplicate Class NUMBER ($classnumber)" if $tcref->{$classnumber};
|
||||||
|
}
|
||||||
|
|
||||||
$tcref->{$markval} = { tos => [] ,
|
$tcref->{$classnumber} = { tos => [] ,
|
||||||
rate => convert_rate( $full, $rate ) ,
|
rate => convert_rate( $full, $rate ) ,
|
||||||
ceiling => convert_rate( $full, $ceil ) ,
|
ceiling => convert_rate( $full, $ceil ) ,
|
||||||
priority => $prio eq '-' ? 1 : $prio
|
priority => $prio eq '-' ? 1 : $prio
|
||||||
};
|
};
|
||||||
|
|
||||||
$tcref = $tcref->{$markval};
|
$tcref = $tcref->{$classnumber};
|
||||||
|
|
||||||
unless ( $options eq '-' ) {
|
unless ( $options eq '-' ) {
|
||||||
for my $option ( split_list "\L$options", 'option' ) {
|
for my $option ( split_list "\L$options", 'option' ) {
|
||||||
@ -412,7 +488,7 @@ sub validate_tc_class( $$$$$$ ) {
|
|||||||
|
|
||||||
if ( $option eq 'default' ) {
|
if ( $option eq 'default' ) {
|
||||||
fatal_error "Only one default class may be specified for device $device" if $devref->{default};
|
fatal_error "Only one default class may be specified for device $device" if $devref->{default};
|
||||||
$devref->{default} = $markval;
|
$devref->{default} = $classnumber;
|
||||||
} elsif ( $option eq 'tcp-ack' ) {
|
} elsif ( $option eq 'tcp-ack' ) {
|
||||||
$tcref->{tcp_ack} = 1;
|
$tcref->{tcp_ack} = 1;
|
||||||
} elsif ( $option =~ /^tos=0x[0-9a-f]{2}$/ ) {
|
} elsif ( $option =~ /^tos=0x[0-9a-f]{2}$/ ) {
|
||||||
@ -427,10 +503,71 @@ sub validate_tc_class( $$$$$$ ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
push @tcclasses, "$device:$markval";
|
push @tcclasses, "$device:$classnumber";
|
||||||
progress_message " Tcclass \"$currentline\" $done.";
|
progress_message " Tcclass \"$currentline\" $done.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub process_tc_filter( $$$$$$ ) {
|
||||||
|
my ($devclass , $source, $dest , $proto, $port , $sport ) = @_;
|
||||||
|
|
||||||
|
my ($device, $class, $rest ) = split /:/, $devclass, 3;
|
||||||
|
|
||||||
|
fatal_error "Invalid INTERFACE:CLASS ($devclass)" if defined $rest || ! ($device && $class );
|
||||||
|
|
||||||
|
( $device , my $devref ) = dev_by_number( $device );
|
||||||
|
|
||||||
|
my $tcref = $tcclasses{$device};
|
||||||
|
|
||||||
|
fatal_error "No Classes were defined for INTERFACE $device" unless $tcref;
|
||||||
|
|
||||||
|
$tcref = $tcref->{$class};
|
||||||
|
|
||||||
|
fatal_error "Unknown CLASS ($class)" unless $tcref;
|
||||||
|
|
||||||
|
my $rule = "filter add dev $device protocol ip parent $devref->{number}:0 pref 10 u32";
|
||||||
|
|
||||||
|
my ( $net , $mask ) = decompose_net( $source );
|
||||||
|
|
||||||
|
$rule .= "\\\n match u32 $net $mask at 12" unless $mask eq '0x00000000';
|
||||||
|
|
||||||
|
( $net , $mask ) = decompose_net( $dest );
|
||||||
|
|
||||||
|
$rule .= "\\\n match u32 $net $mask at 16" unless $mask eq '0x00000000';
|
||||||
|
|
||||||
|
my $protonumber = 0;
|
||||||
|
|
||||||
|
unless ( $proto eq '-' ) {
|
||||||
|
$protonumber = resolve_proto $proto;
|
||||||
|
fatal_error "Unknown PROTO ($proto)" unless defined $protonumber;
|
||||||
|
|
||||||
|
$rule .= "\\\n match u8 $protonumber 0xFF at 9";
|
||||||
|
}
|
||||||
|
|
||||||
|
unless ( $port eq '-' ) {
|
||||||
|
fatal_error "Only TCP, UDP and SCTP may specify DEST PORT"
|
||||||
|
unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP;
|
||||||
|
my $portnumber = in_hex8 validate_port( $protonumber , $port );
|
||||||
|
|
||||||
|
$rule .= "\\\n match u32 $portnumber 0x0000ffff at nexthdr+0";
|
||||||
|
}
|
||||||
|
|
||||||
|
unless ( $sport eq '-' ) {
|
||||||
|
fatal_error "Only TCP, UDP and SCTP may specify SOURCE PORT"
|
||||||
|
unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP;
|
||||||
|
my $portnumber = in_hex8 validate_port( $protonumber , $sport );
|
||||||
|
|
||||||
|
$portnumber =~ s/0x0000/0x/;
|
||||||
|
|
||||||
|
$rule .= "\\\n match u32 ${portnumber}0000 0xffff0000 at nexthdr+0";
|
||||||
|
}
|
||||||
|
|
||||||
|
emit( "run_tc $rule\\" ,
|
||||||
|
" flowid $devref->{number}:$class" ,
|
||||||
|
'' );
|
||||||
|
|
||||||
|
progress_message " TC Filter \"$currentline\" $done";
|
||||||
|
}
|
||||||
|
|
||||||
sub setup_traffic_shaping() {
|
sub setup_traffic_shaping() {
|
||||||
save_progress_message "Setting up Traffic Control...";
|
save_progress_message "Setting up Traffic Control...";
|
||||||
|
|
||||||
@ -448,6 +585,8 @@ sub setup_traffic_shaping() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$devnum = $devnum > 10 ? 1000 : 100;
|
||||||
|
|
||||||
$fn = open_file 'tcclasses';
|
$fn = open_file 'tcclasses';
|
||||||
|
|
||||||
if ( $fn ) {
|
if ( $fn ) {
|
||||||
@ -461,16 +600,11 @@ sub setup_traffic_shaping() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my $devnum = 1;
|
|
||||||
|
|
||||||
$prefix = '10' if @tcdevices > 10;
|
|
||||||
|
|
||||||
for my $device ( @tcdevices ) {
|
for my $device ( @tcdevices ) {
|
||||||
my $dev = chain_base( $device );
|
my $dev = chain_base( $device );
|
||||||
my $devref = $tcdevices{$device};
|
my $devref = $tcdevices{$device};
|
||||||
my $defmark = $devref->{default} || 0;
|
my $defmark = $devref->{default} || 0;
|
||||||
|
my $devnum = $devref->{number};
|
||||||
$defmark = "${prefix}${defmark}" if $defmark;
|
|
||||||
|
|
||||||
emit "if interface_is_up $device; then";
|
emit "if interface_is_up $device; then";
|
||||||
|
|
||||||
@ -491,15 +625,14 @@ sub setup_traffic_shaping() {
|
|||||||
emit ( "run_tc qdisc add dev $device handle ffff: ingress",
|
emit ( "run_tc qdisc add dev $device handle ffff: ingress",
|
||||||
"run_tc filter add dev $device parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${inband}kbit burst 10k drop flowid :1"
|
"run_tc filter add dev $device parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${inband}kbit burst 10k drop flowid :1"
|
||||||
);
|
);
|
||||||
|
} elsif ( @{$devref->{redirected}} ) {
|
||||||
|
emit ( "run_tc qdisc add dev $device handle ffff: ingress" );
|
||||||
}
|
}
|
||||||
|
|
||||||
for my $rdev ( @{$devref->{redirected}} ) {
|
for my $rdev ( @{$devref->{redirected}} ) {
|
||||||
emit ( "run_tc qdisc add dev $rdev handle ffff: ingress" );
|
|
||||||
emit( "run_tc filter add dev $rdev parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $device" );
|
emit( "run_tc filter add dev $rdev parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $device" );
|
||||||
}
|
}
|
||||||
|
|
||||||
$devref->{number} = $devnum++;
|
|
||||||
|
|
||||||
save_progress_message_short " TC Device $device defined.";
|
save_progress_message_short " TC Device $device defined.";
|
||||||
|
|
||||||
pop_indent;
|
pop_indent;
|
||||||
@ -518,8 +651,8 @@ sub setup_traffic_shaping() {
|
|||||||
my ( $device, $mark ) = split /:/, $class;
|
my ( $device, $mark ) = split /:/, $class;
|
||||||
my $devref = $tcdevices{$device};
|
my $devref = $tcdevices{$device};
|
||||||
my $tcref = $tcclasses{$device}{$mark};
|
my $tcref = $tcclasses{$device}{$mark};
|
||||||
my $devnum = $devref->{number};
|
my $devicenumber = $devref->{number};
|
||||||
my $classid = join( '', $devnum, ':', $prefix, $mark);
|
my $classid = join( '', $devicenumber, ':', $mark);
|
||||||
my $rate = $tcref->{rate};
|
my $rate = $tcref->{rate};
|
||||||
my $quantum = calculate_quantum $rate, calculate_r2q( $devref->{out_bandwidth} );
|
my $quantum = calculate_quantum $rate, calculate_r2q( $devref->{out_bandwidth} );
|
||||||
my $dev = chain_base $device;
|
my $dev = chain_base $device;
|
||||||
@ -539,12 +672,12 @@ sub setup_traffic_shaping() {
|
|||||||
|
|
||||||
emit ( "[ \$${dev}_mtu -gt $quantum ] && quantum=\$${dev}_mtu || quantum=$quantum",
|
emit ( "[ \$${dev}_mtu -gt $quantum ] && quantum=\$${dev}_mtu || quantum=$quantum",
|
||||||
"run_tc class add dev $device parent $devref->{number}:1 classid $classid htb rate $rate ceil $tcref->{ceiling} prio $tcref->{priority} \$${dev}_mtu1 quantum \$quantum",
|
"run_tc class add dev $device parent $devref->{number}:1 classid $classid htb rate $rate ceil $tcref->{ceiling} prio $tcref->{priority} \$${dev}_mtu1 quantum \$quantum",
|
||||||
"run_tc qdisc add dev $device parent $classid handle ${prefix}${mark}: sfq perturb 10"
|
"run_tc qdisc add dev $device parent $classid handle ${mark}: sfq perturb 10"
|
||||||
);
|
);
|
||||||
#
|
#
|
||||||
# add filters
|
# add filters
|
||||||
#
|
#
|
||||||
emit "run_tc filter add dev $device protocol ip parent $devnum:0 prio 1 handle $mark fw classid $classid" unless $devref->{classify};
|
emit "run_tc filter add dev $device protocol ip parent $devicenumber:0 prio 1 handle $mark fw classid $classid" unless $devref->{classify};
|
||||||
#
|
#
|
||||||
#options
|
#options
|
||||||
#
|
#
|
||||||
@ -552,7 +685,7 @@ sub setup_traffic_shaping() {
|
|||||||
|
|
||||||
for my $tospair ( @{$tcref->{tos}} ) {
|
for my $tospair ( @{$tcref->{tos}} ) {
|
||||||
my ( $tos, $mask ) = split q(/), $tospair;
|
my ( $tos, $mask ) = split q(/), $tospair;
|
||||||
emit "run_tc filter add dev $device parent $devnum:0 protocol ip prio 10 u32 match ip tos $tos $mask flowid $classid";
|
emit "run_tc filter add dev $device parent $devicenumber:0 protocol ip prio 10 u32 match ip tos $tos $mask flowid $classid";
|
||||||
}
|
}
|
||||||
|
|
||||||
save_progress_message_short qq(" TC Class $class defined.");
|
save_progress_message_short qq(" TC Class $class defined.");
|
||||||
@ -563,6 +696,19 @@ sub setup_traffic_shaping() {
|
|||||||
pop_indent;
|
pop_indent;
|
||||||
emit "fi\n";
|
emit "fi\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$fn = open_file 'tcfilters';
|
||||||
|
|
||||||
|
if ( $fn ) {
|
||||||
|
first_entry "$doing $fn...";
|
||||||
|
|
||||||
|
while ( read_a_line ) {
|
||||||
|
|
||||||
|
my ( $devclass, $source, $dest, $proto, $port, $sport ) = split_line 2, 6, 'tcfilters file';
|
||||||
|
|
||||||
|
process_tc_filter( $devclass, $source, $dest, $proto, $port, $sport );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user