forked from extern/shorewall_code
Implement 'load=<load-factor>' in providers file.
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
531474592c
commit
7316a2c51a
@ -138,6 +138,7 @@ our %EXPORT_TAGS = (
|
|||||||
snat_chain
|
snat_chain
|
||||||
ecn_chain
|
ecn_chain
|
||||||
notrack_chain
|
notrack_chain
|
||||||
|
load_chain
|
||||||
first_chains
|
first_chains
|
||||||
option_chains
|
option_chains
|
||||||
reserved_name
|
reserved_name
|
||||||
@ -666,11 +667,19 @@ sub set_rule_option( $$$ ) {
|
|||||||
my $opttype = $opttype{$option} || MATCH;
|
my $opttype = $opttype{$option} || MATCH;
|
||||||
|
|
||||||
if ( exists $ruleref->{$option} ) {
|
if ( exists $ruleref->{$option} ) {
|
||||||
assert( defined $ruleref->{$option} );
|
assert( defined( my $value1 = $ruleref->{$option} ) );
|
||||||
|
|
||||||
if ( $opttype == MATCH ) {
|
if ( $opttype == MATCH ) {
|
||||||
assert( $globals{KLUDGEFREE} );
|
assert( $globals{KLUDGEFREE} );
|
||||||
$ruleref->{$option} = [ $ruleref->{$option} ] unless reftype $ruleref->{$option};
|
|
||||||
|
unless ( reftype $value1 ) {
|
||||||
|
unless ( reftype $value ) {
|
||||||
|
return if $value1 eq $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ruleref->{$option} = [ $ruleref->{$option} ];
|
||||||
|
}
|
||||||
|
|
||||||
push @{$ruleref->{$option}}, ( reftype $value ? @$value : $value );
|
push @{$ruleref->{$option}}, ( reftype $value ? @$value : $value );
|
||||||
} elsif ( $opttype == EXCLUSIVE ) {
|
} elsif ( $opttype == EXCLUSIVE ) {
|
||||||
$ruleref->{$option} .= ",$value";
|
$ruleref->{$option} .= ",$value";
|
||||||
@ -1775,6 +1784,13 @@ sub notrack_chain( $ )
|
|||||||
$_[0] . '_notrk';
|
$_[0] . '_notrk';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Load Chain for a provider
|
||||||
|
#
|
||||||
|
sub load_chain( $ ) {
|
||||||
|
'~' . $_[0];
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# SNAT Chain to an interface
|
# SNAT Chain to an interface
|
||||||
#
|
#
|
||||||
|
@ -53,6 +53,7 @@ my @routemarked_providers;
|
|||||||
my %routemarked_interfaces;
|
my %routemarked_interfaces;
|
||||||
our @routemarked_interfaces;
|
our @routemarked_interfaces;
|
||||||
my %provider_interfaces;
|
my %provider_interfaces;
|
||||||
|
my @load_providers;
|
||||||
|
|
||||||
my $balancing;
|
my $balancing;
|
||||||
my $fallback;
|
my $fallback;
|
||||||
@ -86,6 +87,7 @@ sub initialize( $ ) {
|
|||||||
%routemarked_interfaces = ();
|
%routemarked_interfaces = ();
|
||||||
@routemarked_interfaces = ();
|
@routemarked_interfaces = ();
|
||||||
%provider_interfaces = ();
|
%provider_interfaces = ();
|
||||||
|
@load_providers = ();
|
||||||
$balancing = 0;
|
$balancing = 0;
|
||||||
$fallback = 0;
|
$fallback = 0;
|
||||||
$first_default_route = 1;
|
$first_default_route = 1;
|
||||||
@ -110,6 +112,8 @@ sub setup_route_marking() {
|
|||||||
add_ijump $mangle_table->{$_} , j => 'CONNMARK', targetopts => "--restore-mark --mask $mask", connmark => "! --mark 0/$mask" for qw/PREROUTING OUTPUT/;
|
add_ijump $mangle_table->{$_} , j => 'CONNMARK', targetopts => "--restore-mark --mask $mask", connmark => "! --mark 0/$mask" for qw/PREROUTING OUTPUT/;
|
||||||
|
|
||||||
my $chainref = new_chain 'mangle', 'routemark';
|
my $chainref = new_chain 'mangle', 'routemark';
|
||||||
|
|
||||||
|
if ( @routemarked_providers ) {
|
||||||
my $chainref1 = new_chain 'mangle', 'setsticky';
|
my $chainref1 = new_chain 'mangle', 'setsticky';
|
||||||
my $chainref2 = new_chain 'mangle', 'setsticko';
|
my $chainref2 = new_chain 'mangle', 'setsticko';
|
||||||
|
|
||||||
@ -137,6 +141,43 @@ sub setup_route_marking() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
add_ijump $chainref, j => 'CONNMARK', targetopts => "--save-mark --mask $mask", mark => "! --mark 0/$mask";
|
add_ijump $chainref, j => 'CONNMARK', targetopts => "--save-mark --mask $mask", mark => "! --mark 0/$mask";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( @load_providers ) {
|
||||||
|
my $chainref1 = new_chain 'mangle', 'balance';
|
||||||
|
my @match;
|
||||||
|
|
||||||
|
add_ijump $chainref, g => $chainref1, mark => "--mark 0/$mask";
|
||||||
|
add_ijump $mangle_table->{OUTPUT}, j => $chainref1, state_imatch( 'NEW,RELATED' ), mark => "--mark 0/$mask";
|
||||||
|
|
||||||
|
for my $providerref ( @load_providers ) {
|
||||||
|
|
||||||
|
my $chainref2 = new_chain( 'mangle', load_chain( $providerref->{provider} ) );
|
||||||
|
|
||||||
|
dont_optimize $chainref2;
|
||||||
|
dont_move $chainref2;
|
||||||
|
dont_delete $chainref2;
|
||||||
|
|
||||||
|
if ( $providerref->{optional} ) {
|
||||||
|
my $dev = chain_base $providerref->{physical};
|
||||||
|
my $base = uc $dev;
|
||||||
|
|
||||||
|
add_commands( $chainref2, qq(if [ -n "\$SW_${base}_IS_USABLE" ]; then) );
|
||||||
|
incr_cmd_level $chainref2;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_ijump( $chainref2, j => 'MARK', targetopts => "--set-mark $providerref->{mark}/$globals{PROVIDER_MASK}", statistic => "--mode random --probability $providerref->{load}" );
|
||||||
|
|
||||||
|
if ( $providerref->{optional} ) {
|
||||||
|
add_commands( $chainref2 , 'fi' );
|
||||||
|
decr_cmd_level( $chainref2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
add_ijump ( $chainref1,
|
||||||
|
j => $chainref2 ,
|
||||||
|
mark => "--mark 0/$mask" );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub copy_table( $$$ ) {
|
sub copy_table( $$$ ) {
|
||||||
@ -366,8 +407,8 @@ sub process_a_provider() {
|
|||||||
$gateway = '';
|
$gateway = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
my ( $loose, $track, $balance , $default, $default_balance, $optional, $mtu, $local ) =
|
my ( $loose, $track, $balance , $default, $default_balance, $optional, $mtu, $local , $load ) =
|
||||||
(0, $config{TRACK_PROVIDERS}, 0 , 0, $config{USE_DEFAULT_RT} ? 1 : 0, interface_is_optional( $interface ), '' , 0 );
|
(0, $config{TRACK_PROVIDERS}, 0 , 0, $config{USE_DEFAULT_RT} ? 1 : 0, interface_is_optional( $interface ), '' , 0 , 0 );
|
||||||
|
|
||||||
unless ( $options eq '-' ) {
|
unless ( $options eq '-' ) {
|
||||||
for my $option ( split_list $options, 'option' ) {
|
for my $option ( split_list $options, 'option' ) {
|
||||||
@ -408,6 +449,9 @@ sub process_a_provider() {
|
|||||||
$local = 1;
|
$local = 1;
|
||||||
$track = 0 if $config{TRACK_PROVIDERS};
|
$track = 0 if $config{TRACK_PROVIDERS};
|
||||||
$default_balance = 0 if $config{USE_DEFAULT_RT};
|
$default_balance = 0 if $config{USE_DEFAULT_RT};
|
||||||
|
} elsif ( $option =~ /^load=(0?\.\d{1,8})/ ) {
|
||||||
|
$load = $1;
|
||||||
|
require_capability 'STATISTIC_MATCH', "load=$load", 's';
|
||||||
} else {
|
} else {
|
||||||
fatal_error "Invalid option ($option)";
|
fatal_error "Invalid option ($option)";
|
||||||
}
|
}
|
||||||
@ -416,6 +460,11 @@ sub process_a_provider() {
|
|||||||
|
|
||||||
fatal_error q(The 'balance' and 'fallback' options are mutually exclusive) if $balance && $default;
|
fatal_error q(The 'balance' and 'fallback' options are mutually exclusive) if $balance && $default;
|
||||||
|
|
||||||
|
if ( $load ) {
|
||||||
|
fatal_error q(The 'balance=<weight>' and 'load=<load-factor>' options are mutually exclusive) if $balance > 1;
|
||||||
|
fatal_error q(The 'fallback=<weight>' and 'load=<load-factor>' options are mutually exclusive) if $default > 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ( $local ) {
|
if ( $local ) {
|
||||||
fatal_error "GATEWAY not valid with 'local' provider" unless $gatewaycase eq 'none';
|
fatal_error "GATEWAY not valid with 'local' provider" unless $gatewaycase eq 'none';
|
||||||
fatal_error "'track' not valid with 'local'" if $track;
|
fatal_error "'track' not valid with 'local'" if $track;
|
||||||
@ -488,6 +537,7 @@ sub process_a_provider() {
|
|||||||
duplicate => $duplicate ,
|
duplicate => $duplicate ,
|
||||||
address => $address ,
|
address => $address ,
|
||||||
local => $local ,
|
local => $local ,
|
||||||
|
load => $load ,
|
||||||
rules => [] ,
|
rules => [] ,
|
||||||
routes => [] ,
|
routes => [] ,
|
||||||
};
|
};
|
||||||
@ -506,6 +556,8 @@ sub process_a_provider() {
|
|||||||
push @routemarked_providers, $providers{$table};
|
push @routemarked_providers, $providers{$table};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
push @load_providers, $providers{$table} if $load;
|
||||||
|
|
||||||
push @providers, $table;
|
push @providers, $table;
|
||||||
|
|
||||||
progress_message " Provider \"$currentline\" $done";
|
progress_message " Provider \"$currentline\" $done";
|
||||||
@ -537,6 +589,8 @@ sub add_a_provider( $$ ) {
|
|||||||
my $duplicate = $providerref->{duplicate};
|
my $duplicate = $providerref->{duplicate};
|
||||||
my $address = $providerref->{address};
|
my $address = $providerref->{address};
|
||||||
my $local = $providerref->{local};
|
my $local = $providerref->{local};
|
||||||
|
my $load = $providerref->{load};
|
||||||
|
|
||||||
my $dev = chain_base $physical;
|
my $dev = chain_base $physical;
|
||||||
my $base = uc $dev;
|
my $base = uc $dev;
|
||||||
my $realm = '';
|
my $realm = '';
|
||||||
@ -703,6 +757,9 @@ sub add_a_provider( $$ ) {
|
|||||||
$weight = 1;
|
$weight = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit( 'run_iptables -t mangle -A ' . load_chain( $table ) . ' -m statistic --mode random --probability ' . $load,
|
||||||
|
'' ) if $load;
|
||||||
|
|
||||||
unless ( $shared ) {
|
unless ( $shared ) {
|
||||||
emit( "setup_${dev}_tc" ) if $tcdevices->{$interface};
|
emit( "setup_${dev}_tc" ) if $tcdevices->{$interface};
|
||||||
}
|
}
|
||||||
@ -784,6 +841,9 @@ sub add_a_provider( $$ ) {
|
|||||||
emit (". $undo",
|
emit (". $undo",
|
||||||
"> $undo" );
|
"> $undo" );
|
||||||
|
|
||||||
|
emit( '',
|
||||||
|
'run_iptables -t mangle -X ' . load_chain( $table ) ) if $load;
|
||||||
|
|
||||||
unless ( $shared ) {
|
unless ( $shared ) {
|
||||||
emit( '',
|
emit( '',
|
||||||
"qt \$TC qdisc del dev $physical root",
|
"qt \$TC qdisc del dev $physical root",
|
||||||
@ -1232,7 +1292,7 @@ sub setup_providers() {
|
|||||||
pop_indent;
|
pop_indent;
|
||||||
emit "fi\n";
|
emit "fi\n";
|
||||||
|
|
||||||
setup_route_marking if @routemarked_interfaces;
|
setup_route_marking if @routemarked_interfaces || @load_providers;
|
||||||
} else {
|
} else {
|
||||||
emit "\nif [ -z \"\$g_noroutes\" ]; then";
|
emit "\nif [ -z \"\$g_noroutes\" ]; then";
|
||||||
|
|
||||||
@ -1504,7 +1564,7 @@ sub handle_stickiness( $ ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( @routemarked_providers ) {
|
if ( @routemarked_providers || @load_providers ) {
|
||||||
delete_jumps $mangle_table->{PREROUTING}, $setstickyref unless @{$setstickyref->{rules}};
|
delete_jumps $mangle_table->{PREROUTING}, $setstickyref unless @{$setstickyref->{rules}};
|
||||||
delete_jumps $mangle_table->{OUTPUT}, $setstickoref unless @{$setstickoref->{rules}};
|
delete_jumps $mangle_table->{OUTPUT}, $setstickoref unless @{$setstickoref->{rules}};
|
||||||
}
|
}
|
||||||
|
@ -1300,9 +1300,8 @@ lillycat: #</programlisting>
|
|||||||
<para>Although 'balance' is automatically assumed when
|
<para>Although 'balance' is automatically assumed when
|
||||||
USE_DEFAULT_RT=Yes, you can easily cause all traffic to use one provider
|
USE_DEFAULT_RT=Yes, you can easily cause all traffic to use one provider
|
||||||
except when you explicitly direct it to use the other provider via
|
except when you explicitly direct it to use the other provider via
|
||||||
<ulink
|
<ulink url="manpages/shorewall-rtrules.html">shorewall-rtrules</ulink>
|
||||||
url="manpages/shorewall-rtrules.html">shorewall-rtrules</ulink> (5)
|
(5) or <ulink
|
||||||
or <ulink
|
|
||||||
url="manpages/shorewall-tcrules.html">shorewall-tcrules</ulink>
|
url="manpages/shorewall-tcrules.html">shorewall-tcrules</ulink>
|
||||||
(5).</para>
|
(5).</para>
|
||||||
|
|
||||||
@ -1354,9 +1353,15 @@ shorewall 2 2 - eth0 192.168.1.254 track,balance=2,optional<
|
|||||||
<ulink
|
<ulink
|
||||||
url="manpages/shorewall-providers.html">shorewall-providers</ulink> (5)
|
url="manpages/shorewall-providers.html">shorewall-providers</ulink> (5)
|
||||||
is available in the form of a PROBABILITY column in <ulink
|
is available in the form of a PROBABILITY column in <ulink
|
||||||
url="???">shorewall-tcrules</ulink> (5).</para>
|
url="???">shorewall-tcrules</ulink> (5). This feature requires the
|
||||||
|
<firstterm>Statistic Match</firstterm> capability in your iptables and
|
||||||
|
kernel.</para>
|
||||||
|
|
||||||
<para>Here's an example:</para>
|
<para>This method works when there are two links to the same ISP where
|
||||||
|
both links have the same default gateway.</para>
|
||||||
|
|
||||||
|
<para>Here's an example that sends 1/3 of the connections through
|
||||||
|
provider ComcastC and the rest through ComastB.</para>
|
||||||
|
|
||||||
<para><filename>/etc/shorewall/shorewall.conf</filename>:</para>
|
<para><filename>/etc/shorewall/shorewall.conf</filename>:</para>
|
||||||
|
|
||||||
@ -1372,7 +1377,7 @@ ZONE_BITS=4
|
|||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para> PROVIDER_OFFSET=16 and ZONE_BITS=4 means that the provider mask
|
<para>PROVIDER_OFFSET=16 and ZONE_BITS=4 means that the provider mask
|
||||||
will be 0xf0000.</para>
|
will be 0xf0000.</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
@ -1380,11 +1385,10 @@ ZONE_BITS=4
|
|||||||
|
|
||||||
<programlisting>#NAME NUMBER MARK DUPLICATE INTERFACE GATEWAY OPTIONS
|
<programlisting>#NAME NUMBER MARK DUPLICATE INTERFACE GATEWAY OPTIONS
|
||||||
ComcastB 1 - - eth1 70.90.191.126 loose,balance
|
ComcastB 1 - - eth1 70.90.191.126 loose,balance
|
||||||
ComcastC 2 - - eth0 detect loose,balance
|
ComcastC 2 - - eth0 detect loose,fallback,load=0.33333333</programlisting>
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para> The <option>loose</option> option is specified so that the
|
<para>The <option>loose</option> option is specified so that the
|
||||||
compiler will not generate and rules based on interface IP addresses.
|
compiler will not generate and rules based on interface IP addresses.
|
||||||
That way we have complete control over the priority of such rules
|
That way we have complete control over the priority of such rules
|
||||||
through entries in the rtrules file.</para>
|
through entries in the rtrules file.</para>
|
||||||
@ -1404,41 +1408,29 @@ ComcastC 2 - - eth0 detect loose,balance
|
|||||||
</note>
|
</note>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para> Priority = 1000 means that these rules will come before rules
|
<para>Priority = 1000 means that these rules will come before rules
|
||||||
that select a provider based on marks.</para>
|
that select a provider based on marks.</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para><filename>/etc/shorewall/tcrules</filename>:</para>
|
<para>As shown in the above example, this technique works best when
|
||||||
|
there are two providers.</para>
|
||||||
|
|
||||||
<programlisting> #MARK SOURCE DEST PROTO DEST
|
<orderedlist>
|
||||||
# PORT(S)
|
<listitem>
|
||||||
CONTINUE - 70.90.191.120/29
|
<para>One is configured with <option>balance</option> and the other
|
||||||
CONTINUE - 10.0.10.0/24
|
with <option>fallback</option>.</para>
|
||||||
CONTINUE - - tcp 80
|
</listitem>
|
||||||
|
|
||||||
# 70.90.191.120/29 is the local public subnet. 10.0.10.0/24 is a
|
<listitem>
|
||||||
# local network on eth1. We don't want to mark TCP 80, because
|
<para>The provider with the <option>fallback</option> option is
|
||||||
# we run a transparent proxy on the firewall.
|
configured whith load=<replaceable>number</replaceable> where the
|
||||||
|
<replaceable>number</replaceable> has a value in the range 0 <
|
||||||
0X10000/0xf0000 eth2 - ; probability=0.66666667
|
<replaceable>number</replaceable> <= 1. This
|
||||||
0x20000/0xf0000 eth2 - ; test=0/0x30000
|
<replaceable>number</replaceable> defines the probability that each
|
||||||
|
new connection will be sent to the fallback provider and may have up
|
||||||
# The above two split traffic entering the firewall through eth2
|
to 8 digits to the right of the decimal point.</para>
|
||||||
# (local LAN) between the two providers with 2/3 of the traffic
|
</listitem>
|
||||||
# going to eth1 and 1/3 going to eth0.
|
</orderedlist>
|
||||||
|
|
||||||
CONTINUE fw:70.90.191.120/29
|
|
||||||
CONTINUE fw 172.20.1.0/22
|
|
||||||
CONTINUE fw 70.90.191.120/29
|
|
||||||
CONTINUE fw 10.0.10.0/24
|
|
||||||
|
|
||||||
# Similar to rules above
|
|
||||||
|
|
||||||
0X10000/0xf0000 fw - ; probability=0.66666667
|
|
||||||
0x20000/0xf0000 fw - ; test=0/0x30000
|
|
||||||
|
|
||||||
# Again, split traffic from the firewall 2:1 in favor of eth1.
|
|
||||||
</programlisting>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="LinkMonitor">
|
<section id="LinkMonitor">
|
||||||
|
Loading…
Reference in New Issue
Block a user